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

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

Issue 1306693002: media: Convert I420 VideoFrame to UYVY GpuMemoryBuffer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cleaned up. VideoFormat propagated. Test. 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 <algorithm>
11 #include <list> 11 #include <list>
12 #include <utility> 12 #include <utility>
13 13
14 #include "base/barrier_closure.h" 14 #include "base/barrier_closure.h"
15 #include "base/bind.h" 15 #include "base/bind.h"
16 #include "base/containers/stack_container.h" 16 #include "base/containers/stack_container.h"
17 #include "base/location.h" 17 #include "base/location.h"
18 #include "base/memory/linked_ptr.h" 18 #include "base/memory/linked_ptr.h"
19 #include "base/trace_event/trace_event.h" 19 #include "base/trace_event/trace_event.h"
20 #include "gpu/command_buffer/client/gles2_interface.h" 20 #include "gpu/command_buffer/client/gles2_interface.h"
21 #include "media/renderers/gpu_video_accelerator_factories.h" 21 #include "media/renderers/gpu_video_accelerator_factories.h"
22 #include "third_party/libyuv/include/libyuv.h"
22 23
23 namespace media { 24 namespace media {
24 25
25 // Implementation of a pool of GpuMemoryBuffers used to back VideoFrames. 26 // Implementation of a pool of GpuMemoryBuffers used to back VideoFrames.
26 class GpuMemoryBufferVideoFramePool::PoolImpl 27 class GpuMemoryBufferVideoFramePool::PoolImpl
27 : public base::RefCountedThreadSafe< 28 : public base::RefCountedThreadSafe<
28 GpuMemoryBufferVideoFramePool::PoolImpl> { 29 GpuMemoryBufferVideoFramePool::PoolImpl> {
29 public: 30 public:
30 // |media_task_runner| is the media task runner associated with the 31 // |media_task_runner| is the media task runner associated with the
31 // GL context provided by |gpu_factories| 32 // GL context provided by |gpu_factories|
32 // |worker_task_runner| is a task runner used to asynchronously copy 33 // |worker_task_runner| is a task runner used to asynchronously copy
33 // video frame's planes. 34 // video frame's planes.
34 // |gpu_factories| is an interface to GPU related operation and can be 35 // |gpu_factories| is an interface to GPU related operation and can be
35 // null if a GL context is not available. 36 // null if a GL context is not available.
36 PoolImpl(const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, 37 PoolImpl(const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
37 const scoped_refptr<base::TaskRunner>& worker_task_runner, 38 const scoped_refptr<base::TaskRunner>& worker_task_runner,
38 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories) 39 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories)
39 : media_task_runner_(media_task_runner), 40 : media_task_runner_(media_task_runner),
40 worker_task_runner_(worker_task_runner), 41 worker_task_runner_(worker_task_runner),
41 gpu_factories_(gpu_factories), 42 gpu_factories_(gpu_factories),
42 texture_target_(gpu_factories ? gpu_factories->ImageTextureTarget() 43 texture_target_(gpu_factories ? gpu_factories->ImageTextureTarget()
43 : GL_TEXTURE_2D) { 44 : GL_TEXTURE_2D),
45 format_((gpu_factories ? gpu_factories->VideoFramePixelFormat()
46 : PIXEL_FORMAT_I420)) {
Andre 2015/08/21 18:18:36 nit: don't need double parenthesis.
Daniele Castagna 2015/08/21 18:49:02 Done.
44 DCHECK(media_task_runner_); 47 DCHECK(media_task_runner_);
45 DCHECK(worker_task_runner_); 48 DCHECK(worker_task_runner_);
46 } 49 }
47 50
48 // Takes a software VideoFrame and calls |frame_ready_cb| with a VideoFrame 51 // Takes a software VideoFrame and calls |frame_ready_cb| with a VideoFrame
49 // backed by native textures if possible. 52 // backed by native textures if possible.
50 // The data contained in video_frame is copied into the returned frame 53 // The data contained in video_frame is copied into the returned frame
51 // asynchronously posting tasks to |worker_task_runner_|, while 54 // asynchronously posting tasks to |worker_task_runner_|, while
52 // |frame_ready_cb| will be called on |media_task_runner_| once all the data 55 // |frame_ready_cb| will be called on |media_task_runner_| once all the data
53 // has been copied. 56 // has been copied.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 // Task runner used to asynchronously copy planes. 137 // Task runner used to asynchronously copy planes.
135 scoped_refptr<base::TaskRunner> worker_task_runner_; 138 scoped_refptr<base::TaskRunner> worker_task_runner_;
136 139
137 // Interface to GPU related operations. 140 // Interface to GPU related operations.
138 scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories_; 141 scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories_;
139 142
140 // Pool of resources. 143 // Pool of resources.
141 std::list<FrameResources*> resources_pool_; 144 std::list<FrameResources*> resources_pool_;
142 145
143 const unsigned texture_target_; 146 const unsigned texture_target_;
147 const VideoPixelFormat format_;
Andre 2015/08/21 18:18:36 Maybe call this output_format_ or hardware_format_
Daniele Castagna 2015/08/21 18:49:02 Good point. Removed.
148
144 DISALLOW_COPY_AND_ASSIGN(PoolImpl); 149 DISALLOW_COPY_AND_ASSIGN(PoolImpl);
145 }; 150 };
146 151
147 namespace { 152 namespace {
148 153
149 // VideoFrame copies to GpuMemoryBuffers will be split in |kBytesPerCopyTarget| 154 // VideoFrame copies to GpuMemoryBuffers will be split in copies where the
150 // bytes copies and run in parallel. 155 // output
Andre 2015/08/21 18:18:36 don't wrap before output.
Daniele Castagna 2015/08/21 18:49:02 Done.
156 // size is |kBytesPerCopyTarget| bytes and run in parallel.
151 const size_t kBytesPerCopyTarget = 1024 * 1024; // 1MB 157 const size_t kBytesPerCopyTarget = 1024 * 1024; // 1MB
152 158
153 void CopyRowsToBuffer(int first_row, 159 // Return the GpuMemoryBuffer format to use for a specific VideoPixelFormat
154 int rows, 160 // and plane.
155 int bytes_per_row, 161 gfx::BufferFormat GpuMemoryBufferFormat(VideoPixelFormat format, size_t plane) {
156 const uint8* source, 162 switch (format) {
157 int source_stride, 163 case PIXEL_FORMAT_I420:
158 uint8* output, 164 DCHECK_LE(plane, 2u);
159 int dest_stride, 165 return gfx::BufferFormat::R_8;
160 const base::Closure& done) { 166 case PIXEL_FORMAT_UYVY:
161 TRACE_EVENT2("media", "CopyRowsToBuffer", "bytes_per_row", bytes_per_row, 167 DCHECK_EQ(0u, plane);
168 return gfx::BufferFormat::UYVY_422;
169 default:
170 NOTREACHED();
171 return gfx::BufferFormat::BGRA_8888;
172 }
173 }
174
175 unsigned ImageInternalFormat(VideoPixelFormat format, size_t plane) {
176 switch (format) {
177 case PIXEL_FORMAT_I420:
178 DCHECK_LE(plane, 2u);
179 return GL_R8_EXT;
180 case PIXEL_FORMAT_UYVY:
181 DCHECK_EQ(0u, plane);
182 return GL_RGB;
183 default:
184 NOTREACHED();
185 return 0;
186 }
187 }
188
189 void CopyRowsToI420Buffer(int first_row,
190 int rows,
191 int bytes_per_row,
192 const uint8* source,
193 int source_stride,
194 uint8* output,
195 int dest_stride,
196 const base::Closure& done) {
197 TRACE_EVENT2("media", "CopyRowsToI420Buffer", "bytes_per_row", bytes_per_row,
162 "rows", rows); 198 "rows", rows);
163 DCHECK_NE(dest_stride, 0); 199 DCHECK_NE(dest_stride, 0);
164 DCHECK_LE(bytes_per_row, std::abs(dest_stride)); 200 DCHECK_LE(bytes_per_row, std::abs(dest_stride));
165 DCHECK_LE(bytes_per_row, source_stride); 201 DCHECK_LE(bytes_per_row, source_stride);
166 for (int row = first_row; row < first_row + rows; ++row) { 202 for (int row = first_row; row < first_row + rows; ++row) {
167 memcpy(output + dest_stride * row, source + source_stride * row, 203 memcpy(output + dest_stride * row, source + source_stride * row,
168 bytes_per_row); 204 bytes_per_row);
169 } 205 }
170 done.Run(); 206 done.Run();
171 } 207 }
172 208
209 void CopyRowsToUYVYBuffer(int first_row,
210 int rows,
211 int width,
212 const scoped_refptr<VideoFrame>& source_frame,
213 uint8* output,
214 int dest_stride,
215 const base::Closure& done) {
216 TRACE_EVENT2("media", "CopyRowsToUYVYBuffer", "bytes_per_row", width * 2,
217 "rows", rows);
218 DCHECK_NE(dest_stride, 0);
219 DCHECK_LE(width, std::abs(dest_stride / 2));
220 DCHECK_EQ(0, first_row % 2);
221 libyuv::I420ToUYVY(
222 source_frame->data(VideoFrame::kYPlane) +
223 first_row * source_frame->stride(VideoFrame::kYPlane),
224 source_frame->stride(VideoFrame::kYPlane),
225 source_frame->data(VideoFrame::kUPlane) +
226 first_row / 2 * source_frame->stride(VideoFrame::kUPlane),
227 source_frame->stride(VideoFrame::kUPlane),
228 source_frame->data(VideoFrame::kVPlane) +
229 first_row / 2 * source_frame->stride(VideoFrame::kVPlane),
230 source_frame->stride(VideoFrame::kVPlane),
231 output + first_row * dest_stride, dest_stride, width, rows);
232 done.Run();
233 }
234
173 } // unnamed namespace 235 } // unnamed namespace
174 236
175 // Creates a VideoFrame backed by native textures starting from a software 237 // Creates a VideoFrame backed by native textures starting from a software
176 // VideoFrame. 238 // VideoFrame.
177 // The data contained in |video_frame| is copied into the VideoFrame passed to 239 // The data contained in |video_frame| is copied into the VideoFrame passed to
178 // |frame_ready_cb|. 240 // |frame_ready_cb|.
179 // This has to be called on the thread where |media_task_runner_| is current. 241 // This has to be called on the thread where |media_task_runner_| is current.
180 void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame( 242 void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame(
181 const scoped_refptr<VideoFrame>& video_frame, 243 const scoped_refptr<VideoFrame>& video_frame,
182 const FrameReadyCB& frame_ready_cb) { 244 const FrameReadyCB& frame_ready_cb) {
183 DCHECK(media_task_runner_->BelongsToCurrentThread()); 245 DCHECK(media_task_runner_->BelongsToCurrentThread());
184 if (!gpu_factories_ || !gpu_factories_->IsTextureRGSupported()) { 246 if (!gpu_factories_ || (format_ == PIXEL_FORMAT_I420 &&
247 !gpu_factories_->IsTextureRGSupported())) {
185 frame_ready_cb.Run(video_frame); 248 frame_ready_cb.Run(video_frame);
186 return; 249 return;
187 } 250 }
188 switch (video_frame->format()) { 251 switch (video_frame->format()) {
189 // Supported cases. 252 // Supported cases.
190 case PIXEL_FORMAT_YV12: 253 case PIXEL_FORMAT_YV12:
191 case PIXEL_FORMAT_I420: 254 case PIXEL_FORMAT_I420:
192 break; 255 break;
193 // Unsupported cases. 256 // Unsupported cases.
194 case PIXEL_FORMAT_YV12A: 257 case PIXEL_FORMAT_YV12A:
195 case PIXEL_FORMAT_YV16: 258 case PIXEL_FORMAT_YV16:
196 case PIXEL_FORMAT_YV24: 259 case PIXEL_FORMAT_YV24:
197 case PIXEL_FORMAT_NV12: 260 case PIXEL_FORMAT_NV12:
198 case PIXEL_FORMAT_ARGB: 261 case PIXEL_FORMAT_ARGB:
199 case PIXEL_FORMAT_XRGB: 262 case PIXEL_FORMAT_XRGB:
200 case PIXEL_FORMAT_UYVY: 263 case PIXEL_FORMAT_UYVY:
201 case PIXEL_FORMAT_UNKNOWN: 264 case PIXEL_FORMAT_UNKNOWN:
202 frame_ready_cb.Run(video_frame); 265 frame_ready_cb.Run(video_frame);
203 return; 266 return;
204 } 267 }
205 268
206 VideoPixelFormat format = video_frame->format();
207 DCHECK(video_frame->visible_rect().origin().IsOrigin()); 269 DCHECK(video_frame->visible_rect().origin().IsOrigin());
208 const gfx::Size size = video_frame->visible_rect().size(); 270 const gfx::Size size = video_frame->visible_rect().size();
209 271
210 // Acquire resources. Incompatible ones will be dropped from the pool. 272 // Acquire resources. Incompatible ones will be dropped from the pool.
211 FrameResources* frame_resources = GetOrCreateFrameResources(size, format); 273 FrameResources* frame_resources = GetOrCreateFrameResources(size, format_);
212 if (!frame_resources) { 274 if (!frame_resources) {
213 frame_ready_cb.Run(video_frame); 275 frame_ready_cb.Run(video_frame);
214 return; 276 return;
215 } 277 }
216 278
217 worker_task_runner_->PostTask( 279 worker_task_runner_->PostTask(
218 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this, 280 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this,
219 video_frame, frame_resources, frame_ready_cb)); 281 video_frame, frame_resources, frame_ready_cb));
220 } 282 }
221 283
222 void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone( 284 void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone(
223 const scoped_refptr<VideoFrame>& video_frame, 285 const scoped_refptr<VideoFrame>& video_frame,
224 FrameResources* frame_resources, 286 FrameResources* frame_resources,
225 const FrameReadyCB& frame_ready_cb) { 287 const FrameReadyCB& frame_ready_cb) {
226 const VideoPixelFormat format = video_frame->format(); 288 const size_t planes = VideoFrame::NumPlanes(frame_resources->format);
227 const size_t planes = VideoFrame::NumPlanes(format);
228 for (size_t i = 0; i < planes; ++i) { 289 for (size_t i = 0; i < planes; ++i) {
229 frame_resources->plane_resources[i].gpu_memory_buffer->Unmap(); 290 frame_resources->plane_resources[i].gpu_memory_buffer->Unmap();
230 } 291 }
231 292
232 media_task_runner_->PostTask( 293 media_task_runner_->PostTask(
233 FROM_HERE, 294 FROM_HERE,
234 base::Bind(&PoolImpl::BindAndCreateMailboxesHardwareFrameResources, this, 295 base::Bind(&PoolImpl::BindAndCreateMailboxesHardwareFrameResources, this,
235 video_frame, frame_resources, frame_ready_cb)); 296 video_frame, frame_resources, frame_ready_cb));
236 } 297 }
237 298
238 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks 299 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks
239 // that will be synchronized by a barrier. 300 // that will be synchronized by a barrier.
240 // After the barrier is passed OnCopiesDone will be called. 301 // After the barrier is passed OnCopiesDone will be called.
241 void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers( 302 void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers(
242 const scoped_refptr<VideoFrame>& video_frame, 303 const scoped_refptr<VideoFrame>& video_frame,
243 FrameResources* frame_resources, 304 FrameResources* frame_resources,
244 const FrameReadyCB& frame_ready_cb) { 305 const FrameReadyCB& frame_ready_cb) {
245 const VideoPixelFormat format = video_frame->format(); 306 // Compute the number of tasks to post and create the barrier.
246 const size_t planes = VideoFrame::NumPlanes(format); 307 const VideoPixelFormat dest_format = frame_resources->format;
308 const size_t dest_planes = VideoFrame::NumPlanes(dest_format);
247 gfx::Size size = video_frame->visible_rect().size(); 309 gfx::Size size = video_frame->visible_rect().size();
248 size_t copies = 0; 310 size_t copies = 0;
249 for (size_t i = 0; i < planes; ++i) { 311 for (size_t i = 0; i < dest_planes; ++i) {
250 int rows = VideoFrame::Rows(i, format, size.height()); 312 int rows = VideoFrame::Rows(i, dest_format, size.height());
251 int bytes_per_row = VideoFrame::RowBytes(i, format, size.width()); 313 int bytes_per_row = VideoFrame::RowBytes(i, dest_format, size.width());
314 // Copy a even number of lines, and at least one.
252 int rows_per_copy = 315 int rows_per_copy =
253 std::max<size_t>(kBytesPerCopyTarget / bytes_per_row, 1); 316 std::max<size_t>((kBytesPerCopyTarget / bytes_per_row) & ~1, 1);
254 copies += rows / rows_per_copy; 317 copies += rows / rows_per_copy;
255 if (rows % rows_per_copy) 318 if (rows % rows_per_copy)
256 ++copies; 319 ++copies;
257 } 320 }
258
259 base::Closure copies_done = 321 base::Closure copies_done =
260 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources, 322 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources,
261 frame_ready_cb); 323 frame_ready_cb);
262 base::Closure barrier = base::BarrierClosure(copies, copies_done); 324 base::Closure barrier = base::BarrierClosure(copies, copies_done);
325 // Post all the async tasks.
326 for (size_t i = 0; i < dest_planes; ++i) {
327 int rows = VideoFrame::Rows(i, dest_format, size.height());
328 int bytes_per_row = VideoFrame::RowBytes(i, dest_format, size.width());
329 int rows_per_copy =
330 std::max<size_t>((kBytesPerCopyTarget / bytes_per_row) & ~1, 1);
263 331
264 for (size_t i = 0; i < planes; ++i) { 332 void* data = nullptr;
Andre 2015/08/21 18:18:36 CHECK_EQ(1, gfx::NumberOfPlanesForBufferFormat(des
Daniele Castagna 2015/08/21 18:49:02 Done.
265 int rows = VideoFrame::Rows(i, format, size.height()); 333 CHECK(frame_resources->plane_resources[i].gpu_memory_buffer->Map(&data));
266 int bytes_per_row = VideoFrame::RowBytes(i, format, size.width()); 334 uint8* mapped_buffer = static_cast<uint8*>(data);
267 int rows_per_copy =
268 std::max<size_t>(kBytesPerCopyTarget / bytes_per_row, 1);
269 335
270 PlaneResource& plane_resource = frame_resources->plane_resources[i];
271 void* data = nullptr;
272 CHECK(plane_resource.gpu_memory_buffer->Map(&data));
273 uint8* mapped_buffer = static_cast<uint8*>(data);
274 int dest_stride = 0; 336 int dest_stride = 0;
275 plane_resource.gpu_memory_buffer->GetStride(&dest_stride); 337 frame_resources->plane_resources[i].gpu_memory_buffer->GetStride(
338 &dest_stride);
276 339
277 for (int row = 0; row < rows; row += rows_per_copy) { 340 for (int row = 0; row < rows; row += rows_per_copy) {
278 worker_task_runner_->PostTask( 341 switch (dest_format) {
279 FROM_HERE, 342 case PIXEL_FORMAT_I420:
280 base::Bind(&CopyRowsToBuffer, row, 343 worker_task_runner_->PostTask(
281 std::min(rows_per_copy, rows - row), bytes_per_row, 344 FROM_HERE,
282 video_frame->data(i), video_frame->stride(i), 345 base::Bind(&CopyRowsToI420Buffer, row,
283 mapped_buffer, dest_stride, barrier)); 346 std::min(rows_per_copy, rows - row), bytes_per_row,
347 video_frame->data(i), video_frame->stride(i),
348 mapped_buffer, dest_stride, barrier));
349 break;
350 case PIXEL_FORMAT_UYVY:
351 worker_task_runner_->PostTask(
352 FROM_HERE,
353 base::Bind(&CopyRowsToUYVYBuffer, row,
354 std::min(rows_per_copy, rows - row), size.width(),
355 video_frame, mapped_buffer, dest_stride, barrier));
356 break;
357 default:
358 NOTREACHED();
359 }
284 } 360 }
285 } 361 }
286 } 362 }
287 363
288 void GpuMemoryBufferVideoFramePool::PoolImpl:: 364 void GpuMemoryBufferVideoFramePool::PoolImpl::
289 BindAndCreateMailboxesHardwareFrameResources( 365 BindAndCreateMailboxesHardwareFrameResources(
290 const scoped_refptr<VideoFrame>& video_frame, 366 const scoped_refptr<VideoFrame>& video_frame,
291 FrameResources* frame_resources, 367 FrameResources* frame_resources,
292 const FrameReadyCB& frame_ready_cb) { 368 const FrameReadyCB& frame_ready_cb) {
293 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface(); 369 gpu::gles2::GLES2Interface* gles2 = gpu_factories_->GetGLES2Interface();
294 if (!gles2) { 370 if (!gles2) {
295 frame_ready_cb.Run(video_frame); 371 frame_ready_cb.Run(video_frame);
296 return; 372 return;
297 } 373 }
298 374
299 const VideoPixelFormat format = video_frame->format(); 375 const size_t planes = VideoFrame::NumPlanes(frame_resources->format);
300 const size_t planes = VideoFrame::NumPlanes(format);
301 const gfx::Size size = video_frame->visible_rect().size(); 376 const gfx::Size size = video_frame->visible_rect().size();
302 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; 377 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
303 // Set up the planes creating the mailboxes needed to refer to the textures. 378 // Set up the planes creating the mailboxes needed to refer to the textures.
304 for (size_t i = 0; i < planes; ++i) { 379 for (size_t i = 0; i < planes; ++i) {
305 PlaneResource& plane_resource = frame_resources->plane_resources[i]; 380 PlaneResource& plane_resource = frame_resources->plane_resources[i];
306 // Bind the texture and create or rebind the image. 381 // Bind the texture and create or rebind the image.
307 gles2->BindTexture(texture_target_, plane_resource.texture_id); 382 gles2->BindTexture(texture_target_, plane_resource.texture_id);
308 383
309 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) { 384 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) {
310 const size_t width = VideoFrame::Columns(i, format, size.width()); 385 const size_t width =
311 const size_t height = VideoFrame::Rows(i, format, size.height()); 386 VideoFrame::Columns(i, frame_resources->format, size.width());
387 const size_t height =
388 VideoFrame::Rows(i, frame_resources->format, size.height());
312 plane_resource.image_id = gles2->CreateImageCHROMIUM( 389 plane_resource.image_id = gles2->CreateImageCHROMIUM(
313 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, 390 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height,
314 GL_R8_EXT); 391 ImageInternalFormat(frame_resources->format, i));
315 } else { 392 } else {
316 gles2->ReleaseTexImage2DCHROMIUM(texture_target_, 393 gles2->ReleaseTexImage2DCHROMIUM(texture_target_,
317 plane_resource.image_id); 394 plane_resource.image_id);
318 } 395 }
319 gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id); 396 gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id);
320 mailbox_holders[i] = 397 mailbox_holders[i] =
321 gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0); 398 gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0);
322 } 399 }
323 400
324 // Insert a sync_point, this is needed to make sure that the textures the 401 // Insert a sync_point, this is needed to make sure that the textures the
325 // mailboxes refer to will be used only after all the previous commands posted 402 // mailboxes refer to will be used only after all the previous commands posted
326 // in the command buffer have been processed. 403 // in the command buffer have been processed.
327 unsigned sync_point = gles2->InsertSyncPointCHROMIUM(); 404 unsigned sync_point = gles2->InsertSyncPointCHROMIUM();
328 for (size_t i = 0; i < planes; ++i) { 405 for (size_t i = 0; i < planes; ++i) {
329 mailbox_holders[i].sync_point = sync_point; 406 mailbox_holders[i].sync_point = sync_point;
330 } 407 }
331 408
409 scoped_refptr<VideoFrame> frame;
332 // Create the VideoFrame backed by native textures. 410 // Create the VideoFrame backed by native textures.
333 scoped_refptr<VideoFrame> frame = VideoFrame::WrapYUV420NativeTextures( 411 switch (frame_resources->format) {
334 mailbox_holders[VideoFrame::kYPlane], 412 case PIXEL_FORMAT_I420:
335 mailbox_holders[VideoFrame::kUPlane], 413 frame = VideoFrame::WrapYUV420NativeTextures(
336 mailbox_holders[VideoFrame::kVPlane], 414 mailbox_holders[VideoFrame::kYPlane],
337 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources), 415 mailbox_holders[VideoFrame::kUPlane],
338 size, video_frame->visible_rect(), video_frame->natural_size(), 416 mailbox_holders[VideoFrame::kVPlane],
339 video_frame->timestamp()); 417 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources),
418 size, video_frame->visible_rect(), video_frame->natural_size(),
419 video_frame->timestamp());
340 if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY)) 420 if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY))
Andre 2015/08/21 18:18:36 indent +4
Daniele Castagna 2015/08/21 18:49:02 Done.
341 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); 421 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);
422 break;
423 case PIXEL_FORMAT_UYVY:
424 frame = VideoFrame::WrapNativeTexture(
425 PIXEL_FORMAT_UYVY, mailbox_holders[VideoFrame::kYPlane],
426 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources),
427 size, video_frame->visible_rect(), video_frame->natural_size(),
428 video_frame->timestamp());
429 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);
430 break;
431 default:
432 NOTREACHED();
433 }
342 frame_ready_cb.Run(frame); 434 frame_ready_cb.Run(frame);
343 } 435 }
344 436
345 // Destroy all the resources posting one task per FrameResources 437 // Destroy all the resources posting one task per FrameResources
346 // to the |media_task_runner_|. 438 // to the |media_task_runner_|.
347 GpuMemoryBufferVideoFramePool::PoolImpl::~PoolImpl() { 439 GpuMemoryBufferVideoFramePool::PoolImpl::~PoolImpl() {
348 // Delete all the resources on the media thread. 440 // Delete all the resources on the media thread.
349 while (!resources_pool_.empty()) { 441 while (!resources_pool_.empty()) {
350 FrameResources* frame_resources = resources_pool_.front(); 442 FrameResources* frame_resources = resources_pool_.front();
351 resources_pool_.pop_front(); 443 resources_pool_.pop_front();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 return nullptr; 476 return nullptr;
385 gles2->ActiveTexture(GL_TEXTURE0); 477 gles2->ActiveTexture(GL_TEXTURE0);
386 size_t planes = VideoFrame::NumPlanes(format); 478 size_t planes = VideoFrame::NumPlanes(format);
387 FrameResources* frame_resources = new FrameResources(format, size); 479 FrameResources* frame_resources = new FrameResources(format, size);
388 resources_pool_.push_back(frame_resources); 480 resources_pool_.push_back(frame_resources);
389 for (size_t i = 0; i < planes; ++i) { 481 for (size_t i = 0; i < planes; ++i) {
390 PlaneResource& plane_resource = frame_resources->plane_resources[i]; 482 PlaneResource& plane_resource = frame_resources->plane_resources[i];
391 const size_t width = VideoFrame::Columns(i, format, size.width()); 483 const size_t width = VideoFrame::Columns(i, format, size.width());
392 const size_t height = VideoFrame::Rows(i, format, size.height()); 484 const size_t height = VideoFrame::Rows(i, format, size.height());
393 const gfx::Size plane_size(width, height); 485 const gfx::Size plane_size(width, height);
486
394 plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer( 487 plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer(
395 plane_size, gfx::BufferFormat::R_8, gfx::BufferUsage::MAP); 488 plane_size, GpuMemoryBufferFormat(format, i), gfx::BufferUsage::MAP);
396 489
397 gles2->GenTextures(1, &plane_resource.texture_id); 490 gles2->GenTextures(1, &plane_resource.texture_id);
398 gles2->BindTexture(texture_target_, plane_resource.texture_id); 491 gles2->BindTexture(texture_target_, plane_resource.texture_id);
399 gles2->TexParameteri(texture_target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 492 gles2->TexParameteri(texture_target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
400 gles2->TexParameteri(texture_target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 493 gles2->TexParameteri(texture_target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
401 gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 494 gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
402 gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 495 gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
403 gles2->GenMailboxCHROMIUM(plane_resource.mailbox.name); 496 gles2->GenMailboxCHROMIUM(plane_resource.mailbox.name);
404 gles2->ProduceTextureCHROMIUM(texture_target_, plane_resource.mailbox.name); 497 gles2->ProduceTextureCHROMIUM(texture_target_, plane_resource.mailbox.name);
405 } 498 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 } 553 }
461 554
462 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame( 555 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame(
463 const scoped_refptr<VideoFrame>& video_frame, 556 const scoped_refptr<VideoFrame>& video_frame,
464 const FrameReadyCB& frame_ready_cb) { 557 const FrameReadyCB& frame_ready_cb) {
465 DCHECK(video_frame); 558 DCHECK(video_frame);
466 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb); 559 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb);
467 } 560 }
468 561
469 } // namespace media 562 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698