#ifndef MEDIA_GPU_VAAPI_VAAPI_VIDEO_DECODER_H_
#define MEDIA_GPU_VAAPI_VAAPI_VIDEO_DECODER_H_
#include <stdint.h>
#include <va/va.h>
#include <map>
#include <memory>
#include <optional>
#include <utility>
#include "base/containers/flat_map.h"
#include "base/containers/lru_cache.h"
#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/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "media/base/callback_registry.h"
#include "media/base/cdm_context.h"
#include "media/base/status.h"
#include "media/base/supported_video_decoder_config.h"
#include "media/base/video_aspect_ratio.h"
#include "media/base/video_codecs.h"
#include "media/base/video_frame_layout.h"
#include "media/gpu/chromeos/video_decoder_pipeline.h"
#include "media/gpu/vaapi/vaapi_decode_surface_handler.h"
#include "media/gpu/vaapi/vaapi_status.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/hdr_metadata.h"
namespace media {
class AcceleratedVideoDecoder;
class VaapiVideoDecoderDelegate;
class DmabufVideoFramePool;
class VaapiWrapper;
class FrameResource;
class VASurface;
class ScopedVASurface;
class VaapiVideoDecoder : public VideoDecoderMixin,
public VaapiDecodeSurfaceHandler {
public:
static std::unique_ptr<VideoDecoderMixin> Create(
std::unique_ptr<MediaLog> media_log,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
base::WeakPtr<VideoDecoderMixin::Client> client);
VaapiVideoDecoder(const VaapiVideoDecoder&) = delete;
VaapiVideoDecoder& operator=(const VaapiVideoDecoder&) = delete;
static std::optional<SupportedVideoDecoderConfigs> GetSupportedConfigs();
void Initialize(const VideoDecoderConfig& config,
bool low_delay,
CdmContext* cdm_context,
InitCB init_cb,
const PipelineOutputCB& output_cb,
const WaitingCB& waiting_cb) override;
void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override;
void Reset(base::OnceClosure reset_cb) override;
bool NeedsBitstreamConversion() const override;
bool CanReadWithoutStalling() const override;
int GetMaxDecodeRequests() const override;
VideoDecoderType GetDecoderType() const override;
bool IsPlatformDecoder() const override;
void ApplyResolutionChange() override;
bool NeedsTranscryption() override;
std::unique_ptr<VASurfaceHandle> CreateSurface() override;
void SurfaceReady(VASurfaceID va_surface_id,
int32_t buffer_id,
const gfx::Rect& visible_rect,
const VideoColorSpace& color_space) override;
void set_ignore_resolution_changes_to_smaller_vp9_for_testing(bool value);
~VaapiVideoDecoder() override;
private:
friend class VaapiVideoDecoderTest;
struct DecodeTask {
DecodeTask(scoped_refptr<DecoderBuffer> buffer,
int32_t buffer_id,
DecodeCB decode_done_cb);
DecodeTask(const DecodeTask&) = delete;
DecodeTask& operator=(const DecodeTask&) = delete;
DecodeTask(DecodeTask&&);
DecodeTask& operator=(DecodeTask&&) = default;
~DecodeTask();
scoped_refptr<DecoderBuffer> buffer_;
int32_t buffer_id_ = -1;
DecodeCB decode_done_cb_;
};
enum class State {
kUninitialized,
kWaitingForInput,
kWaitingForOutput,
kWaitingForProtected,
kDecoding,
kChangingResolution,
kExpectingReset,
kResetting,
kError,
};
VaapiVideoDecoder(
std::unique_ptr<MediaLog> media_log,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
base::WeakPtr<VideoDecoderMixin::Client> client);
void ScheduleNextDecodeTask();
void HandleDecodeTask();
void ClearDecodeTaskQueue(DecoderStatus status);
void ReleaseVideoFrame(VASurfaceID surface_id);
void NotifyFrameAvailable();
void ProtectedSessionUpdate(bool success);
void Flush();
void ResetDone(base::OnceClosure reset_cb);
VaapiStatus CreateAcceleratedVideoDecoder();
void SetState(State state);
void SetErrorState(std::string message);
void OnCdmContextEvent(CdmContext::Event event);
void ApplyResolutionChangeWithScreenSizes(
const std::vector<gfx::Size>& screen_resolution);
static CroStatus::Or<scoped_refptr<FrameResource>> AllocateCustomFrameProxy(
base::WeakPtr<VaapiVideoDecoder> decoder,
VideoPixelFormat format,
const gfx::Size& coded_size,
const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
bool use_protected,
bool use_linear_buffers,
bool needs_detiling,
base::TimeDelta timestamp);
CroStatus::Or<scoped_refptr<FrameResource>> AllocateCustomFrame(
VideoPixelFormat format,
const gfx::Size& coded_size,
const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
bool use_protected,
bool use_linear_buffers,
bool needs_detiling,
base::TimeDelta timestamp);
bool IsConfiguredForTesting() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return !!vaapi_wrapper_ && !!decoder_;
}
State state_ GUARDED_BY_CONTEXT(sequence_checker_) = State::kUninitialized;
PipelineOutputCB output_cb_ GUARDED_BY_CONTEXT(sequence_checker_);
WaitingCB waiting_cb_ GUARDED_BY_CONTEXT(sequence_checker_);
VideoCodecProfile profile_ GUARDED_BY_CONTEXT(sequence_checker_) =
VIDEO_CODEC_PROFILE_UNKNOWN;
VideoColorSpace color_space_ GUARDED_BY_CONTEXT(sequence_checker_);
std::optional<gfx::HDRMetadata> hdr_metadata_
GUARDED_BY_CONTEXT(sequence_checker_);
VideoAspectRatio aspect_ratio_ GUARDED_BY_CONTEXT(sequence_checker_);
base::LRUCache<int32_t, base::TimeDelta> buffer_id_to_timestamp_
GUARDED_BY_CONTEXT(sequence_checker_);
base::queue<DecodeTask> decode_task_queue_
GUARDED_BY_CONTEXT(sequence_checker_);
std::optional<DecodeTask> current_decode_task_
GUARDED_BY_CONTEXT(sequence_checker_);
int32_t next_buffer_id_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
std::map<VASurfaceID, scoped_refptr<FrameResource>> output_frames_
GUARDED_BY_CONTEXT(sequence_checker_);
base::flat_map<base::UnguessableToken, std::unique_ptr<ScopedVASurface>>
allocated_va_surfaces_ GUARDED_BY_CONTEXT(sequence_checker_);
std::unique_ptr<CdmContextRef> cdm_context_ref_
GUARDED_BY_CONTEXT(sequence_checker_);
EncryptionScheme encryption_scheme_ GUARDED_BY_CONTEXT(sequence_checker_);
#if BUILDFLAG(IS_CHROMEOS)
std::unique_ptr<CallbackRegistration> cdm_event_cb_registration_
GUARDED_BY_CONTEXT(sequence_checker_);
#endif
std::unique_ptr<AcceleratedVideoDecoder> decoder_
GUARDED_BY_CONTEXT(sequence_checker_);
scoped_refptr<VaapiWrapper> vaapi_wrapper_
GUARDED_BY_CONTEXT(sequence_checker_);
raw_ptr<VaapiVideoDecoderDelegate, DanglingUntriaged> decoder_delegate_
GUARDED_BY_CONTEXT(sequence_checker_) = nullptr;
bool transcryption_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
bool ignore_resolution_changes_to_smaller_for_testing_
GUARDED_BY_CONTEXT(sequence_checker_) = false;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtr<VaapiVideoDecoder> weak_this_;
base::WeakPtrFactory<VaapiVideoDecoder> weak_this_factory_;
};
}
#endif