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

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: Rebase on master. 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 |cb| with a VideoFrame backed by
41 // textures if possible. 49 // 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 |cb| will be
44 const scoped_refptr<VideoFrame>& video_frame); 52 // called on |media_task_runner_| once all the data has been copied.
53 void CreateHardwareFrame(const scoped_refptr<VideoFrame>& video_frame,
54 const FrameReadyCB& cb);
45 55
46 private: 56 private:
47 friend class base::RefCountedThreadSafe< 57 friend class base::RefCountedThreadSafe<
48 GpuMemoryBufferVideoFramePool::PoolImpl>; 58 GpuMemoryBufferVideoFramePool::PoolImpl>;
49 ~PoolImpl(); 59 ~PoolImpl();
50 60
51 // Resource to represent a plane. 61 // Resource to represent a plane.
52 struct PlaneResource { 62 struct PlaneResource {
53 gfx::Size size; 63 gfx::Size size;
54 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer; 64 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer;
55 unsigned texture_id = 0u; 65 unsigned texture_id = 0u;
56 unsigned image_id = 0u; 66 unsigned image_id = 0u;
57 gpu::Mailbox mailbox; 67 gpu::Mailbox mailbox;
58 }; 68 };
59 69
60 // All the resources needed to compose a frame. 70 // All the resources needed to compose a frame.
61 struct FrameResources { 71 struct FrameResources {
62 FrameResources(VideoPixelFormat format, const gfx::Size& size) 72 FrameResources(VideoPixelFormat format, const gfx::Size& size)
63 : format(format), size(size) {} 73 : format(format), size(size) {}
64 bool in_use = true; 74 bool in_use = true;
65 VideoPixelFormat format; 75 VideoPixelFormat format;
66 gfx::Size size; 76 gfx::Size size;
67 PlaneResource plane_resources[VideoFrame::kMaxPlanes]; 77 PlaneResource plane_resources[VideoFrame::kMaxPlanes];
68 }; 78 };
69 79
80 // Copy |video_frame| data into |frame_resouces|
81 // and calls |done| when done.
82 void CopyVideoFrameToGpuMemoryBuffers(
83 const scoped_refptr<VideoFrame>& video_frame,
84 FrameResources* frame_resources,
85 const FrameReadyCB& cb);
DaleCurtis 2015/08/17 18:01:30 Please use something more descriptive than |cb|.
Daniele Castagna 2015/08/19 21:31:25 Done. Change everywhere |cb| to |frame_ready_cb|
86
87 // Called when all the data has been copied.
88 void OnCopiesDone(const scoped_refptr<VideoFrame>& video_frame,
89 FrameResources* frame_resources,
90 const FrameReadyCB& cb);
91
92 // Prepares GL resources, mailboxes and calls |cb| with the new VideoFrame.
93 // This has to be run on |media_task_runner_| where |cb| will also be run.
94 void BindAndCreateMailboxesHardwareFrameResources(
95 const scoped_refptr<VideoFrame>& video_frame,
96 FrameResources* frame_resources,
97 const FrameReadyCB& cb);
98
70 // Return true if |resources| can be used to represent a frame for 99 // Return true if |resources| can be used to represent a frame for
71 // specific |format| and |size|. 100 // specific |format| and |size|.
72 static bool AreFrameResourcesCompatible(const FrameResources* resources, 101 static bool AreFrameResourcesCompatible(const FrameResources* resources,
73 const gfx::Size& size, 102 const gfx::Size& size,
74 VideoPixelFormat format) { 103 VideoPixelFormat format) {
75 return size == resources->size && format == resources->format; 104 return size == resources->size && format == resources->format;
76 } 105 }
77 106
78 // Get the resources needed for a frame out of the pool, or create them if 107 // Get the resources needed for a frame out of the pool, or create them if
79 // necessary. 108 // necessary.
80 // This also drops the LRU resources that can't be reuse for this frame. 109 // This also drops the LRU resources that can't be reuse for this frame.
81 FrameResources* GetOrCreateFrameResources(const gfx::Size& size, 110 FrameResources* GetOrCreateFrameResources(const gfx::Size& size,
82 VideoPixelFormat format); 111 VideoPixelFormat format);
83 112
84 // Callback called when a VideoFrame generated with GetFrameResources is no 113 // Callback called when a VideoFrame generated with GetFrameResources is no
85 // longer referenced. 114 // longer referenced.
86 // This could be called by any thread. 115 // This could be called by any thread.
87 void MailboxHoldersReleased(FrameResources* frame_resources, 116 void MailboxHoldersReleased(FrameResources* frame_resources,
88 uint32 sync_point); 117 uint32 sync_point);
89 118
90 // Return frame resources to the pool. This has to be called on the thread 119 // Return frame resources to the pool. This has to be called on the thread
91 // where |task_runner| is current. 120 // where |media_task_runner_| is current.
92 void ReturnFrameResources(FrameResources* frame_resources); 121 void ReturnFrameResources(FrameResources* frame_resources);
93 122
94 // Delete resources. This has to be called on the thread where |task_runner| 123 // Delete resources. This has to be called on the thread where |task_runner|
95 // is current. 124 // is current.
96 static void DeleteFrameResources( 125 static void DeleteFrameResources(
97 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories, 126 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
98 FrameResources* frame_resources); 127 FrameResources* frame_resources);
99 128
100 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 129 // Task runner associated to the GL context provided by |gpu_factories_|.
130 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
131 // Task runner used to asynchronously copy planes.
132 scoped_refptr<base::TaskRunner> worker_task_runner_;
133
134 // Interface to GPU related operations.
101 scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories_; 135 scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories_;
102 136
103 // Pool of resources. 137 // Pool of resources.
104 std::list<FrameResources*> resources_pool_; 138 std::list<FrameResources*> resources_pool_;
105 139
106 const unsigned texture_target_; 140 const unsigned texture_target_;
107 DISALLOW_COPY_AND_ASSIGN(PoolImpl); 141 DISALLOW_COPY_AND_ASSIGN(PoolImpl);
108 }; 142 };
109 143
110 namespace { 144 namespace {
111 145
112 // Copy a buffer info a GpuMemoryBuffer. 146 void CopyRowsToBuffer(int first_row,
113 // |bytes_per_row| is expected to be less or equal than the strides of the two 147 int rows,
114 // buffers. 148 int bytes_per_row,
115 void CopyPlaneToGpuMemoryBuffer(int rows, 149 const uint8* source,
116 int bytes_per_row, 150 int source_stride,
117 const uint8* source, 151 uint8* output,
118 int source_stride, 152 int dest_stride,
119 gfx::GpuMemoryBuffer* buffer) { 153 base::Closure done) {
DaleCurtis 2015/08/17 18:01:30 const&
Daniele Castagna 2015/08/19 21:31:25 Done.
120 TRACE_EVENT2("media", "CopyPlaneToGpuMemoryBuffer", "bytes_per_row", 154 TRACE_EVENT2("media", "CopyRowsToBuffer", "bytes_per_row", bytes_per_row,
121 bytes_per_row, "rows", rows); 155 "rows", rows);
122
123 DCHECK(buffer);
124 DCHECK(source);
125 void* data = nullptr;
126 CHECK(buffer->Map(&data));
127 uint8* mapped_buffer = static_cast<uint8*>(data);
128 int dest_stride = 0;
129 buffer->GetStride(&dest_stride);
130 DCHECK_NE(dest_stride, 0); 156 DCHECK_NE(dest_stride, 0);
131 DCHECK_LE(bytes_per_row, std::abs(dest_stride)); 157 DCHECK_LE(bytes_per_row, std::abs(dest_stride));
132 DCHECK_LE(bytes_per_row, source_stride); 158 DCHECK_LE(bytes_per_row, source_stride);
133 for (int row = 0; row < rows; ++row) { 159 for (int row = first_row; row < first_row + rows; ++row) {
134 memcpy(mapped_buffer + dest_stride * row, source + source_stride * row, 160 memcpy(output + dest_stride * row, source + source_stride * row,
135 bytes_per_row); 161 bytes_per_row);
136 } 162 }
137 buffer->Unmap(); 163 done.Run();
138 } 164 }
139 165
140 } // unnamed namespace 166 } // unnamed namespace
141 167
142 // Creates a VideoFrame backed by native textures starting from a software 168 // Creates a VideoFrame backed by native textures starting from a software
143 // VideoFrame. 169 // VideoFrame.
144 // The data contained in video_frame is copied into the returned VideoFrame. 170 // The data contained in |video_frame| is copied into the VideoFrame passed to
145 scoped_refptr<VideoFrame> 171 // |cb|.
146 GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame( 172 // This has to be called on the thread where |media_task_runner_| is current.
147 const scoped_refptr<VideoFrame>& video_frame) { 173 void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame(
148 if (!gpu_factories_) 174 const scoped_refptr<VideoFrame>& video_frame,
149 return video_frame; 175 const FrameReadyCB& cb) {
150 176 DCHECK(media_task_runner_->BelongsToCurrentThread());
151 if (!gpu_factories_->IsTextureRGSupported()) 177 if (!gpu_factories_ || !gpu_factories_->IsTextureRGSupported()) {
152 return video_frame; 178 cb.Run(video_frame);
153 179 return;
154 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface(); 180 }
155 if (!gles2) 181 switch (video_frame->format()) {
156 return video_frame; 182 // Supported cases.
183 case PIXEL_FORMAT_YV12:
184 case PIXEL_FORMAT_I420:
185 break;
186 // Unsupported cases.
187 case PIXEL_FORMAT_YV12A:
188 case PIXEL_FORMAT_YV16:
189 case PIXEL_FORMAT_YV24:
190 case PIXEL_FORMAT_NV12:
191 case PIXEL_FORMAT_ARGB:
192 case PIXEL_FORMAT_XRGB:
193 case PIXEL_FORMAT_UNKNOWN:
194 cb.Run(video_frame);
195 return;
196 }
157 197
158 VideoPixelFormat format = video_frame->format(); 198 VideoPixelFormat format = video_frame->format();
159 size_t planes = VideoFrame::NumPlanes(format);
160 DCHECK(video_frame->visible_rect().origin().IsOrigin()); 199 DCHECK(video_frame->visible_rect().origin().IsOrigin());
161 gfx::Size size = video_frame->visible_rect().size(); 200 const gfx::Size size = video_frame->visible_rect().size();
162 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
163 201
164 // Acquire resources. Incompatible ones will be dropped from the pool. 202 // Acquire resources. Incompatible ones will be dropped from the pool.
165 FrameResources* frame_resources = GetOrCreateFrameResources(size, format); 203 FrameResources* frame_resources = GetOrCreateFrameResources(size, format);
DaleCurtis 2015/08/17 18:01:30 How expensive is the create portion here? I.e. is
Daniele Castagna 2015/08/19 21:31:25 It should not be particularly expensive but it def
204 if (!frame_resources) {
205 cb.Run(video_frame);
206 return;
207 }
166 208
167 // Set up the planes copying data into it and creating the mailboxes needed 209 worker_task_runner_->PostTask(
DaleCurtis 2015/08/17 18:01:30 WDYT about doing an inline copy (i.e. w/o post tas
Daniele Castagna 2015/08/19 21:31:25 Sounds like a good idea. Is it OK if we do this af
168 // to refer to the textures. 210 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this,
211 video_frame, frame_resources, cb));
212 }
213
214 void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone(
215 const scoped_refptr<VideoFrame>& video_frame,
216 FrameResources* frame_resources,
217 const FrameReadyCB& cb) {
218 const VideoPixelFormat format = video_frame->format();
219 const size_t planes = VideoFrame::NumPlanes(format);
220 for (size_t i = 0; i < planes; ++i) {
221 frame_resources->plane_resources[i].gpu_memory_buffer->Unmap();
222 }
223
224 media_task_runner_->PostTask(
225 FROM_HERE,
226 base::Bind(&PoolImpl::BindAndCreateMailboxesHardwareFrameResources, this,
227 video_frame, frame_resources, cb));
228 }
229
230 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks
231 // that will be synchronized by a barrier.
232 // After the barrier is passed OnCopiesDone will be called.
233 void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers(
234 const scoped_refptr<VideoFrame>& video_frame,
235 FrameResources* frame_resources,
236 const FrameReadyCB& cb) {
237 const size_t kBytesPerCopyTarget = 1 << 20;
reveman 2015/08/17 16:38:29 Can you add a comment that makes it clear exactly
Daniele Castagna 2015/08/19 21:31:25 Done.
238 const VideoPixelFormat format = video_frame->format();
239 const size_t planes = VideoFrame::NumPlanes(format);
240 gfx::Size size = video_frame->visible_rect().size();
241 size_t copies = 0;
242 for (size_t i = 0; i < planes; ++i) {
243 int rows = VideoFrame::Rows(i, format, size.height());
244 int bytes = VideoFrame::RowBytes(i, format, size.width());
reveman 2015/08/17 16:38:29 nit: s/bytes/bytes_per_row/ or row_bytes
Daniele Castagna 2015/08/19 21:31:25 Done.
245 int rows_per_copy = std::max<size_t>(kBytesPerCopyTarget / bytes, 1);
246 copies += rows / rows_per_copy;
247 if (rows % rows_per_copy)
248 ++copies;
249 }
250
251 base::Closure copies_done = base::Bind(&PoolImpl::OnCopiesDone, this,
252 video_frame, frame_resources, cb);
253 base::Closure barrier = base::BarrierClosure(copies, copies_done);
254
255 for (size_t i = 0; i < planes; ++i) {
256 int rows = VideoFrame::Rows(i, format, size.height());
257 int bytes = VideoFrame::RowBytes(i, format, size.width());
reveman 2015/08/17 16:38:29 nit: s/bytes/bytes_per_row/
Daniele Castagna 2015/08/19 21:31:25 Done.
258 int rows_per_copy = std::max<size_t>(kBytesPerCopyTarget / bytes, 1);
259
260 PlaneResource& plane_resource = frame_resources->plane_resources[i];
261 void* data = nullptr;
262 CHECK(plane_resource.gpu_memory_buffer->Map(&data));
263 uint8* mapped_buffer = static_cast<uint8*>(data);
264 int dest_stride = 0;
265 plane_resource.gpu_memory_buffer->GetStride(&dest_stride);
266
267 for (int row = 0; row < rows; row += rows_per_copy) {
268 worker_task_runner_->PostTask(
DaleCurtis 2015/08/17 18:01:30 Hmm, did you change the worker task runner to run
Daniele Castagna 2015/08/19 21:31:25 Correct, the worker task runner execute tasks in p
269 FROM_HERE, base::Bind(&CopyRowsToBuffer, row,
270 std::min(rows_per_copy, rows - row), bytes,
271 video_frame->data(i), video_frame->stride(i),
272 mapped_buffer, dest_stride, barrier));
273 }
274 }
275 }
276
277 void GpuMemoryBufferVideoFramePool::PoolImpl::
278 BindAndCreateMailboxesHardwareFrameResources(
279 const scoped_refptr<VideoFrame>& video_frame,
280 FrameResources* frame_resources,
281 const FrameReadyCB& cb) {
282 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface();
283 if (!gles2) {
284 cb.Run(video_frame);
285 return;
286 }
287
288 const VideoPixelFormat format = video_frame->format();
289 const size_t planes = VideoFrame::NumPlanes(format);
290 const gfx::Size size = video_frame->visible_rect().size();
291 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
292 // Set up the planes creating the mailboxes needed to refer to the textures.
169 for (size_t i = 0; i < planes; ++i) { 293 for (size_t i = 0; i < planes; ++i) {
170 PlaneResource& plane_resource = frame_resources->plane_resources[i]; 294 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. 295 // Bind the texture and create or rebind the image.
177 gles2->BindTexture(texture_target_, plane_resource.texture_id); 296 gles2->BindTexture(texture_target_, plane_resource.texture_id);
178 297
179 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) { 298 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) {
180 const size_t width = VideoFrame::Columns(i, format, size.width()); 299 const size_t width = VideoFrame::Columns(i, format, size.width());
181 const size_t height = VideoFrame::Rows(i, format, size.height()); 300 const size_t height = VideoFrame::Rows(i, format, size.height());
182 plane_resource.image_id = gles2->CreateImageCHROMIUM( 301 plane_resource.image_id = gles2->CreateImageCHROMIUM(
183 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, 302 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height,
184 GL_R8_EXT); 303 GL_R8_EXT);
185 } else { 304 } else {
(...skipping 16 matching lines...) Expand all
202 // Create the VideoFrame backed by native textures. 321 // Create the VideoFrame backed by native textures.
203 scoped_refptr<VideoFrame> frame = VideoFrame::WrapYUV420NativeTextures( 322 scoped_refptr<VideoFrame> frame = VideoFrame::WrapYUV420NativeTextures(
204 mailbox_holders[VideoFrame::kYPlane], 323 mailbox_holders[VideoFrame::kYPlane],
205 mailbox_holders[VideoFrame::kUPlane], 324 mailbox_holders[VideoFrame::kUPlane],
206 mailbox_holders[VideoFrame::kVPlane], 325 mailbox_holders[VideoFrame::kVPlane],
207 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources), 326 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources),
208 size, video_frame->visible_rect(), video_frame->natural_size(), 327 size, video_frame->visible_rect(), video_frame->natural_size(),
209 video_frame->timestamp()); 328 video_frame->timestamp());
210 if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY)) 329 if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY))
211 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); 330 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);
212 return frame; 331 cb.Run(frame);
213 } 332 }
214 333
215 // Destroy all the resources posting one task per FrameResources 334 // Destroy all the resources posting one task per FrameResources
216 // to the |task_runner_|. 335 // to the |media_task_runner_|.
217 GpuMemoryBufferVideoFramePool::PoolImpl::~PoolImpl() { 336 GpuMemoryBufferVideoFramePool::PoolImpl::~PoolImpl() {
218 // Delete all the resources on the media thread. 337 // Delete all the resources on the media thread.
219 while (!resources_pool_.empty()) { 338 while (!resources_pool_.empty()) {
220 FrameResources* frame_resources = resources_pool_.front(); 339 FrameResources* frame_resources = resources_pool_.front();
221 resources_pool_.pop_front(); 340 resources_pool_.pop_front();
222 task_runner_->PostTask( 341 media_task_runner_->PostTask(
223 FROM_HERE, base::Bind(&PoolImpl::DeleteFrameResources, gpu_factories_, 342 FROM_HERE, base::Bind(&PoolImpl::DeleteFrameResources, gpu_factories_,
224 base::Owned(frame_resources))); 343 base::Owned(frame_resources)));
225 } 344 }
226 } 345 }
227 346
228 // Tries to find the resources in the pool or create them. 347 // Tries to find the resources in the pool or create them.
229 // Incompatible resources will be dropped. 348 // Incompatible resources will be dropped.
230 GpuMemoryBufferVideoFramePool::PoolImpl::FrameResources* 349 GpuMemoryBufferVideoFramePool::PoolImpl::FrameResources*
231 GpuMemoryBufferVideoFramePool::PoolImpl::GetOrCreateFrameResources( 350 GpuMemoryBufferVideoFramePool::PoolImpl::GetOrCreateFrameResources(
232 const gfx::Size& size, 351 const gfx::Size& size,
233 VideoPixelFormat format) { 352 VideoPixelFormat format) {
234 DCHECK(task_runner_->BelongsToCurrentThread());
235
236 auto it = resources_pool_.begin(); 353 auto it = resources_pool_.begin();
237 while (it != resources_pool_.end()) { 354 while (it != resources_pool_.end()) {
238 FrameResources* frame_resources = *it; 355 FrameResources* frame_resources = *it;
239 if (!frame_resources->in_use) { 356 if (!frame_resources->in_use) {
240 if (AreFrameResourcesCompatible(frame_resources, size, format)) { 357 if (AreFrameResourcesCompatible(frame_resources, size, format)) {
241 frame_resources->in_use = true; 358 frame_resources->in_use = true;
242 return frame_resources; 359 return frame_resources;
243 } else { 360 } else {
244 resources_pool_.erase(it++); 361 resources_pool_.erase(it++);
245 DeleteFrameResources(gpu_factories_, frame_resources); 362 DeleteFrameResources(gpu_factories_, frame_resources);
246 delete frame_resources; 363 delete frame_resources;
247 } 364 }
248 } else { 365 } else {
249 it++; 366 it++;
250 } 367 }
251 } 368 }
252 369
253 // Create the resources. 370 // Create the resources.
254 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface(); 371 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface();
255 DCHECK(gles2); 372 if (!gles2)
373 return nullptr;
256 gles2->ActiveTexture(GL_TEXTURE0); 374 gles2->ActiveTexture(GL_TEXTURE0);
257 size_t planes = VideoFrame::NumPlanes(format); 375 size_t planes = VideoFrame::NumPlanes(format);
258 FrameResources* frame_resources = new FrameResources(format, size); 376 FrameResources* frame_resources = new FrameResources(format, size);
259 resources_pool_.push_back(frame_resources); 377 resources_pool_.push_back(frame_resources);
260 for (size_t i = 0; i < planes; ++i) { 378 for (size_t i = 0; i < planes; ++i) {
261 PlaneResource& plane_resource = frame_resources->plane_resources[i]; 379 PlaneResource& plane_resource = frame_resources->plane_resources[i];
262 const size_t width = VideoFrame::Columns(i, format, size.width()); 380 const size_t width = VideoFrame::Columns(i, format, size.width());
263 const size_t height = VideoFrame::Rows(i, format, size.height()); 381 const size_t height = VideoFrame::Rows(i, format, size.height());
264 const gfx::Size plane_size(width, height); 382 const gfx::Size plane_size(width, height);
265 plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer( 383 plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer(
(...skipping 28 matching lines...) Expand all
294 if (plane_resource.texture_id) 412 if (plane_resource.texture_id)
295 gles2->DeleteTextures(1, &plane_resource.texture_id); 413 gles2->DeleteTextures(1, &plane_resource.texture_id);
296 } 414 }
297 } 415 }
298 416
299 // Called when a VideoFrame is no longer references. 417 // Called when a VideoFrame is no longer references.
300 void GpuMemoryBufferVideoFramePool::PoolImpl::MailboxHoldersReleased( 418 void GpuMemoryBufferVideoFramePool::PoolImpl::MailboxHoldersReleased(
301 FrameResources* frame_resources, 419 FrameResources* frame_resources,
302 uint32 sync_point) { 420 uint32 sync_point) {
303 // Return the resource on the media thread. 421 // Return the resource on the media thread.
304 task_runner_->PostTask(FROM_HERE, base::Bind(&PoolImpl::ReturnFrameResources, 422 media_task_runner_->PostTask(
305 this, frame_resources)); 423 FROM_HERE,
424 base::Bind(&PoolImpl::ReturnFrameResources, this, frame_resources));
306 } 425 }
307 426
308 // Put back the resoruces in the pool. 427 // Put back the resoruces in the pool.
309 void GpuMemoryBufferVideoFramePool::PoolImpl::ReturnFrameResources( 428 void GpuMemoryBufferVideoFramePool::PoolImpl::ReturnFrameResources(
310 FrameResources* frame_resources) { 429 FrameResources* frame_resources) {
311 DCHECK(task_runner_->BelongsToCurrentThread());
312 430
313 auto it = std::find(resources_pool_.begin(), resources_pool_.end(), 431 auto it = std::find(resources_pool_.begin(), resources_pool_.end(),
314 frame_resources); 432 frame_resources);
315 DCHECK(it != resources_pool_.end()); 433 DCHECK(it != resources_pool_.end());
316 // We want the pool to behave in a FIFO way. 434 // We want the pool to behave in a FIFO way.
317 // This minimizes the chances of locking the buffer that might be 435 // This minimizes the chances of locking the buffer that might be
318 // still needed for drawing. 436 // still needed for drawing.
319 std::swap(*it, resources_pool_.back()); 437 std::swap(*it, resources_pool_.back());
320 frame_resources->in_use = false; 438 frame_resources->in_use = false;
321 } 439 }
322 440
323 GpuMemoryBufferVideoFramePool::GpuMemoryBufferVideoFramePool( 441 GpuMemoryBufferVideoFramePool::GpuMemoryBufferVideoFramePool(
324 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 442 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
443 const scoped_refptr<base::TaskRunner>& worker_task_runner,
325 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories) 444 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories)
326 : pool_impl_(new PoolImpl(task_runner, gpu_factories)) { 445 : pool_impl_(
327 } 446 new PoolImpl(media_task_runner, worker_task_runner, gpu_factories)) {}
328 447
329 GpuMemoryBufferVideoFramePool::~GpuMemoryBufferVideoFramePool() { 448 GpuMemoryBufferVideoFramePool::~GpuMemoryBufferVideoFramePool() {
330 } 449 }
331 450
332 scoped_refptr<VideoFrame> 451 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame(
333 GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame( 452 const scoped_refptr<VideoFrame>& video_frame,
334 const scoped_refptr<VideoFrame>& video_frame) { 453 const FrameReadyCB& cb) {
335 switch (video_frame->format()) { 454 DCHECK(video_frame);
336 // Supported cases. 455 pool_impl_->CreateHardwareFrame(video_frame, 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 } 456 }
352 457
353 } // namespace media 458 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698