Commit a883b84a authored by Dan Sanders's avatar Dan Sanders Committed by Commit Bot

[media] Remove Promises from WebCodecs VideoDecoder.

Bug: 897297
Change-Id: I7bc070913b53a88a9588836c424cb9f5b6fe8283
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2231593
Commit-Queue: Dan Sanders <sandersd@chromium.org>
Reviewed-by: default avatarChrome Cunningham <chcunningham@chromium.org>
Cr-Commit-Position: refs/heads/master@{#778616}
parent 1c8a83ec
......@@ -101,51 +101,45 @@ int32_t VideoDecoder::decodeQueueSize() {
return requested_decodes_;
}
int32_t VideoDecoder::decodeProcessingCount() {
return pending_decodes_.size();
}
ScriptPromise VideoDecoder::configure(const EncodedVideoConfig* config,
ExceptionState&) {
void VideoDecoder::configure(const EncodedVideoConfig* config,
ExceptionState&) {
DVLOG(1) << __func__;
Request* request = MakeGarbageCollected<Request>();
request->type = Request::Type::kConfigure;
request->config = config;
return EnqueueRequest(request);
requests_.push_back(request);
ProcessRequests();
}
ScriptPromise VideoDecoder::decode(const EncodedVideoChunk* chunk,
ExceptionState&) {
void VideoDecoder::decode(const EncodedVideoChunk* chunk, ExceptionState&) {
DVLOG(3) << __func__;
requested_decodes_++;
Request* request = MakeGarbageCollected<Request>();
request->type = Request::Type::kDecode;
request->chunk = chunk;
return EnqueueRequest(request);
requests_.push_back(request);
++requested_decodes_;
ProcessRequests();
}
ScriptPromise VideoDecoder::flush(ExceptionState&) {
DVLOG(3) << __func__;
Request* request = MakeGarbageCollected<Request>();
request->type = Request::Type::kFlush;
return EnqueueRequest(request);
ScriptPromiseResolver* resolver =
MakeGarbageCollected<ScriptPromiseResolver>(script_state_);
request->resolver = resolver;
requests_.push_back(request);
ProcessRequests();
return resolver->Promise();
}
ScriptPromise VideoDecoder::reset(ExceptionState&) {
void VideoDecoder::reset(ExceptionState&) {
DVLOG(3) << __func__;
requested_resets_++;
Request* request = MakeGarbageCollected<Request>();
request->type = Request::Type::kReset;
return EnqueueRequest(request);
}
ScriptPromise VideoDecoder::EnqueueRequest(Request* request) {
ScriptPromiseResolver* resolver =
MakeGarbageCollected<ScriptPromiseResolver>(script_state_);
request->resolver = resolver;
requests_.push_back(request);
++requested_resets_;
ProcessRequests();
return resolver->Promise();
}
void VideoDecoder::ProcessRequests() {
......@@ -191,9 +185,6 @@ bool VideoDecoder::ProcessConfigureRequest(Request* request) {
media_log_ = std::make_unique<media::NullMediaLog>();
decoder_ = CreateVideoDecoder(media_log_.get());
if (!decoder_) {
request->resolver.Release()->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotSupportedError,
"Codec initialization failed."));
// TODO(sandersd): This is a bit awkward because |request| is still in the
// queue.
HandleError();
......@@ -236,11 +227,10 @@ bool VideoDecoder::ProcessDecodeRequest(Request* request) {
DCHECK(request->chunk);
DCHECK_GT(requested_decodes_, 0);
// TODO(sandersd): If a reset has been requested, resolve immediately.
// TODO(sandersd): If a reset has been requested, complete immediately.
if (!decoder_) {
// TODO(sandersd): Add explanation (no valid configuration).
request->resolver.Release()->Reject();
// TODO(sandersd): Emit an error?
return true;
}
......@@ -348,14 +338,11 @@ void VideoDecoder::OnInitializeDone(media::Status status) {
if (!status.is_ok()) {
// TODO(tmathmeyer) this drops the media error - should we consider logging
// it or converting it to the DOMException type somehow?
pending_request_.Release()->resolver.Release()->Reject(
MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
"Codec initialization failed."));
HandleError();
return;
}
pending_request_.Release()->resolver.Release()->Resolve();
pending_request_.Release();
ProcessRequests();
}
......@@ -370,7 +357,6 @@ void VideoDecoder::OnDecodeDone(uint32_t id, media::DecodeStatus status) {
}
auto it = pending_decodes_.find(id);
it->value->resolver.Release()->Resolve();
pending_decodes_.erase(it);
ProcessRequests();
}
......@@ -394,7 +380,7 @@ void VideoDecoder::OnResetDone() {
DCHECK(pending_request_);
DCHECK_EQ(pending_request_->type, Request::Type::kReset);
pending_request_.Release()->resolver.Release()->Resolve();
pending_request_.Release();
ProcessRequests();
}
......
......@@ -43,11 +43,10 @@ class MODULES_EXPORT VideoDecoder final : public ScriptWrappable {
// video_decoder.idl implementation.
int32_t decodeQueueSize();
int32_t decodeProcessingCount();
ScriptPromise configure(const EncodedVideoConfig*, ExceptionState&);
ScriptPromise decode(const EncodedVideoChunk*, ExceptionState&);
void configure(const EncodedVideoConfig*, ExceptionState&);
void decode(const EncodedVideoChunk*, ExceptionState&);
ScriptPromise flush(ExceptionState&);
ScriptPromise reset(ExceptionState&);
void reset(ExceptionState&);
// GarbageCollected override.
void Trace(Visitor*) const override;
......@@ -64,8 +63,14 @@ class MODULES_EXPORT VideoDecoder final : public ScriptWrappable {
void Trace(Visitor*) const;
Type type;
// For kConfigure Requests.
Member<const EncodedVideoConfig> config;
// For kDecode Requests.
Member<const EncodedVideoChunk> chunk;
// For kFlush Requests.
Member<ScriptPromiseResolver> resolver;
};
......
......@@ -21,69 +21,50 @@
// When in an error state, methods other than reset() will fail.
//
// TODO(sandersd): Consider adding a state or last error attribute.
// TODO(sandersd): Consider aborting pending decodes on error, rather than
// waiting for reset().
[CallWith=ScriptState, RaisesException] constructor(VideoDecoderInit init);
// The number of queued decode requests. This does not include requests that
// have been taken for processing.
// The number of pending decode requests. This does not include requests that
// have been sent to the underlying codec.
//
// Applications can minimize underflow by enqueueing decode requests until
// |decodeQueueSize| is greater than a constant.
readonly attribute long decodeQueueSize;
// The number of decode requests currently being processed.
//
// Applications can minimize resource consumption and decode latency by
// enqueueing decode requests only when |decodeQueueSize| and
// |decodeProcessingCount| are small.
//
// TODO(sandersd): Consider counting queued decode requests as well. This
// could be simpler for apps.
readonly attribute long decodeProcessingCount;
// TODO(sandersd): Consider adding a predicted output count or other
// backpressure mechanism that considers the state of the underlying codec.
// TODO(sandersd): Consider emitting an event when this number decreases.
readonly attribute long decodeQueueSize;
// Enqueue a request to set or change the stream configuration.
// Set the stream configuration for future decode() requests.
//
// The next enqueued decode request must be for a keyframe.
// The next decode request must be for a keyframe.
//
// Resolved after emitting output for all earlier decode requests.
//
// TODO(sandersd): Test that resolution (a microtask) interleaves between
// outputs callback calls in all cases.
// TODO(sandersd): Move the keyframe rule into the bytestream registry.
[RaisesException] Promise<void> configure(EncodedVideoConfig config);
[RaisesException] void configure(EncodedVideoConfig config);
// Enqueue a request to decode an input chunk.
//
// You must call configure() before calling enqueue() for the first time.
// Request decoding of an input chunk.
//
// Resolved after decoding of the input chunk has started (that is, after
// decreasing |decodeQueueSize|).
// You must call configure() before calling decode() for the first time.
//
// TODO(sandersd): Change to a dictionary type.
// TODO(sandersd): Should we guarantee that resolution occurs in order?
// TODO(sandersd): Add status to result.
// TODO(sandersd): Buffer return.
[RaisesException] Promise<void> decode(EncodedVideoChunk chunk);
[RaisesException] void decode(EncodedVideoChunk chunk);
// Enqueue a request to finish decoding queued input chunks.
// Request output from all previous decode requests.
//
// The next enqueued input chunk must be a keyframe.
// Resolved after all output for earlier decode requests has been emitted.
//
// Resolved after emitting output for all earlier decode requests.
// The next decode request must be for a keyframe.
//
// TODO(sandersd): Consider relaxing the keyframe requirement.
// TODO(sandersd): Indicate whether the flush() completed successfully or due
// to a reset.
[RaisesException] Promise<void> flush();
// Discard all pending work.
//
// Output for earlier decode requests will not be emitted, even if processing
// has already started.
//
// The next enqueued input chunk must be a keyframe.
// Discard all pending decode requests.
//
// Resolved after all earlier enqueue() promises have been resolved.
// The next decode request must be for a keyframe.
//
// TODO(sandersd): Require configure() after reset()?
[RaisesException] Promise<void> reset();
// Note: It may be possible to call reset() after a flush() promise has been
// resolved but before it is fulfilled. In that case the flush() promise will
// be fulfilled successfully even though reset() was called.
[RaisesException] void reset();
};
......@@ -8720,7 +8720,6 @@ interface ValidityState
method constructor
interface VideoDecoder
attribute @@toStringTag
getter decodeProcessingCount
getter decodeQueueSize
method configure
method constructor
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment