Commit 925e739c authored by Hirokazu Honda's avatar Hirokazu Honda Committed by Commit Bot

media/gpu/linux: Add GpuMemoryBufferVideoFrameMapper

This introduces VideoFrameMapper for GpuMemoryBuffer-based VideoFrame. It is
required for tests to map the frame for verification and writing into a file.

Bug: 1011281
Test: image_processor_test --save_images on atlas
Change-Id: Ie3963e4c7185096d23a5a30507515a3f32144ee2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1865051
Commit-Queue: Hirokazu Honda <hiroh@chromium.org>
Reviewed-by: default avatarDavid Staessens <dstaessens@chromium.org>
Cr-Commit-Position: refs/heads/master@{#708473}
parent 83aba87d
......@@ -81,7 +81,8 @@ std::unique_ptr<LibYUVImageProcessor> LibYUVImageProcessor::Create(
#if defined(OS_LINUX)
if (input_type == VideoFrame::STORAGE_DMABUFS) {
video_frame_mapper = VideoFrameMapperFactory::CreateMapper(
input_config.fourcc.ToVideoPixelFormat(), true);
input_config.fourcc.ToVideoPixelFormat(), VideoFrame::STORAGE_DMABUFS,
true);
if (video_frame_mapper) {
input_storage_type = input_type;
break;
......
......@@ -43,6 +43,8 @@ source_set("video_frame_mapper") {
sources = [
"generic_dmabuf_video_frame_mapper.cc",
"generic_dmabuf_video_frame_mapper.h",
"gpu_memory_buffer_video_frame_mapper.cc",
"gpu_memory_buffer_video_frame_mapper.h",
]
deps = [
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/linux/gpu_memory_buffer_video_frame_mapper.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "media/gpu/macros.h"
#include "ui/gfx/gpu_memory_buffer.h"
namespace media {
// static
std::unique_ptr<GpuMemoryBufferVideoFrameMapper>
GpuMemoryBufferVideoFrameMapper::Create(VideoPixelFormat format) {
return base::WrapUnique(new GpuMemoryBufferVideoFrameMapper(format));
}
GpuMemoryBufferVideoFrameMapper::GpuMemoryBufferVideoFrameMapper(
VideoPixelFormat format)
: VideoFrameMapper(format) {}
scoped_refptr<VideoFrame> GpuMemoryBufferVideoFrameMapper::Map(
scoped_refptr<const VideoFrame> video_frame) const {
if (video_frame->storage_type() !=
VideoFrame::StorageType::STORAGE_GPU_MEMORY_BUFFER) {
VLOGF(1) << "VideoFrame's storage type is not GPU_MEMORY_BUFFER: "
<< video_frame->storage_type();
return nullptr;
}
if (video_frame->format() != format_) {
VLOGF(1) << "Unexpected format: " << video_frame->format()
<< ", expected: " << format_;
return nullptr;
}
gfx::GpuMemoryBuffer* gmb = video_frame->GetGpuMemoryBuffer();
if (!gmb)
return nullptr;
if (!gmb->Map()) {
VLOGF(1) << "Failed to map GpuMemoryBuffer";
return nullptr;
}
const size_t num_planes = VideoFrame::NumPlanes(format_);
uint8_t* plane_addrs[VideoFrame::kMaxPlanes] = {};
for (size_t i = 0; i < num_planes; i++)
plane_addrs[i] = static_cast<uint8_t*>(gmb->memory(i));
scoped_refptr<VideoFrame> mapped_frame;
if (IsYuvPlanar(format_)) {
mapped_frame = VideoFrame::WrapExternalYuvDataWithLayout(
video_frame->layout(), video_frame->visible_rect(),
video_frame->natural_size(), plane_addrs[0], plane_addrs[1],
plane_addrs[2], video_frame->timestamp());
} else if (num_planes == 1) {
size_t buffer_size = VideoFrame::AllocationSize(
format_, gfx::Size(gmb->stride(0), gmb->GetSize().height()));
mapped_frame = VideoFrame::WrapExternalDataWithLayout(
video_frame->layout(), video_frame->visible_rect(),
video_frame->natural_size(), plane_addrs[0], buffer_size,
video_frame->timestamp());
}
if (!mapped_frame)
return nullptr;
// Pass |video_frame| so that it outlives |mapped_frame| and the mapped buffer
// is unmapped on destruction.
mapped_frame->AddDestructionObserver(base::BindOnce(
[](scoped_refptr<const VideoFrame> frame) {
DCHECK(frame->HasGpuMemoryBuffer());
frame->GetGpuMemoryBuffer()->Unmap();
},
std::move(video_frame)));
return mapped_frame;
}
} // namespace media
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_LINUX_GPU_MEMORY_BUFFER_VIDEO_FRAME_MAPPER_H_
#define MEDIA_GPU_LINUX_GPU_MEMORY_BUFFER_VIDEO_FRAME_MAPPER_H_
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/video_frame_mapper.h"
namespace media {
// The GpuMemoryBufferVideoFrameMapper implements functionality to map
// GpuMemoryBuffer-based video frames into memory.
class MEDIA_GPU_EXPORT GpuMemoryBufferVideoFrameMapper
: public VideoFrameMapper {
public:
static std::unique_ptr<GpuMemoryBufferVideoFrameMapper> Create(
VideoPixelFormat format);
~GpuMemoryBufferVideoFrameMapper() override = default;
// VideoFrameMapper implementation.
scoped_refptr<VideoFrame> Map(
scoped_refptr<const VideoFrame> video_frame) const override;
private:
explicit GpuMemoryBufferVideoFrameMapper(VideoPixelFormat format);
DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferVideoFrameMapper);
};
} // namespace media
#endif // MEDIA_GPU_LINUX_GPU_MEMORY_BUFFER_VIDEO_FRAME_MAPPER_H_
......@@ -122,9 +122,11 @@ void VideoFrameFileWriter::ProcessVideoFrameTask(
// Create VideoFrameMapper if not yet created. The decoder's output pixel
// format is not known yet when creating the VideoFrameWriter. We can only
// create the VideoFrameMapper upon receiving the first video frame.
if (!video_frame_mapper_) {
video_frame_mapper_ =
VideoFrameMapperFactory::CreateMapper(video_frame->format());
if ((video_frame->storage_type() == VideoFrame::STORAGE_DMABUFS ||
video_frame->storage_type() == VideoFrame::STORAGE_GPU_MEMORY_BUFFER) &&
!video_frame_mapper_) {
video_frame_mapper_ = VideoFrameMapperFactory::CreateMapper(
video_frame->format(), video_frame->storage_type());
LOG_ASSERT(video_frame_mapper_) << "Failed to create VideoFrameMapper";
}
#endif
......@@ -151,8 +153,12 @@ void VideoFrameFileWriter::WriteVideoFramePNG(
auto mapped_frame = video_frame;
#if defined(OS_CHROMEOS)
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) {
DCHECK(video_frame_mapper_);
mapped_frame = video_frame_mapper_->Map(std::move(video_frame));
}
#endif
if (!mapped_frame) {
......@@ -193,8 +199,11 @@ void VideoFrameFileWriter::WriteVideoFrameYUV(
auto mapped_frame = video_frame;
#if defined(OS_CHROMEOS)
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) {
DCHECK(video_frame_mapper_);
mapped_frame = video_frame_mapper_->Map(std::move(video_frame));
}
#endif
if (!mapped_frame) {
......
......@@ -132,8 +132,8 @@ bool CopyVideoFrame(const VideoFrame* src_frame,
// buffer into memory. We use a VideoFrameMapper to create a memory-based
// VideoFrame that refers to the |dst_frame|'s buffer.
if (dst_frame->storage_type() == VideoFrame::STORAGE_DMABUFS) {
auto video_frame_mapper =
VideoFrameMapperFactory::CreateMapper(dst_frame->format(), true);
auto video_frame_mapper = VideoFrameMapperFactory::CreateMapper(
dst_frame->format(), VideoFrame::STORAGE_DMABUFS, true);
LOG_ASSERT(video_frame_mapper);
dst_frame = video_frame_mapper->Map(std::move(dst_frame));
if (!dst_frame) {
......
......@@ -119,13 +119,15 @@ void VideoFrameValidator::ProcessVideoFrameTask(
scoped_refptr<const VideoFrame> validated_frame = video_frame;
// If this is a DMABuf-backed memory frame we need to map it before accessing.
#if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
if (validated_frame->storage_type() == VideoFrame::STORAGE_DMABUFS) {
if (validated_frame->storage_type() == VideoFrame::STORAGE_DMABUFS ||
validated_frame->storage_type() ==
VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
// Create VideoFrameMapper if not yet created. The decoder's output pixel
// format is not known yet when creating the VideoFrameValidator. We can
// only create the VideoFrameMapper upon receiving the first video frame.
if (!video_frame_mapper_) {
video_frame_mapper_ =
VideoFrameMapperFactory::CreateMapper(video_frame->format());
video_frame_mapper_ = VideoFrameMapperFactory::CreateMapper(
video_frame->format(), video_frame->storage_type());
LOG_ASSERT(video_frame_mapper_) << "Failed to create VideoFrameMapper";
}
......
......@@ -862,7 +862,8 @@ bool V4L2MjpegDecodeAccelerator::ConvertOutputImage(
// Dmabuf-backed frame needs to be mapped for SW access.
if (dst_frame->HasDmaBufs()) {
std::unique_ptr<VideoFrameMapper> frame_mapper =
VideoFrameMapperFactory::CreateMapper(dst_frame->format());
VideoFrameMapperFactory::CreateMapper(dst_frame->format(),
VideoFrame::STORAGE_DMABUFS);
if (!frame_mapper) {
VLOGF(1) << "Failed to create video frame mapper";
return false;
......
......@@ -9,6 +9,7 @@
#if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
#include "media/gpu/linux/generic_dmabuf_video_frame_mapper.h"
#include "media/gpu/linux/gpu_memory_buffer_video_frame_mapper.h"
#endif // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
#if BUILDFLAG(USE_VAAPI)
......@@ -19,19 +20,24 @@ namespace media {
// static
std::unique_ptr<VideoFrameMapper> VideoFrameMapperFactory::CreateMapper(
VideoPixelFormat format) {
VideoPixelFormat format,
VideoFrame::StorageType storage_type) {
#if BUILDFLAG(USE_VAAPI)
return CreateMapper(format, false);
return CreateMapper(format, storage_type, false);
#else
return CreateMapper(format, true);
return CreateMapper(format, storage_type, true);
#endif // BUILDFLAG(USE_VAAPI)
}
// static
std::unique_ptr<VideoFrameMapper> VideoFrameMapperFactory::CreateMapper(
VideoPixelFormat format,
VideoFrame::StorageType storage_type,
bool linear_buffer_mapper) {
#if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
if (storage_type == VideoFrame::STORAGE_GPU_MEMORY_BUFFER)
return GpuMemoryBufferVideoFrameMapper::Create(format);
if (linear_buffer_mapper)
return GenericDmaBufVideoFrameMapper::Create(format);
#endif // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
......
......@@ -17,14 +17,17 @@ namespace media {
// The appropriate VideoFrameMapper is a platform-dependent.
class MEDIA_GPU_EXPORT VideoFrameMapperFactory {
public:
// Create an instance of the frame mapper.
// Create an instance of the frame mapper that maps a video frame whose format
// is |format| and storage type is |storage_type|.
static std::unique_ptr<VideoFrameMapper> CreateMapper(
VideoPixelFormat format);
VideoPixelFormat format,
VideoFrame::StorageType storage_type);
// |linear_buffer_mapper| stands for a created mapper type. If true, the
// mapper will expect frames passed to it to be in linear format.
static std::unique_ptr<VideoFrameMapper> CreateMapper(
VideoPixelFormat format,
VideoFrame::StorageType storage_type,
bool force_linear_buffer_mapper);
};
......
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