#ifndef MEDIA_GPU_V4L2_V4L2_MJPEG_DECODE_ACCELERATOR_H_
#define MEDIA_GPU_V4L2_V4L2_MJPEG_DECODE_ACCELERATOR_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/containers/queue.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/threading/thread.h"
#include "components/chromeos_camera/mjpeg_decode_accelerator.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/v4l2/v4l2_device.h"
namespace base {
class SingleThreadTaskRunner;
class SequencedTaskRunner;
}
namespace media {
class VideoFrame;
class MEDIA_GPU_EXPORT V4L2MjpegDecodeAccelerator
: public chromeos_camera::MjpegDecodeAccelerator {
public:
class JobRecord;
V4L2MjpegDecodeAccelerator(
const scoped_refptr<V4L2Device>& device,
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
V4L2MjpegDecodeAccelerator(const V4L2MjpegDecodeAccelerator&) = delete;
V4L2MjpegDecodeAccelerator& operator=(const V4L2MjpegDecodeAccelerator&) =
delete;
~V4L2MjpegDecodeAccelerator() override;
void InitializeAsync(
chromeos_camera::MjpegDecodeAccelerator::Client* client,
chromeos_camera::MjpegDecodeAccelerator::InitCB init_cb) override;
void Decode(BitstreamBuffer bitstream_buffer,
scoped_refptr<VideoFrame> video_frame) override;
void Decode(int32_t task_id,
base::ScopedFD src_dmabuf_fd,
size_t src_size,
off_t src_offset,
scoped_refptr<media::VideoFrame> dst_frame) override;
bool IsSupported() override;
private:
struct BufferRecord {
BufferRecord() = default;
~BufferRecord() = default;
void* address[VIDEO_MAX_PLANES] = {};
size_t length[VIDEO_MAX_PLANES] = {};
bool at_device = false;
};
void EnqueueInput();
void EnqueueOutput();
void Dequeue();
bool EnqueueInputRecord();
bool EnqueueOutputRecord();
bool CreateInputBuffers();
bool CreateOutputBuffers();
void DestroyInputBuffers();
void DestroyOutputBuffers();
void InitializeOnDecoderTaskRunner(
chromeos_camera::MjpegDecodeAccelerator::Client* client,
InitCB init_cb);
bool ConvertOutputImage(const BufferRecord& output_buffer,
scoped_refptr<VideoFrame> dst_frame);
size_t InputBufferQueuedCount();
size_t OutputBufferQueuedCount();
bool ShouldRecreateInputBuffers();
bool RecreateInputBuffers();
bool RecreateOutputBuffers();
void VideoFrameReady(int32_t task_id);
void NotifyError(int32_t task_id, Error error);
void PostNotifyError(int32_t task_id, Error error);
void DecodeTask(std::unique_ptr<JobRecord> job_record);
void ServiceDeviceTask(bool event_pending);
bool DequeueSourceChangeEvent();
void StartDevicePoll();
bool StopDevicePoll();
void DevicePollTask();
void DestroyTask(base::WaitableEvent* waiter);
const size_t kBufferCount = 2;
gfx::Size output_buffer_coded_size_ GUARDED_BY_CONTEXT(decoder_sequence_);
uint32_t output_buffer_pixelformat_ GUARDED_BY_CONTEXT(decoder_sequence_);
size_t output_buffer_num_planes_ GUARDED_BY_CONTEXT(decoder_sequence_);
size_t output_strides_[VIDEO_MAX_PLANES] GUARDED_BY_CONTEXT(
decoder_sequence_);
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
raw_ptr<chromeos_camera::MjpegDecodeAccelerator::Client> client_;
scoped_refptr<V4L2Device> device_;
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner_;
base::Thread device_poll_thread_ GUARDED_BY_CONTEXT(decoder_sequence_);
scoped_refptr<base::SingleThreadTaskRunner> device_poll_task_runner_;
base::queue<std::unique_ptr<JobRecord>> input_jobs_
GUARDED_BY_CONTEXT(decoder_sequence_);
base::queue<std::unique_ptr<JobRecord>> running_jobs_
GUARDED_BY_CONTEXT(decoder_sequence_);
bool input_streamon_ GUARDED_BY_CONTEXT(decoder_sequence_);
std::vector<BufferRecord> input_buffer_map_
GUARDED_BY_CONTEXT(decoder_sequence_);
std::vector<int> free_input_buffers_ GUARDED_BY_CONTEXT(decoder_sequence_);
bool output_streamon_ GUARDED_BY_CONTEXT(decoder_sequence_);
std::vector<BufferRecord> output_buffer_map_
GUARDED_BY_CONTEXT(decoder_sequence_);
std::vector<int> free_output_buffers_ GUARDED_BY_CONTEXT(decoder_sequence_);
SEQUENCE_CHECKER(decoder_sequence_);
base::WeakPtr<V4L2MjpegDecodeAccelerator> weak_ptr_for_decoder_;
base::WeakPtr<V4L2MjpegDecodeAccelerator> weak_ptr_;
base::WeakPtrFactory<V4L2MjpegDecodeAccelerator> weak_factory_for_decoder_;
base::WeakPtrFactory<V4L2MjpegDecodeAccelerator> weak_factory_;
};
}
#endif