#ifndef MEDIA_GPU_ANDROID_MEDIA_CODEC_VIDEO_DECODER_H_
#define MEDIA_GPU_ANDROID_MEDIA_CODEC_VIDEO_DECODER_H_
#include <memory>
#include <optional>
#include <vector>
#include "base/containers/circular_deque.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "base/threading/thread_checker.h"
#include "gpu/command_buffer/service/ref_counted_lock.h"
#include "gpu/config/gpu_preferences.h"
#include "media/base/android/media_crypto_context.h"
#include "media/base/android_overlay_mojo_factory.h"
#include "media/base/callback_registry.h"
#include "media/base/cdm_context.h"
#include "media/base/decoder_status.h"
#include "media/base/overlay_info.h"
#include "media/base/scoped_async_trace.h"
#include "media/base/video_decoder.h"
#include "media/base/video_decoder_config.h"
#include "media/gpu/android/android_video_surface_chooser.h"
#include "media/gpu/android/codec_allocator.h"
#include "media/gpu/android/codec_wrapper.h"
#include "media/gpu/android/device_info.h"
#include "media/gpu/android/surface_chooser_helper.h"
#include "media/gpu/android/video_frame_factory.h"
#include "media/gpu/media_gpu_export.h"
namespace media {
class MediaLog;
struct SupportedVideoDecoderConfig;
struct PendingDecode {
static PendingDecode CreateEos();
PendingDecode(scoped_refptr<DecoderBuffer> buffer,
VideoDecoder::DecodeCB decode_cb);
PendingDecode(const PendingDecode&) = delete;
PendingDecode& operator=(const PendingDecode&) = delete;
PendingDecode(PendingDecode&& other);
~PendingDecode();
scoped_refptr<DecoderBuffer> buffer;
VideoDecoder::DecodeCB decode_cb;
};
class MEDIA_GPU_EXPORT MediaCodecVideoDecoder final
: public VideoDecoder,
public gpu::RefCountedLockHelperDrDc {
public:
static std::vector<SupportedVideoDecoderConfig> GetSupportedConfigs();
MediaCodecVideoDecoder(const MediaCodecVideoDecoder&) = delete;
MediaCodecVideoDecoder& operator=(const MediaCodecVideoDecoder&) = delete;
~MediaCodecVideoDecoder() override;
static void DestroyAsync(std::unique_ptr<MediaCodecVideoDecoder>);
static std::unique_ptr<VideoDecoder> Create(
const gpu::GpuPreferences& gpu_preferences,
bool is_surface_control_enabled,
std::unique_ptr<MediaLog> media_log,
DeviceInfo* device_info,
CodecAllocator* codec_allocator,
std::unique_ptr<AndroidVideoSurfaceChooser> surface_chooser,
AndroidOverlayMojoFactoryCB overlay_factory_cb,
RequestOverlayInfoCB request_overlay_info_cb,
std::unique_ptr<VideoFrameFactory> video_frame_factory,
scoped_refptr<gpu::RefCountedLock> drdc_lock);
VideoDecoderType GetDecoderType() const override;
void Initialize(const VideoDecoderConfig& config,
bool low_delay,
CdmContext* cdm_context,
InitCB init_cb,
const OutputCB& output_cb,
const WaitingCB& waiting_cb) override;
void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override;
void Reset(base::OnceClosure closure) override;
bool NeedsBitstreamConversion() const override;
bool CanReadWithoutStalling() const override;
int GetMaxDecodeRequests() const override;
private:
friend class MediaCodecVideoDecoderTest;
MediaCodecVideoDecoder(
const gpu::GpuPreferences& gpu_preferences,
bool is_surface_control_enabled,
std::unique_ptr<MediaLog> media_log,
DeviceInfo* device_info,
CodecAllocator* codec_allocator,
std::unique_ptr<AndroidVideoSurfaceChooser> surface_chooser,
AndroidOverlayMojoFactoryCB overlay_factory_cb,
RequestOverlayInfoCB request_overlay_info_cb,
std::unique_ptr<VideoFrameFactory> video_frame_factory,
scoped_refptr<gpu::RefCountedLock> drdc_lock);
void SetCdm(CdmContext* cdm_context, InitCB init_cb);
void OnMediaCryptoReady(
InitCB init_cb,
base::android::ScopedJavaGlobalRef<jobject> media_crypto,
bool requires_secure_video_codec);
enum class State {
kInitializing,
kRunning,
kError,
kSurfaceDestroyed
};
enum class DrainType { kForReset, kForDestroy };
void StartLazyInit();
void OnVideoFrameFactoryInitialized(
scoped_refptr<gpu::TextureOwner> texture_owner);
void OnCdmContextEvent(CdmContext::Event event);
void OnOverlayInfoChanged(const OverlayInfo& overlay_info);
void OnSurfaceChosen(std::unique_ptr<AndroidOverlay> overlay);
void OnSurfaceDestroyed(AndroidOverlay* overlay);
bool SurfaceTransitionPending();
void TransitionToTargetSurface();
void CreateCodec();
static void OnCodecConfiguredInternal(
base::WeakPtr<MediaCodecVideoDecoder> weak_this,
CodecAllocator* codec_allocator,
scoped_refptr<CodecSurfaceBundle> surface_bundle,
std::unique_ptr<MediaCodecBridge> codec);
void OnCodecConfigured(scoped_refptr<CodecSurfaceBundle> surface_bundle,
std::unique_ptr<MediaCodecBridge> media_codec);
void FlushCodec();
void PumpCodec();
bool QueueInput();
bool DequeueOutput();
void RunEosDecodeCb(int reset_generation);
void ForwardVideoFrame(int reset_generation,
std::unique_ptr<ScopedAsyncTrace> async_trace,
base::TimeTicks started_at,
scoped_refptr<VideoFrame> frame);
void StartDrainingCodec(DrainType drain_type);
void OnCodecDrained();
void CancelPendingDecodes(DecoderStatus status);
void EnterTerminalState(State state, DecoderStatus reason);
bool InTerminalState();
void ReleaseCodec();
bool IsUsingOverlay() const;
void NotifyPromotionHint(PromotionHintAggregator::Hint hint);
void CacheFrameInformation();
AndroidOverlayFactoryCB CreateOverlayFactoryCb();
PromotionHintAggregator::NotifyPromotionHintCB CreatePromotionHintCB();
bool CodecNeedsReallocation(int new_width);
std::vector<SupportedVideoDecoderConfig> GetSupportedConfigsInternal();
std::unique_ptr<MediaLog> media_log_;
State state_ = State::kInitializing;
bool lazy_init_pending_ = true;
base::circular_deque<PendingDecode> pending_decodes_;
bool waiting_for_key_ = false;
std::optional<DrainType> drain_type_;
base::OnceClosure reset_cb_;
int reset_generation_ = 0;
DecodeCB eos_decode_cb_;
OutputCB output_cb_;
WaitingCB waiting_cb_;
VideoDecoderConfig decoder_config_;
bool low_delay_ = false;
std::vector<uint8_t> csd0_;
std::vector<uint8_t> csd1_;
std::unique_ptr<CodecWrapper> codec_;
raw_ptr<CodecAllocator> codec_allocator_;
scoped_refptr<CodecSurfaceBundle> target_surface_bundle_;
scoped_refptr<CodecSurfaceBundle> texture_owner_bundle_;
RequestOverlayInfoCB request_overlay_info_cb_;
OverlayInfo overlay_info_;
const bool is_surface_control_enabled_;
SurfaceChooserHelper surface_chooser_helper_;
std::unique_ptr<VideoFrameFactory> video_frame_factory_;
AndroidOverlayMojoFactoryCB overlay_factory_cb_;
raw_ptr<DeviceInfo> device_info_;
bool enable_threaded_texture_mailboxes_;
SurfaceChooserHelper::FrameInformation cached_frame_information_ =
SurfaceChooserHelper::FrameInformation::NON_OVERLAY_INSECURE;
raw_ptr<MediaCryptoContext> media_crypto_context_ = nullptr;
std::unique_ptr<CallbackRegistration> event_cb_registration_;
bool requires_secure_codec_ = false;
bool deferred_flush_pending_ = false;
bool deferred_reallocation_pending_ = false;
int last_width_ = 0;
size_t max_input_size_ = 0;
base::android::ScopedJavaGlobalRef<jobject> media_crypto_;
bool should_retry_codec_allocation_ = false;
std::string codec_name_;
const bool use_block_model_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<MediaCodecVideoDecoder> weak_factory_{this};
base::WeakPtrFactory<MediaCodecVideoDecoder> codec_allocator_weak_factory_{
this};
};
}
namespace std {
template <>
struct MEDIA_GPU_EXPORT default_delete<media::MediaCodecVideoDecoder>
: public default_delete<media::VideoDecoder> {};
}
#endif