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

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

Issue 1304843005: Deal with AllocateGpuMemoryBuffer returning null. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: s/fail_to_allocated/fail_to_allocate Created 5 years, 3 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>
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 // This has to be run on |media_task_runner_| where |frame_ready_cb| will also 97 // This has to be run on |media_task_runner_| where |frame_ready_cb| will also
98 // be run. 98 // be run.
99 void BindAndCreateMailboxesHardwareFrameResources( 99 void BindAndCreateMailboxesHardwareFrameResources(
100 const scoped_refptr<VideoFrame>& video_frame, 100 const scoped_refptr<VideoFrame>& video_frame,
101 FrameResources* frame_resources, 101 FrameResources* frame_resources,
102 const FrameReadyCB& frame_ready_cb); 102 const FrameReadyCB& frame_ready_cb);
103 103
104 // Return true if |resources| can be used to represent a frame for 104 // Return true if |resources| can be used to represent a frame for
105 // specific |format| and |size|. 105 // specific |format| and |size|.
106 static bool AreFrameResourcesCompatible(const FrameResources* resources, 106 static bool AreFrameResourcesCompatible(const FrameResources* resources,
107 const gfx::Size& size) { 107 const gfx::Size& size);
108 return size == resources->size;
109 }
110 108
111 // Get the resources needed for a frame out of the pool, or create them if 109 // Get the resources needed for a frame out of the pool, or create them if
112 // necessary. 110 // necessary.
113 // This also drops the LRU resources that can't be reuse for this frame. 111 // This also drops the LRU resources that can't be reuse for this frame.
114 FrameResources* GetOrCreateFrameResources(const gfx::Size& size, 112 FrameResources* GetOrCreateFrameResources(const gfx::Size& size,
115 VideoPixelFormat format); 113 VideoPixelFormat format);
116 114
117 // Callback called when a VideoFrame generated with GetFrameResources is no 115 // Callback called when a VideoFrame generated with GetFrameResources is no
118 // longer referenced. 116 // longer referenced.
119 // This could be called by any thread. 117 // This could be called by any thread.
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 void CopyRowsToI420Buffer(int first_row, 217 void CopyRowsToI420Buffer(int first_row,
220 int rows, 218 int rows,
221 int bytes_per_row, 219 int bytes_per_row,
222 const uint8* source, 220 const uint8* source,
223 int source_stride, 221 int source_stride,
224 uint8* output, 222 uint8* output,
225 int dest_stride, 223 int dest_stride,
226 const base::Closure& done) { 224 const base::Closure& done) {
227 TRACE_EVENT2("media", "CopyRowsToI420Buffer", "bytes_per_row", bytes_per_row, 225 TRACE_EVENT2("media", "CopyRowsToI420Buffer", "bytes_per_row", bytes_per_row,
228 "rows", rows); 226 "rows", rows);
229 DCHECK_NE(dest_stride, 0); 227 if (output) {
230 DCHECK_LE(bytes_per_row, std::abs(dest_stride)); 228 DCHECK_NE(dest_stride, 0);
231 DCHECK_LE(bytes_per_row, source_stride); 229 DCHECK_LE(bytes_per_row, std::abs(dest_stride));
232 for (int row = first_row; row < first_row + rows; ++row) { 230 DCHECK_LE(bytes_per_row, source_stride);
233 memcpy(output + dest_stride * row, source + source_stride * row, 231 for (int row = first_row; row < first_row + rows; ++row) {
234 bytes_per_row); 232 memcpy(output + dest_stride * row, source + source_stride * row,
233 bytes_per_row);
234 }
235 } 235 }
236 done.Run(); 236 done.Run();
237 } 237 }
238 238
239 void CopyRowsToNV12Buffer(int first_row, 239 void CopyRowsToNV12Buffer(int first_row,
240 int rows, 240 int rows,
241 int bytes_per_row, 241 int bytes_per_row,
242 const scoped_refptr<VideoFrame>& source_frame, 242 const scoped_refptr<VideoFrame>& source_frame,
243 uint8* dest_y, 243 uint8* dest_y,
244 int dest_stride_y, 244 int dest_stride_y,
245 uint8* dest_uv, 245 uint8* dest_uv,
246 int dest_stride_uv, 246 int dest_stride_uv,
247 const base::Closure& done) { 247 const base::Closure& done) {
248 TRACE_EVENT2("media", "CopyRowsToNV12Buffer", "bytes_per_row", bytes_per_row, 248 TRACE_EVENT2("media", "CopyRowsToNV12Buffer", "bytes_per_row", bytes_per_row,
249 "rows", rows); 249 "rows", rows);
250 DCHECK_NE(dest_stride_y, 0); 250 if (dest_y && dest_uv) {
251 DCHECK_NE(dest_stride_uv, 0); 251 DCHECK_NE(dest_stride_y, 0);
252 DCHECK_LE(bytes_per_row, std::abs(dest_stride_y)); 252 DCHECK_NE(dest_stride_uv, 0);
253 DCHECK_LE(bytes_per_row, std::abs(dest_stride_uv)); 253 DCHECK_LE(bytes_per_row, std::abs(dest_stride_y));
254 DCHECK_EQ(0, first_row % 2); 254 DCHECK_LE(bytes_per_row, std::abs(dest_stride_uv));
255 libyuv::I420ToNV12( 255 DCHECK_EQ(0, first_row % 2);
256 source_frame->data(VideoFrame::kYPlane) + 256
257 first_row * source_frame->stride(VideoFrame::kYPlane), 257 libyuv::I420ToNV12(
258 source_frame->stride(VideoFrame::kYPlane), 258 source_frame->data(VideoFrame::kYPlane) +
259 source_frame->data(VideoFrame::kUPlane) + 259 first_row * source_frame->stride(VideoFrame::kYPlane),
260 first_row / 2 * source_frame->stride(VideoFrame::kUPlane), 260 source_frame->stride(VideoFrame::kYPlane),
261 source_frame->stride(VideoFrame::kUPlane), 261 source_frame->data(VideoFrame::kUPlane) +
262 source_frame->data(VideoFrame::kVPlane) + 262 first_row / 2 * source_frame->stride(VideoFrame::kUPlane),
263 first_row / 2 * source_frame->stride(VideoFrame::kVPlane), 263 source_frame->stride(VideoFrame::kUPlane),
264 source_frame->stride(VideoFrame::kVPlane), 264 source_frame->data(VideoFrame::kVPlane) +
265 dest_y + first_row * dest_stride_y, dest_stride_y, 265 first_row / 2 * source_frame->stride(VideoFrame::kVPlane),
266 dest_uv + first_row / 2 * dest_stride_uv, dest_stride_uv, 266 source_frame->stride(VideoFrame::kVPlane),
267 bytes_per_row, rows); 267 dest_y + first_row * dest_stride_y, dest_stride_y,
268 dest_uv + first_row / 2 * dest_stride_uv, dest_stride_uv, bytes_per_row,
269 rows);
270 }
268 done.Run(); 271 done.Run();
269 } 272 }
270 273
271 void CopyRowsToUYVYBuffer(int first_row, 274 void CopyRowsToUYVYBuffer(int first_row,
272 int rows, 275 int rows,
273 int width, 276 int width,
274 const scoped_refptr<VideoFrame>& source_frame, 277 const scoped_refptr<VideoFrame>& source_frame,
275 uint8* output, 278 uint8* output,
276 int dest_stride, 279 int dest_stride,
277 const base::Closure& done) { 280 const base::Closure& done) {
278 TRACE_EVENT2("media", "CopyRowsToUYVYBuffer", "bytes_per_row", width * 2, 281 TRACE_EVENT2("media", "CopyRowsToUYVYBuffer", "bytes_per_row", width * 2,
279 "rows", rows); 282 "rows", rows);
280 DCHECK_NE(dest_stride, 0); 283 if (output) {
281 DCHECK_LE(width, std::abs(dest_stride / 2)); 284 DCHECK_NE(dest_stride, 0);
282 DCHECK_EQ(0, first_row % 2); 285 DCHECK_LE(width, std::abs(dest_stride / 2));
283 libyuv::I420ToUYVY( 286 DCHECK_EQ(0, first_row % 2);
284 source_frame->data(VideoFrame::kYPlane) + 287 libyuv::I420ToUYVY(
285 first_row * source_frame->stride(VideoFrame::kYPlane), 288 source_frame->data(VideoFrame::kYPlane) +
286 source_frame->stride(VideoFrame::kYPlane), 289 first_row * source_frame->stride(VideoFrame::kYPlane),
287 source_frame->data(VideoFrame::kUPlane) + 290 source_frame->stride(VideoFrame::kYPlane),
288 first_row / 2 * source_frame->stride(VideoFrame::kUPlane), 291 source_frame->data(VideoFrame::kUPlane) +
289 source_frame->stride(VideoFrame::kUPlane), 292 first_row / 2 * source_frame->stride(VideoFrame::kUPlane),
290 source_frame->data(VideoFrame::kVPlane) + 293 source_frame->stride(VideoFrame::kUPlane),
291 first_row / 2 * source_frame->stride(VideoFrame::kVPlane), 294 source_frame->data(VideoFrame::kVPlane) +
292 source_frame->stride(VideoFrame::kVPlane), 295 first_row / 2 * source_frame->stride(VideoFrame::kVPlane),
293 output + first_row * dest_stride, dest_stride, width, rows); 296 source_frame->stride(VideoFrame::kVPlane),
297 output + first_row * dest_stride, dest_stride, width, rows);
298 }
294 done.Run(); 299 done.Run();
295 } 300 }
296 301
297 } // unnamed namespace 302 } // unnamed namespace
298 303
299 // Creates a VideoFrame backed by native textures starting from a software 304 // Creates a VideoFrame backed by native textures starting from a software
300 // VideoFrame. 305 // VideoFrame.
301 // The data contained in |video_frame| is copied into the VideoFrame passed to 306 // The data contained in |video_frame| is copied into the VideoFrame passed to
302 // |frame_ready_cb|. 307 // |frame_ready_cb|.
303 // This has to be called on the thread where |media_task_runner_| is current. 308 // This has to be called on the thread where |media_task_runner_| is current.
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 } 399 }
395 base::Closure copies_done = 400 base::Closure copies_done =
396 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources, 401 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources,
397 frame_ready_cb); 402 frame_ready_cb);
398 base::Closure barrier = base::BarrierClosure(copies, copies_done); 403 base::Closure barrier = base::BarrierClosure(copies, copies_done);
399 404
400 // Post all the async tasks. 405 // Post all the async tasks.
401 for (size_t i = 0; i < num_planes; i += planes_per_copy) { 406 for (size_t i = 0; i < num_planes; i += planes_per_copy) {
402 gfx::GpuMemoryBuffer* buffer = 407 gfx::GpuMemoryBuffer* buffer =
403 frame_resources->plane_resources[i].gpu_memory_buffer.get(); 408 frame_resources->plane_resources[i].gpu_memory_buffer.get();
404 DCHECK(buffer); 409 uint8* dest_buffers[VideoFrame::kMaxPlanes] = {0};
405 DCHECK_EQ(planes_per_copy, 410 int dest_strides[VideoFrame::kMaxPlanes] = {0};
406 gfx::NumberOfPlanesForBufferFormat(buffer->GetFormat())); 411 if (buffer) {
407 uint8* dest_buffers[VideoFrame::kMaxPlanes]; 412 DCHECK_EQ(planes_per_copy,
408 int dest_strides[VideoFrame::kMaxPlanes]; 413 gfx::NumberOfPlanesForBufferFormat(buffer->GetFormat()));
409 bool rv = buffer->Map(reinterpret_cast<void**>(dest_buffers)); 414 bool rv = buffer->Map(reinterpret_cast<void**>(dest_buffers));
410 DCHECK(rv); 415 DCHECK(rv);
411 buffer->GetStride(dest_strides); 416 buffer->GetStride(dest_strides);
417 }
412 418
413 const int rows = VideoFrame::Rows(i, output_format_, size.height()); 419 const int rows = VideoFrame::Rows(i, output_format_, size.height());
414 const int rows_per_copy = RowsPerCopy(i, output_format_, size.width()); 420 const int rows_per_copy = RowsPerCopy(i, output_format_, size.width());
415 421
416 for (int row = 0; row < rows; row += rows_per_copy) { 422 for (int row = 0; row < rows; row += rows_per_copy) {
417 const int rows_to_copy = std::min(rows_per_copy, rows - row); 423 const int rows_to_copy = std::min(rows_per_copy, rows - row);
418 switch (output_format_) { 424 switch (output_format_) {
419 case PIXEL_FORMAT_I420: { 425 case PIXEL_FORMAT_I420: {
420 const int bytes_per_row = 426 const int bytes_per_row =
421 VideoFrame::RowBytes(i, output_format_, size.width()); 427 VideoFrame::RowBytes(i, output_format_, size.width());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 return; 466 return;
461 } 467 }
462 468
463 const size_t num_planes = VideoFrame::NumPlanes(output_format_); 469 const size_t num_planes = VideoFrame::NumPlanes(output_format_);
464 const size_t planes_per_copy = PlanesPerCopy(output_format_); 470 const size_t planes_per_copy = PlanesPerCopy(output_format_);
465 const gfx::Size size = video_frame->visible_rect().size(); 471 const gfx::Size size = video_frame->visible_rect().size();
466 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; 472 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
467 // Set up the planes creating the mailboxes needed to refer to the textures. 473 // Set up the planes creating the mailboxes needed to refer to the textures.
468 for (size_t i = 0; i < num_planes; i += planes_per_copy) { 474 for (size_t i = 0; i < num_planes; i += planes_per_copy) {
469 PlaneResource& plane_resource = frame_resources->plane_resources[i]; 475 PlaneResource& plane_resource = frame_resources->plane_resources[i];
470 DCHECK(plane_resource.gpu_memory_buffer);
471 // Bind the texture and create or rebind the image. 476 // Bind the texture and create or rebind the image.
472 gles2->BindTexture(texture_target_, plane_resource.texture_id); 477 gles2->BindTexture(texture_target_, plane_resource.texture_id);
473 478
474 if (!plane_resource.image_id) { 479 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) {
475 const size_t width = VideoFrame::Columns(i, output_format_, size.width()); 480 const size_t width = VideoFrame::Columns(i, output_format_, size.width());
476 const size_t height = VideoFrame::Rows(i, output_format_, size.height()); 481 const size_t height = VideoFrame::Rows(i, output_format_, size.height());
477 plane_resource.image_id = gles2->CreateImageCHROMIUM( 482 plane_resource.image_id = gles2->CreateImageCHROMIUM(
478 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, 483 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height,
479 ImageInternalFormat(output_format_, i)); 484 ImageInternalFormat(output_format_, i));
480 } else { 485 } else if (plane_resource.image_id) {
481 gles2->ReleaseTexImage2DCHROMIUM(texture_target_, 486 gles2->ReleaseTexImage2DCHROMIUM(texture_target_,
482 plane_resource.image_id); 487 plane_resource.image_id);
483 } 488 }
484 gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id); 489 if (plane_resource.image_id)
490 gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id);
485 mailbox_holders[i] = 491 mailbox_holders[i] =
486 gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0); 492 gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0);
487 } 493 }
488 494
489 // Insert a sync_point, this is needed to make sure that the textures the 495 // Insert a sync_point, this is needed to make sure that the textures the
490 // mailboxes refer to will be used only after all the previous commands posted 496 // mailboxes refer to will be used only after all the previous commands posted
491 // in the command buffer have been processed. 497 // in the command buffer have been processed.
492 unsigned sync_point = gles2->InsertSyncPointCHROMIUM(); 498 unsigned sync_point = gles2->InsertSyncPointCHROMIUM();
493 for (size_t i = 0; i < num_planes; i += planes_per_copy) 499 for (size_t i = 0; i < num_planes; i += planes_per_copy)
494 mailbox_holders[i].sync_point = sync_point; 500 mailbox_holders[i].sync_point = sync_point;
(...skipping 20 matching lines...) Expand all
515 size, video_frame->visible_rect(), video_frame->natural_size(), 521 size, video_frame->visible_rect(), video_frame->natural_size(),
516 video_frame->timestamp()); 522 video_frame->timestamp());
517 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); 523 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);
518 break; 524 break;
519 default: 525 default:
520 NOTREACHED(); 526 NOTREACHED();
521 } 527 }
522 frame_ready_cb.Run(frame); 528 frame_ready_cb.Run(frame);
523 } 529 }
524 530
531 // static
532 bool GpuMemoryBufferVideoFramePool::PoolImpl::AreFrameResourcesCompatible(
533 const FrameResources* resources,
534 const gfx::Size& size) {
535 if (size != resources->size)
536 return false;
537 for (const PlaneResource& plane : resources->plane_resources) {
538 if (!plane.gpu_memory_buffer &&
539 plane.texture_id) // This happens if we failed to allocate a GMB
540 return false;
reveman 2015/09/09 22:45:28 Not needed as discussed.
Daniele Castagna 2015/09/10 00:04:20 Done. Also removed the second part of the test tha
541 }
542 return true;
543 }
544
525 // Destroy all the resources posting one task per FrameResources 545 // Destroy all the resources posting one task per FrameResources
526 // to the |media_task_runner_|. 546 // to the |media_task_runner_|.
527 GpuMemoryBufferVideoFramePool::PoolImpl::~PoolImpl() { 547 GpuMemoryBufferVideoFramePool::PoolImpl::~PoolImpl() {
528 // Delete all the resources on the media thread. 548 // Delete all the resources on the media thread.
529 while (!resources_pool_.empty()) { 549 while (!resources_pool_.empty()) {
530 FrameResources* frame_resources = resources_pool_.front(); 550 FrameResources* frame_resources = resources_pool_.front();
531 resources_pool_.pop_front(); 551 resources_pool_.pop_front();
532 media_task_runner_->PostTask( 552 media_task_runner_->PostTask(
533 FROM_HERE, base::Bind(&PoolImpl::DeleteFrameResources, gpu_factories_, 553 FROM_HERE, base::Bind(&PoolImpl::DeleteFrameResources, gpu_factories_,
534 base::Owned(frame_resources))); 554 base::Owned(frame_resources)));
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 } 664 }
645 665
646 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame( 666 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame(
647 const scoped_refptr<VideoFrame>& video_frame, 667 const scoped_refptr<VideoFrame>& video_frame,
648 const FrameReadyCB& frame_ready_cb) { 668 const FrameReadyCB& frame_ready_cb) {
649 DCHECK(video_frame); 669 DCHECK(video_frame);
650 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb); 670 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb);
651 } 671 }
652 672
653 } // namespace media 673 } // namespace media
OLDNEW
« no previous file with comments | « media/renderers/mock_gpu_video_accelerator_factories.cc ('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