| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_DECODER_TEMPLATE_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_DECODER_TEMPLATE_H_ |
| |
| #include <stdint.h> |
| #include <memory> |
| |
| #include "media/base/decoder_status.h" |
| #include "media/base/media_log.h" |
| #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" |
| #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" |
| #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" |
| #include "third_party/blink/renderer/bindings/modules/v8/v8_codec_state.h" |
| #include "third_party/blink/renderer/bindings/modules/v8/v8_webcodecs_error_callback.h" |
| #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" |
| #include "third_party/blink/renderer/modules/modules_export.h" |
| #include "third_party/blink/renderer/modules/webcodecs/codec_config_eval.h" |
| #include "third_party/blink/renderer/modules/webcodecs/codec_logger.h" |
| #include "third_party/blink/renderer/modules/webcodecs/codec_trace_names.h" |
| #include "third_party/blink/renderer/modules/webcodecs/hardware_preference.h" |
| #include "third_party/blink/renderer/modules/webcodecs/reclaimable_codec.h" |
| #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" |
| #include "third_party/blink/renderer/platform/heap/collection_support/heap_deque.h" |
| #include "third_party/blink/renderer/platform/heap/garbage_collected.h" |
| #include "third_party/blink/renderer/platform/heap/member.h" |
| |
| namespace base { |
| class SingleThreadTaskRunner; |
| } |
| |
| namespace media { |
| class GpuVideoAcceleratorFactories; |
| class ScopedDecodeTrace; |
| } |
| |
| namespace blink { |
| |
| template <typename Traits> |
| class MODULES_EXPORT DecoderTemplate |
| : public ScriptWrappable, |
| public ActiveScriptWrappable<DecoderTemplate<Traits>>, |
| public ReclaimableCodec, |
| public ExecutionContextLifecycleObserver { |
| public: |
| typedef typename Traits::ConfigType ConfigType; |
| typedef typename Traits::MediaConfigType MediaConfigType; |
| typedef typename Traits::InputType InputType; |
| typedef typename Traits::InitType InitType; |
| typedef typename Traits::MediaDecoderType MediaDecoderType; |
| typedef typename Traits::MediaOutputType MediaOutputType; |
| typedef typename Traits::OutputType OutputType; |
| typedef typename Traits::OutputCallbackType OutputCallbackType; |
| |
| static const CodecTraceNames* GetTraceNames(); |
| |
| DecoderTemplate(ScriptState*, const InitType*, ExceptionState&); |
| ~DecoderTemplate() override; |
| |
| int32_t decodeQueueSize(); |
| void configure(const ConfigType*, ExceptionState&); |
| void decode(const InputType*, ExceptionState&); |
| ScriptPromise flush(ExceptionState&); |
| void reset(ExceptionState&); |
| void close(ExceptionState&); |
| String state() const { return state_; } |
| |
| // ExecutionContextLifecycleObserver override. |
| void ContextDestroyed() override; |
| |
| // ScriptWrappable override. |
| bool HasPendingActivity() const override; |
| |
| // GarbageCollected override. |
| void Trace(Visitor*) const override; |
| |
| protected: |
| // Convert a configuration to a DecoderConfig. |
| virtual CodecConfigEval MakeMediaConfig(const ConfigType& config, |
| MediaConfigType* out_media_config, |
| String* out_console_message) = 0; |
| |
| // Gets the AccelerationPreference from a config. |
| // If derived classes do not override this, this will default to kAllow. |
| virtual HardwarePreference GetHardwarePreference(const ConfigType& config); |
| |
| // Get the low delay preference from a config. |
| // If derived classes do not override this, this will default to false. |
| virtual bool GetLowDelayPreference(const ConfigType& config); |
| |
| // Sets the HardwarePreference on the |decoder_|. |
| // The default implementation does nothing and must be overridden by derived |
| // classes if needed. |
| // Decoder |
| virtual void SetHardwarePreference(HardwarePreference preference); |
| |
| MediaDecoderType* decoder() { return decoder_.get(); } |
| |
| // Convert a chunk to a DecoderBuffer. You can assume that the last |
| // configuration sent to MakeMediaConfig() is the active configuration for |
| // |chunk|. If there is an error in the conversion process, the resulting |
| // DecoderBuffer will be null, and |out_status| will contain a description of |
| // the error. |
| // |
| // When |verify_key_frame| is true, clients are expected to verify and set the |
| // DecoderBuffer::is_key_frame() value. I.e., they must process the encoded |
| // data to ensure the value is actually what the chunk says it is. |
| virtual media::DecoderStatus::Or<scoped_refptr<media::DecoderBuffer>> |
| MakeDecoderBuffer(const InputType& chunk, bool verify_key_frame) = 0; |
| |
| private: |
| struct Request final : public GarbageCollected<Request> { |
| enum class Type { |
| kConfigure, |
| kDecode, |
| kFlush, |
| kReset, |
| }; |
| |
| void Trace(Visitor*) const; |
| |
| // Starts an async trace event. |
| void StartTracing(); |
| |
| // Ends the async trace event associated with |this|. |
| void EndTracing(bool shutting_down = false); |
| |
| // Get a trace event name from DecoderTemplate::GetTraceNames() and |type|. |
| const char* TraceNameFromType(); |
| |
| Type type; |
| |
| // For kConfigure Requests. Prefer absl::optional<> to ensure values are |
| // only accessed on the proper request type. |
| std::unique_ptr<MediaConfigType> media_config; |
| absl::optional<HardwarePreference> hw_pref; |
| absl::optional<bool> low_delay; |
| |
| // For kDecode Requests. |
| scoped_refptr<media::DecoderBuffer> decoder_buffer; |
| |
| // For kFlush Requests. |
| Member<ScriptPromiseResolver> resolver; |
| |
| // For reporting an error at the time when a request is processed. |
| media::DecoderStatus status; |
| |
| // The value of |reset_generation_| at the time of this request. Used to |
| // abort pending requests following a reset(). |
| uint32_t reset_generation = 0; |
| |
| // Used for tracing kDecode requests. |
| std::unique_ptr<media::ScopedDecodeTrace> decode_trace; |
| |
| #if DCHECK_IS_ON() |
| // Tracks the state of tracing for debug purposes. |
| bool is_tracing; |
| #endif |
| }; |
| |
| void ProcessRequests(); |
| bool ProcessConfigureRequest(Request* request); |
| void ContinueConfigureWithGpuFactories( |
| Request* request, |
| media::GpuVideoAcceleratorFactories* factories); |
| bool ProcessDecodeRequest(Request* request); |
| bool ProcessFlushRequest(Request* request); |
| bool ProcessResetRequest(Request* request); |
| void ResetAlgorithm(); |
| void Shutdown(DOMException* ex = nullptr); |
| |
| // Called by |decoder_|. |
| void OnInitializeDone(media::DecoderStatus status); |
| void OnDecodeDone(uint32_t id, media::DecoderStatus); |
| void OnFlushDone(media::DecoderStatus); |
| void OnResetDone(); |
| void OnOutput(uint32_t reset_generation, scoped_refptr<MediaOutputType>); |
| |
| // Helper function making it easier to check |state_|. |
| bool IsClosed(); |
| |
| // ReclaimableCodec implementation. |
| void OnCodecReclaimed(DOMException*) override; |
| |
| void TraceQueueSizes() const; |
| |
| Member<ScriptState> script_state_; |
| Member<OutputCallbackType> output_cb_; |
| Member<V8WebCodecsErrorCallback> error_cb_; |
| |
| HeapDeque<Member<Request>> requests_; |
| int32_t num_pending_decodes_ = 0; |
| |
| // Monotonic increasing generation counter for calls to ResetAlgorithm(). |
| uint32_t reset_generation_ = 0; |
| |
| // Which state the codec is in, determining which calls we can receive. |
| V8CodecState state_; |
| |
| // An in-flight, mutually-exclusive request. |
| // Could be a configure, flush, or reset. Decodes go in |pending_decodes_|. |
| Member<Request> pending_request_; |
| |
| std::unique_ptr<CodecLogger<media::DecoderStatus>> logger_; |
| |
| // Empty - GPU factories haven't been retrieved yet. |
| // nullptr - We tried to get GPU factories, but acceleration is unavailable. |
| absl::optional<media::GpuVideoAcceleratorFactories*> gpu_factories_; |
| |
| // Cached config from the last kConfigure request which successfully completed |
| // initialization. |
| bool low_delay_ = false; |
| std::unique_ptr<MediaConfigType> active_config_; |
| |
| // TODO(sandersd): Store the last config, flush, and reset so that |
| // duplicates can be elided. |
| std::unique_ptr<MediaDecoderType> decoder_; |
| bool initializing_sync_ = false; |
| |
| // TODO(sandersd): Can this just be a HashSet by ptr comparison? |
| uint32_t pending_decode_id_ = 0; |
| |
| // Used to differentiate Decoders' counters during tracing. |
| int trace_counter_id_; |
| |
| HeapHashMap<uint32_t, Member<Request>> pending_decodes_; |
| |
| // Keyframes are required after configure(), flush(), and reset(). |
| bool require_key_frame_ = true; |
| |
| // Task runner for main thread. |
| scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_DECODER_TEMPLATE_H_ |