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

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

Issue 1420943002: media: Compute proper VideoFrame::coded_rect for copies to GMBs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase on master. Created 5 years, 2 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
« no previous file with comments | « cc/layers/video_layer_impl.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 first_row / 2 * source_frame->stride(VideoFrame::kUPlane), 300 first_row / 2 * source_frame->stride(VideoFrame::kUPlane),
301 source_frame->stride(VideoFrame::kUPlane), 301 source_frame->stride(VideoFrame::kUPlane),
302 source_frame->visible_data(VideoFrame::kVPlane) + 302 source_frame->visible_data(VideoFrame::kVPlane) +
303 first_row / 2 * source_frame->stride(VideoFrame::kVPlane), 303 first_row / 2 * source_frame->stride(VideoFrame::kVPlane),
304 source_frame->stride(VideoFrame::kVPlane), 304 source_frame->stride(VideoFrame::kVPlane),
305 output + first_row * dest_stride, dest_stride, width, rows); 305 output + first_row * dest_stride, dest_stride, width, rows);
306 } 306 }
307 done.Run(); 307 done.Run();
308 } 308 }
309 309
310 gfx::Size CodedSize(const scoped_refptr<VideoFrame>& video_frame,
311 VideoPixelFormat output_format) {
312 DCHECK(gfx::Rect(video_frame->coded_size())
313 .Contains(video_frame->visible_rect()));
314 DCHECK((video_frame->visible_rect().x() & 1) == 0);
315 gfx::Size output;
316 switch (output_format) {
317 case PIXEL_FORMAT_I420:
318 case PIXEL_FORMAT_NV12:
319 DCHECK((video_frame->visible_rect().y() & 1) == 0);
320 output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1,
321 (video_frame->visible_rect().height() + 1) & ~1);
322 break;
323 case PIXEL_FORMAT_UYVY:
324 output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1,
325 video_frame->visible_rect().height());
326 break;
327 default:
328 NOTREACHED();
329 }
330 DCHECK(gfx::Rect(video_frame->coded_size()).Contains(gfx::Rect(output)));
331 return output;
332 }
310 } // unnamed namespace 333 } // unnamed namespace
311 334
312 // Creates a VideoFrame backed by native textures starting from a software 335 // Creates a VideoFrame backed by native textures starting from a software
313 // VideoFrame. 336 // VideoFrame.
314 // The data contained in |video_frame| is copied into the VideoFrame passed to 337 // The data contained in |video_frame| is copied into the VideoFrame passed to
315 // |frame_ready_cb|. 338 // |frame_ready_cb|.
316 // This has to be called on the thread where |media_task_runner_| is current. 339 // This has to be called on the thread where |media_task_runner_| is current.
317 void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame( 340 void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame(
318 const scoped_refptr<VideoFrame>& video_frame, 341 const scoped_refptr<VideoFrame>& video_frame,
319 const FrameReadyCB& frame_ready_cb) { 342 const FrameReadyCB& frame_ready_cb) {
(...skipping 24 matching lines...) Expand all
344 case PIXEL_FORMAT_XRGB: 367 case PIXEL_FORMAT_XRGB:
345 case PIXEL_FORMAT_RGB24: 368 case PIXEL_FORMAT_RGB24:
346 case PIXEL_FORMAT_RGB32: 369 case PIXEL_FORMAT_RGB32:
347 case PIXEL_FORMAT_MJPEG: 370 case PIXEL_FORMAT_MJPEG:
348 case PIXEL_FORMAT_MT21: 371 case PIXEL_FORMAT_MT21:
349 case PIXEL_FORMAT_UNKNOWN: 372 case PIXEL_FORMAT_UNKNOWN:
350 frame_ready_cb.Run(video_frame); 373 frame_ready_cb.Run(video_frame);
351 return; 374 return;
352 } 375 }
353 376
354 const gfx::Size size = video_frame->visible_rect().size(); 377 const gfx::Size coded_size = CodedSize(video_frame, output_format_);
355
356 // Acquire resources. Incompatible ones will be dropped from the pool. 378 // Acquire resources. Incompatible ones will be dropped from the pool.
357 FrameResources* frame_resources = 379 FrameResources* frame_resources =
358 GetOrCreateFrameResources(size, output_format_); 380 GetOrCreateFrameResources(coded_size, output_format_);
359 if (!frame_resources) { 381 if (!frame_resources) {
360 frame_ready_cb.Run(video_frame); 382 frame_ready_cb.Run(video_frame);
361 return; 383 return;
362 } 384 }
363 385
364 worker_task_runner_->PostTask( 386 worker_task_runner_->PostTask(
365 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this, 387 FROM_HERE, base::Bind(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers, this,
366 video_frame, frame_resources, frame_ready_cb)); 388 video_frame, frame_resources, frame_ready_cb));
367 } 389 }
368 390
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks 442 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks
421 // that will be synchronized by a barrier. 443 // that will be synchronized by a barrier.
422 // After the barrier is passed OnCopiesDone will be called. 444 // After the barrier is passed OnCopiesDone will be called.
423 void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers( 445 void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers(
424 const scoped_refptr<VideoFrame>& video_frame, 446 const scoped_refptr<VideoFrame>& video_frame,
425 FrameResources* frame_resources, 447 FrameResources* frame_resources,
426 const FrameReadyCB& frame_ready_cb) { 448 const FrameReadyCB& frame_ready_cb) {
427 // Compute the number of tasks to post and create the barrier. 449 // Compute the number of tasks to post and create the barrier.
428 const size_t num_planes = VideoFrame::NumPlanes(output_format_); 450 const size_t num_planes = VideoFrame::NumPlanes(output_format_);
429 const size_t planes_per_copy = PlanesPerCopy(output_format_); 451 const size_t planes_per_copy = PlanesPerCopy(output_format_);
430 const gfx::Size size = video_frame->visible_rect().size(); 452 const gfx::Size coded_size = CodedSize(video_frame, output_format_);
431 size_t copies = 0; 453 size_t copies = 0;
432 for (size_t i = 0; i < num_planes; i += planes_per_copy) { 454 for (size_t i = 0; i < num_planes; i += planes_per_copy) {
433 const int rows = VideoFrame::Rows(i, output_format_, size.height()); 455 const int rows = VideoFrame::Rows(i, output_format_, coded_size.height());
434 const int rows_per_copy = RowsPerCopy(i, output_format_, size.width()); 456 const int rows_per_copy =
457 RowsPerCopy(i, output_format_, coded_size.width());
435 copies += rows / rows_per_copy; 458 copies += rows / rows_per_copy;
436 if (rows % rows_per_copy) 459 if (rows % rows_per_copy)
437 ++copies; 460 ++copies;
438 } 461 }
439 const base::Closure copies_done = 462 const base::Closure copies_done =
440 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources, 463 base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources,
441 frame_ready_cb); 464 frame_ready_cb);
442 const base::Closure barrier = base::BarrierClosure(copies, copies_done); 465 const base::Closure barrier = base::BarrierClosure(copies, copies_done);
443 466
444 // Post all the async tasks. 467 // Post all the async tasks.
445 for (size_t i = 0; i < num_planes; i += planes_per_copy) { 468 for (size_t i = 0; i < num_planes; i += planes_per_copy) {
446 gfx::GpuMemoryBuffer* buffer = 469 gfx::GpuMemoryBuffer* buffer =
447 frame_resources->plane_resources[i].gpu_memory_buffer.get(); 470 frame_resources->plane_resources[i].gpu_memory_buffer.get();
448 471
449 if (!buffer || !buffer->Map()) { 472 if (!buffer || !buffer->Map()) {
450 DLOG(ERROR) << "Could not get or Map() buffer"; 473 DLOG(ERROR) << "Could not get or Map() buffer";
451 return; 474 return;
452 } 475 }
453 DCHECK_EQ(planes_per_copy, 476 DCHECK_EQ(planes_per_copy,
454 gfx::NumberOfPlanesForBufferFormat(buffer->GetFormat())); 477 gfx::NumberOfPlanesForBufferFormat(buffer->GetFormat()));
455 478
456 const int rows = VideoFrame::Rows(i, output_format_, size.height()); 479 const int rows = VideoFrame::Rows(i, output_format_, coded_size.height());
457 const int rows_per_copy = RowsPerCopy(i, output_format_, size.width()); 480 const int rows_per_copy =
481 RowsPerCopy(i, output_format_, coded_size.width());
458 482
459 for (int row = 0; row < rows; row += rows_per_copy) { 483 for (int row = 0; row < rows; row += rows_per_copy) {
460 const int rows_to_copy = std::min(rows_per_copy, rows - row); 484 const int rows_to_copy = std::min(rows_per_copy, rows - row);
461 switch (output_format_) { 485 switch (output_format_) {
462 case PIXEL_FORMAT_I420: { 486 case PIXEL_FORMAT_I420: {
463 const int bytes_per_row = 487 const int bytes_per_row =
464 VideoFrame::RowBytes(i, output_format_, size.width()); 488 VideoFrame::RowBytes(i, output_format_, coded_size.width());
465 worker_task_runner_->PostTask( 489 worker_task_runner_->PostTask(
466 FROM_HERE, base::Bind(&CopyRowsToI420Buffer, row, rows_to_copy, 490 FROM_HERE, base::Bind(&CopyRowsToI420Buffer, row, rows_to_copy,
467 bytes_per_row, video_frame->visible_data(i), 491 bytes_per_row, video_frame->visible_data(i),
468 video_frame->stride(i), 492 video_frame->stride(i),
469 static_cast<uint8_t*>(buffer->memory(0)), 493 static_cast<uint8_t*>(buffer->memory(0)),
470 buffer->stride(0), barrier)); 494 buffer->stride(0), barrier));
471 break; 495 break;
472 } 496 }
473 case PIXEL_FORMAT_NV12: 497 case PIXEL_FORMAT_NV12:
474 worker_task_runner_->PostTask( 498 worker_task_runner_->PostTask(
475 FROM_HERE, 499 FROM_HERE, base::Bind(&CopyRowsToNV12Buffer, row, rows_to_copy,
476 base::Bind(&CopyRowsToNV12Buffer, row, rows_to_copy, size.width(), 500 coded_size.width(), video_frame,
477 video_frame, static_cast<uint8_t*>(buffer->memory(0)), 501 static_cast<uint8_t*>(buffer->memory(0)),
478 buffer->stride(0), 502 buffer->stride(0),
479 static_cast<uint8_t*>(buffer->memory(1)), 503 static_cast<uint8_t*>(buffer->memory(1)),
480 buffer->stride(1), barrier)); 504 buffer->stride(1), barrier));
481 break; 505 break;
482 case PIXEL_FORMAT_UYVY: 506 case PIXEL_FORMAT_UYVY:
483 worker_task_runner_->PostTask( 507 worker_task_runner_->PostTask(
484 FROM_HERE, 508 FROM_HERE, base::Bind(&CopyRowsToUYVYBuffer, row, rows_to_copy,
485 base::Bind(&CopyRowsToUYVYBuffer, row, rows_to_copy, size.width(), 509 coded_size.width(), video_frame,
486 video_frame, static_cast<uint8_t*>(buffer->memory(0)), 510 static_cast<uint8_t*>(buffer->memory(0)),
487 buffer->stride(0), barrier)); 511 buffer->stride(0), barrier));
488 break; 512 break;
489 default: 513 default:
490 NOTREACHED(); 514 NOTREACHED();
491 } 515 }
492 } 516 }
493 } 517 }
494 } 518 }
495 519
496 void GpuMemoryBufferVideoFramePool::PoolImpl:: 520 void GpuMemoryBufferVideoFramePool::PoolImpl::
497 BindAndCreateMailboxesHardwareFrameResources( 521 BindAndCreateMailboxesHardwareFrameResources(
498 const scoped_refptr<VideoFrame>& video_frame, 522 const scoped_refptr<VideoFrame>& video_frame,
499 FrameResources* frame_resources, 523 FrameResources* frame_resources,
500 const FrameReadyCB& frame_ready_cb) { 524 const FrameReadyCB& frame_ready_cb) {
501 scoped_ptr<GpuVideoAcceleratorFactories::ScopedGLContextLock> lock( 525 scoped_ptr<GpuVideoAcceleratorFactories::ScopedGLContextLock> lock(
502 gpu_factories_->GetGLContextLock()); 526 gpu_factories_->GetGLContextLock());
503 if (!lock) { 527 if (!lock) {
504 frame_ready_cb.Run(video_frame); 528 frame_ready_cb.Run(video_frame);
505 return; 529 return;
506 } 530 }
507 gpu::gles2::GLES2Interface* gles2 = lock->ContextGL(); 531 gpu::gles2::GLES2Interface* gles2 = lock->ContextGL();
508 532
509 const size_t num_planes = VideoFrame::NumPlanes(output_format_); 533 const size_t num_planes = VideoFrame::NumPlanes(output_format_);
510 const size_t planes_per_copy = PlanesPerCopy(output_format_); 534 const size_t planes_per_copy = PlanesPerCopy(output_format_);
511 const gfx::Size size = video_frame->visible_rect().size(); 535 const gfx::Size coded_size = CodedSize(video_frame, output_format_);
512 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; 536 gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
513 // Set up the planes creating the mailboxes needed to refer to the textures. 537 // Set up the planes creating the mailboxes needed to refer to the textures.
514 for (size_t i = 0; i < num_planes; i += planes_per_copy) { 538 for (size_t i = 0; i < num_planes; i += planes_per_copy) {
515 PlaneResource& plane_resource = frame_resources->plane_resources[i]; 539 PlaneResource& plane_resource = frame_resources->plane_resources[i];
516 // Bind the texture and create or rebind the image. 540 // Bind the texture and create or rebind the image.
517 gles2->BindTexture(texture_target_, plane_resource.texture_id); 541 gles2->BindTexture(texture_target_, plane_resource.texture_id);
518 542
519 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) { 543 if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) {
520 const size_t width = VideoFrame::Columns(i, output_format_, size.width()); 544 const size_t width =
521 const size_t height = VideoFrame::Rows(i, output_format_, size.height()); 545 VideoFrame::Columns(i, output_format_, coded_size.width());
546 const size_t height =
547 VideoFrame::Rows(i, output_format_, coded_size.height());
522 plane_resource.image_id = gles2->CreateImageCHROMIUM( 548 plane_resource.image_id = gles2->CreateImageCHROMIUM(
523 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, 549 plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height,
524 ImageInternalFormat(output_format_, i)); 550 ImageInternalFormat(output_format_, i));
525 } else if (plane_resource.image_id) { 551 } else if (plane_resource.image_id) {
526 gles2->ReleaseTexImage2DCHROMIUM(texture_target_, 552 gles2->ReleaseTexImage2DCHROMIUM(texture_target_,
527 plane_resource.image_id); 553 plane_resource.image_id);
528 } 554 }
529 if (plane_resource.image_id) 555 if (plane_resource.image_id)
530 gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id); 556 gles2->BindTexImage2DCHROMIUM(texture_target_, plane_resource.image_id);
531 mailbox_holders[i] = 557 mailbox_holders[i] =
532 gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0); 558 gpu::MailboxHolder(plane_resource.mailbox, texture_target_, 0);
533 } 559 }
534 560
535 // Insert a sync_point, this is needed to make sure that the textures the 561 // Insert a sync_point, this is needed to make sure that the textures the
536 // mailboxes refer to will be used only after all the previous commands posted 562 // mailboxes refer to will be used only after all the previous commands posted
537 // in the command buffer have been processed. 563 // in the command buffer have been processed.
538 unsigned sync_point = gles2->InsertSyncPointCHROMIUM(); 564 unsigned sync_point = gles2->InsertSyncPointCHROMIUM();
539 for (size_t i = 0; i < num_planes; i += planes_per_copy) 565 for (size_t i = 0; i < num_planes; i += planes_per_copy)
540 mailbox_holders[i].sync_point = sync_point; 566 mailbox_holders[i].sync_point = sync_point;
541 567
542 scoped_refptr<VideoFrame> frame; 568 scoped_refptr<VideoFrame> frame;
543 569
544 auto release_mailbox_callback = 570 auto release_mailbox_callback =
545 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources); 571 base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources);
546 572
547 // Create the VideoFrame backed by native textures. 573 // Create the VideoFrame backed by native textures.
574 gfx::Size visible_size = video_frame->visible_rect().size();
548 switch (output_format_) { 575 switch (output_format_) {
549 case PIXEL_FORMAT_I420: 576 case PIXEL_FORMAT_I420:
550 frame = VideoFrame::WrapYUV420NativeTextures( 577 frame = VideoFrame::WrapYUV420NativeTextures(
551 mailbox_holders[VideoFrame::kYPlane], 578 mailbox_holders[VideoFrame::kYPlane],
552 mailbox_holders[VideoFrame::kUPlane], 579 mailbox_holders[VideoFrame::kUPlane],
553 mailbox_holders[VideoFrame::kVPlane], release_mailbox_callback, size, 580 mailbox_holders[VideoFrame::kVPlane], release_mailbox_callback,
554 gfx::Rect(size), video_frame->natural_size(), 581 coded_size, gfx::Rect(visible_size), video_frame->natural_size(),
555 video_frame->timestamp()); 582 video_frame->timestamp());
556 if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY)) 583 if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY))
557 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); 584 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);
558 break; 585 break;
559 case PIXEL_FORMAT_NV12: 586 case PIXEL_FORMAT_NV12:
560 case PIXEL_FORMAT_UYVY: 587 case PIXEL_FORMAT_UYVY:
561 frame = VideoFrame::WrapNativeTexture( 588 frame = VideoFrame::WrapNativeTexture(
562 output_format_, mailbox_holders[VideoFrame::kYPlane], 589 output_format_, mailbox_holders[VideoFrame::kYPlane],
563 release_mailbox_callback, size, gfx::Rect(size), 590 release_mailbox_callback, coded_size, gfx::Rect(visible_size),
564 video_frame->natural_size(), video_frame->timestamp()); 591 video_frame->natural_size(), video_frame->timestamp());
565 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); 592 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);
566 break; 593 break;
567 default: 594 default:
568 NOTREACHED(); 595 NOTREACHED();
569 } 596 }
570 frame_ready_cb.Run(frame); 597 frame_ready_cb.Run(frame);
571 } 598 }
572 599
573 // Destroy all the resources posting one task per FrameResources 600 // Destroy all the resources posting one task per FrameResources
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 } 729 }
703 730
704 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame( 731 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame(
705 const scoped_refptr<VideoFrame>& video_frame, 732 const scoped_refptr<VideoFrame>& video_frame,
706 const FrameReadyCB& frame_ready_cb) { 733 const FrameReadyCB& frame_ready_cb) {
707 DCHECK(video_frame); 734 DCHECK(video_frame);
708 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb); 735 pool_impl_->CreateHardwareFrame(video_frame, frame_ready_cb);
709 } 736 }
710 737
711 } // namespace media 738 } // namespace media
OLDNEW
« no previous file with comments | « cc/layers/video_layer_impl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698