#ifndef MEDIA_GPU_V4L2_V4L2_VIDEO_DECODER_BACKEND_STATELESS_H_
#define MEDIA_GPU_V4L2_V4L2_VIDEO_DECODER_BACKEND_STATELESS_H_
#include "base/containers/lru_cache.h"
#include "base/containers/queue.h"
#include "base/containers/small_map.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/types/id_type.h"
#include "media/base/cdm_context.h"
#include "media/base/decoder_status.h"
#include "media/base/video_decoder.h"
#include "media/gpu/chromeos/dmabuf_video_frame_pool.h"
#include "media/gpu/v4l2/v4l2_decode_surface_handler.h"
#include "media/gpu/v4l2/v4l2_video_decoder_backend.h"
namespace media {
class AcceleratedVideoDecoder;
class V4L2StatelessVideoDecoderBackend : public V4L2VideoDecoderBackend,
public V4L2DecodeSurfaceHandler {
public:
V4L2StatelessVideoDecoderBackend(
Client* const client,
scoped_refptr<V4L2Device> device,
VideoCodecProfile profile,
const VideoColorSpace& color_space,
scoped_refptr<base::SequencedTaskRunner> task_runner,
CdmContext* cdm_context);
V4L2StatelessVideoDecoderBackend(const V4L2StatelessVideoDecoderBackend&) =
delete;
V4L2StatelessVideoDecoderBackend& operator=(
const V4L2StatelessVideoDecoderBackend&) = delete;
~V4L2StatelessVideoDecoderBackend() override;
bool Initialize() override;
void EnqueueDecodeTask(scoped_refptr<DecoderBuffer> buffer,
VideoDecoder::DecodeCB decode_cb) override;
void OnOutputBufferDequeued(V4L2ReadableBufferRef buffer) override;
void OnStreamStopped(bool stop_input_queue) override;
bool ApplyResolution(const gfx::Size& pic_size,
const gfx::Rect& visible_rect) override;
void OnChangeResolutionDone(CroStatus status) override;
void ClearPendingRequests(DecoderStatus status) override;
bool StopInputQueueOnResChange() const override;
size_t GetNumOUTPUTQueueBuffers(bool secure_mode) const override;
scoped_refptr<V4L2DecodeSurface> CreateSurface() override;
scoped_refptr<V4L2DecodeSurface> CreateSecureSurface(
uint64_t secure_handle) override;
bool SubmitSlice(V4L2DecodeSurface* dec_surface,
const uint8_t* data,
size_t size) override;
void DecodeSurface(scoped_refptr<V4L2DecodeSurface> dec_surface) override;
void SurfaceReady(scoped_refptr<V4L2DecodeSurface> dec_surface,
int32_t bitstream_id,
const gfx::Rect& visible_rect,
const VideoColorSpace& color_space) override;
void ResumeDecoding() override;
private:
struct OutputRequest;
struct DecodeRequest {
scoped_refptr<DecoderBuffer> buffer;
VideoDecoder::DecodeCB decode_cb;
int32_t bitstream_id;
DecodeRequest(scoped_refptr<DecoderBuffer> buf,
VideoDecoder::DecodeCB cb,
int32_t id);
DecodeRequest(const DecodeRequest&) = delete;
DecodeRequest& operator=(const DecodeRequest&) = delete;
DecodeRequest(DecodeRequest&&);
DecodeRequest& operator=(DecodeRequest&&);
~DecodeRequest();
};
enum class PauseReason {
kNone,
kRanOutOfSurfaces,
};
static void ReuseOutputBufferThunk(
scoped_refptr<base::SequencedTaskRunner> task_runner,
std::optional<base::WeakPtr<V4L2StatelessVideoDecoderBackend>> weak_this,
V4L2ReadableBufferRef buffer);
void ReuseOutputBuffer(V4L2ReadableBufferRef buffer);
void DoDecodeWork();
bool PumpDecodeTask();
void PumpOutputSurfaces();
void ChangeResolution();
bool IsSupportedProfile(VideoCodecProfile profile);
bool CreateDecoder();
VideoCodecProfile profile_;
VideoColorSpace color_space_;
gfx::Size pic_size_;
std::unique_ptr<AcceleratedVideoDecoder> decoder_;
std::optional<DecodeRequest> current_decode_request_;
base::queue<scoped_refptr<V4L2DecodeSurface>> surfaces_at_device_;
base::queue<DecodeRequest> decode_request_queue_;
base::queue<OutputRequest> output_request_queue_;
PauseReason pause_reason_ = PauseReason::kNone;
base::LRUCache<int32_t, base::TimeDelta> bitstream_id_to_timestamp_;
const scoped_refptr<base::SequencedTaskRunner> task_runner_;
VideoDecoder::DecodeCB flush_cb_;
std::vector<VideoCodecProfile> supported_profiles_;
raw_ptr<V4L2RequestsQueue> requests_queue_;
base::small_map<std::map<int64_t, base::TimeTicks>> enqueuing_timestamps_;
base::small_map<std::map<base::TimeDelta, std::unique_ptr<ScopedDecodeTrace>>>
buffer_tracers_ GUARDED_BY_CONTEXT(sequence_checker_);
struct BitstreamID {};
base::IdType32<BitstreamID>::Generator bitstream_id_generator_
GUARDED_BY_CONTEXT(sequence_checker_);
raw_ptr<CdmContext> cdm_context_;
base::WeakPtr<V4L2StatelessVideoDecoderBackend> weak_this_;
base::WeakPtrFactory<V4L2StatelessVideoDecoderBackend> weak_this_factory_{
this};
};
}
#endif