blob: d12a2d5a0c5bb730386cf499995fc5c0a3b07223 [file] [log] [blame]
// 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/decode_status.h"
#include "media/base/media_log.h"
#include "media/base/status.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/hardware_preference.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/heap/member.h"
namespace media {
class GpuVideoAcceleratorFactories;
}
namespace blink {
template <typename Traits>
class MODULES_EXPORT DecoderTemplate
: public ScriptWrappable,
public ActiveScriptWrappable<DecoderTemplate<Traits>>,
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;
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);
// 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.
virtual media::StatusOr<scoped_refptr<media::DecoderBuffer>>
MakeDecoderBuffer(const InputType& chunk) = 0;
private:
struct Request final : public GarbageCollected<Request> {
enum class Type {
kConfigure,
kDecode,
kFlush,
kReset,
};
void Trace(Visitor*) const;
Type type;
// For kConfigure Requests.
std::unique_ptr<MediaConfigType> media_config;
HardwarePreference hw_pref = HardwarePreference::kAllow;
// 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::Status 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;
};
void ProcessRequests();
bool ProcessConfigureRequest(Request* request);
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::Status status);
void OnDecodeDone(uint32_t id, media::Status);
void OnFlushDone(media::Status);
void OnConfigureFlushDone(media::Status);
void OnResetDone();
void OnOutput(uint32_t reset_generation, scoped_refptr<MediaOutputType>);
// Helper function making it easier to check |state_|.
bool IsClosed();
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> logger_;
media::GpuVideoAcceleratorFactories* gpu_factories_ = nullptr;
// 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;
HeapHashMap<uint32_t, Member<Request>> pending_decodes_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_DECODER_TEMPLATE_H_