Commit fe1f2f90 authored by Hirokazu Honda's avatar Hirokazu Honda Committed by Commit Bot

media/gpu/test/VFFWriter: Save GpuMemoryBuffer output by VideoDecoder

VideoDecoder outputs GpuMemoryBuffer which is not allowed to map
by GpuMemoryBuffer interface. This causes VideoFrameFileWriter
cannot save it to the disk. This CL resolves the issue by
extracting the dmabuf-fds wrapped by the GpuMemoryBuffer and
map them.

Bug: 1115112
Test: video_decode_accelerator_tests --output_frames=all --use_vd
Change-Id: Ib6328e81aa12bda49a39f155db7e2ce9573fa0d1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2463010
Commit-Queue: Hirokazu Honda <hiroh@chromium.org>
Reviewed-by: default avatarDavid Staessens <dstaessens@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821142}
parent 7331788a
...@@ -14,8 +14,10 @@ ...@@ -14,8 +14,10 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "build/chromeos_buildflags.h" #include "build/chromeos_buildflags.h"
#include "media/gpu/buildflags.h"
#include "media/gpu/video_frame_mapper.h" #include "media/gpu/video_frame_mapper.h"
#include "media/gpu/video_frame_mapper_factory.h" #include "media/gpu/video_frame_mapper_factory.h"
#include "media/media_buildflags.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/codec/png_codec.h" #include "ui/gfx/codec/png_codec.h"
...@@ -127,26 +129,39 @@ void VideoFrameFileWriter::ProcessVideoFrameTask( ...@@ -127,26 +129,39 @@ void VideoFrameFileWriter::ProcessVideoFrameTask(
const gfx::Size& visible_size = video_frame->visible_rect().size(); const gfx::Size& visible_size = video_frame->visible_rect().size();
base::SStringPrintf(&filename, FILE_PATH_LITERAL("frame_%04zu_%dx%d"), base::SStringPrintf(&filename, FILE_PATH_LITERAL("frame_%04zu_%dx%d"),
frame_index, visible_size.width(), visible_size.height()); frame_index, visible_size.width(), visible_size.height());
// Copies to |frame| in this function so that |video_frame| stays alive until
#if BUILDFLAG(IS_ASH) // in the end of function.
auto frame = video_frame;
#if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
if (frame->storage_type() == VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
// TODO(andrescj): This is a workaround. ClientNativePixmapFactoryDmabuf
// creates ClientNativePixmapOpaque for SCANOUT_VDA_WRITE buffers which does
// not allow us to map GpuMemoryBuffers easily for testing. Therefore, we
// extract the dma-buf FDs. Alternatively, we could consider creating our
// own ClientNativePixmapFactory for testing.
frame = CreateDmabufVideoFrame(frame.get());
if (!frame) {
LOG(ERROR) << "Failed to create Dmabuf-backed VideoFrame from "
<< "GpuMemoryBuffer-based VideoFrame";
return;
}
}
// Create VideoFrameMapper if not yet created. The decoder's output pixel // Create VideoFrameMapper if not yet created. The decoder's output pixel
// format is not known yet when creating the VideoFrameWriter. We can only // format is not known yet when creating the VideoFrameWriter. We can only
// create the VideoFrameMapper upon receiving the first video frame. // create the VideoFrameMapper upon receiving the first video frame.
if ((video_frame->storage_type() == VideoFrame::STORAGE_DMABUFS || if (frame->storage_type() == VideoFrame::STORAGE_DMABUFS &&
video_frame->storage_type() == VideoFrame::STORAGE_GPU_MEMORY_BUFFER) &&
!video_frame_mapper_) { !video_frame_mapper_) {
video_frame_mapper_ = VideoFrameMapperFactory::CreateMapper( video_frame_mapper_ = VideoFrameMapperFactory::CreateMapper(
video_frame->format(), video_frame->storage_type()); frame->format(), frame->storage_type());
ASSERT_TRUE(video_frame_mapper_) << "Failed to create VideoFrameMapper"; ASSERT_TRUE(video_frame_mapper_) << "Failed to create VideoFrameMapper";
} }
#endif #endif // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
switch (output_format_) { switch (output_format_) {
case OutputFormat::kPNG: case OutputFormat::kPNG:
WriteVideoFramePNG(video_frame, base::FilePath(filename)); WriteVideoFramePNG(frame, base::FilePath(filename));
break; break;
case OutputFormat::kYUV: case OutputFormat::kYUV:
WriteVideoFrameYUV(video_frame, base::FilePath(filename)); WriteVideoFrameYUV(frame, base::FilePath(filename));
break; break;
} }
...@@ -161,14 +176,12 @@ void VideoFrameFileWriter::WriteVideoFramePNG( ...@@ -161,14 +176,12 @@ void VideoFrameFileWriter::WriteVideoFramePNG(
DCHECK_CALLED_ON_VALID_SEQUENCE(writer_thread_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(writer_thread_sequence_checker_);
auto mapped_frame = video_frame; auto mapped_frame = video_frame;
#if BUILDFLAG(IS_ASH) #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
if (video_frame->storage_type() == VideoFrame::STORAGE_DMABUFS || if (video_frame->storage_type() == VideoFrame::STORAGE_DMABUFS) {
video_frame->storage_type() == VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
CHECK(video_frame_mapper_); CHECK(video_frame_mapper_);
mapped_frame = video_frame_mapper_->Map(std::move(video_frame)); mapped_frame = video_frame_mapper_->Map(std::move(video_frame));
} }
#endif // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
#endif
if (!mapped_frame) { if (!mapped_frame) {
LOG(ERROR) << "Failed to map video frame"; LOG(ERROR) << "Failed to map video frame";
...@@ -206,9 +219,8 @@ void VideoFrameFileWriter::WriteVideoFrameYUV( ...@@ -206,9 +219,8 @@ void VideoFrameFileWriter::WriteVideoFrameYUV(
DCHECK_CALLED_ON_VALID_SEQUENCE(writer_thread_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(writer_thread_sequence_checker_);
auto mapped_frame = video_frame; auto mapped_frame = video_frame;
#if BUILDFLAG(IS_ASH) #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
if (video_frame->storage_type() == VideoFrame::STORAGE_DMABUFS || if (video_frame->storage_type() == VideoFrame::STORAGE_DMABUFS) {
video_frame->storage_type() == VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
CHECK(video_frame_mapper_); CHECK(video_frame_mapper_);
mapped_frame = video_frame_mapper_->Map(std::move(video_frame)); mapped_frame = video_frame_mapper_->Map(std::move(video_frame));
} }
......
...@@ -345,6 +345,28 @@ scoped_refptr<VideoFrame> CloneVideoFrame( ...@@ -345,6 +345,28 @@ scoped_refptr<VideoFrame> CloneVideoFrame(
return dst_frame; return dst_frame;
} }
scoped_refptr<VideoFrame> CreateDmabufVideoFrame(
const VideoFrame* const frame) {
#if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
if (!frame || frame->storage_type() != VideoFrame::STORAGE_GPU_MEMORY_BUFFER)
return nullptr;
gfx::GpuMemoryBuffer* gmb = frame->GetGpuMemoryBuffer();
gfx::GpuMemoryBufferHandle gmb_handle = gmb->CloneHandle();
DCHECK_EQ(gmb_handle.type, gfx::GpuMemoryBufferType::NATIVE_PIXMAP);
std::vector<ColorPlaneLayout> planes;
std::vector<base::ScopedFD> dmabuf_fds;
for (auto& plane : gmb_handle.native_pixmap_handle.planes) {
planes.emplace_back(plane.stride, plane.offset, plane.size);
dmabuf_fds.emplace_back(plane.fd.release());
}
return VideoFrame::WrapExternalDmabufs(
frame->layout(), frame->visible_rect(), frame->natural_size(),
std::move(dmabuf_fds), frame->timestamp());
#else
return nullptr;
#endif // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)}
}
scoped_refptr<VideoFrame> CreateGpuMemoryBufferVideoFrame( scoped_refptr<VideoFrame> CreateGpuMemoryBufferVideoFrame(
gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory, gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory,
const VideoFrame* const frame, const VideoFrame* const frame,
......
...@@ -70,6 +70,12 @@ scoped_refptr<VideoFrame> CloneVideoFrame( ...@@ -70,6 +70,12 @@ scoped_refptr<VideoFrame> CloneVideoFrame(
VideoFrame::StorageType dst_storage_type = VideoFrame::STORAGE_OWNED_MEMORY, VideoFrame::StorageType dst_storage_type = VideoFrame::STORAGE_OWNED_MEMORY,
base::Optional<gfx::BufferUsage> dst_buffer_usage = base::nullopt); base::Optional<gfx::BufferUsage> dst_buffer_usage = base::nullopt);
// Create Dmabuf-backed VideoFrame from |src_frame|. The created VideoFrame
// doesn't depend on |src_frame|'s lifetime. |src_frame| should be a
// GpuMemoryBuffer-backed VideoFrame.
scoped_refptr<VideoFrame> CreateDmabufVideoFrame(
const VideoFrame* const src_frame);
// Create GpuMemoryBuffer-based VideoFrame from |frame|. The created VideoFrame // Create GpuMemoryBuffer-based VideoFrame from |frame|. The created VideoFrame
// doesn't depend on |frame|'s lifetime. // doesn't depend on |frame|'s lifetime.
// |frame| should be a DMABUF-backed VideoFrame. |buffer_usage| is a // |frame| should be a DMABUF-backed VideoFrame. |buffer_usage| is a
......
...@@ -134,24 +134,12 @@ void VideoFrameValidator::ProcessVideoFrameTask( ...@@ -134,24 +134,12 @@ void VideoFrameValidator::ProcessVideoFrameTask(
// not allow us to map GpuMemoryBuffers easily for testing. Therefore, we // not allow us to map GpuMemoryBuffers easily for testing. Therefore, we
// extract the dma-buf FDs. Alternatively, we could consider creating our // extract the dma-buf FDs. Alternatively, we could consider creating our
// own ClientNativePixmapFactory for testing. // own ClientNativePixmapFactory for testing.
gfx::GpuMemoryBuffer* gmb = video_frame->GetGpuMemoryBuffer(); frame = CreateDmabufVideoFrame(frame.get());
gfx::GpuMemoryBufferHandle gmb_handle = gmb->CloneHandle(); if (!frame) {
ASSERT_EQ(gmb_handle.type, gfx::GpuMemoryBufferType::NATIVE_PIXMAP); LOG(ERROR) << "Failed to create Dmabuf-backed VideoFrame from "
std::vector<ColorPlaneLayout> planes; << "GpuMemoryBuffer-based VideoFrame";
std::vector<base::ScopedFD> dmabuf_fds; return;
for (auto& plane : gmb_handle.native_pixmap_handle.planes) {
planes.emplace_back(plane.stride, plane.offset, plane.size);
dmabuf_fds.emplace_back(plane.fd.release());
} }
auto layout = VideoFrameLayout::CreateWithPlanes(
frame->format(), video_frame->coded_size(), std::move(planes),
VideoFrameLayout::kBufferAddressAlignment,
gmb_handle.native_pixmap_handle.modifier);
ASSERT_TRUE(layout);
frame = VideoFrame::WrapExternalDmabufs(
*layout, frame->visible_rect(), frame->natural_size(),
std::move(dmabuf_fds), frame->timestamp());
ASSERT_TRUE(frame);
} }
if (frame->storage_type() == VideoFrame::STORAGE_DMABUFS) { if (frame->storage_type() == VideoFrame::STORAGE_DMABUFS) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment