Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: media/video/gpu_memory_buffer_video_frame_pool.cc

Issue 1273943002: media: Make GpuMemoryBuffers VideoFrame copies asynchronous. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address reveman's and dalecurtis' comments. Disable GMB VideoFrames. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/video/gpu_memory_buffer_video_frame_pool.h" 5 #include "media/video/gpu_memory_buffer_video_frame_pool.h"
6 6
7 #include <GLES2/gl2.h> 7 #include <GLES2/gl2.h>
8 #include <GLES2/gl2ext.h> 8 #include <GLES2/gl2ext.h>
9 9
10 #include <algorithm>
10 #include <list> 11 #include <list>
11 #include <utility> 12 #include <utility>
12 13
14 #include "base/barrier_closure.h"
13 #include "base/bind.h" 15 #include "base/bind.h"
14 #include "base/containers/stack_container.h" 16 #include "base/containers/stack_container.h"
15 #include "base/location.h" 17 #include "base/location.h"
16 #include "base/memory/linked_ptr.h" 18 #include "base/memory/linked_ptr.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/trace_event/trace_event.h" 19 #include "base/trace_event/trace_event.h"
19 #include "gpu/command_buffer/client/gles2_interface.h" 20 #include "gpu/command_buffer/client/gles2_interface.h"
20 #include "media/renderers/gpu_video_accelerator_factories.h" 21 #include "media/renderers/gpu_video_accelerator_factories.h"
21 22
22 namespace media { 23 namespace media {
23 24
24 // Implementation of a pool of GpuMemoryBuffers used to back VideoFrames. 25 // Implementation of a pool of GpuMemoryBuffers used to back VideoFrames.
25 class GpuMemoryBufferVideoFramePool::PoolImpl 26 class GpuMemoryBufferVideoFramePool::PoolImpl
26 : public base::RefCountedThreadSafe< 27 : public base::RefCountedThreadSafe<
27 GpuMemoryBufferVideoFramePool::PoolImpl> { 28 GpuMemoryBufferVideoFramePool::PoolImpl> {
28 public: 29 public:
29 // |task_runner| is associated to the thread where the context of 30 // |media_task_runner| is the media task runner associated with the
30 // GLES2Interface returned by |gpu_factories| lives. 31 // GL context provided by |gpu_factories|
32 // |worker_task_runner| is a task runner used to asynchronously copy
33 // video frame's planes.
31 // |gpu_factories| is an interface to GPU related operation and can be 34 // |gpu_factories| is an interface to GPU related operation and can be
32 // null. 35 // null if a GL context is not available.
33 PoolImpl(const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 36 PoolImpl(const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
37 const scoped_refptr<base::TaskRunner>& worker_task_runner,
34 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories) 38 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories)
35 : task_runner_(task_runner), 39 : media_task_runner_(media_task_runner),
40 worker_task_runner_(worker_task_runner),
36 gpu_factories_(gpu_factories), 41 gpu_factories_(gpu_factories),
37 texture_target_(gpu_factories_ ? gpu_factories_->ImageTextureTarget() 42 texture_target_(gpu_factories ? gpu_factories->ImageTextureTarget()
38 : GL_TEXTURE_2D) {} 43 : GL_TEXTURE_2D) {
44 DCHECK(media_task_runner_);
45 DCHECK(worker_task_runner_);
46 }
39 47
40 // Takes a software VideoFrame and returns a VideoFrame backed by native 48 // Takes a software VideoFrame and calls |frame_ready_cb| with a VideoFrame
41 // textures if possible. 49 // backed by native textures if possible.
42 // The data contained in video_frame is copied into the returned frame. 50 // The data contained in video_frame is copied into the returned frame
43 scoped_refptr<VideoFrame> CreateHardwareFrame( 51 // asynchronously posting tasks to |worker_task_runner_|, while
44 const scoped_refptr<VideoFrame>& video_frame); 52 // |frame_ready_cb| will be called on |media_task_runner_| once all the data
53 // has been copied.
54 void CreateHardwareFrame(const scoped_refptr<VideoFrame>& video_frame,
55 const FrameReadyCB& cb);
45 56
46 private: 57 private:
47 friend class base::RefCountedThreadSafe< 58 friend class base::RefCountedThreadSafe<
48 GpuMemoryBufferVideoFramePool::PoolImpl>; 59 GpuMemoryBufferVideoFramePool::PoolImpl>;
49 ~PoolImpl(); 60 ~PoolImpl();
50 61
51 // Resource to represent a plane. 62 // Resource to represent a plane.
52 struct PlaneResource { 63 struct PlaneResource {
53 gfx::Size size; 64 gfx::Size size;
54 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer; 65 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer;
55 unsigned texture_id = 0u; 66 unsigned texture_id = 0u;
56 unsigned image_id = 0u; 67 unsigned image_id = 0u;
57 gpu::Mailbox mailbox; 68 gpu::Mailbox mailbox;
58 }; 69 };
59 70
60 // All the resources needed to compose a frame. 71 // All the resources needed to compose a frame.
61 struct FrameResources { 72 struct FrameResources {
62 FrameResources(VideoPixelFormat format, const gfx::Size& size) 73 FrameResources(VideoPixelFormat format, const gfx::Size& size)
63 : format(format), size(size) {} 74 : format(format), size(size) {}
64 bool in_use = true; 75 bool in_use = true;
65 VideoPixelFormat format; 76 VideoPixelFormat format;
66 gfx::Size size; 77 gfx::Size size;
67 PlaneResource plane_resources[VideoFrame::kMaxPlanes]; 78 PlaneResource plane_resources[VideoFrame::kMaxPlanes];
68 }; 79 };
69 80
81 // Copy |video_frame| data into |frame_resouces|
82 // and calls |done| when done.
83 void CopyVideoFrameToGpuMemoryBuffers(
84 const scoped_refptr<VideoFrame>& video_frame,
85 FrameResources* frame_resources,
86 const FrameReadyCB& frame_ready_cb);
87
88 // Called when all the data has been copied.
89 void OnCopiesDone(const scoped_refptr<VideoFrame>& video_frame,
90 FrameResources* frame_resources,
91 const FrameReadyCB& frame_ready_cb);
92
93 // Prepares GL resources, mailboxes and calls |frame_ready_cb| with the new
94 // VideoFrame.
95 // This has to be run on |media_task_runner_| where |frame_ready_cb| will also
96 // be run.
97 void BindAndCreateMailboxesHardwareFrameResources(
98 const scoped_refptr<VideoFrame>& video_frame,
99 FrameResources* frame_resources,
100 const FrameReadyCB& frame_ready_cb);
101
70 // Return true if |resources| can be used to represent a frame for 102 // Return true if |resources| can be used to represent a frame for
71 // specific |format| and |size|. 103 // specific |format| and |size|.
72 static bool AreFrameResourcesCompatible(const FrameResources* resources, 104 static bool AreFrameResourcesCompatible(const FrameResources* resources,
73 const gfx::Size& size, 105 const gfx::Size& size,
74 VideoPixelFormat format) { 106 VideoPixelFormat format) {
75 return size == resources->size && format == resources->format; 107 return size == resources->size && format == resources->format;
76 } 108 }
77 109
78 // Get the resources needed for a frame out of the pool, or create them if 110 // Get the resources needed for a frame out of the pool, or create them if
79 // necessary. 111 // necessary.
80 // This also drops the LRU resources that can't be reuse for this frame. 112 // This also drops the LRU resources that can't be reuse for this frame.
81 FrameResources* GetOrCreateFrameResources(const gfx::Size& size, 113 FrameResources* GetOrCreateFrameResources(const gfx::Size& size,
82 VideoPixelFormat format); 114 VideoPixelFormat format);
83 115
84 // Callback called when a VideoFrame generated with GetFrameResources is no 116 // Callback called when a VideoFrame generated with GetFrameResources is no
85 // longer referenced. 117 // longer referenced.
86 // This could be called by any thread. 118 // This could be called by any thread.
87 void MailboxHoldersReleased(FrameResources* frame_resources, 119 void MailboxHoldersReleased(FrameResources* frame_resources,
88 uint32 sync_point); 120 uint32 sync_point);
89 121
90 // Return frame resources to the pool. This has to be called on the thread 122 // Return frame resources to the pool. This has to be called on the thread
91 // where |task_runner| is current. 123 // where |media_task_runner_| is current.
92 void ReturnFrameResources(FrameResources* frame_resources); 124 void ReturnFrameResources(FrameResources* frame_resources);
93 125
94 // Delete resources. This has to be called on the thread where |task_runner| 126 // Delete resources. This has to be called on the thread where |task_runner|
95 // is current. 127 // is current.
96 static void DeleteFrameResources( 128 static void DeleteFrameResources(
97 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories, 129 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
98 FrameResources* frame_resources); 130 FrameResources* frame_resources);
99 131
100 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 132 // Task runner associated to the GL context provided by |gpu_factories_|.
133 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
134 // Task runner used to asynchronously copy planes.
135 scoped_refptr<base::TaskRunner> worker_task_runner_;
136
137 // Interface to GPU related operations.
101 scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories_; 138 scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories_;
102 139
103 // Pool of resources. 140 // Pool of resources.
104 std::list<FrameResources*> resources_pool_; 141 std::list<FrameResources*> resources_pool_;
105 142
106 const unsigned texture_target_; 143 const unsigned texture_target_;
107 DISALLOW_COPY_AND_ASSIGN(PoolImpl); 144 DISALLOW_COPY_AND_ASSIGN(PoolImpl);
108 }; 145 };
109 146
110 namespace { 147 namespace {
111 148
112 // Copy a buffer info a GpuMemoryBuffer. 149 // VideoFrame copies to GpuMemoryBuffers will be split in |kBytesPerCopyTarget|
113 // |bytes_per_row| is expected to be less or equal than the strides of the two 150 // bytes copies and run in parallel.
114 // buffers. 151 const size_t kBytesPerCopyTarget = 1024 * 1024; // 1MB
115 void CopyPlaneToGpuMemoryBuffer(int rows,
116 int bytes_per_row,
117 const uint8* source,
118 int source_stride,
119 gfx::GpuMemoryBuffer* buffer) {
120 TRACE_EVENT2("media", "CopyPlaneToGpuMemoryBuffer", "bytes_per_row",
121 bytes_per_row, "rows", rows);
122 152
123 DCHECK(buffer); 153 void CopyRowsToBuffer(int first_row,
124 DCHECK(source); 154 int rows,
125 void* data = nullptr; 155 int bytes_per_row,
126 CHECK(buffer->Map(&data)); 156 const uint8* source,
127 uint8* mapped_buffer = static_cast<uint8*>(data); 157 int source_stride,
128 int dest_stride = 0; 158 uint8* output,
129 buffer->GetStride(&dest_stride); 159 int dest_stride,
160 const base::Closure& done) {
161 TRACE_EVENT2("media", "CopyRowsToBuffer", "bytes_per_row", bytes_per_row,
162 "rows", rows);
130 DCHECK_NE(dest_stride, 0); 163 DCHECK_NE(dest_stride, 0);
131 DCHECK_LE(bytes_per_row, std::abs(dest_stride)); 164 DCHECK_LE(bytes_per_row, std::abs(dest_stride));
132 DCHECK_LE(bytes_per_row, source_stride); 165 DCHECK_LE(bytes_per_row, source_stride);
133 for (int row = 0; row < rows; ++row) { 166 for (int row = first_row; row < first_row + rows; ++row) {
134 memcpy(mapped_buffer + dest_stride * row, source + source_stride * row, 167 memcpy(output + dest_stride * row, source + source_stride * row,
135 bytes_per_row); 168 bytes_per_row);
136 } 169 }
137 buffer->Unmap(); 170 done.Run();
138 } 171 }
139 172
140 } // unnamed namespace 173 } // unnamed namespace
141 174
142 // Creates a VideoFrame backed by native textures starting from a software 175 // Creates a VideoFrame backed by native textures starting from a software
143 // VideoFrame. 176 // VideoFrame.
144 // The data contained in video_frame is copied into the returned VideoFrame. 177 // The data contained in |video_frame| is copied into the VideoFrame passed to
145 scoped_refptr<VideoFrame> 178 // |frame_ready_cb|.
146 GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame( 179 // This has to be called on the thread where |media_task_runner_| is current.
147 const scoped_refptr<VideoFrame>& video_frame) { 180 void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame(
148 if (!gpu_factories_) 181 const scoped_refptr<VideoFrame>& video_frame,
149 return video_frame; 182 const FrameReadyCB& frame_ready_cb) {
150 183 DCHECK(media_task_runner_->BelongsToCurrentThread());
151 if (!gpu_factories_->IsTextureRGSupported()) 184 if (!gpu_factories_ || !gpu_factories_->IsTextureRGSupported()) {
152 return video_frame; 185 frame_ready_cb.Run(video_frame);
153 186 return;
154 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface(); 187 }
155 if (!gles2) 188 switch (video_frame->format()) {
156 return video_frame; 189 // Supported cases.
190 case PIXEL_FORMAT_YV12:
191 case PIXEL_FORMAT_I420:
192 break;
193 // Unsupported cases.
194 case PIXEL_FORMAT_YV12A:
195 case PIXEL_FORMAT_YV16:
196 case PIXEL_FORMAT_YV24:
197 case PIXEL_FORMAT_NV12:
198 case PIXEL_FORMAT_ARGB:
199 case PIXEL_FORMAT_XRGB:
200 case PIXEL_FORMAT_UNKNOWN:
201 frame_ready_cb.Run(video_frame);
202 return;
203 }
157 204
158 VideoPixelFormat format = video_frame->format(); 205 VideoPixelFormat format = video_frame->format();
159 size_t planes = VideoFrame::NumPlanes(format);
160 DCHECK(video_frame->visible_rect().origin().IsOrigin()); 206 DCHECK(video_frame->visible_rect().origin().IsOrigin());
161 gfx::Size size = video_frame->visible_rect().size(); 207 const gfx::Size size = video_frame->visible_rect().size();
162 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
163 208
164 // Acquire resources. Incompatible ones will be dropped from the pool. 209 // Acquire resources. Incompatible ones will be dropped from the pool.
165 FrameResources* frame_resources = GetOrCreateFrameResources(size, format); 210 FrameResources* frame_resources = GetOrCreateFrameResources(size, format);
211 if (!frame_resources) {
212 frame_ready_cb.Run(video_frame);
213 return;
214 }
166 215
167 // Set up the planes copying data into it and creating the mailboxes needed 216 worker_task_runner_->PostTask(
168 // to refer to the textures. 217 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this,
218 video_frame, frame_resources, frame_ready_cb));
219 }
220
221 void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone(
222 const scoped_refptr<VideoFrame>& video_frame,
223 FrameResources* frame_resources,
224 const FrameReadyCB& frame_ready_cb) {
225 const VideoPixelFormat format = video_frame->format();
226 const size_t planes = VideoFrame::NumPlanes(format);
227 for (size_t i = 0; i < planes; ++i) {
228 frame_resources->plane_resources[i].gpu_memory_buffer->Unmap();
229 }
230
231 media_task_runner_->PostTask(
232 FROM_HERE,
233 base::Bind(&PoolImpl::BindAndCreateMailboxesHardwareFrameResources, this,
234 video_frame, frame_resources, frame_ready_cb));
235 }
236
237 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks
238 // that will be synchronized by a barrier.
239 // After the barrier is passed OnCopiesDone will be called.
240 void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers(
241 const scoped_refptr<VideoFrame>& video_frame,
242 FrameResources* frame_resources,
243 const FrameReadyCB& frame_ready_cb) {
244 const VideoPixelFormat format = video_frame->format();
245 const size_t planes = VideoFrame::NumPlanes(format);
246 gfx::Size size = video_frame->visible_rect().size();
247 size_t copies = 0;
248 for (size_t i = 0; i < planes; ++i) {
249 int rows = VideoFrame::Rows(i, format, size.height());
250 int bytes_per_row = VideoFrame::RowBytes(i, format, size.width());
251 int rows_per_copy =
252 std::max<size_t>(kBytesPerCopyTarget / bytes_per_row, 1);
253 copies += rows / rows_per_copy;
254 if (rows % rows_per_copy)
255 ++copies;
256 }
257
258 base::Closure copies_done =
259 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources,
260 frame_ready_cb);
261 base::Closure barrier = base::BarrierClosure(copies, copies_done);
262
263 for (size_t i = 0; i < planes; ++i) {
264 int rows = VideoFrame::Rows(i, format, size.height());
265 int bytes_per_row = VideoFrame::RowBytes(i, format, size.width());
266 int rows_per_copy =
267 std::max<size_t>(kBytesPerCopyTarget / bytes_per_row, 1);
268
269 PlaneResource& plane_resource = frame_resources->plane_resources[i];
270 void* data = nullptr;
271 CHECK(plane_resource.gpu_memory_buffer->Map(&data));
272 uint8* mapped_buffer = static_cast<uint8*>(data);
273 int dest_stride = 0;
274 plane_resource.gpu_memory_buffer->GetStride(&dest_stride);
275
276 for (int row = 0; row < rows; row += rows_per_copy) {
277 worker_task_runner_->PostTask(
278 FROM_HERE,
279 base::Bind(&CopyRowsToBuffer, row,
280 std::min(rows_per_copy, rows - row), bytes_per_row,
281 video_frame->data(i), video_frame->stride(i),
282 mapped_buffer, dest_stride, barrier));
283 }
284 }
285 }
286
287 void GpuMemoryBufferVideoFramePool::PoolImpl::
288 BindAndCreateMailboxesHardwareFrameResources(
289 const scoped_refptr<VideoFrame>& video_frame,
290 FrameResources* frame_resources,
291 const FrameReadyCB& frame_ready_cb) {
292 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface();
293 if (!gles2) {
294 frame_ready_cb.Run(video_frame);
295 return;
296 }
297
298 const VideoPixelFormat format = video_frame->format();
299 const size_t planes = VideoFrame::NumPlanes(format);
300 const gfx::Size size = video_frame->visible_rect().size();
301 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
302 // Set up the planes creating the mailboxes needed to refer to the textures.
169 for (size_t i = 0; i < planes; ++i) { 303 for (size_t i = 0; i < planes; ++i) {
170 PlaneResource& plane_resource = frame_resources->plane_resources[i]; 304 PlaneResource& plane_resource = frame_resources->plane_resources[i];
171 CopyPlaneToGpuMemoryBuffer(VideoFrame::Rows(i, format, size.height()),
172 VideoFrame::RowBytes(i, format, size.width()),
173 video_frame->data(i), video_frame->stride(i),
174 plane_resource.gpu_memory_buffer.get());
175
176 // Bind the texture and create or rebind the image. 305 // Bind the texture and create or rebind the image.
177 gles2->BindTexture(texture_target_, plane_resource.texture_id); 306 gles2->BindTexture(texture_target_, plane_resource.texture_id);
178 307
179 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) { 308 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) {
180 const size_t width = VideoFrame::Columns(i, format, size.width()); 309 const size_t width = VideoFrame::Columns(i, format, size.width());
181 const size_t height = VideoFrame::Rows(i, format, size.height()); 310 const size_t height = VideoFrame::Rows(i, format, size.height());
182 plane_resource.image_id = gles2->CreateImageCHROMIUM( 311 plane_resource.image_id = gles2->CreateImageCHROMIUM(
183 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, 312 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height,
184 GL_R8_EXT); 313 GL_R8_EXT);
185 } else { 314 } else {
(...skipping 16 matching lines...) Expand all
202 // Create the VideoFrame backed by native textures. 331 // Create the VideoFrame backed by native textures.
203 scoped_refptr<VideoFrame> frame = VideoFrame::WrapYUV420NativeTextures( 332 scoped_refptr<VideoFrame> frame = VideoFrame::WrapYUV420NativeTextures(
204 mailbox_holders[VideoFrame::kYPlane], 333 mailbox_holders[VideoFrame::kYPlane],
205 mailbox_holders[VideoFrame::kUPlane], 334 mailbox_holders[VideoFrame::kUPlane],
206 mailbox_holders[VideoFrame::kVPlane], 335 mailbox_holders[VideoFrame::kVPlane],
207 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources), 336 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources),
208 size, video_frame->visible_rect(), video_frame->natural_size(), 337 size, video_frame->visible_rect(), video_frame->natural_size(),
209 video_frame->timestamp()); 338 video_frame->timestamp());
210 if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY)) 339 if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY))
211 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); 340 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);
212 return frame; 341 frame_ready_cb.Run(frame);
213 } 342 }
214 343
215 // Destroy all the resources posting one task per FrameResources 344 // Destroy all the resources posting one task per FrameResources
216 // to the |task_runner_|. 345 // to the |media_task_runner_|.
217 GpuMemoryBufferVideoFramePool::PoolImpl::~PoolImpl() { 346 GpuMemoryBufferVideoFramePool::PoolImpl::~PoolImpl() {
218 // Delete all the resources on the media thread. 347 // Delete all the resources on the media thread.
219 while (!resources_pool_.empty()) { 348 while (!resources_pool_.empty()) {
220 FrameResources* frame_resources = resources_pool_.front(); 349 FrameResources* frame_resources = resources_pool_.front();
221 resources_pool_.pop_front(); 350 resources_pool_.pop_front();
222 task_runner_->PostTask( 351 media_task_runner_->PostTask(
223 FROM_HERE, base::Bind(&PoolImpl::DeleteFrameResources, gpu_factories_, 352 FROM_HERE, base::Bind(&PoolImpl::DeleteFrameResources, gpu_factories_,
224 base::Owned(frame_resources))); 353 base::Owned(frame_resources)));
225 } 354 }
226 } 355 }
227 356
228 // Tries to find the resources in the pool or create them. 357 // Tries to find the resources in the pool or create them.
229 // Incompatible resources will be dropped. 358 // Incompatible resources will be dropped.
230 GpuMemoryBufferVideoFramePool::PoolImpl::FrameResources* 359 GpuMemoryBufferVideoFramePool::PoolImpl::FrameResources*
231 GpuMemoryBufferVideoFramePool::PoolImpl::GetOrCreateFrameResources( 360 GpuMemoryBufferVideoFramePool::PoolImpl::GetOrCreateFrameResources(
232 const gfx::Size& size, 361 const gfx::Size& size,
233 VideoPixelFormat format) { 362 VideoPixelFormat format) {
234 DCHECK(task_runner_->BelongsToCurrentThread());
235
236 auto it = resources_pool_.begin(); 363 auto it = resources_pool_.begin();
237 while (it != resources_pool_.end()) { 364 while (it != resources_pool_.end()) {
238 FrameResources* frame_resources = *it; 365 FrameResources* frame_resources = *it;
239 if (!frame_resources->in_use) { 366 if (!frame_resources->in_use) {
240 if (AreFrameResourcesCompatible(frame_resources, size, format)) { 367 if (AreFrameResourcesCompatible(frame_resources, size, format)) {
241 frame_resources->in_use = true; 368 frame_resources->in_use = true;
242 return frame_resources; 369 return frame_resources;
243 } else { 370 } else {
244 resources_pool_.erase(it++); 371 resources_pool_.erase(it++);
245 DeleteFrameResources(gpu_factories_, frame_resources); 372 DeleteFrameResources(gpu_factories_, frame_resources);
246 delete frame_resources; 373 delete frame_resources;
247 } 374 }
248 } else { 375 } else {
249 it++; 376 it++;
250 } 377 }
251 } 378 }
252 379
253 // Create the resources. 380 // Create the resources.
254 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface(); 381 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface();
255 DCHECK(gles2); 382 if (!gles2)
383 return nullptr;
256 gles2->ActiveTexture(GL_TEXTURE0); 384 gles2->ActiveTexture(GL_TEXTURE0);
257 size_t planes = VideoFrame::NumPlanes(format); 385 size_t planes = VideoFrame::NumPlanes(format);
258 FrameResources* frame_resources = new FrameResources(format, size); 386 FrameResources* frame_resources = new FrameResources(format, size);
259 resources_pool_.push_back(frame_resources); 387 resources_pool_.push_back(frame_resources);
260 for (size_t i = 0; i < planes; ++i) { 388 for (size_t i = 0; i < planes; ++i) {
261 PlaneResource& plane_resource = frame_resources->plane_resources[i]; 389 PlaneResource& plane_resource = frame_resources->plane_resources[i];
262 const size_t width = VideoFrame::Columns(i, format, size.width()); 390 const size_t width = VideoFrame::Columns(i, format, size.width());
263 const size_t height = VideoFrame::Rows(i, format, size.height()); 391 const size_t height = VideoFrame::Rows(i, format, size.height());
264 const gfx::Size plane_size(width, height); 392 const gfx::Size plane_size(width, height);
265 plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer( 393 plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer(
(...skipping 28 matching lines...) Expand all
294 if (plane_resource.texture_id) 422 if (plane_resource.texture_id)
295 gles2->DeleteTextures(1, &plane_resource.texture_id); 423 gles2->DeleteTextures(1, &plane_resource.texture_id);
296 } 424 }
297 } 425 }
298 426
299 // Called when a VideoFrame is no longer references. 427 // Called when a VideoFrame is no longer references.
300 void GpuMemoryBufferVideoFramePool::PoolImpl::MailboxHoldersReleased( 428 void GpuMemoryBufferVideoFramePool::PoolImpl::MailboxHoldersReleased(
301 FrameResources* frame_resources, 429 FrameResources* frame_resources,
302 uint32 sync_point) { 430 uint32 sync_point) {
303 // Return the resource on the media thread. 431 // Return the resource on the media thread.
304 task_runner_->PostTask(FROM_HERE, base::Bind(&PoolImpl::ReturnFrameResources, 432 media_task_runner_->PostTask(
305 this, frame_resources)); 433 FROM_HERE,
434 base::Bind(&PoolImpl::ReturnFrameResources, this, frame_resources));
306 } 435 }
307 436
308 // Put back the resoruces in the pool. 437 // Put back the resoruces in the pool.
309 void GpuMemoryBufferVideoFramePool::PoolImpl::ReturnFrameResources( 438 void GpuMemoryBufferVideoFramePool::PoolImpl::ReturnFrameResources(
310 FrameResources* frame_resources) { 439 FrameResources* frame_resources) {
311 DCHECK(task_runner_->BelongsToCurrentThread());
312 440
313 auto it = std::find(resources_pool_.begin(), resources_pool_.end(), 441 auto it = std::find(resources_pool_.begin(), resources_pool_.end(),
314 frame_resources); 442 frame_resources);
315 DCHECK(it != resources_pool_.end()); 443 DCHECK(it != resources_pool_.end());
316 // We want the pool to behave in a FIFO way. 444 // We want the pool to behave in a FIFO way.
317 // This minimizes the chances of locking the buffer that might be 445 // This minimizes the chances of locking the buffer that might be
318 // still needed for drawing. 446 // still needed for drawing.
319 std::swap(*it, resources_pool_.back()); 447 std::swap(*it, resources_pool_.back());
320 frame_resources->in_use = false; 448 frame_resources->in_use = false;
321 } 449 }
322 450
323 GpuMemoryBufferVideoFramePool::GpuMemoryBufferVideoFramePool( 451 GpuMemoryBufferVideoFramePool::GpuMemoryBufferVideoFramePool(
324 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 452 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
453 const scoped_refptr<base::TaskRunner>& worker_task_runner,
325 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories) 454 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories)
326 : pool_impl_(new PoolImpl(task_runner, gpu_factories)) { 455 : pool_impl_(
327 } 456 new PoolImpl(media_task_runner, worker_task_runner, gpu_factories)) {}
328 457
329 GpuMemoryBufferVideoFramePool::~GpuMemoryBufferVideoFramePool() { 458 GpuMemoryBufferVideoFramePool::~GpuMemoryBufferVideoFramePool() {
330 } 459 }
331 460
332 scoped_refptr<VideoFrame> 461 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame(
333 GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame( 462 const scoped_refptr<VideoFrame>& video_frame,
334 const scoped_refptr<VideoFrame>& video_frame) { 463 const FrameReadyCB& frame_ready_cb) {
335 switch (video_frame->format()) { 464 DCHECK(video_frame);
336 // Supported cases. 465 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb);
337 case PIXEL_FORMAT_YV12:
338 case PIXEL_FORMAT_I420:
339 return pool_impl_->CreateHardwareFrame(video_frame);
340 // Unsupported cases.
341 case PIXEL_FORMAT_YV12A:
342 case PIXEL_FORMAT_YV16:
343 case PIXEL_FORMAT_YV24:
344 case PIXEL_FORMAT_NV12:
345 case PIXEL_FORMAT_ARGB:
346 case PIXEL_FORMAT_XRGB:
347 case PIXEL_FORMAT_UNKNOWN:
348 break;
349 }
350 return video_frame;
351 } 466 }
352 467
353 } // namespace media 468 } // namespace media
OLDNEW
« no previous file with comments | « media/video/gpu_memory_buffer_video_frame_pool.h ('k') | media/video/gpu_memory_buffer_video_frame_pool_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698