Commit 82e057a6 authored by Hirokazu Honda's avatar Hirokazu Honda Committed by Commit Bot

media/mojo/MojoVEA: Add GpuMemoryBuffer based VideoFrame path

This adds a path to enable MojoVideoEncodeAccelerator to encode GpuMemoryBuffer
based VideoFrame.

Bug: 1001413
Test: video_frame_mojom_traits_unittest
Change-Id: I842f8966e50a718e225111c8889facdf4636cc49
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1809120
Commit-Queue: Hirokazu Honda <hiroh@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarXiaohan Wang <xhwang@chromium.org>
Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Reviewed-by: default avatarRicky Liang <jcliang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#700181}
parent a864d50d
......@@ -12,6 +12,11 @@ include_rules = [
"+services/metrics",
"+services/service_manager",
# For converting GpuMemoryBufferHandle to GpuMemoryBuffer in
# video_frame_mojom_traits.cc.
"+gpu/ipc/common/gpu_memory_buffer_support.h",
# media/mojo is not part of "media" target and should not use MEDIA_EXPORT.
"-media/base/media_export.h"
]
......@@ -125,15 +125,24 @@ void MojoVideoEncodeAccelerator::Encode(scoped_refptr<VideoFrame> frame,
DCHECK(vea_.is_bound());
#if defined(OS_LINUX)
// TODO(crbug.com/1003197): Remove this once we stop supporting STORAGE_DMABUF
// in VideoEncodeAccelerator.
if (frame->storage_type() == VideoFrame::STORAGE_DMABUFS) {
DCHECK(frame->HasDmaBufs());
vea_->Encode(
std::move(frame), force_keyframe,
frame, force_keyframe,
base::BindOnce(base::DoNothing::Once<scoped_refptr<VideoFrame>>(),
frame));
return;
}
#endif
if (frame->storage_type() == VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
vea_->Encode(
frame, force_keyframe,
base::BindOnce(base::DoNothing::Once<scoped_refptr<VideoFrame>>(),
frame));
return;
}
DCHECK_EQ(PIXEL_FORMAT_I420, frame->format());
DCHECK_EQ(VideoFrame::STORAGE_SHMEM, frame->storage_type());
......
......@@ -133,6 +133,7 @@ source_set("unit_tests") {
deps = [
"//base",
"//base/test:test_support",
"//media:test_support",
"//media/mojo:test_support",
"//testing/gmock",
"//testing/gtest",
......
......@@ -9,6 +9,7 @@ import "gpu/ipc/common/vulkan_ycbcr_info.mojom";
import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/values.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
import "ui/gfx/mojom/buffer_types.mojom";
import "ui/gfx/mojom/color_space.mojom";
// See media/base/audio_codecs.h for descriptions.
......@@ -275,6 +276,7 @@ union VideoFrameData {
EosVideoFrameData eos_data;
SharedBufferVideoFrameData shared_buffer_data;
DmabufVideoFrameData dmabuf_data;
GpuMemoryBufferVideoFrameData gpu_memory_buffer_data;
MailboxVideoFrameData mailbox_data;
};
......@@ -304,6 +306,11 @@ struct DmabufVideoFrameData {
array<handle> dmabuf_fds;
};
struct GpuMemoryBufferVideoFrameData {
gfx.mojom.GpuMemoryBufferHandle gpu_memory_buffer_handle;
array<gpu.mojom.MailboxHolder, 4> mailbox_holder;
};
// This defines video frame data stored in texture mailboxes.
struct MailboxVideoFrameData {
// Size must be kept in sync with media::VideoFrame::kMaxPlanes.
......
......@@ -27,6 +27,7 @@ public_deps = [
]
deps = [
"//gpu/ipc/common:common",
"//gpu/ipc/common:mojom_traits",
"//media/base/ipc",
"//media/mojo/common:mojo_shared_buffer_video_frame",
......
......@@ -9,11 +9,14 @@
#include "base/logging.h"
#include "build/build_config.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
#include "media/base/format_utils.h"
#include "media/mojo/common/mojo_shared_buffer_video_frame.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "mojo/public/cpp/base/values_mojom_traits.h"
#include "mojo/public/cpp/system/handle.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "ui/gfx/mojom/buffer_types_mojom_traits.h"
#include "ui/gfx/mojom/color_space_mojom_traits.h"
namespace mojo {
......@@ -69,12 +72,20 @@ media::mojom::VideoFrameDataPtr MakeVideoFrameData(
}
#endif
if (input->HasTextures()) {
std::vector<gpu::MailboxHolder> mailbox_holder(
media::VideoFrame::kMaxPlanes);
size_t num_planes = media::VideoFrame::NumPlanes(input->format());
for (size_t i = 0; i < num_planes; i++)
mailbox_holder[i] = input->mailbox_holder(i);
std::vector<gpu::MailboxHolder> mailbox_holder(media::VideoFrame::kMaxPlanes);
size_t num_planes = media::VideoFrame::NumPlanes(input->format());
DCHECK_LE(num_planes, mailbox_holder.size());
for (size_t i = 0; i < num_planes; i++)
mailbox_holder[i] = input->mailbox_holder(i);
if (input->storage_type() == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle;
if (input->HasGpuMemoryBuffer())
gpu_memory_buffer_handle = input->GetGpuMemoryBuffer()->CloneHandle();
return media::mojom::VideoFrameData::NewGpuMemoryBufferData(
media::mojom::GpuMemoryBufferVideoFrameData::New(
std::move(gpu_memory_buffer_handle), std::move(mailbox_holder)));
} else if (input->HasTextures()) {
return media::mojom::VideoFrameData::NewMailboxData(
media::mojom::MailboxVideoFrameData::New(
std::move(mailbox_holder), std::move(input->ycbcr_info())));
......@@ -186,6 +197,47 @@ bool StructTraits<media::mojom::VideoFrameDataView,
frame = media::VideoFrame::WrapExternalDmabufs(
*layout, visible_rect, natural_size, std::move(dmabuf_fds), timestamp);
#endif
} else if (data.is_gpu_memory_buffer_data()) {
media::mojom::GpuMemoryBufferVideoFrameDataDataView gpu_memory_buffer_data;
data.GetGpuMemoryBufferDataDataView(&gpu_memory_buffer_data);
gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle;
if (!gpu_memory_buffer_data.ReadGpuMemoryBufferHandle(
&gpu_memory_buffer_handle)) {
return false;
}
std::vector<gpu::MailboxHolder> mailbox_holder;
if (!gpu_memory_buffer_data.ReadMailboxHolder(&mailbox_holder)) {
DLOG(WARNING) << "Failed to get mailbox holder";
}
if (mailbox_holder.size() > media::VideoFrame::kMaxPlanes) {
DLOG(ERROR) << "The size of mailbox holder is too large: "
<< mailbox_holder.size();
return false;
}
gpu::MailboxHolder mailbox_holder_array[media::VideoFrame::kMaxPlanes];
for (size_t i = 0; i < mailbox_holder.size(); i++)
mailbox_holder_array[i] = mailbox_holder[i];
base::Optional<gfx::BufferFormat> buffer_format =
VideoPixelFormatToGfxBufferFormat(format);
if (!buffer_format)
return false;
gpu::GpuMemoryBufferSupport support;
std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
support.CreateGpuMemoryBufferImplFromHandle(
std::move(gpu_memory_buffer_handle), coded_size, *buffer_format,
gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE,
base::NullCallback());
if (!gpu_memory_buffer)
return false;
frame = media::VideoFrame::WrapExternalGpuMemoryBuffer(
visible_rect, natural_size, std::move(gpu_memory_buffer),
mailbox_holder_array, media::VideoFrame::ReleaseMailboxCB(), timestamp);
} else if (data.is_mailbox_data()) {
media::mojom::MailboxVideoFrameDataDataView mailbox_data;
data.GetMailboxDataDataView(&mailbox_data);
......
......@@ -7,12 +7,14 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "media/base/video_frame.h"
#include "media/mojo/common/mojo_shared_buffer_video_frame.h"
#include "media/mojo/mojom/traits_test_service.mojom.h"
#include "media/video/fake_gpu_memory_buffer.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/system/buffer.h"
......@@ -154,4 +156,41 @@ TEST_F(VideoFrameStructTraitsTest, MailboxVideoFrame) {
ASSERT_EQ(frame->mailbox_holder(0).mailbox, mailbox);
}
// defined(OS_LINUX) because media::FakeGpuMemoryBuffer supports
// NativePixmapHandle backed GpuMemoryBufferHandle only.
// !defined(USE_OZONE) so as to force GpuMemoryBufferSupport to select
// gfx::ClientNativePixmapFactoryDmabuf for gfx::ClientNativePixmapFactory.
#if defined(OS_LINUX) && !defined(USE_OZONE)
TEST_F(VideoFrameStructTraitsTest, GpuMemoryBufferVideoFrame) {
gfx::Size coded_size = gfx::Size(256, 256);
gfx::Rect visible_rect(coded_size);
auto timestamp = base::TimeDelta::FromMilliseconds(1);
std::unique_ptr<gfx::GpuMemoryBuffer> gmb =
std::make_unique<FakeGpuMemoryBuffer>(
coded_size, gfx::BufferFormat::YUV_420_BIPLANAR);
gfx::BufferFormat expected_gmb_format = gmb->GetFormat();
gfx::Size expected_gmb_size = gmb->GetSize();
gpu::MailboxHolder mailbox_holders[media::VideoFrame::kMaxPlanes] = {
gpu::MailboxHolder(gpu::Mailbox::Generate(), gpu::SyncToken(), 5),
gpu::MailboxHolder(gpu::Mailbox::Generate(), gpu::SyncToken(), 10)};
auto frame = VideoFrame::WrapExternalGpuMemoryBuffer(
visible_rect, visible_rect.size(), std::move(gmb), mailbox_holders,
base::DoNothing::Once<const gpu::SyncToken&>(), timestamp);
ASSERT_TRUE(RoundTrip(&frame));
ASSERT_TRUE(frame);
ASSERT_EQ(frame->storage_type(), VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
EXPECT_TRUE(frame->HasGpuMemoryBuffer());
EXPECT_FALSE(frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM));
EXPECT_EQ(frame->format(), PIXEL_FORMAT_NV12);
EXPECT_EQ(frame->coded_size(), coded_size);
EXPECT_EQ(frame->visible_rect(), visible_rect);
EXPECT_EQ(frame->natural_size(), visible_rect.size());
EXPECT_EQ(frame->timestamp(), timestamp);
ASSERT_TRUE(frame->HasTextures());
EXPECT_EQ(frame->mailbox_holder(0).mailbox, mailbox_holders[0].mailbox);
EXPECT_EQ(frame->mailbox_holder(1).mailbox, mailbox_holders[1].mailbox);
EXPECT_EQ(frame->GetGpuMemoryBuffer()->GetFormat(), expected_gmb_format);
EXPECT_EQ(frame->GetGpuMemoryBuffer()->GetSize(), expected_gmb_size);
}
#endif // defined(OS_LINUX) && !defined(USE_OZONE)
} // namespace media
......@@ -6,7 +6,7 @@
#include "build/build_config.h"
#if defined(OS_CHROMEOS)
#if defined(OS_LINUX)
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
......@@ -14,9 +14,9 @@
namespace media {
#if defined(OS_CHROMEOS)
#if defined(OS_LINUX)
base::ScopedFD GetDummyFD() {
base::ScopedFD fd(open("/dev/zero", O_RDONLY));
base::ScopedFD fd(open("/dev/zero", O_RDWR));
DCHECK(fd.is_valid());
return fd;
}
......@@ -37,7 +37,7 @@ FakeGpuMemoryBuffer::FakeGpuMemoryBuffer(const gfx::Size& size,
// Set a dummy id since this is for testing only.
handle_.id = gfx::GpuMemoryBufferId(0);
#if defined(OS_CHROMEOS)
#if defined(OS_LINUX)
// Set a dummy fd since this is for testing only.
handle_.native_pixmap_handle.planes.push_back(
gfx::NativePixmapPlane(size_.width(), 0, y_plane_size, GetDummyFD()));
......@@ -46,7 +46,7 @@ FakeGpuMemoryBuffer::FakeGpuMemoryBuffer(const gfx::Size& size,
size_.width(), handle_.native_pixmap_handle.planes[0].size,
uv_plane_size, GetDummyFD()));
}
#endif
#endif // defined(OS_LINUX)
}
FakeGpuMemoryBuffer::~FakeGpuMemoryBuffer() = default;
......
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