Index: media/video/gpu_memory_buffer_video_frame_pool.cc |
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc |
index cfe8d69b00a9c38031156dee6bf067e3057e6c2a..9510c80c83be563b7e398ee528337e338062534e 100644 |
--- a/media/video/gpu_memory_buffer_video_frame_pool.cc |
+++ b/media/video/gpu_memory_buffer_video_frame_pool.cc |
@@ -307,6 +307,29 @@ void CopyRowsToUYVYBuffer(int first_row, |
done.Run(); |
} |
+gfx::Size CodedSize(const scoped_refptr<VideoFrame>& video_frame, |
+ VideoPixelFormat output_format) { |
+ DCHECK(gfx::Rect(video_frame->coded_size()) |
+ .Contains(video_frame->visible_rect())); |
+ DCHECK((video_frame->visible_rect().x() & 1) == 0); |
+ gfx::Size output; |
+ switch (output_format) { |
+ case PIXEL_FORMAT_I420: |
+ case PIXEL_FORMAT_NV12: |
+ DCHECK((video_frame->visible_rect().y() & 1) == 0); |
+ output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1, |
+ (video_frame->visible_rect().height() + 1) & ~1); |
+ break; |
+ case PIXEL_FORMAT_UYVY: |
+ output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1, |
+ video_frame->visible_rect().height()); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+ DCHECK(gfx::Rect(video_frame->coded_size()).Contains(gfx::Rect(output))); |
+ return output; |
+} |
} // unnamed namespace |
// Creates a VideoFrame backed by native textures starting from a software |
@@ -351,11 +374,10 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame( |
return; |
} |
- const gfx::Size size = video_frame->visible_rect().size(); |
- |
+ const gfx::Size coded_size = CodedSize(video_frame, output_format_); |
// Acquire resources. Incompatible ones will be dropped from the pool. |
FrameResources* frame_resources = |
- GetOrCreateFrameResources(size, output_format_); |
+ GetOrCreateFrameResources(coded_size, output_format_); |
if (!frame_resources) { |
frame_ready_cb.Run(video_frame); |
return; |
@@ -427,11 +449,12 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers( |
// Compute the number of tasks to post and create the barrier. |
const size_t num_planes = VideoFrame::NumPlanes(output_format_); |
const size_t planes_per_copy = PlanesPerCopy(output_format_); |
- const gfx::Size size = video_frame->visible_rect().size(); |
+ const gfx::Size coded_size = CodedSize(video_frame, output_format_); |
size_t copies = 0; |
for (size_t i = 0; i < num_planes; i += planes_per_copy) { |
- const int rows = VideoFrame::Rows(i, output_format_, size.height()); |
- const int rows_per_copy = RowsPerCopy(i, output_format_, size.width()); |
+ const int rows = VideoFrame::Rows(i, output_format_, coded_size.height()); |
+ const int rows_per_copy = |
+ RowsPerCopy(i, output_format_, coded_size.width()); |
copies += rows / rows_per_copy; |
if (rows % rows_per_copy) |
++copies; |
@@ -453,15 +476,16 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers( |
DCHECK_EQ(planes_per_copy, |
gfx::NumberOfPlanesForBufferFormat(buffer->GetFormat())); |
- const int rows = VideoFrame::Rows(i, output_format_, size.height()); |
- const int rows_per_copy = RowsPerCopy(i, output_format_, size.width()); |
+ const int rows = VideoFrame::Rows(i, output_format_, coded_size.height()); |
+ const int rows_per_copy = |
+ RowsPerCopy(i, output_format_, coded_size.width()); |
for (int row = 0; row < rows; row += rows_per_copy) { |
const int rows_to_copy = std::min(rows_per_copy, rows - row); |
switch (output_format_) { |
case PIXEL_FORMAT_I420: { |
const int bytes_per_row = |
- VideoFrame::RowBytes(i, output_format_, size.width()); |
+ VideoFrame::RowBytes(i, output_format_, coded_size.width()); |
worker_task_runner_->PostTask( |
FROM_HERE, base::Bind(&CopyRowsToI420Buffer, row, rows_to_copy, |
bytes_per_row, video_frame->visible_data(i), |
@@ -472,19 +496,19 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers( |
} |
case PIXEL_FORMAT_NV12: |
worker_task_runner_->PostTask( |
- FROM_HERE, |
- base::Bind(&CopyRowsToNV12Buffer, row, rows_to_copy, size.width(), |
- video_frame, static_cast<uint8_t*>(buffer->memory(0)), |
- buffer->stride(0), |
- static_cast<uint8_t*>(buffer->memory(1)), |
- buffer->stride(1), barrier)); |
+ FROM_HERE, base::Bind(&CopyRowsToNV12Buffer, row, rows_to_copy, |
+ coded_size.width(), video_frame, |
+ static_cast<uint8_t*>(buffer->memory(0)), |
+ buffer->stride(0), |
+ static_cast<uint8_t*>(buffer->memory(1)), |
+ buffer->stride(1), barrier)); |
break; |
case PIXEL_FORMAT_UYVY: |
worker_task_runner_->PostTask( |
- FROM_HERE, |
- base::Bind(&CopyRowsToUYVYBuffer, row, rows_to_copy, size.width(), |
- video_frame, static_cast<uint8_t*>(buffer->memory(0)), |
- buffer->stride(0), barrier)); |
+ FROM_HERE, base::Bind(&CopyRowsToUYVYBuffer, row, rows_to_copy, |
+ coded_size.width(), video_frame, |
+ static_cast<uint8_t*>(buffer->memory(0)), |
+ buffer->stride(0), barrier)); |
break; |
default: |
NOTREACHED(); |
@@ -508,7 +532,7 @@ void GpuMemoryBufferVideoFramePool::PoolImpl:: |
const size_t num_planes = VideoFrame::NumPlanes(output_format_); |
const size_t planes_per_copy = PlanesPerCopy(output_format_); |
- const gfx::Size size = video_frame->visible_rect().size(); |
+ const gfx::Size coded_size = CodedSize(video_frame, output_format_); |
gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; |
// Set up the planes creating the mailboxes needed to refer to the textures. |
for (size_t i = 0; i < num_planes; i += planes_per_copy) { |
@@ -517,8 +541,10 @@ void GpuMemoryBufferVideoFramePool::PoolImpl:: |
gles2->BindTexture(texture_target_, plane_resource.texture_id); |
if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) { |
- const size_t width = VideoFrame::Columns(i, output_format_, size.width()); |
- const size_t height = VideoFrame::Rows(i, output_format_, size.height()); |
+ const size_t width = |
+ VideoFrame::Columns(i, output_format_, coded_size.width()); |
+ const size_t height = |
+ VideoFrame::Rows(i, output_format_, coded_size.height()); |
plane_resource.image_id = gles2->CreateImageCHROMIUM( |
plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, |
ImageInternalFormat(output_format_, i)); |
@@ -545,13 +571,14 @@ void GpuMemoryBufferVideoFramePool::PoolImpl:: |
base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources); |
// Create the VideoFrame backed by native textures. |
+ gfx::Size visible_size = video_frame->visible_rect().size(); |
switch (output_format_) { |
case PIXEL_FORMAT_I420: |
frame = VideoFrame::WrapYUV420NativeTextures( |
mailbox_holders[VideoFrame::kYPlane], |
mailbox_holders[VideoFrame::kUPlane], |
- mailbox_holders[VideoFrame::kVPlane], release_mailbox_callback, size, |
- gfx::Rect(size), video_frame->natural_size(), |
+ mailbox_holders[VideoFrame::kVPlane], release_mailbox_callback, |
+ coded_size, gfx::Rect(visible_size), video_frame->natural_size(), |
video_frame->timestamp()); |
if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY)) |
frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); |
@@ -560,7 +587,7 @@ void GpuMemoryBufferVideoFramePool::PoolImpl:: |
case PIXEL_FORMAT_UYVY: |
frame = VideoFrame::WrapNativeTexture( |
output_format_, mailbox_holders[VideoFrame::kYPlane], |
- release_mailbox_callback, size, gfx::Rect(size), |
+ release_mailbox_callback, coded_size, gfx::Rect(visible_size), |
video_frame->natural_size(), video_frame->timestamp()); |
frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); |
break; |