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