#ifndef MEDIA_GPU_V4L2_V4L2_IMAGE_PROCESSOR_BACKEND_H_
#define MEDIA_GPU_V4L2_V4L2_IMAGE_PROCESSOR_BACKEND_H_
#include <linux/videodev2.h>
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <optional>
#include <vector>
#include "base/containers/queue.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "media/gpu/chromeos/image_processor_backend.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/v4l2/v4l2_device.h"
#include "ui/gfx/geometry/size.h"
namespace base {
class TimeTicks;
}
namespace media {
class MEDIA_GPU_EXPORT V4L2ImageProcessorBackend
: public ImageProcessorBackend {
public:
static std::unique_ptr<ImageProcessorBackend> Create(
scoped_refptr<V4L2Device> device,
size_t num_buffers,
const PortConfig& input_config,
const PortConfig& output_config,
OutputMode output_mode,
ErrorCB error_cb);
V4L2ImageProcessorBackend(const V4L2ImageProcessorBackend&) = delete;
V4L2ImageProcessorBackend& operator=(const V4L2ImageProcessorBackend&) =
delete;
void ProcessFrame(scoped_refptr<FrameResource> input_frame,
scoped_refptr<FrameResource> output_frame,
FrameResourceReadyCB cb) override;
void ProcessLegacyFrame(scoped_refptr<FrameResource> frame,
LegacyFrameResourceReadyCB cb) override;
void Reset() override;
static bool IsSupported();
static std::vector<uint32_t> GetSupportedInputFormats();
static std::vector<uint32_t> GetSupportedOutputFormats();
static bool TryOutputFormat(uint32_t input_pixelformat,
uint32_t output_pixelformat,
const gfx::Size& input_size,
gfx::Size* output_size,
size_t* num_planes);
std::string type() const override;
private:
friend struct std::default_delete<V4L2ImageProcessorBackend>;
using InitCB = base::OnceCallback<void(bool)>;
struct JobRecord {
JobRecord();
~JobRecord();
scoped_refptr<FrameResource> input_frame;
FrameResourceReadyCB ready_cb;
LegacyFrameResourceReadyCB legacy_ready_cb;
scoped_refptr<FrameResource> output_frame;
size_t output_buffer_id;
std::optional<base::TimeTicks> start_time;
};
V4L2ImageProcessorBackend(scoped_refptr<V4L2Device> device,
const PortConfig& input_config,
const PortConfig& output_config,
v4l2_memory input_memory_type,
v4l2_memory output_memory_type,
OutputMode output_mode,
ErrorCB error_cb);
~V4L2ImageProcessorBackend() override;
void Destroy() override;
void DestroyOnPollSequence();
void EnqueueInput(const JobRecord* job_record, V4L2WritableBufferRef buffer);
void EnqueueOutput(JobRecord* job_record, V4L2WritableBufferRef buffer);
void Dequeue();
bool EnqueueInputRecord(const JobRecord* job_record,
V4L2WritableBufferRef buffer);
bool EnqueueOutputRecord(JobRecord* job_record, V4L2WritableBufferRef buffer);
bool CreateInputBuffers(size_t num_buffers);
bool CreateOutputBuffers(size_t num_buffers);
bool ReconfigureV4L2Format(const gfx::Size& size, enum v4l2_buf_type type);
static void V4L2VFRecycleThunk(
scoped_refptr<base::SequencedTaskRunner> task_runner,
std::optional<base::WeakPtr<V4L2ImageProcessorBackend>> image_processor,
V4L2ReadableBufferRef buf);
void V4L2VFRecycleTask(V4L2ReadableBufferRef buf);
void NotifyError();
void ProcessJobs();
void ServiceDevice();
void TriggerPoll(bool poll_device);
void DevicePollTask(bool poll_device);
const v4l2_memory input_memory_type_;
const v4l2_memory output_memory_type_;
scoped_refptr<V4L2Device> device_ GUARDED_BY_FIXME(sequence_checker_);
base::queue<std::unique_ptr<JobRecord>> input_job_queue_
GUARDED_BY_CONTEXT(sequence_checker_);
base::queue<std::unique_ptr<JobRecord>> running_jobs_
GUARDED_BY_CONTEXT(sequence_checker_);
scoped_refptr<V4L2Queue> input_queue_ GUARDED_BY_CONTEXT(sequence_checker_);
scoped_refptr<V4L2Queue> output_queue_ GUARDED_BY_CONTEXT(sequence_checker_);
scoped_refptr<base::SingleThreadTaskRunner> poll_task_runner_;
SEQUENCE_CHECKER(poll_sequence_checker_);
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtr<V4L2ImageProcessorBackend> weak_this_;
base::WeakPtr<V4L2ImageProcessorBackend> poll_weak_this_;
base::WeakPtrFactory<V4L2ImageProcessorBackend> weak_this_factory_{this};
base::WeakPtrFactory<V4L2ImageProcessorBackend> poll_weak_this_factory_{this};
};
}
namespace std {
template <>
struct default_delete<media::V4L2ImageProcessorBackend>
: public default_delete<media::ImageProcessorBackend> {};
}
#endif