Commit cca42a8b authored by Dean Liao's avatar Dean Liao Committed by Commit Bot

media/gpu: Obtain V4L2ImageProcessor object via factory method.

We used to get V4L2ImageProcessor instance from constructor and perform
initialization later. And Initialize() set several data members which
are not changed after Initialize(). With factory method, Create(), we
can perform Initialize() before constructing V4L2ImageProcessor instance.
And those data members set by Initialize() can be const-qualified.

This commit is a leading commit for using VideoFrameLayout to
encapsulate input/output format and size. Because VideoFrameLayout
is a const object, the input/output VideoFrameLayout variables for
creating V4L2ImageProcessor should be determined before calling
constructor. Thus factory method becomes a natural design choice.

BUG=b:110815424,b:73752373
TEST=Run VEA VDA unittest on devices (peach_pit and elm)
VEA:
video_encode_accelerator_unittest \
--test_stream_data=bear-320x180.yuv:320:180:1:bear.mp4:100000:30 \
--disable_flush --single-process-tests -v=0

VDA:
video_decode_accelerator_unittest \
--test_stream_data=/usr/local/video/test-25fps.h264:320:240:250:258:\
35:150:1 -v=0 --disable_flush --single-process-tests --ozone-platform=gbm

Change-Id: I6909b2c1dbe5eda5845681a51af9e3d1c88d89ec
Reviewed-on: https://chromium-review.googlesource.com/c/1339084
Commit-Queue: Shuo-Peng Liao <deanliao@google.com>
Reviewed-by: default avatarHirokazu Honda <hiroh@chromium.org>
Reviewed-by: default avatarAlexandre Courbot <acourbot@chromium.org>
Cr-Commit-Position: refs/heads/master@{#609201}
parent 98aefef6
......@@ -7,14 +7,15 @@
#include <vector>
#include "base/callback.h"
#include "base/callback_forward.h"
#include "base/files/scoped_file.h"
#include "media/base/video_frame.h"
#include "media/base/video_types.h"
#include "base/memory/ref_counted.h"
#include "ui/gfx/geometry/size.h"
namespace media {
class VideoFrame;
// An image processor is used to convert from one image format to another (e.g.
// I420 to NV12) while optionally scaling. It is useful in situations where
// a given video hardware (e.g. decoder or encoder) accepts or produces data
......@@ -23,21 +24,6 @@ namespace media {
// This class exposes the interface that an image processor should implement.
class ImageProcessor {
public:
// Initializes the processor to convert from |input_format| to |output_format|
// and/or scale from |input_visible_size| to |output_visible_size|.
// Request the input buffers to be of at least |input_allocated_size| and the
// output buffers to be of at least |output_allocated_size|. The number of
// input buffers and output buffers will be |num_buffers|. Provided |error_cb|
// will be posted to the child thread if an error occurs after initialization.
// Return true if the requested configuration is supported.
virtual bool Initialize(VideoPixelFormat input_format,
VideoPixelFormat output_format,
gfx::Size input_visible_size,
gfx::Size input_allocated_size,
gfx::Size output_visible_size,
gfx::Size output_allocated_size,
int num_buffers,
const base::Closure& error_cb) = 0;
// Returns input allocated size required by the processor to be fed with.
virtual gfx::Size input_allocated_size() const = 0;
......
This diff is collapsed.
......@@ -11,12 +11,15 @@
#include <memory>
#include <vector>
#include <linux/videodev2.h>
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread.h"
#include "media/base/video_frame.h"
#include "media/base/video_types.h"
#include "media/gpu/image_processor.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/v4l2/v4l2_device.h"
......@@ -28,26 +31,16 @@ namespace media {
// hardware accelerators (see V4L2VideoDecodeAccelerator) for more details.
class MEDIA_GPU_EXPORT V4L2ImageProcessor : public ImageProcessor {
public:
explicit V4L2ImageProcessor(scoped_refptr<V4L2Device> device,
v4l2_memory input_memory_type,
v4l2_memory output_memory_type);
// ImageProcessor implementation.
~V4L2ImageProcessor() override;
gfx::Size input_allocated_size() const override;
gfx::Size output_allocated_size() const override;
bool Process(scoped_refptr<VideoFrame> frame,
int output_buffer_index,
std::vector<base::ScopedFD> output_dmabuf_fds,
FrameReadyCB cb) override;
bool Reset() override;
// Initializes the processor to convert from |input_format| to |output_format|
// and/or scale from |input_visible_size| to |output_visible_size|.
// Request the input buffers to be of at least |input_allocated_size| and the
// output buffers to be of at least |output_allocated_size|. The number of
// input buffers and output buffers will be |num_buffers|. Provided |error_cb|
// will be called if an error occurs. Return true if the requested
// configuration is supported.
bool Initialize(VideoPixelFormat input_format,
VideoPixelFormat output_format,
gfx::Size input_visible_size,
gfx::Size input_allocated_size,
gfx::Size output_visible_size,
gfx::Size output_allocated_size,
int num_buffers,
const base::Closure& error_cb) override;
// Returns true if image processing is supported on this platform.
static bool IsSupported();
......@@ -67,24 +60,23 @@ class MEDIA_GPU_EXPORT V4L2ImageProcessor : public ImageProcessor {
gfx::Size* size,
size_t* num_planes);
gfx::Size input_allocated_size() const override;
gfx::Size output_allocated_size() const override;
// Called by client to process |frame|. The resulting processed frame will be
// stored in |output_buffer_index| output buffer and notified via |cb|. The
// processor will drop all its references to |frame| after it finishes
// accessing it. If |output_memory_type_| is V4L2_MEMORY_DMABUF, the caller
// should pass non-empty |output_dmabuf_fds| and the processed frame will be
// stored in those buffers. If the number of |output_dmabuf_fds| is not
// expected, this function will return false.
bool Process(scoped_refptr<VideoFrame> frame,
int output_buffer_index,
std::vector<base::ScopedFD> output_dmabuf_fds,
FrameReadyCB cb) override;
// Reset all processing frames. After this method returns, no more callbacks
// will be invoked. V4L2ImageProcessor is ready to process more frames.
bool Reset() override;
// Factory method to create V4L2ImageProcessor to convert from
// input_format to output_format. The number of input buffers and output
// buffers will be |num_buffers|. Provided |error_cb| will be posted to the
// child thread if an error occurs after initialization. Returns nullptr if
// V4L2ImageProcessor fails to create.
static std::unique_ptr<V4L2ImageProcessor> Create(
scoped_refptr<V4L2Device> device,
v4l2_memory input_memory_type,
v4l2_memory output_memory_type,
VideoPixelFormat input_format,
VideoPixelFormat output_format,
gfx::Size input_visible_size,
gfx::Size input_allocated_size,
gfx::Size output_visible_size,
gfx::Size output_allocated_size,
size_t num_buffers,
const base::Closure& error_cb);
private:
// Record for input buffers.
......@@ -123,6 +115,21 @@ class MEDIA_GPU_EXPORT V4L2ImageProcessor : public ImageProcessor {
FrameReadyCB ready_cb;
};
V4L2ImageProcessor(scoped_refptr<V4L2Device> device,
v4l2_memory input_memory_type,
v4l2_memory output_memory_type,
VideoPixelFormat input_format,
VideoPixelFormat output_format,
gfx::Size input_visible_size,
gfx::Size input_allocated_size,
gfx::Size output_visible_size,
gfx::Size output_allocated_size,
size_t input_planes_count,
size_t output_planes_count,
size_t num_buffers,
const base::Closure& error_cb);
bool Initialize();
void EnqueueInput();
void EnqueueOutput(const JobRecord* job_record);
void Dequeue();
......@@ -155,22 +162,20 @@ class MEDIA_GPU_EXPORT V4L2ImageProcessor : public ImageProcessor {
// Size and format-related members remain constant after initialization.
// The visible/allocated sizes of the input frame.
gfx::Size input_visible_size_;
gfx::Size input_allocated_size_;
const gfx::Size input_visible_size_;
const gfx::Size input_allocated_size_;
// The visible/allocated sizes of the destination frame.
gfx::Size output_visible_size_;
gfx::Size output_allocated_size_;
const gfx::Size output_visible_size_;
const gfx::Size output_allocated_size_;
VideoPixelFormat input_format_;
VideoPixelFormat output_format_;
v4l2_memory input_memory_type_;
v4l2_memory output_memory_type_;
uint32_t input_format_fourcc_;
uint32_t output_format_fourcc_;
const VideoPixelFormat input_format_;
const VideoPixelFormat output_format_;
const v4l2_memory input_memory_type_;
const v4l2_memory output_memory_type_;
size_t input_planes_count_;
size_t output_planes_count_;
const size_t input_planes_count_;
const size_t output_planes_count_;
// Our original calling task runner for the child thread.
const scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_;
......@@ -204,7 +209,7 @@ class MEDIA_GPU_EXPORT V4L2ImageProcessor : public ImageProcessor {
// Mapping of int index to an output buffer record.
std::vector<OutputRecord> output_buffer_map_;
// The number of input or output buffers.
int num_buffers_;
const size_t num_buffers_;
// Error callback to the client.
base::Closure error_cb_;
......
......@@ -2352,20 +2352,23 @@ bool V4L2VideoDecodeAccelerator::ResetImageProcessor() {
bool V4L2VideoDecodeAccelerator::CreateImageProcessor() {
VLOGF(2);
DCHECK(!image_processor_);
v4l2_memory output_memory_type =
const v4l2_memory input_memory_type = V4L2_MEMORY_DMABUF;
const v4l2_memory output_memory_type =
(output_mode_ == Config::OutputMode::ALLOCATE ? V4L2_MEMORY_MMAP
: V4L2_MEMORY_DMABUF);
image_processor_.reset(new V4L2ImageProcessor(
image_processor_device_, V4L2_MEMORY_DMABUF, output_memory_type));
// Unretained is safe because |this| owns image processor and there will be
// no callbacks after processor destroys.
if (!image_processor_->Initialize(
V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_),
V4L2Device::V4L2PixFmtToVideoPixelFormat(egl_image_format_fourcc_),
visible_size_, coded_size_, visible_size_, egl_image_size_,
output_buffer_map_.size(),
base::Bind(&V4L2VideoDecodeAccelerator::ImageProcessorError,
base::Unretained(this)))) {
image_processor_ = V4L2ImageProcessor::Create(
image_processor_device_, input_memory_type, output_memory_type,
V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_),
V4L2Device::V4L2PixFmtToVideoPixelFormat(egl_image_format_fourcc_),
visible_size_, coded_size_, visible_size_, egl_image_size_,
output_buffer_map_.size(),
base::Bind(&V4L2VideoDecodeAccelerator::ImageProcessorError,
base::Unretained(this)));
if (!image_processor_) {
VLOGF(1) << "Initialize image processor failed";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
......
......@@ -209,20 +209,17 @@ bool V4L2VideoEncodeAccelerator::Initialize(const Config& config,
return false;
}
scoped_refptr<V4L2Device> device = V4L2Device::Create();
image_processor_.reset(
new V4L2ImageProcessor(device, V4L2_MEMORY_USERPTR, V4L2_MEMORY_MMAP));
// Convert from |config.input_format| to |device_input_format_|, keeping the
// size at |visible_size_| and requiring the output buffers to be of at
// least |input_allocated_size_|. Unretained is safe because |this| owns
// image processor and there will be no callbacks after processor destroys.
if (!image_processor_->Initialize(
config.input_format, device_input_format_, visible_size_,
visible_size_, visible_size_, input_allocated_size_,
kImageProcBufferCount,
base::Bind(&V4L2VideoEncodeAccelerator::ImageProcessorError,
base::Unretained(this)))) {
image_processor_ = V4L2ImageProcessor::Create(
V4L2Device::Create(), V4L2_MEMORY_USERPTR, V4L2_MEMORY_MMAP,
config.input_format, device_input_format_, visible_size_, visible_size_,
visible_size_, input_allocated_size_, kImageProcBufferCount,
base::Bind(&V4L2VideoEncodeAccelerator::ImageProcessorError,
base::Unretained(this)));
if (!image_processor_) {
VLOGF(1) << "Failed initializing image processor";
return false;
}
......
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