blob: 4b7cbcb6ec27e4d7404e724df4a92f6efe0c66de [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// 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_IMAGE_DECODER_EXTERNAL_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_IMAGE_DECODER_EXTERNAL_H_
#include <memory>
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.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_property.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/image_decoder_core.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/member.h"
#include "third_party/blink/renderer/platform/heap/weak_cell.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h"
#include "third_party/blink/renderer/platform/wtf/sequence_bound.h"
namespace blink {
class DOMException;
class ExceptionState;
class ScriptState;
class ImageDecodeOptions;
class ImageDecoderInit;
class ImageDecodeResult;
class ImageTrackList;
class ReadableStreamBytesConsumer;
class MODULES_EXPORT ImageDecoderExternal final
: public ScriptWrappable,
public ActiveScriptWrappable<ImageDecoderExternal>,
public BytesConsumer::Client,
public ExecutionContextLifecycleObserver {
DEFINE_WRAPPERTYPEINFO();
public:
static ImageDecoderExternal* Create(ScriptState*,
const ImageDecoderInit*,
ExceptionState&);
ImageDecoderExternal(ScriptState*, const ImageDecoderInit*, ExceptionState&);
~ImageDecoderExternal() override;
static ScriptPromise<IDLBoolean> isTypeSupported(ScriptState*, String type);
// image_decoder.idl implementation.
ScriptPromise<ImageDecodeResult> decode(
const ImageDecodeOptions* options = nullptr);
void reset(DOMException* exception = nullptr);
void close();
String type() const;
bool complete() const;
ScriptPromise<IDLUndefined> completed(ScriptState* script_state);
ImageTrackList& tracks() const;
// BytesConsumer::Client implementation.
void OnStateChange() override;
String DebugName() const override;
// GarbageCollected override.
void Trace(Visitor*) const override;
// ExecutionContextLifecycleObserver override.
void ContextDestroyed() override;
// ScriptWrappable override.
bool HasPendingActivity() const override;
// Called by ImageTrack to change the current track.
void UpdateSelectedTrack();
private:
void MaybeSatisfyPendingDecodes();
void OnDecodeReady(
std::unique_ptr<ImageDecoderCore::ImageDecodeResult> result);
void DecodeMetadata();
void OnMetadata(ImageDecoderCore::ImageMetadata metadata);
void SetFailed();
void CloseInternal(DOMException*);
Member<ScriptState> script_state_;
// Used when a ReadableStream is provided.
Member<ReadableStreamBytesConsumer> consumer_;
size_t bytes_read_ = 0u;
// Mime type provided at construction time. Cleared upon close().
String mime_type_;
// Copy of |preferAnimation| from |init_data_|.
std::optional<bool> prefer_animation_;
// Currently configured AnimationOption for |decoder_|.
ImageDecoder::AnimationOption animation_option_ =
ImageDecoder::AnimationOption::kUnspecified;
// Set to true upon ImageDecodeCore::Decode() or
// ImageDecoderCore::DecodeMetadata() failure. Once true, never cleared.
bool failed_ = false;
// Set to true either during construction or upon
// ImageDecoderCore::DecodeMetadata() indicating it has received all data.
// Once true, never cleared.
bool data_complete_ = false;
// Internal value used by OnStateChange() to ensure we don't Append() after
// the ReadableStream becomes complete.
bool internal_data_complete_ = false;
// Set to true when close() has been called. Once set, never cleared.
bool closed_ = false;
// Number of ImageDecoderCore::Decode() calls in flight. Decremented during
// OnDecodeReady() or zeroed out by reset() or close().
size_t num_submitted_decodes_ = 0u;
// Number of outstanding calls to DecodeMetadata(). Required to ensure the
// class isn't destructed while we have outstanding WeakPtrs.
int pending_metadata_requests_ = 0;
// The workhorse which actually does the decoding. Bound to another sequence.
scoped_refptr<base::SequencedTaskRunner> decode_task_runner_;
std::unique_ptr<SequenceBound<ImageDecoderCore>> decoder_;
// List of tracks in this image. Filled in during OnMetadata().
Member<ImageTrackList> tracks_;
// Set to true if we make it out of the constructor without an exception.
bool construction_succeeded_ = false;
// Pending decode() requests.
struct DecodeRequest final : public GarbageCollected<DecodeRequest> {
DecodeRequest(ScriptPromiseResolver<ImageDecodeResult>* resolver,
uint32_t frame_index,
bool complete_frames_only);
~DecodeRequest();
void Trace(Visitor*) const;
bool IsFinal() const;
Member<ScriptPromiseResolver<ImageDecodeResult>> resolver;
uint32_t frame_index;
bool complete_frames_only;
bool pending = false;
std::optional<size_t> bytes_read_index;
Member<ImageDecodeResult> result;
std::unique_ptr<base::AtomicFlag> abort_flag;
String range_error_message;
Member<DOMException> exception;
};
HeapVector<Member<DecodeRequest>> pending_decodes_;
using CompletedProperty = ScriptPromiseProperty<IDLUndefined, DOMException>;
Member<CompletedProperty> completed_property_;
// WeakPtrFactory used only for decode() requests. Invalidated upon decoding
// errors or a call to reset().
WeakCellFactory<ImageDecoderExternal> decode_weak_factory_{this};
// WeakPtrFactory for all other cancelable tasks.
WeakCellFactory<ImageDecoderExternal> weak_factory_{this};
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_IMAGE_DECODER_EXTERNAL_H_