Skip to content

Commit

Permalink
[webcodecs] Add dequeue event to AudioDecoder + VideoDecoder interfaces
Browse files Browse the repository at this point in the history
Implementation is behind flag:
--enable-blink-features=WebCodecsDequeueEvent

Bug: 1341116
Change-Id: I8915e4573ee9175cb67c9923f0d93e1b28d6e9e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3807054
Commit-Queue: Chrome Cunningham <chcunningham@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Auto-Submit: Chrome Cunningham <chcunningham@chromium.org>
Reviewed-by: Mike Taylor <miketaylr@chromium.org>
Reviewed-by: Thomas Guilbert <tguilbert@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1033102}
  • Loading branch information
chcunningham authored and Chromium LUCI CQ committed Aug 9, 2022
1 parent fa7fa6e commit 700a5d8
Show file tree
Hide file tree
Showing 16 changed files with 210 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,7 @@
"WindowControlsOverlay",
"AudioEncoder",
"VideoEncoder",
"AudioDecoder",
"VideoDecoder",
],
}
4 changes: 4 additions & 0 deletions third_party/blink/renderer/modules/webcodecs/audio_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -269,4 +269,8 @@ AudioDecoder::MakeDecoderBuffer(const InputType& chunk, bool verify_key_frame) {
return chunk.buffer();
}

const AtomicString& AudioDecoder::InterfaceName() const {
return event_target_names::kAudioDecoder;
}

} // namespace blink
3 changes: 3 additions & 0 deletions third_party/blink/renderer/modules/webcodecs/audio_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ class MODULES_EXPORT AudioDecoder : public DecoderTemplate<AudioDecoderTraits> {
AudioDecoder(ScriptState*, const AudioDecoderInit*, ExceptionState&);
~AudioDecoder() override = default;

// EventTarget interface
const AtomicString& InterfaceName() const override;

protected:
bool IsValidConfig(const ConfigType& config,
String* js_error_message) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
SecureContext,
RuntimeEnabled=WebCodecs,
ActiveScriptWrappable
] interface AudioDecoder {
] interface AudioDecoder : EventTarget {
// |init| includes an |output| callback for emitting AudioBuffers and an
// |error| callback for emitting decode errors. All errors are permanent;
// construct a new decoder to recover.
Expand All @@ -24,6 +24,11 @@
// |decodeQueueSize| is greater than a constant.
readonly attribute unsigned long decodeQueueSize;

// Fires to signal a decrease in decodeQueueSize. Will fire at most once for a
// given turn of the event loop.
[RuntimeEnabled=WebCodecsDequeueEvent]
attribute EventHandler ondequeue;

// Which state the decoder is in, indicating which methods can be called.
readonly attribute CodecState state;

Expand Down
67 changes: 65 additions & 2 deletions third_party/blink/renderer/modules/webcodecs/decoder_template.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_init.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/webcodecs/audio_data.h"
#include "third_party/blink/renderer/modules/webcodecs/audio_decoder.h"
Expand All @@ -41,6 +43,7 @@
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
Expand Down Expand Up @@ -131,6 +134,7 @@ template <typename Traits>
void DecoderTemplate<Traits>::configure(const ConfigType* config,
ExceptionState& exception_state) {
DVLOG(1) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (ThrowIfCodecStateClosed(state_, "decode", exception_state))
return;

Expand Down Expand Up @@ -167,6 +171,7 @@ template <typename Traits>
void DecoderTemplate<Traits>::decode(const InputType* chunk,
ExceptionState& exception_state) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (ThrowIfCodecStateClosed(state_, "decode", exception_state))
return;

Expand Down Expand Up @@ -199,6 +204,7 @@ void DecoderTemplate<Traits>::decode(const InputType* chunk,
template <typename Traits>
ScriptPromise DecoderTemplate<Traits>::flush(ExceptionState& exception_state) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (ThrowIfCodecStateClosed(state_, "flush", exception_state))
return ScriptPromise();

Expand All @@ -223,6 +229,7 @@ ScriptPromise DecoderTemplate<Traits>::flush(ExceptionState& exception_state) {
template <typename Traits>
void DecoderTemplate<Traits>::reset(ExceptionState& exception_state) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (ThrowIfCodecStateClosed(state_, "reset", exception_state))
return;

Expand All @@ -234,6 +241,7 @@ void DecoderTemplate<Traits>::reset(ExceptionState& exception_state) {
template <typename Traits>
void DecoderTemplate<Traits>::close(ExceptionState& exception_state) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (ThrowIfCodecStateClosed(state_, "close", exception_state))
return;

Expand All @@ -243,6 +251,7 @@ void DecoderTemplate<Traits>::close(ExceptionState& exception_state) {
template <typename Traits>
void DecoderTemplate<Traits>::ProcessRequests() {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!IsClosed());
while (!pending_request_ && !requests_.IsEmpty()) {
Request* request = requests_.front();
Expand Down Expand Up @@ -289,6 +298,7 @@ void DecoderTemplate<Traits>::ProcessRequests() {
template <typename Traits>
bool DecoderTemplate<Traits>::ProcessConfigureRequest(Request* request) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!IsClosed());
DCHECK(!pending_request_);
DCHECK_EQ(request->type, Request::Type::kConfigure);
Expand Down Expand Up @@ -322,6 +332,7 @@ template <typename Traits>
void DecoderTemplate<Traits>::ContinueConfigureWithGpuFactories(
Request* request,
media::GpuVideoAcceleratorFactories* gpu_factories) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(request);
DCHECK_EQ(request->type, Request::Type::kConfigure);

Expand Down Expand Up @@ -362,6 +373,7 @@ void DecoderTemplate<Traits>::ContinueConfigureWithGpuFactories(
template <typename Traits>
bool DecoderTemplate<Traits>::ProcessDecodeRequest(Request* request) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(state_, V8CodecState::Enum::kConfigured);
DCHECK(!pending_request_);
DCHECK_EQ(request->type, Request::Type::kDecode);
Expand Down Expand Up @@ -402,6 +414,7 @@ bool DecoderTemplate<Traits>::ProcessDecodeRequest(Request* request) {
;
pending_decodes_.Set(pending_decode_id_, request);
--num_pending_decodes_;
ScheduleDequeueEvent();

if (media::ScopedDecodeTrace::IsEnabled()) {
request->decode_trace = std::make_unique<media::ScopedDecodeTrace>(
Expand All @@ -417,6 +430,7 @@ bool DecoderTemplate<Traits>::ProcessDecodeRequest(Request* request) {
template <typename Traits>
bool DecoderTemplate<Traits>::ProcessFlushRequest(Request* request) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!IsClosed());
DCHECK(!pending_request_);
DCHECK_EQ(request->type, Request::Type::kFlush);
Expand Down Expand Up @@ -445,6 +459,7 @@ bool DecoderTemplate<Traits>::ProcessFlushRequest(Request* request) {
template <typename Traits>
bool DecoderTemplate<Traits>::ProcessResetRequest(Request* request) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!IsClosed());
DCHECK(!pending_request_);
DCHECK_EQ(request->type, Request::Type::kReset);
Expand All @@ -467,6 +482,7 @@ bool DecoderTemplate<Traits>::ProcessResetRequest(Request* request) {
template <typename Traits>
void DecoderTemplate<Traits>::Shutdown(DOMException* exception) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (IsClosed())
return;

Expand Down Expand Up @@ -525,6 +541,7 @@ void DecoderTemplate<Traits>::Shutdown(DOMException* exception) {

pending_decodes_.clear();
num_pending_decodes_ = 0;
ScheduleDequeueEvent();

// Fire the error callback if necessary.
if (exception)
Expand All @@ -533,6 +550,7 @@ void DecoderTemplate<Traits>::Shutdown(DOMException* exception) {

template <typename Traits>
void DecoderTemplate<Traits>::ResetAlgorithm() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (state_ == V8CodecState::Enum::kUnconfigured)
return;

Expand All @@ -545,6 +563,7 @@ void DecoderTemplate<Traits>::ResetAlgorithm() {
// Any previous pending decode will be filtered by ProcessRequests(). Reset
// the count immediately to report the correct value in decodeQueueSize().
num_pending_decodes_ = 0;
ScheduleDequeueEvent();

// Since configure is always required after reset we can drop any cached
// configuration.
Expand All @@ -560,6 +579,7 @@ void DecoderTemplate<Traits>::ResetAlgorithm() {
template <typename Traits>
void DecoderTemplate<Traits>::OnFlushDone(media::DecoderStatus status) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (IsClosed())
return;

Expand Down Expand Up @@ -603,6 +623,7 @@ void DecoderTemplate<Traits>::OnFlushDone(media::DecoderStatus status) {
template <typename Traits>
void DecoderTemplate<Traits>::OnInitializeDone(media::DecoderStatus status) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (IsClosed())
return;

Expand Down Expand Up @@ -654,6 +675,7 @@ template <typename Traits>
void DecoderTemplate<Traits>::OnDecodeDone(uint32_t id,
media::DecoderStatus status) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (IsClosed())
return;

Expand All @@ -676,6 +698,7 @@ void DecoderTemplate<Traits>::OnDecodeDone(uint32_t id,
template <typename Traits>
void DecoderTemplate<Traits>::OnResetDone() {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (IsClosed())
return;

Expand All @@ -690,6 +713,7 @@ template <typename Traits>
void DecoderTemplate<Traits>::OnOutput(uint32_t reset_generation,
scoped_refptr<MediaOutputType> output) {
DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

// Suppress outputs belonging to an earlier reset_generation.
if (reset_generation != reset_generation_)
Expand Down Expand Up @@ -724,14 +748,51 @@ void DecoderTemplate<Traits>::OnOutput(uint32_t reset_generation,

template <typename Traits>
void DecoderTemplate<Traits>::TraceQueueSizes() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
TRACE_COUNTER_ID2(kCategory, GetTraceNames()->requests_counter.c_str(),
trace_counter_id_, "decodes", num_pending_decodes_, "other",
requests_.size() - num_pending_decodes_);
}

template <typename Traits>
void DecoderTemplate<Traits>::DispatchDequeueEvent(Event* event) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
probe::AsyncTask async_task(GetExecutionContext(),
event->async_task_context());
dequeue_event_pending_ = false;
DispatchEvent(*event);
}

template <typename Traits>
void DecoderTemplate<Traits>::ScheduleDequeueEvent() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

if (!RuntimeEnabledFeatures::WebCodecsDequeueEventEnabled())
return;

if (dequeue_event_pending_)
return;
dequeue_event_pending_ = true;

Event* event = Event::Create(event_type_names::kDequeue);
event->SetTarget(this);
event->async_task_context()->Schedule(GetExecutionContext(), event->type());

main_thread_task_runner_->PostTask(
FROM_HERE, WTF::Bind(&DecoderTemplate<Traits>::DispatchDequeueEvent,
WrapWeakPersistent(this), WrapPersistent(event)));
}

template <typename Traits>
ExecutionContext* DecoderTemplate<Traits>::GetExecutionContext() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return ExecutionContextLifecycleObserver::GetExecutionContext();
}

template <typename Traits>
void DecoderTemplate<Traits>::ContextDestroyed() {
// Deallocate resources and supress late callbacks from media thread.
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Deallocate resources and suppress late callbacks from media thread.
Shutdown();
}

Expand All @@ -743,14 +804,15 @@ void DecoderTemplate<Traits>::Trace(Visitor* visitor) const {
visitor->Trace(requests_);
visitor->Trace(pending_request_);
visitor->Trace(pending_decodes_);
ScriptWrappable::Trace(visitor);
EventTargetWithInlineData::Trace(visitor);
ExecutionContextLifecycleObserver::Trace(visitor);
ReclaimableCodec::Trace(visitor);
}

template <typename Traits>
void DecoderTemplate<Traits>::OnCodecReclaimed(DOMException* exception) {
TRACE_EVENT0(kCategory, GetTraceNames()->reclaimed.c_str());
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(is_applying_codec_pressure());

if (state_.AsEnum() == V8CodecState::Enum::kUnconfigured) {
Expand All @@ -768,6 +830,7 @@ void DecoderTemplate<Traits>::OnCodecReclaimed(DOMException* exception) {

template <typename Traits>
bool DecoderTemplate<Traits>::HasPendingActivity() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return pending_request_ || !requests_.IsEmpty();
}

Expand Down
13 changes: 12 additions & 1 deletion third_party/blink/renderer/modules/webcodecs/decoder_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#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/event_target_modules.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/webcodecs/codec_logger.h"
#include "third_party/blink/renderer/modules/webcodecs/codec_trace_names.h"
Expand All @@ -40,7 +41,7 @@ namespace blink {

template <typename Traits>
class MODULES_EXPORT DecoderTemplate
: public ScriptWrappable,
: public EventTargetWithInlineData,
public ActiveScriptWrappable<DecoderTemplate<Traits>>,
public ReclaimableCodec {
public:
Expand All @@ -59,13 +60,17 @@ class MODULES_EXPORT DecoderTemplate
~DecoderTemplate() override;

uint32_t decodeQueueSize();
DEFINE_ATTRIBUTE_EVENT_LISTENER(dequeue, kDequeue);
void configure(const ConfigType*, ExceptionState&);
void decode(const InputType*, ExceptionState&);
ScriptPromise flush(ExceptionState&);
void reset(ExceptionState&);
void close(ExceptionState&);
String state() const { return state_; }

// EventTarget override.
ExecutionContext* GetExecutionContext() const override;

// ExecutionContextLifecycleObserver override.
void ContextDestroyed() override;

Expand Down Expand Up @@ -189,6 +194,10 @@ class MODULES_EXPORT DecoderTemplate

void TraceQueueSizes() const;

void ScheduleDequeueEvent();
void DispatchDequeueEvent(Event* event);
bool dequeue_event_pending_ = false;

Member<ScriptState> script_state_;
Member<OutputCallbackType> output_cb_;
Member<V8WebCodecsErrorCallback> error_cb_;
Expand Down Expand Up @@ -235,6 +244,8 @@ class MODULES_EXPORT DecoderTemplate

// Task runner for main thread.
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;

SEQUENCE_CHECKER(sequence_checker_);
};

} // namespace blink
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,6 @@ void EncoderBase<Traits>::Trace(Visitor* visitor) const {
visitor->Trace(error_callback_);
visitor->Trace(requests_);
EventTargetWithInlineData::Trace(visitor);
ScriptWrappable::Trace(visitor);
ExecutionContextLifecycleObserver::Trace(visitor);
ReclaimableCodec::Trace(visitor);
}
Expand Down
4 changes: 4 additions & 0 deletions third_party/blink/renderer/modules/webcodecs/video_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -599,4 +599,8 @@ VideoDecoder::MakeDecoderBuffer(const InputType& chunk, bool verify_key_frame) {
return decoder_buffer;
}

const AtomicString& VideoDecoder::InterfaceName() const {
return event_target_names::kVideoDecoder;
}

} // namespace blink
3 changes: 3 additions & 0 deletions third_party/blink/renderer/modules/webcodecs/video_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ class MODULES_EXPORT VideoDecoder : public DecoderTemplate<VideoDecoderTraits> {
VideoDecoder(ScriptState*, const VideoDecoderInit*, ExceptionState&);
~VideoDecoder() override = default;

// EventTarget interface
const AtomicString& InterfaceName() const override;

protected:
bool IsValidConfig(const ConfigType& config,
String* js_error_message) override;
Expand Down
Loading

0 comments on commit 700a5d8

Please sign in to comment.