Commit 53bc536c authored by Fritz Koenig's avatar Fritz Koenig Committed by Commit Bot

media/gpu: Add modifiers to gpu buffer layout

Modifiers are associated with buffers.  They
need to be passed along to V4L2 decoders so
they can take advantage of the modifier.

BUG=b:149525848
TEST=decode with modifiers on trogdor
TEST=PlatformVideoFramePoolTest.ModifierIsPassed

Change-Id: I2708918d6fce43f75579908ab9f3292f03aa0095
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2343043
Commit-Queue: Fritz Koenig <frkoenig@chromium.org>
Reviewed-by: default avatarChih-Yu Huang <akahuang@chromium.org>
Reviewed-by: default avatarAndres Calderon Jaramillo <andrescj@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#802707}
parent 091629ca
...@@ -564,13 +564,27 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalGpuMemoryBuffer( ...@@ -564,13 +564,27 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalGpuMemoryBuffer(
return nullptr; return nullptr;
} }
uint64_t modifier = gfx::NativePixmapHandle::kNoModifier;
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
if (gpu_memory_buffer->GetType() == gfx::NATIVE_PIXMAP) {
const auto gmb_handle = gpu_memory_buffer->CloneHandle();
if (gmb_handle.is_null() ||
gmb_handle.native_pixmap_handle.planes.empty()) {
DLOG(ERROR) << "Failed to clone the GpuMemoryBufferHandle";
return nullptr;
}
modifier = gmb_handle.native_pixmap_handle.modifier;
}
#endif
const size_t num_planes = const size_t num_planes =
NumberOfPlanesForLinearBufferFormat(gpu_memory_buffer->GetFormat()); NumberOfPlanesForLinearBufferFormat(gpu_memory_buffer->GetFormat());
std::vector<int32_t> strides; std::vector<int32_t> strides;
for (size_t i = 0; i < num_planes; ++i) for (size_t i = 0; i < num_planes; ++i)
strides.push_back(gpu_memory_buffer->stride(i)); strides.push_back(gpu_memory_buffer->stride(i));
const auto layout = VideoFrameLayout::CreateWithStrides(*format, coded_size, const auto layout = VideoFrameLayout::CreateWithStrides(
std::move(strides)); *format, coded_size, std::move(strides),
VideoFrameLayout::kBufferAddressAlignment, modifier);
if (!layout) { if (!layout) {
DLOG(ERROR) << __func__ << " Invalid layout"; DLOG(ERROR) << __func__ << " Invalid layout";
return nullptr; return nullptr;
......
...@@ -97,8 +97,11 @@ base::Optional<VideoFrameLayout> VideoFrameLayout::Create( ...@@ -97,8 +97,11 @@ base::Optional<VideoFrameLayout> VideoFrameLayout::Create(
base::Optional<VideoFrameLayout> VideoFrameLayout::CreateWithStrides( base::Optional<VideoFrameLayout> VideoFrameLayout::CreateWithStrides(
VideoPixelFormat format, VideoPixelFormat format,
const gfx::Size& coded_size, const gfx::Size& coded_size,
std::vector<int32_t> strides) { std::vector<int32_t> strides,
return CreateWithPlanes(format, coded_size, PlanesFromStrides(strides)); size_t buffer_addr_align,
uint64_t modifier) {
return CreateWithPlanes(format, coded_size, PlanesFromStrides(strides),
buffer_addr_align, modifier);
} }
// static // static
......
...@@ -62,7 +62,9 @@ class MEDIA_EXPORT VideoFrameLayout { ...@@ -62,7 +62,9 @@ class MEDIA_EXPORT VideoFrameLayout {
static base::Optional<VideoFrameLayout> CreateWithStrides( static base::Optional<VideoFrameLayout> CreateWithStrides(
VideoPixelFormat format, VideoPixelFormat format,
const gfx::Size& coded_size, const gfx::Size& coded_size,
std::vector<int32_t> strides); std::vector<int32_t> strides,
size_t buffer_addr_align = kBufferAddressAlignment,
uint64_t modifier = gfx::NativePixmapHandle::kNoModifier);
// Create a layout suitable for |format| at |coded_size|, with the |planes| // Create a layout suitable for |format| at |coded_size|, with the |planes|
// fully provided. // fully provided.
......
...@@ -441,9 +441,14 @@ TEST(VideoFrame, WrapExternalGpuMemoryBuffer) { ...@@ -441,9 +441,14 @@ TEST(VideoFrame, WrapExternalGpuMemoryBuffer) {
gfx::Size coded_size = gfx::Size(256, 256); gfx::Size coded_size = gfx::Size(256, 256);
gfx::Rect visible_rect(coded_size); gfx::Rect visible_rect(coded_size);
auto timestamp = base::TimeDelta::FromMilliseconds(1); auto timestamp = base::TimeDelta::FromMilliseconds(1);
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
const uint64_t modifier = 0x001234567890abcdULL;
#else
const uint64_t modifier = gfx::NativePixmapHandle::kNoModifier;
#endif
std::unique_ptr<gfx::GpuMemoryBuffer> gmb = std::unique_ptr<gfx::GpuMemoryBuffer> gmb =
std::make_unique<FakeGpuMemoryBuffer>( std::make_unique<FakeGpuMemoryBuffer>(
coded_size, gfx::BufferFormat::YUV_420_BIPLANAR); coded_size, gfx::BufferFormat::YUV_420_BIPLANAR, modifier);
gfx::GpuMemoryBuffer* gmb_raw_ptr = gmb.get(); gfx::GpuMemoryBuffer* gmb_raw_ptr = gmb.get();
gpu::MailboxHolder mailbox_holders[media::VideoFrame::kMaxPlanes] = { gpu::MailboxHolder mailbox_holders[media::VideoFrame::kMaxPlanes] = {
gpu::MailboxHolder(gpu::Mailbox::Generate(), gpu::SyncToken(), 5), gpu::MailboxHolder(gpu::Mailbox::Generate(), gpu::SyncToken(), 5),
...@@ -459,6 +464,7 @@ TEST(VideoFrame, WrapExternalGpuMemoryBuffer) { ...@@ -459,6 +464,7 @@ TEST(VideoFrame, WrapExternalGpuMemoryBuffer) {
for (size_t i = 0; i < 2; ++i) { for (size_t i = 0; i < 2; ++i) {
EXPECT_EQ(frame->layout().planes()[i].stride, coded_size.width()); EXPECT_EQ(frame->layout().planes()[i].stride, coded_size.width());
} }
EXPECT_EQ(frame->layout().modifier(), modifier);
EXPECT_EQ(frame->storage_type(), VideoFrame::STORAGE_GPU_MEMORY_BUFFER); EXPECT_EQ(frame->storage_type(), VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
EXPECT_TRUE(frame->HasGpuMemoryBuffer()); EXPECT_TRUE(frame->HasGpuMemoryBuffer());
EXPECT_EQ(frame->GetGpuMemoryBuffer(), gmb_raw_ptr); EXPECT_EQ(frame->GetGpuMemoryBuffer(), gmb_raw_ptr);
......
...@@ -32,23 +32,26 @@ std::string VectorToString(const std::vector<T>& vec) { ...@@ -32,23 +32,26 @@ std::string VectorToString(const std::vector<T>& vec) {
base::Optional<GpuBufferLayout> GpuBufferLayout::Create( base::Optional<GpuBufferLayout> GpuBufferLayout::Create(
const Fourcc& fourcc, const Fourcc& fourcc,
const gfx::Size& size, const gfx::Size& size,
const std::vector<ColorPlaneLayout>& planes) { const std::vector<ColorPlaneLayout>& planes,
uint64_t modifier) {
// TODO(akahuang): Check planes.size() is equal to the expected value // TODO(akahuang): Check planes.size() is equal to the expected value
// according to |fourcc|. // according to |fourcc|.
if (size.IsEmpty() || planes.size() == 0) { if (size.IsEmpty() || planes.size() == 0) {
VLOGF(1) << "Invalid parameters. fourcc: " << fourcc.ToString() VLOGF(1) << "Invalid parameters. fourcc: " << fourcc.ToString()
<< ", size: " << size.ToString() << ", size: " << size.ToString()
<< ", planes: " << VectorToString(planes); << ", planes: " << VectorToString(planes)
<< ", modifier: " << std::hex << modifier;
return base::nullopt; return base::nullopt;
} }
return GpuBufferLayout(fourcc, size, planes); return GpuBufferLayout(fourcc, size, planes, modifier);
} }
GpuBufferLayout::GpuBufferLayout(const Fourcc& fourcc, GpuBufferLayout::GpuBufferLayout(const Fourcc& fourcc,
const gfx::Size& size, const gfx::Size& size,
const std::vector<ColorPlaneLayout>& planes) const std::vector<ColorPlaneLayout>& planes,
: fourcc_(fourcc), size_(size), planes_(planes) {} uint64_t modifier)
: fourcc_(fourcc), size_(size), planes_(planes), modifier_(modifier) {}
GpuBufferLayout::~GpuBufferLayout() = default; GpuBufferLayout::~GpuBufferLayout() = default;
GpuBufferLayout::GpuBufferLayout(const GpuBufferLayout&) = default; GpuBufferLayout::GpuBufferLayout(const GpuBufferLayout&) = default;
...@@ -57,7 +60,8 @@ GpuBufferLayout& GpuBufferLayout::operator=(const GpuBufferLayout& other) = ...@@ -57,7 +60,8 @@ GpuBufferLayout& GpuBufferLayout::operator=(const GpuBufferLayout& other) =
default; default;
bool GpuBufferLayout::operator==(const GpuBufferLayout& rhs) const { bool GpuBufferLayout::operator==(const GpuBufferLayout& rhs) const {
return fourcc_ == rhs.fourcc_ && size_ == rhs.size_ && planes_ == rhs.planes_; return fourcc_ == rhs.fourcc_ && size_ == rhs.size_ &&
planes_ == rhs.planes_ && modifier_ == rhs.modifier_;
} }
bool GpuBufferLayout::operator!=(const GpuBufferLayout& rhs) const { bool GpuBufferLayout::operator!=(const GpuBufferLayout& rhs) const {
...@@ -68,7 +72,8 @@ std::ostream& operator<<(std::ostream& ostream, const GpuBufferLayout& layout) { ...@@ -68,7 +72,8 @@ std::ostream& operator<<(std::ostream& ostream, const GpuBufferLayout& layout) {
ostream << "GpuBufferLayout(fourcc: " << layout.fourcc().ToString() ostream << "GpuBufferLayout(fourcc: " << layout.fourcc().ToString()
<< ", size: " << layout.size().ToString() << ", size: " << layout.size().ToString()
<< ", planes (stride, offset, size): " << ", planes (stride, offset, size): "
<< VectorToString(layout.planes()); << VectorToString(layout.planes()) << ", modifier: " << std::hex
<< layout.modifier();
return ostream; return ostream;
} }
......
...@@ -22,7 +22,8 @@ class MEDIA_GPU_EXPORT GpuBufferLayout { ...@@ -22,7 +22,8 @@ class MEDIA_GPU_EXPORT GpuBufferLayout {
static base::Optional<GpuBufferLayout> Create( static base::Optional<GpuBufferLayout> Create(
const Fourcc& fourcc, const Fourcc& fourcc,
const gfx::Size& size, const gfx::Size& size,
const std::vector<ColorPlaneLayout>& planes); const std::vector<ColorPlaneLayout>& planes,
uint64_t modifier);
GpuBufferLayout() = delete; GpuBufferLayout() = delete;
GpuBufferLayout(const GpuBufferLayout&); GpuBufferLayout(const GpuBufferLayout&);
GpuBufferLayout(GpuBufferLayout&&); GpuBufferLayout(GpuBufferLayout&&);
...@@ -35,11 +36,13 @@ class MEDIA_GPU_EXPORT GpuBufferLayout { ...@@ -35,11 +36,13 @@ class MEDIA_GPU_EXPORT GpuBufferLayout {
const Fourcc& fourcc() const { return fourcc_; } const Fourcc& fourcc() const { return fourcc_; }
const gfx::Size& size() const { return size_; } const gfx::Size& size() const { return size_; }
const std::vector<ColorPlaneLayout>& planes() const { return planes_; } const std::vector<ColorPlaneLayout>& planes() const { return planes_; }
uint64_t modifier() const { return modifier_; }
private: private:
GpuBufferLayout(const Fourcc& fourcc, GpuBufferLayout(const Fourcc& fourcc,
const gfx::Size& size, const gfx::Size& size,
const std::vector<ColorPlaneLayout>& planes); const std::vector<ColorPlaneLayout>& planes,
uint64_t modifier);
// Fourcc format of the buffer. // Fourcc format of the buffer.
Fourcc fourcc_; Fourcc fourcc_;
...@@ -51,6 +54,8 @@ class MEDIA_GPU_EXPORT GpuBufferLayout { ...@@ -51,6 +54,8 @@ class MEDIA_GPU_EXPORT GpuBufferLayout {
gfx::Size size_; gfx::Size size_;
// Layout property for each color planes, e.g. stride and buffer offset. // Layout property for each color planes, e.g. stride and buffer offset.
std::vector<ColorPlaneLayout> planes_; std::vector<ColorPlaneLayout> planes_;
// DRM format modifier associated with buffer.
uint64_t modifier_;
}; };
// Outputs GpuBufferLayout to stream. // Outputs GpuBufferLayout to stream.
......
...@@ -160,7 +160,8 @@ base::Optional<GpuBufferLayout> PlatformVideoFramePool::Initialize( ...@@ -160,7 +160,8 @@ base::Optional<GpuBufferLayout> PlatformVideoFramePool::Initialize(
return base::nullopt; return base::nullopt;
} }
frame_layout_ = GpuBufferLayout::Create(fourcc, frame->coded_size(), frame_layout_ = GpuBufferLayout::Create(fourcc, frame->coded_size(),
frame->layout().planes()); frame->layout().planes(),
frame->layout().modifier());
} }
visible_rect_ = visible_rect; visible_rect_ = visible_rect;
......
...@@ -23,6 +23,7 @@ namespace media { ...@@ -23,6 +23,7 @@ namespace media {
namespace { namespace {
template <uint64_t modifier>
scoped_refptr<VideoFrame> CreateGpuMemoryBufferVideoFrame( scoped_refptr<VideoFrame> CreateGpuMemoryBufferVideoFrame(
gpu::GpuMemoryBufferFactory* factory, gpu::GpuMemoryBufferFactory* factory,
VideoPixelFormat format, VideoPixelFormat format,
...@@ -36,7 +37,7 @@ scoped_refptr<VideoFrame> CreateGpuMemoryBufferVideoFrame( ...@@ -36,7 +37,7 @@ scoped_refptr<VideoFrame> CreateGpuMemoryBufferVideoFrame(
const gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes] = {}; const gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes] = {};
return VideoFrame::WrapExternalGpuMemoryBuffer( return VideoFrame::WrapExternalGpuMemoryBuffer(
visible_rect, natural_size, visible_rect, natural_size,
std::make_unique<FakeGpuMemoryBuffer>(coded_size, *gfx_format), std::make_unique<FakeGpuMemoryBuffer>(coded_size, *gfx_format, modifier),
mailbox_holders, base::NullCallback(), timestamp); mailbox_holders, base::NullCallback(), timestamp);
} }
...@@ -48,7 +49,9 @@ class PlatformVideoFramePoolTest ...@@ -48,7 +49,9 @@ class PlatformVideoFramePoolTest
PlatformVideoFramePoolTest() PlatformVideoFramePoolTest()
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME), : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
pool_(new PlatformVideoFramePool(nullptr)) { pool_(new PlatformVideoFramePool(nullptr)) {
SetCreateFrameCB(base::BindRepeating(&CreateGpuMemoryBufferVideoFrame)); SetCreateFrameCB(
base::BindRepeating(&CreateGpuMemoryBufferVideoFrame<
gfx::NativePixmapHandle::kNoModifier>));
pool_->set_parent_task_runner(base::ThreadTaskRunnerHandle::Get()); pool_->set_parent_task_runner(base::ThreadTaskRunnerHandle::Get());
} }
...@@ -73,6 +76,7 @@ class PlatformVideoFramePoolTest ...@@ -73,6 +76,7 @@ class PlatformVideoFramePoolTest
scoped_refptr<VideoFrame> frame = pool_->GetFrame(); scoped_refptr<VideoFrame> frame = pool_->GetFrame();
frame->set_timestamp(base::TimeDelta::FromMilliseconds(timestamp_ms)); frame->set_timestamp(base::TimeDelta::FromMilliseconds(timestamp_ms));
EXPECT_EQ(layout_->modifier(), frame->layout().modifier());
EXPECT_EQ(layout_->fourcc(), EXPECT_EQ(layout_->fourcc(),
*Fourcc::FromVideoPixelFormat(frame->format())); *Fourcc::FromVideoPixelFormat(frame->format()));
EXPECT_EQ(layout_->size(), frame->coded_size()); EXPECT_EQ(layout_->size(), frame->coded_size());
...@@ -292,6 +296,18 @@ TEST_P(PlatformVideoFramePoolTest, InitializeFail) { ...@@ -292,6 +296,18 @@ TEST_P(PlatformVideoFramePoolTest, InitializeFail) {
EXPECT_FALSE(Initialize(fourcc.value())); EXPECT_FALSE(Initialize(fourcc.value()));
} }
TEST_P(PlatformVideoFramePoolTest, ModifierIsPassed) {
const uint64_t kSampleModifier = 0x001234567890abcdULL;
const auto fourcc = Fourcc::FromVideoPixelFormat(GetParam());
ASSERT_TRUE(fourcc.has_value());
SetCreateFrameCB(
base::BindRepeating(&CreateGpuMemoryBufferVideoFrame<kSampleModifier>));
ASSERT_TRUE(Initialize(fourcc.value()));
EXPECT_EQ(layout_->modifier(), kSampleModifier);
EXPECT_TRUE(GetFrame(10));
}
// TODO(akahuang): Add a testcase to verify calling Initialize() only with // TODO(akahuang): Add a testcase to verify calling Initialize() only with
// different |max_num_frames|. // different |max_num_frames|.
......
...@@ -329,20 +329,26 @@ void VdVideoDecodeAccelerator::ImportBufferForPicture( ...@@ -329,20 +329,26 @@ void VdVideoDecodeAccelerator::ImportBufferForPicture(
return; return;
} }
const uint64_t modifier = gmb_handle.type == gfx::NATIVE_PIXMAP
? gmb_handle.native_pixmap_handle.modifier
: gfx::NativePixmapHandle::kNoModifier;
std::vector<ColorPlaneLayout> planes = ExtractColorPlaneLayout(gmb_handle); std::vector<ColorPlaneLayout> planes = ExtractColorPlaneLayout(gmb_handle);
layout_ = layout_ = VideoFrameLayout::CreateWithPlanes(
VideoFrameLayout::CreateWithPlanes(pixel_format, coded_size_, planes); pixel_format, coded_size_, planes,
VideoFrameLayout::kBufferAddressAlignment, modifier);
if (!layout_) { if (!layout_) {
VLOGF(1) << "Failed to create VideoFrameLayout. format: " VLOGF(1) << "Failed to create VideoFrameLayout. format: "
<< VideoPixelFormatToString(pixel_format) << VideoPixelFormatToString(pixel_format)
<< ", coded_size: " << coded_size_.ToString() << ", coded_size: " << coded_size_.ToString()
<< ", planes: " << VectorToString(planes); << ", planes: " << VectorToString(planes)
<< ", modifier: " << std::hex << modifier;
std::move(notify_layout_changed_cb_).Run(base::nullopt); std::move(notify_layout_changed_cb_).Run(base::nullopt);
return; return;
} }
std::move(notify_layout_changed_cb_) std::move(notify_layout_changed_cb_)
.Run(GpuBufferLayout::Create(*fourcc, coded_size_, planes)); .Run(GpuBufferLayout::Create(*fourcc, coded_size_, planes, modifier));
} }
if (!layout_) if (!layout_)
......
...@@ -110,7 +110,8 @@ void VdaVideoFramePool::ImportFrame(scoped_refptr<VideoFrame> frame) { ...@@ -110,7 +110,8 @@ void VdaVideoFramePool::ImportFrame(scoped_refptr<VideoFrame> frame) {
DCHECK_CALLED_ON_VALID_SEQUENCE(parent_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(parent_sequence_checker_);
if (!layout_ || layout_->fourcc().ToVideoPixelFormat() != frame->format() || if (!layout_ || layout_->fourcc().ToVideoPixelFormat() != frame->format() ||
layout_->size() != frame->coded_size()) { layout_->size() != frame->coded_size() ||
layout_->modifier() != frame->layout().modifier()) {
return; return;
} }
......
...@@ -58,6 +58,11 @@ base::ScopedFD GetDummyFD() { ...@@ -58,6 +58,11 @@ base::ScopedFD GetDummyFD() {
FakeGpuMemoryBuffer::FakeGpuMemoryBuffer(const gfx::Size& size, FakeGpuMemoryBuffer::FakeGpuMemoryBuffer(const gfx::Size& size,
gfx::BufferFormat format) gfx::BufferFormat format)
: FakeGpuMemoryBuffer(size, format, gfx::NativePixmapHandle::kNoModifier) {}
FakeGpuMemoryBuffer::FakeGpuMemoryBuffer(const gfx::Size& size,
gfx::BufferFormat format,
uint64_t modifier)
: size_(size), format_(format) { : size_(size), format_(format) {
base::Optional<VideoPixelFormat> video_pixel_format = base::Optional<VideoPixelFormat> video_pixel_format =
GfxBufferFormatToVideoPixelFormat(format); GfxBufferFormatToVideoPixelFormat(format);
...@@ -81,6 +86,7 @@ FakeGpuMemoryBuffer::FakeGpuMemoryBuffer(const gfx::Size& size, ...@@ -81,6 +86,7 @@ FakeGpuMemoryBuffer::FakeGpuMemoryBuffer(const gfx::Size& size,
plane_size_in_bytes.width(), 0, plane_size_in_bytes.GetArea(), plane_size_in_bytes.width(), 0, plane_size_in_bytes.GetArea(),
GetDummyFD()); GetDummyFD());
} }
handle_.native_pixmap_handle.modifier = modifier;
#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) #endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
} }
......
...@@ -17,6 +17,9 @@ namespace media { ...@@ -17,6 +17,9 @@ namespace media {
class FakeGpuMemoryBuffer : public gfx::GpuMemoryBuffer { class FakeGpuMemoryBuffer : public gfx::GpuMemoryBuffer {
public: public:
FakeGpuMemoryBuffer(const gfx::Size& size, gfx::BufferFormat format); FakeGpuMemoryBuffer(const gfx::Size& size, gfx::BufferFormat format);
FakeGpuMemoryBuffer(const gfx::Size& size,
gfx::BufferFormat format,
uint64_t modifier);
// gfx::GpuMemoryBuffer implementation. // gfx::GpuMemoryBuffer implementation.
~FakeGpuMemoryBuffer() override; ~FakeGpuMemoryBuffer() override;
......
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