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

Unified Diff: media/video/gpu_memory_buffer_video_frame_pool.cc

Issue 1316493004: Add support for converting I420 software frames into NV12 hardware frames (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@snapshot
Patch Set: 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 side-by-side diff with in-line comments
Download patch
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 41de9d97d262a47d226a43aae43da66cb9b63e6e..a5de7f5d7c8d0c41af0320031f8c50635a298f67 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -160,6 +160,9 @@ gfx::BufferFormat GpuMemoryBufferFormat(VideoPixelFormat format, size_t plane) {
case PIXEL_FORMAT_I420:
DCHECK_LE(plane, 2u);
return gfx::BufferFormat::R_8;
+ case PIXEL_FORMAT_NV12:
+ DCHECK_LE(plane, 1u);
+ return gfx::BufferFormat::YUV_420_BIPLANAR;
case PIXEL_FORMAT_UYVY:
DCHECK_EQ(0u, plane);
return gfx::BufferFormat::UYVY_422;
@@ -174,6 +177,9 @@ unsigned ImageInternalFormat(VideoPixelFormat format, size_t plane) {
case PIXEL_FORMAT_I420:
DCHECK_LE(plane, 2u);
return GL_R8_EXT;
+ case PIXEL_FORMAT_NV12:
+ DCHECK_LE(plane, 1u);
+ return GL_R8_EXT;
case PIXEL_FORMAT_UYVY:
DCHECK_EQ(0u, plane);
return GL_RGB;
@@ -203,6 +209,39 @@ void CopyRowsToI420Buffer(int first_row,
done.Run();
}
+void CopyRowsToNV12Buffer(int first_row,
+ int rows,
+ int bytes_per_row,
+ const scoped_refptr<VideoFrame>& source_frame,
+ uint8* dest_y,
+ int dest_stride_y,
+ uint8* dest_uv,
+ int dest_stride_uv,
+ const base::Closure& done) {
+ TRACE_EVENT2("media", "CopyRowsToNV12Buffer", "bytes_per_row", bytes_per_row,
+ "rows", rows);
+ DCHECK_NE(dest_stride_y, 0);
+ DCHECK_NE(dest_stride_uv, 0);
+ DCHECK_LE(bytes_per_row, std::abs(dest_stride_y));
+ DCHECK_LE(bytes_per_row, std::abs(dest_stride_uv));
+ DCHECK_EQ(0, first_row % 2);
+ libyuv::I420ToNV12(
+ source_frame->data(VideoFrame::kYPlane) +
+ first_row * source_frame->stride(VideoFrame::kYPlane),
+ source_frame->stride(VideoFrame::kYPlane),
+ source_frame->data(VideoFrame::kUPlane) +
+ first_row / 2 * source_frame->stride(VideoFrame::kUPlane),
+ source_frame->stride(VideoFrame::kUPlane),
+ source_frame->data(VideoFrame::kVPlane) +
+ first_row / 2 * source_frame->stride(VideoFrame::kVPlane),
+ source_frame->stride(VideoFrame::kVPlane),
+ dest_y + first_row * dest_stride_y, dest_stride_y,
+ dest_uv + first_row / 2 * dest_stride_uv, dest_stride_uv,
+ bytes_per_row, rows);
+ done.Run();
+ done.Run();
+}
+
void CopyRowsToUYVYBuffer(int first_row,
int rows,
int width,
@@ -283,9 +322,9 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone(
const scoped_refptr<VideoFrame>& video_frame,
FrameResources* frame_resources,
const FrameReadyCB& frame_ready_cb) {
- const size_t planes = VideoFrame::NumPlanes(output_format_);
- for (size_t i = 0; i < planes; ++i) {
- frame_resources->plane_resources[i].gpu_memory_buffer->Unmap();
+ for (const auto& plane_resource : frame_resources->plane_resources) {
+ if (plane_resource.gpu_memory_buffer)
+ plane_resource.gpu_memory_buffer->Unmap();
}
media_task_runner_->PostTask(
@@ -319,40 +358,55 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers(
base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources,
frame_ready_cb);
base::Closure barrier = base::BarrierClosure(copies, copies_done);
+
// Post all the async tasks.
for (size_t i = 0; i < dest_planes; ++i) {
+ gfx::GpuMemoryBuffer* buffer =
+ frame_resources->plane_resources[i].gpu_memory_buffer.get();
+ DCHECK(buffer);
+ const size_t buffer_planes =
+ gfx::NumberOfPlanesForBufferFormat(buffer->GetFormat());
+ DCHECK_LE(buffer_planes, VideoFrame::kMaxPlanes);
+ uint8* dest_buffers[VideoFrame::kMaxPlanes];
+ int dest_strides[VideoFrame::kMaxPlanes];
+ bool rv = buffer->Map(reinterpret_cast<void**>(dest_buffers));
+ DCHECK(rv);
+ buffer->GetStride(dest_strides);
+
int rows = VideoFrame::Rows(i, output_format_, size.height());
int bytes_per_row = VideoFrame::RowBytes(i, output_format_, size.width());
int rows_per_copy =
std::max<size_t>((kBytesPerCopyTarget / bytes_per_row) & ~1, 1);
- void* data = nullptr;
- DCHECK_EQ(1u, gfx::NumberOfPlanesForBufferFormat(
- GpuMemoryBufferFormat(output_format_, i)));
- bool rv = frame_resources->plane_resources[i].gpu_memory_buffer->Map(&data);
- DCHECK(rv);
- uint8* mapped_buffer = static_cast<uint8*>(data);
-
- int dest_stride = 0;
- frame_resources->plane_resources[i].gpu_memory_buffer->GetStride(
- &dest_stride);
-
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:
+ DCHECK_EQ(1u, buffer_planes);
+ worker_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&CopyRowsToI420Buffer, row, rows_to_copy,
+ bytes_per_row, video_frame->data(i),
+ video_frame->stride(i), dest_buffers[0],
+ dest_strides[0], barrier));
+ break;
+ case PIXEL_FORMAT_NV12:
+ DCHECK_EQ(2u, buffer_planes);
worker_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&CopyRowsToI420Buffer, row,
- std::min(rows_per_copy, rows - row), bytes_per_row,
- video_frame->data(i), video_frame->stride(i),
- mapped_buffer, dest_stride, barrier));
+ base::Bind(&CopyRowsToNV12Buffer, row, rows_to_copy,
+ bytes_per_row, video_frame, dest_buffers[0],
+ dest_strides[0], dest_buffers[1], dest_strides[1],
+ barrier));
+ ++i; // Consume an extra plane since we copied 2 planes into 1 GMB.
break;
case PIXEL_FORMAT_UYVY:
+ DCHECK_EQ(1u, buffer_planes);
worker_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&CopyRowsToUYVYBuffer, row,
- std::min(rows_per_copy, rows - row), size.width(),
- video_frame, mapped_buffer, dest_stride, barrier));
+ base::Bind(&CopyRowsToUYVYBuffer, row, rows_to_copy, size.width(),
+ video_frame, dest_buffers[0], dest_strides[0],
+ barrier));
break;
default:
NOTREACHED();
@@ -418,9 +472,10 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::
if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY))
frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);
break;
+ case PIXEL_FORMAT_NV12:
case PIXEL_FORMAT_UYVY:
frame = VideoFrame::WrapNativeTexture(
- PIXEL_FORMAT_UYVY, mailbox_holders[VideoFrame::kYPlane],
+ output_format_, mailbox_holders[VideoFrame::kYPlane],
base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources),
size, video_frame->visible_rect(), video_frame->natural_size(),
video_frame->timestamp());
@@ -482,8 +537,9 @@ GpuMemoryBufferVideoFramePool::PoolImpl::GetOrCreateFrameResources(
const size_t height = VideoFrame::Rows(i, format, size.height());
const gfx::Size plane_size(width, height);
+ const gfx::BufferFormat buffer_format = GpuMemoryBufferFormat(format, i);
plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer(
- plane_size, GpuMemoryBufferFormat(format, i), gfx::BufferUsage::MAP);
+ plane_size, buffer_format, gfx::BufferUsage::MAP);
gles2->GenTextures(1, &plane_resource.texture_id);
gles2->BindTexture(texture_target_, plane_resource.texture_id);
@@ -493,6 +549,13 @@ GpuMemoryBufferVideoFramePool::PoolImpl::GetOrCreateFrameResources(
gles2->TexParameteri(texture_target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gles2->GenMailboxCHROMIUM(plane_resource.mailbox.name);
gles2->ProduceTextureCHROMIUM(texture_target_, plane_resource.mailbox.name);
+
+ size_t buffer_planes = gfx::NumberOfPlanesForBufferFormat(buffer_format);
+ if (buffer_planes > 1) {
+ // Got a multi-planar buffer, assume all the planes fit in it.
+ DCHECK_EQ(planes, buffer_planes);
+ break;
+ }
}
return frame_resources;
}
« 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