Backed out 3 changesets (bug 1901078, bug 1749048) for causing interface related mochitests failures. CLOSED TREE

Backed out changeset 0c7ce075a24f (bug 1749048)
Backed out changeset 0b609b8fcff3 (bug 1749048)
Backed out changeset 18ce2638e512 (bug 1901078)
This commit is contained in:
Stanca Serban 2024-07-23 21:50:08 +03:00
parent 16285037d4
commit b3c85ac11d
31 changed files with 847 additions and 2972 deletions

View File

@ -4,7 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ImageUtils.h"
#include "ImageUtils.h"
#include "ImageContainer.h"
#include "Intervals.h"

View File

@ -1,62 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaResult.h"
#include "mozilla/Assertions.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/Promise.h"
namespace mozilla {
#define EXTENDED_EXCEPTIONS \
DOMEXCEPTION(AbortError, NS_ERROR_ABORT); \
DOMEXCEPTION(AbortError, NS_ERROR_DOM_MEDIA_ABORT_ERR); \
DOMEXCEPTION(RangeError, NS_ERROR_DOM_MEDIA_RANGE_ERR); \
DOMEXCEPTION(NotAllowedError, NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR); \
DOMEXCEPTION(NotSupportedError, NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR); \
DOMEXCEPTION(TypeError, NS_ERROR_DOM_MEDIA_TYPE_ERR);
void MediaResult::ThrowTo(ErrorResult& aRv) const {
switch (mCode) {
#define DOMEXCEPTION(name, code) \
case code: \
aRv.Throw##name(mMessage); \
break;
#include "mozilla/dom/DOMExceptionNames.h"
EXTENDED_EXCEPTIONS
default:
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
MOZ_CRASH_UNSAFE_PRINTF("Unhandled result 0x%08x",
static_cast<uint32_t>(mCode));
#endif
aRv.ThrowUnknownError(mMessage);
break;
}
#undef DOMEXCEPTION
}
void MediaResult::RejectTo(dom::Promise* aPromise) const {
switch (mCode) {
#define DOMEXCEPTION(name, code) \
case code: \
aPromise->MaybeRejectWith##name(mMessage); \
break;
#include "mozilla/dom/DOMExceptionNames.h"
EXTENDED_EXCEPTIONS
default:
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
MOZ_CRASH_UNSAFE_PRINTF("Unhandled result 0x%08x",
static_cast<uint32_t>(mCode));
#endif
aPromise->MaybeRejectWithUnknownError(mMessage);
break;
}
#undef DOMEXCEPTION
}
} // namespace mozilla

View File

@ -19,12 +19,7 @@
// MediaResult const references is recommended.
namespace mozilla {
namespace dom {
class Promise;
}
class CDMProxy;
class ErrorResult;
class MediaResult {
public:
@ -68,9 +63,6 @@ class MediaResult {
CDMProxy* GetCDMProxy() const { return mCDMProxy; }
void ThrowTo(ErrorResult& aRv) const;
void RejectTo(dom::Promise* aPromise) const;
private:
nsresult mCode;
nsCString mMessage;

View File

@ -297,7 +297,6 @@ UNIFIED_SOURCES += [
"MediaPlaybackDelayPolicy.cpp",
"MediaRecorder.cpp",
"MediaResource.cpp",
"MediaResult.cpp",
"MediaShutdownManager.cpp",
"MediaStreamError.cpp",
"MediaStreamTrack.cpp",

File diff suppressed because it is too large Load Diff

View File

@ -1,159 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_ImageDecoder_h
#define mozilla_dom_ImageDecoder_h
#include "FrameTimeout.h"
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/NotNull.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/dom/ImageDecoderBinding.h"
#include "mozilla/dom/WebCodecsUtils.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
class nsIGlobalObject;
namespace mozilla {
class MediaResult;
namespace image {
class AnonymousDecoder;
class SourceBuffer;
enum class DecoderType;
enum class SurfaceFlags : uint8_t;
struct DecodeFramesResult;
struct DecodeFrameCountResult;
struct DecodeMetadataResult;
} // namespace image
namespace dom {
class Promise;
struct ImageDecoderReadRequest;
class ImageDecoder final : public nsISupports,
public nsWrapperCache,
public SupportsWeakPtr {
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ImageDecoder)
public:
ImageDecoder(nsCOMPtr<nsIGlobalObject>&& aParent, const nsAString& aType);
public:
nsIGlobalObject* GetParentObject() const { return mParent; }
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
static already_AddRefed<ImageDecoder> Constructor(
const GlobalObject& aGlobal, const ImageDecoderInit& aInit,
ErrorResult& aRv);
static already_AddRefed<Promise> IsTypeSupported(const GlobalObject& aGlobal,
const nsAString& aType,
ErrorResult& aRv);
void GetType(nsAString& aType) const;
bool Complete() const { return mComplete; }
Promise* Completed() const { return mCompletePromise; }
ImageTrackList* Tracks() const { return mTracks; }
already_AddRefed<Promise> Decode(const ImageDecodeOptions& aOptions,
ErrorResult& aRv);
void Reset();
void Close();
void OnSourceBufferComplete(const MediaResult& aResult);
void QueueSelectTrackMessage(uint32_t aSelectedIndex);
void ProcessControlMessageQueue();
private:
~ImageDecoder();
class ControlMessage;
class ConfigureMessage;
class DecodeMetadataMessage;
class DecodeFrameMessage;
class SelectTrackMessage;
std::queue<UniquePtr<ControlMessage>> mControlMessageQueue;
bool mMessageQueueBlocked = false;
bool mTracksEstablished = false;
struct OutstandingDecode {
RefPtr<Promise> mPromise;
uint32_t mFrameIndex = 0;
bool mCompleteFramesOnly = true;
};
// VideoFrame can run on either main thread or worker thread.
void AssertIsOnOwningThread() const { NS_ASSERT_OWNINGTHREAD(ImageDecoder); }
void Initialize(const GlobalObject& aGLobal, const ImageDecoderInit& aInit,
ErrorResult& aRv);
void Destroy();
void Reset(const MediaResult& aResult);
void Close(const MediaResult& aResult);
void QueueConfigureMessage(ColorSpaceConversion aColorSpaceConversion);
void QueueDecodeMetadataMessage();
void QueueDecodeFrameMessage();
void ResumeControlMessageQueue();
MessageProcessedResult ProcessConfigureMessage(ConfigureMessage* aMsg);
MessageProcessedResult ProcessDecodeMetadataMessage(
DecodeMetadataMessage* aMsg);
MessageProcessedResult ProcessDecodeFrameMessage(DecodeFrameMessage* aMsg);
MessageProcessedResult ProcessSelectTrackMessage(SelectTrackMessage* aMsg);
void CheckOutstandingDecodes();
void OnCompleteSuccess();
void OnCompleteFailed(const MediaResult& aResult);
void OnMetadataSuccess(const image::DecodeMetadataResult& aMetadata);
void OnMetadataFailed(const nsresult& aErr);
void RequestFrameCount(uint32_t aKnownFrameCount);
void OnFrameCountSuccess(const image::DecodeFrameCountResult& aResult);
void OnFrameCountFailed(const nsresult& aErr);
void RequestDecodeFrames(uint32_t aFramesToDecode);
void OnDecodeFramesSuccess(const image::DecodeFramesResult& aResult);
void OnDecodeFramesFailed(const nsresult& aErr);
nsCOMPtr<nsIGlobalObject> mParent;
RefPtr<ImageTrackList> mTracks;
RefPtr<ImageDecoderReadRequest> mReadRequest;
RefPtr<Promise> mCompletePromise;
RefPtr<image::SourceBuffer> mSourceBuffer;
RefPtr<image::AnonymousDecoder> mDecoder;
AutoTArray<OutstandingDecode, 1> mOutstandingDecodes;
nsAutoString mType;
image::FrameTimeout mFramesTimestamp;
bool mComplete = false;
bool mHasFrameCount = false;
bool mHasFramePending = false;
bool mTypeNotSupported = false;
bool mClosed = false;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ImageDecoder_h

View File

@ -1,294 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ImageDecoderReadRequest.h"
#include "MediaResult.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/dom/ImageDecoder.h"
#include "mozilla/dom/ReadableStream.h"
#include "mozilla/dom/ReadableStreamDefaultReader.h"
#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/dom/WorkerRef.h"
#include "mozilla/image/SourceBuffer.h"
#include "mozilla/Logging.h"
extern mozilla::LazyLogModule gWebCodecsLog;
namespace mozilla::dom {
NS_IMPL_CYCLE_COLLECTION_INHERITED(ImageDecoderReadRequest, ReadRequest,
mDecoder, mReader)
NS_IMPL_ADDREF_INHERITED(ImageDecoderReadRequest, ReadRequest)
NS_IMPL_RELEASE_INHERITED(ImageDecoderReadRequest, ReadRequest)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ImageDecoderReadRequest)
NS_INTERFACE_MAP_END_INHERITING(ReadRequest)
ImageDecoderReadRequest::ImageDecoderReadRequest(
image::SourceBuffer* aSourceBuffer)
: mSourceBuffer(std::move(aSourceBuffer)) {
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p ImageDecoderReadRequest", this));
}
ImageDecoderReadRequest::~ImageDecoderReadRequest() {
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p ~ImageDecoderReadRequest", this));
}
bool ImageDecoderReadRequest::Initialize(const GlobalObject& aGlobal,
ImageDecoder* aDecoder,
ReadableStream& aStream) {
if (WorkerPrivate* wp = GetCurrentThreadWorkerPrivate()) {
mWorkerRef = WeakWorkerRef::Create(wp, [self = RefPtr{this}]() {
self->Destroy(/* aCycleCollect */ false);
});
if (NS_WARN_IF(!mWorkerRef)) {
MOZ_LOG(gWebCodecsLog, LogLevel::Error,
("ImageDecoderReadRequest %p Initialize -- cannot get worker ref",
this));
mSourceBuffer->Complete(NS_ERROR_FAILURE);
Destroy(/* aCycleCollect */ false);
return false;
}
}
IgnoredErrorResult rv;
mReader = aStream.GetReader(rv);
if (NS_WARN_IF(rv.Failed())) {
MOZ_LOG(
gWebCodecsLog, LogLevel::Error,
("ImageDecoderReadRequest %p Initialize -- cannot get stream reader",
this));
mSourceBuffer->Complete(NS_ERROR_FAILURE);
Destroy(/* aCycleCollect */ false);
return false;
}
mDecoder = aDecoder;
QueueRead();
return true;
}
void ImageDecoderReadRequest::Destroy(bool aCycleCollect /* = true */) {
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p Destroy", this));
if (!aCycleCollect) {
// Ensure we stop reading from the ReadableStream.
Cancel();
}
if (mSourceBuffer) {
if (!mSourceBuffer->IsComplete()) {
mSourceBuffer->Complete(NS_ERROR_ABORT);
}
mSourceBuffer = nullptr;
}
mDecoder = nullptr;
mReader = nullptr;
}
void ImageDecoderReadRequest::QueueRead() {
class ReadRunnable final : public CancelableRunnable {
public:
explicit ReadRunnable(ImageDecoderReadRequest* aOwner)
: CancelableRunnable(
"mozilla::dom::ImageDecoderReadRequest::QueueRead"),
mOwner(aOwner) {}
NS_IMETHODIMP Run() override {
mOwner->Read();
mOwner = nullptr;
return NS_OK;
}
nsresult Cancel() override {
mOwner->Complete(
MediaResult(NS_ERROR_DOM_MEDIA_ABORT_ERR, "Read cancelled"_ns));
mOwner = nullptr;
return NS_OK;
}
private:
virtual ~ReadRunnable() {
if (mOwner) {
Cancel();
}
}
RefPtr<ImageDecoderReadRequest> mOwner;
};
if (!mReader) {
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p QueueRead -- destroyed", this));
return;
}
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p QueueRead -- queue", this));
auto task = MakeRefPtr<ReadRunnable>(this);
NS_DispatchToCurrentThread(task.forget());
}
void ImageDecoderReadRequest::Read() {
if (!mReader || !mDecoder) {
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p Read -- destroyed", this));
return;
}
AutoJSAPI jsapi;
if (!jsapi.Init(mDecoder->GetParentObject())) {
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p Read -- no jsapi", this));
Complete(MediaResult(NS_ERROR_DOM_FILE_NOT_READABLE_ERR,
"Reader cannot init jsapi"_ns));
return;
}
RefPtr<ImageDecoderReadRequest> self(this);
RefPtr<ReadableStreamDefaultReader> reader(mReader);
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p Read -- begin read chunk", this));
IgnoredErrorResult err;
reader->ReadChunk(jsapi.cx(), *self, err);
if (NS_WARN_IF(err.Failed())) {
MOZ_LOG(gWebCodecsLog, LogLevel::Error,
("ImageDecoderReadRequest %p Read -- read chunk failed", this));
Complete(MediaResult(NS_ERROR_DOM_FILE_NOT_READABLE_ERR,
"Reader cannot read chunk from stream"_ns));
}
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p Read -- end read chunk", this));
}
void ImageDecoderReadRequest::Cancel() {
RefPtr<ReadableStreamDefaultReader> reader = std::move(mReader);
if (!reader || !mDecoder) {
return;
}
RefPtr<ImageDecoderReadRequest> self(this);
AutoJSAPI jsapi;
if (!jsapi.Init(mDecoder->GetParentObject())) {
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p Cancel -- no jsapi", this));
return;
}
ErrorResult rv;
rv.ThrowAbortError("ImageDecoderReadRequest destroyed");
JS::Rooted<JS::Value> errorValue(jsapi.cx());
if (ToJSValue(jsapi.cx(), std::move(rv), &errorValue)) {
IgnoredErrorResult ignoredRv;
if (RefPtr<Promise> p = reader->Cancel(jsapi.cx(), errorValue, ignoredRv)) {
MOZ_ALWAYS_TRUE(p->SetAnyPromiseIsHandled());
}
}
jsapi.ClearException();
}
void ImageDecoderReadRequest::Complete(const MediaResult& aResult) {
if (!mReader) {
return;
}
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p Read -- complete, success %d", this,
NS_SUCCEEDED(aResult.Code())));
if (mSourceBuffer && !mSourceBuffer->IsComplete()) {
mSourceBuffer->Complete(aResult.Code());
}
if (mDecoder) {
mDecoder->OnSourceBufferComplete(aResult);
}
Destroy(/* aCycleComplete */ false);
}
void ImageDecoderReadRequest::ChunkSteps(JSContext* aCx,
JS::Handle<JS::Value> aChunk,
ErrorResult& aRv) {
// 10.2.5. Fetch Stream Data Loop (with reader) - chunk steps
// 1. If [[closed]] is true, abort these steps.
if (!mSourceBuffer) {
return;
}
// 2. If chunk is not a Uint8Array object, queue a task to run the Close
// ImageDecoder algorithm with a DataError DOMException and abort these steps.
RootedSpiderMonkeyInterface<Uint8Array> chunk(aCx);
if (!aChunk.isObject() || !chunk.Init(&aChunk.toObject())) {
MOZ_LOG(gWebCodecsLog, LogLevel::Error,
("ImageDecoderReadRequest %p ChunkSteps -- bad chunk", this));
Complete(MediaResult(NS_ERROR_DOM_DATA_ERR,
"Reader cannot read chunk from stream"_ns));
return;
}
chunk.ProcessData([&](const Span<uint8_t>& aData, JS::AutoCheckCannotGC&&) {
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p ChunkSteps -- write %zu bytes", this,
aData.Length()));
// 3. Let bytes be the byte sequence represented by the Uint8Array object.
// 4. Append bytes to the [[encoded data]] internal slot.
nsresult rv = mSourceBuffer->Append(
reinterpret_cast<const char*>(aData.Elements()), aData.Length());
if (NS_WARN_IF(NS_FAILED(rv))) {
MOZ_LOG(
gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p ChunkSteps -- failed to append", this));
Complete(MediaResult(NS_ERROR_DOM_UNKNOWN_ERR,
"Reader cannot allocate storage for chunk"_ns));
}
// 5. If [[tracks established]] is false, run the Establish Tracks
// algorithm.
// 6. Otherwise, run the Update Tracks algorithm.
//
// Note that these steps will be triggered by the decoder promise callbacks.
});
// 7. Run the Fetch Stream Data Loop algorithm with reader.
QueueRead();
}
void ImageDecoderReadRequest::CloseSteps(JSContext* aCx, ErrorResult& aRv) {
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p CloseSteps", this));
// 10.2.5. Fetch Stream Data Loop (with reader) - close steps
// 1. Assign true to [[complete]]
// 2. Resolve [[completed promise]].
Complete(MediaResult(NS_OK));
}
void ImageDecoderReadRequest::ErrorSteps(JSContext* aCx,
JS::Handle<JS::Value> aError,
ErrorResult& aRv) {
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageDecoderReadRequest %p ErrorSteps", this));
// 10.2.5. Fetch Stream Data Loop (with reader) - error steps
// 1. Queue a task to run the Close ImageDecoder algorithm with a
// NotReadableError DOMException
Complete(MediaResult(NS_ERROR_DOM_FILE_NOT_READABLE_ERR,
"Reader failed while waiting for chunk from stream"_ns));
}
} // namespace mozilla::dom

View File

@ -1,66 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_ImageDecoderReadRequest_h
#define mozilla_dom_ImageDecoderReadRequest_h
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/ReadRequest.h"
namespace mozilla {
class MediaResult;
namespace image {
class SourceBuffer;
}
namespace dom {
class ImageDecoder;
class ReadableStream;
class ReadableStreamDefaultReader;
class WeakWorkerRef;
struct ImageDecoderReadRequest final : public ReadRequest {
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ImageDecoderReadRequest, ReadRequest)
public:
explicit ImageDecoderReadRequest(image::SourceBuffer* aSourceBuffer);
bool Initialize(const GlobalObject& aGlobal, ImageDecoder* aDecoder,
ReadableStream& aStream);
void Destroy(bool aCycleCollect = true);
MOZ_CAN_RUN_SCRIPT_BOUNDARY void ChunkSteps(JSContext* aCx,
JS::Handle<JS::Value> aChunk,
ErrorResult& aRv) override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY void CloseSteps(JSContext* aCx,
ErrorResult& aRv) override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY void ErrorSteps(JSContext* aCx,
JS::Handle<JS::Value> aError,
ErrorResult& aRv) override;
private:
~ImageDecoderReadRequest() override;
void QueueRead();
MOZ_CAN_RUN_SCRIPT_BOUNDARY void Read();
MOZ_CAN_RUN_SCRIPT_BOUNDARY void Cancel();
void Complete(const MediaResult& aResult);
RefPtr<WeakWorkerRef> mWorkerRef;
RefPtr<ImageDecoder> mDecoder;
RefPtr<ReadableStreamDefaultReader> mReader;
RefPtr<image::SourceBuffer> mSourceBuffer;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ImageDecoderReadRequest_h

View File

@ -1,107 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ImageTrack.h"
#include "ImageContainer.h"
#include "mozilla/dom/ImageTrackList.h"
#include "mozilla/dom/WebCodecsUtils.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/image/ImageUtils.h"
extern mozilla::LazyLogModule gWebCodecsLog;
namespace mozilla::dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ImageTrack, mParent, mTrackList,
mDecodedFrames)
NS_IMPL_CYCLE_COLLECTING_ADDREF(ImageTrack)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ImageTrack)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ImageTrack)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
ImageTrack::ImageTrack(ImageTrackList* aTrackList, int32_t aIndex,
bool aSelected, bool aAnimated, uint32_t aFrameCount,
bool aFrameCountComplete, float aRepetitionCount)
: mParent(aTrackList->GetParentObject()),
mTrackList(aTrackList),
mFramesTimestamp(image::FrameTimeout::Zero()),
mIndex(aIndex),
mRepetitionCount(aRepetitionCount),
mFrameCount(aFrameCount),
mFrameCountComplete(aFrameCountComplete),
mAnimated(aAnimated),
mSelected(aSelected) {}
ImageTrack::~ImageTrack() = default;
void ImageTrack::Destroy() { mTrackList = nullptr; }
JSObject* ImageTrack::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
AssertIsOnOwningThread();
return ImageTrack_Binding::Wrap(aCx, this, aGivenProto);
}
void ImageTrack::SetSelected(bool aSelected) {
if (mTrackList) {
mTrackList->SetSelectedIndex(mIndex, aSelected);
}
}
void ImageTrack::OnFrameCountSuccess(
const image::DecodeFrameCountResult& aResult) {
MOZ_ASSERT_IF(mFrameCountComplete, mFrameCount == aResult.mFrameCount);
MOZ_ASSERT_IF(!aResult.mFinished, !mFrameCountComplete);
MOZ_ASSERT_IF(!mAnimated, aResult.mFrameCount <= 1);
MOZ_ASSERT(aResult.mFrameCount >= mFrameCount);
mFrameCount = aResult.mFrameCount;
mFrameCountComplete = aResult.mFinished;
}
void ImageTrack::OnDecodeFramesSuccess(
const image::DecodeFramesResult& aResult) {
MOZ_LOG(gWebCodecsLog, LogLevel::Debug,
("ImageTrack %p OnDecodeFramesSuccess -- decoded %zu frames, %zu "
"total, finished %d",
this, aResult.mFrames.Length(), mDecodedFrames.Length(),
aResult.mFinished));
mDecodedFrames.SetCapacity(mDecodedFrames.Length() +
aResult.mFrames.Length());
for (const auto& f : aResult.mFrames) {
VideoColorSpaceInit colorSpace;
gfx::IntSize size = f.mSurface->GetSize();
gfx::IntRect rect(gfx::IntPoint(0, 0), size);
Maybe<VideoPixelFormat> format =
SurfaceFormatToVideoPixelFormat(f.mSurface->GetFormat());
MOZ_ASSERT(format, "Unexpected format for image!");
Maybe<uint64_t> duration;
if (f.mTimeout != image::FrameTimeout::Forever()) {
duration =
Some(static_cast<uint64_t>(f.mTimeout.AsMilliseconds()) * 1000);
}
uint64_t timestamp = UINT64_MAX;
if (mFramesTimestamp != image::FrameTimeout::Forever()) {
timestamp =
static_cast<uint64_t>(mFramesTimestamp.AsMilliseconds()) * 1000;
}
mFramesTimestamp += f.mTimeout;
auto image = MakeRefPtr<layers::SourceSurfaceImage>(size, f.mSurface);
auto frame = MakeRefPtr<VideoFrame>(mParent, image, format, size, rect,
size, duration, timestamp, colorSpace);
mDecodedFrames.AppendElement(std::move(frame));
}
}
} // namespace mozilla::dom

View File

@ -1,100 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_ImageTrack_h
#define mozilla_dom_ImageTrack_h
#include "FrameTimeout.h"
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/NotNull.h"
#include "mozilla/dom/ImageDecoderBinding.h"
#include "nsCycleCollectionParticipant.h"
#include "nsTArray.h"
#include "nsWrapperCache.h"
class nsIGlobalObject;
namespace mozilla {
namespace image {
struct DecodeFrameCountResult;
struct DecodeFramesResult;
} // namespace image
namespace dom {
class ImageTrackList;
class VideoFrame;
class ImageTrack final : public nsISupports, public nsWrapperCache {
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ImageTrack)
public:
ImageTrack(ImageTrackList* aTrackList, int32_t aIndex, bool aSelected,
bool aAnimated, uint32_t aFrameCount, bool aFrameCountComplete,
float aRepetitionCount);
protected:
~ImageTrack();
public:
nsIGlobalObject* GetParentObject() const { return mParent; }
void Destroy();
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
int32_t Index() const { return mIndex; }
bool Animated() const { return mAnimated; }
uint32_t FrameCount() const { return mFrameCount; }
bool FrameCountComplete() const { return mFrameCountComplete; }
float RepetitionCount() const { return mRepetitionCount; }
bool Selected() const { return mSelected; }
void SetSelected(bool aSelected);
void ClearSelected() { mSelected = false; }
void MarkSelected() { mSelected = true; }
size_t DecodedFrameCount() const { return mDecodedFrames.Length(); }
VideoFrame* GetDecodedFrame(uint32_t aIndex) const {
if (mDecodedFrames.Length() <= aIndex) {
return nullptr;
}
return mDecodedFrames[aIndex];
}
void OnFrameCountSuccess(const image::DecodeFrameCountResult& aResult);
void OnDecodeFramesSuccess(const image::DecodeFramesResult& aResult);
private:
// ImageTrack can run on either main thread or worker thread.
void AssertIsOnOwningThread() const { NS_ASSERT_OWNINGTHREAD(ImageTrack); }
nsCOMPtr<nsIGlobalObject> mParent;
RefPtr<ImageTrackList> mTrackList;
AutoTArray<RefPtr<VideoFrame>, 1> mDecodedFrames;
image::FrameTimeout mFramesTimestamp;
int32_t mIndex = 0;
float mRepetitionCount = 0.0f;
uint32_t mFrameCount = 0;
bool mFrameCountComplete = false;
bool mAnimated = false;
bool mSelected = false;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ImageTrack_h

View File

@ -1,206 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ImageTrackList.h"
#include "MediaResult.h"
#include "mozilla/dom/ImageDecoder.h"
#include "mozilla/dom/ImageTrack.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/image/ImageUtils.h"
namespace mozilla::dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ImageTrackList, mParent, mDecoder,
mReadyPromise, mTracks)
NS_IMPL_CYCLE_COLLECTING_ADDREF(ImageTrackList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ImageTrackList)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ImageTrackList)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
ImageTrackList::ImageTrackList(nsIGlobalObject* aParent, ImageDecoder* aDecoder)
: mParent(aParent), mDecoder(aDecoder) {}
ImageTrackList::~ImageTrackList() = default;
JSObject* ImageTrackList::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
AssertIsOnOwningThread();
return ImageTrackList_Binding::Wrap(aCx, this, aGivenProto);
}
void ImageTrackList::Initialize(ErrorResult& aRv) {
mReadyPromise = Promise::Create(mParent, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
}
void ImageTrackList::Destroy() {
if (!mIsReady && mReadyPromise && mReadyPromise->PromiseObj()) {
mReadyPromise->MaybeRejectWithAbortError("ImageTrackList destroyed");
mIsReady = true;
}
for (auto& track : mTracks) {
track->Destroy();
}
mTracks.Clear();
mDecoder = nullptr;
mSelectedIndex = -1;
}
void ImageTrackList::MaybeRejectReady(const MediaResult& aResult) {
if (mIsReady || !mReadyPromise || !mReadyPromise->PromiseObj()) {
return;
}
aResult.RejectTo(mReadyPromise);
mIsReady = true;
}
void ImageTrackList::OnMetadataSuccess(
const image::DecodeMetadataResult& aMetadata) {
// 10.2.5. Establish Tracks
//
// Note that our implementation only supports one track, so many of these
// steps are simplified.
// 4. Let newTrackList be a new list.
MOZ_ASSERT(mTracks.IsEmpty());
// 5. For each image track found in [[encoded data]]:
// 5.1. Let newTrack be a new ImageTrack, initialized as follows:
// 5.1.1. Assign this to [[ImageDecoder]].
// 5.1.2. Assign tracks to [[ImageTrackList]].
// 5.1.3. If image track is found to be animated, assign true to newTrack's
// [[animated]] internal slot. Otherwise, assign false.
// 5.1.4. If image track is found to describe a frame count, assign that
// count to newTrack's [[frame count]] internal slot. Otherwise, assign
// 0.
// 5.1.5. If image track is found to describe a repetition count, assign that
// count to [[repetition count]] internal slot. Otherwise, assign 0.
// 5.1.6. Assign false to newTracks [[selected]] internal slot.
// 5.2. Append newTrack to newTrackList.
// 6. Let selectedTrackIndex be the result of running the Get Default Selected
// Track Index algorithm with newTrackList.
// 7. Let selectedTrack be the track at position selectedTrackIndex within
// newTrackList.
// 8. Assign true to selectedTracks [[selected]] internal slot.
// 9. Assign selectedTrackIndex to [[internal selected track index]].
const float repetitions = aMetadata.mRepetitions < 0
? std::numeric_limits<float>::infinity()
: static_cast<float>(aMetadata.mRepetitions);
auto track = MakeRefPtr<ImageTrack>(
this, /* aIndex */ 0, /* aSelected */ true, aMetadata.mAnimated,
aMetadata.mFrameCount, aMetadata.mFrameCountComplete, repetitions);
// 11. Queue a task to perform the following steps:
//
// Note that we were already dispatched by the image decoder.
// 11.1. Assign newTrackList to the tracks [[track list]] internal slot.
mTracks.AppendElement(std::move(track));
// 11.2. Assign selectedTrackIndex to tracks [[selected index]].
mSelectedIndex = 0;
// 11.3. Resolve [[ready promise]].
MOZ_ASSERT(!mIsReady);
mReadyPromise->MaybeResolveWithUndefined();
mIsReady = true;
}
void ImageTrackList::OnFrameCountSuccess(
const image::DecodeFrameCountResult& aResult) {
if (mTracks.IsEmpty()) {
return;
}
// 10.2.5. Update Tracks
//
// Note that we were already dispatched from the decoding threads.
// 3. Let trackList be a copy of tracks' [[track list]].
// 4. For each track in trackList:
// 4.1. Let trackIndex be the position of track in trackList.
// 4.2. Let latestFrameCount be the frame count as indicated by
// [[encoded data]] for the track corresponding to track.
// 4.3. Assert that latestFrameCount is greater than or equal to
// track.frameCount.
// 4.4. If latestFrameCount is greater than track.frameCount:
// 4.4.1. Let change be a track update struct whose track index is trackIndex
// and frame count is latestFrameCount.
// 4.4.2. Append change to tracksChanges.
// 5. If tracksChanges is empty, abort these steps.
// 6. Queue a task to perform the following steps:
// 6.1. For each update in trackChanges:
// 6.1.1. Let updateTrack be the ImageTrack at position update.trackIndex
// within tracks' [[track list]].
// 6.1.2. Assign update.frameCount to updateTracks [[frame count]].
mTracks.LastElement()->OnFrameCountSuccess(aResult);
}
void ImageTrackList::SetSelectedIndex(int32_t aIndex, bool aSelected) {
MOZ_ASSERT(aIndex >= 0);
MOZ_ASSERT(uint32_t(aIndex) < mTracks.Length());
// 10.7.2. Attributes - selected, of type boolean
// 1. If [[ImageDecoder]]'s [[closed]] slot is true, abort these steps.
if (!mDecoder) {
return;
}
// 2. Let newValue be the given value.
// 3. If newValue equals [[selected]], abort these steps.
// 4. Assign newValue to [[selected]].
// 5. Let parentTrackList be [[ImageTrackList]]
// 6. Let oldSelectedIndex be the value of parentTrackList [[selected index]].
// 7. If oldSelectedIndex is not -1:
// 7.1. Let oldSelectedTrack be the ImageTrack in parentTrackList
// [[track list]] at the position of oldSelectedIndex.
// 7.2. Assign false to oldSelectedTrack [[selected]]
// 8. If newValue is true, let selectedIndex be the index of this ImageTrack
// within parentTrackList's [[track list]]. Otherwise, let selectedIndex be
// -1.
// 9. Assign selectedIndex to parentTrackList [[selected index]].
if (aSelected) {
if (mSelectedIndex == -1) {
MOZ_ASSERT(!mTracks[aIndex]->Selected());
mTracks[aIndex]->MarkSelected();
mSelectedIndex = aIndex;
} else if (mSelectedIndex != aIndex) {
MOZ_ASSERT(mTracks[mSelectedIndex]->Selected());
MOZ_ASSERT(!mTracks[aIndex]->Selected());
mTracks[mSelectedIndex]->ClearSelected();
mTracks[aIndex]->MarkSelected();
mSelectedIndex = aIndex;
} else {
MOZ_ASSERT(mTracks[mSelectedIndex]->Selected());
return;
}
} else if (mSelectedIndex == aIndex) {
mTracks[mSelectedIndex]->ClearSelected();
mSelectedIndex = -1;
} else {
MOZ_ASSERT(!mTracks[aIndex]->Selected());
return;
}
// 10. Run the Reset ImageDecoder algorithm on [[ImageDecoder]].
mDecoder->Reset();
// 11. Queue a control message to [[ImageDecoder]]'s control message queue to
// update the internal selected track index with selectedIndex.
mDecoder->QueueSelectTrackMessage(mSelectedIndex);
// 12. Process the control message queue belonging to [[ImageDecoder]].
mDecoder->ProcessControlMessageQueue();
}
} // namespace mozilla::dom

View File

@ -1,104 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_ImageTrackList_h
#define mozilla_dom_ImageTrackList_h
#include "mozilla/Attributes.h"
#include "mozilla/dom/ImageDecoderBinding.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
class nsIGlobalObject;
namespace mozilla {
class MediaResult;
namespace image {
struct DecodeFrameCountResult;
struct DecodeMetadataResult;
} // namespace image
namespace dom {
class ImageTrack;
class Promise;
class ImageTrackList final : public nsISupports, public nsWrapperCache {
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ImageTrackList)
public:
ImageTrackList(nsIGlobalObject* aParent, ImageDecoder* aDecoder);
void Initialize(ErrorResult& aRv);
void MaybeRejectReady(const MediaResult& aResult);
void Destroy();
void OnMetadataSuccess(const image::DecodeMetadataResult& aMetadata);
void OnFrameCountSuccess(const image::DecodeFrameCountResult& aResult);
void SetSelectedIndex(int32_t aIndex, bool aSelected);
protected:
~ImageTrackList();
public:
nsIGlobalObject* GetParentObject() const { return mParent; }
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
Promise* Ready() const { return mReadyPromise; }
bool IsReady() const { return mIsReady; }
uint32_t Length() const { return mTracks.Length(); }
int32_t SelectedIndex() const { return mSelectedIndex; }
ImageTrack* GetSelectedTrack() const {
if (mSelectedIndex < 0) {
return nullptr;
}
return mTracks[mSelectedIndex];
}
ImageTrack* GetDefaultTrack() const {
if (mTracks.IsEmpty()) {
return nullptr;
}
return mTracks[0];
}
ImageTrack* IndexedGetter(uint32_t aIndex, bool& aFound) const {
if (aIndex >= mTracks.Length()) {
aFound = false;
return nullptr;
}
MOZ_ASSERT(mTracks[aIndex]);
aFound = true;
return mTracks[aIndex];
}
private:
// ImageTrackList can run on either main thread or worker thread.
void AssertIsOnOwningThread() const {
NS_ASSERT_OWNINGTHREAD(ImageTrackList);
}
nsCOMPtr<nsIGlobalObject> mParent;
RefPtr<ImageDecoder> mDecoder;
AutoTArray<RefPtr<ImageTrack>, 1> mTracks;
RefPtr<Promise> mReadyPromise;
int32_t mSelectedIndex = -1;
bool mIsReady = false;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ImageTrackList_h

View File

@ -31,9 +31,6 @@ EXPORTS.mozilla.dom += [
"EncoderAgent.h",
"EncoderTemplate.h",
"EncoderTypes.h",
"ImageDecoder.h",
"ImageTrack.h",
"ImageTrackList.h",
"VideoColorSpace.h",
"VideoDecoder.h",
"VideoEncoder.h",
@ -51,10 +48,6 @@ UNIFIED_SOURCES += [
"EncodedVideoChunk.cpp",
"EncoderAgent.cpp",
"EncoderTemplate.cpp",
"ImageDecoder.cpp",
"ImageDecoderReadRequest.cpp",
"ImageTrack.cpp",
"ImageTrackList.cpp",
"VideoColorSpace.cpp",
"VideoDecoder.cpp",
"VideoEncoder.cpp",

View File

@ -1,71 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* https://w3c.github.io/webcodecs/#image-decoding
*/
// Bug 1696216: Should be AllowSharedBufferSource or ReadableStream
typedef ([AllowShared] ArrayBufferView or [AllowShared] ArrayBuffer or ReadableStream) ImageBufferSource;
dictionary ImageDecoderInit {
required DOMString type;
required ImageBufferSource data;
ColorSpaceConversion colorSpaceConversion = "default";
[EnforceRange] unsigned long desiredWidth;
[EnforceRange] unsigned long desiredHeight;
boolean preferAnimation;
sequence<ArrayBuffer> transfer = [];
};
dictionary ImageDecodeOptions {
[EnforceRange] unsigned long frameIndex = 0;
boolean completeFramesOnly = true;
};
dictionary ImageDecodeResult {
required VideoFrame image;
required boolean complete;
};
[Exposed=(Window,DedicatedWorker),
Func="mozilla::dom::ImageDecoder::PrefEnabled"]
interface ImageTrack {
readonly attribute boolean animated;
readonly attribute unsigned long frameCount;
readonly attribute unrestricted float repetitionCount;
attribute boolean selected;
};
[Exposed=(Window,DedicatedWorker),
Func="mozilla::dom::ImageDecoder::PrefEnabled"]
interface ImageTrackList {
getter ImageTrack (unsigned long index);
readonly attribute Promise<undefined> ready;
readonly attribute unsigned long length;
readonly attribute long selectedIndex;
readonly attribute ImageTrack? selectedTrack;
};
[Exposed=(Window,DedicatedWorker),
SecureContext,
Func="mozilla::dom::ImageDecoder::PrefEnabled"]
interface ImageDecoder {
[Throws]
constructor(ImageDecoderInit init);
readonly attribute DOMString type;
readonly attribute boolean complete;
readonly attribute Promise<undefined> completed;
readonly attribute ImageTrackList tracks;
[Throws]
Promise<ImageDecodeResult> decode(optional ImageDecodeOptions options = {});
undefined reset();
undefined close();
[Throws]
static Promise<boolean> isTypeSupported(DOMString type);
};

View File

@ -166,9 +166,6 @@ with Files("ImageBitmap*"):
with Files("ImageCapture*"):
BUG_COMPONENT = ("Core", "Audio/Video")
with Files("ImageDecoder.webidl"):
BUG_COMPONENT = ("Core", "Audio/Video: Web Codecs")
with Files("InputEvent.webidl"):
BUG_COMPONENT = ("Core", "DOM: UI Events & Focus Handling")
@ -695,7 +692,6 @@ WEBIDL_FILES = [
"ImageBitmapRenderingContext.webidl",
"ImageCapture.webidl",
"ImageData.webidl",
"ImageDecoder.webidl",
"ImageDocument.webidl",
"InputEvent.webidl",
"IntersectionObserver.webidl",

View File

@ -319,32 +319,6 @@ already_AddRefed<Decoder> DecoderFactory::CloneAnimationDecoder(
return decoder.forget();
}
/* static */
already_AddRefed<Decoder> DecoderFactory::CloneAnonymousMetadataDecoder(
Decoder* aDecoder, const Maybe<DecoderFlags>& aDecoderFlags) {
MOZ_ASSERT(aDecoder);
DecoderType type = aDecoder->GetType();
RefPtr<Decoder> decoder =
GetDecoder(type, nullptr, /* aIsRedecode = */ false);
MOZ_ASSERT(decoder, "Should have a decoder now");
// Initialize the decoder.
decoder->SetMetadataDecode(true);
decoder->SetIterator(aDecoder->GetSourceBuffer()->Iterator());
if (aDecoderFlags) {
decoder->SetDecoderFlags(*aDecoderFlags);
} else {
decoder->SetDecoderFlags(aDecoder->GetDecoderFlags());
}
if (NS_FAILED(decoder->Init())) {
return nullptr;
}
return decoder.forget();
}
/* static */
already_AddRefed<IDecodingTask> DecoderFactory::CreateMetadataDecoder(
DecoderType aType, NotNull<RasterImage*> aImage, DecoderFlags aFlags,

View File

@ -12,7 +12,6 @@
#include "mozilla/Maybe.h"
#include "mozilla/NotNull.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/image/ImageUtils.h"
#include "nsCOMPtr.h"
#include "Orientation.h"
#include "SurfaceFlags.h"
@ -26,6 +25,24 @@ class RasterImage;
class SourceBuffer;
class SourceBufferIterator;
/**
* The type of decoder; this is usually determined from a MIME type using
* DecoderFactory::GetDecoderType().
*/
enum class DecoderType {
PNG,
GIF,
JPEG,
BMP,
BMP_CLIPBOARD,
ICO,
ICON,
WEBP,
AVIF,
JXL,
UNKNOWN
};
class DecoderFactory {
public:
/// @return the type of decoder which is appropriate for @aMimeType.
@ -101,15 +118,6 @@ class DecoderFactory {
*/
static already_AddRefed<Decoder> CloneAnimationDecoder(Decoder* aDecoder);
/**
* Creates and initializes a metadata decoder for an anonymous image, cloned
* from the given decoder.
*
* @param aDecoder Decoder to clone.
*/
static already_AddRefed<Decoder> CloneAnonymousMetadataDecoder(
Decoder* aDecoder, const Maybe<DecoderFlags>& aDecoderFlags = Nothing());
/**
* Creates and initializes a metadata decoder of type @aType. This decoder
* will only decode the image's header, extracting metadata like the size of

View File

@ -1,567 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/image/ImageUtils.h"
#include "DecodePool.h"
#include "Decoder.h"
#include "DecoderFactory.h"
#include "IDecodingTask.h"
#include "mozilla/AppShutdown.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/Logging.h"
#include "nsNetUtil.h"
#include "nsStreamUtils.h"
namespace mozilla::image {
static LazyLogModule sLog("ImageUtils");
AnonymousDecoder::AnonymousDecoder() = default;
AnonymousDecoder::~AnonymousDecoder() = default;
class AnonymousDecoderTask : public IDecodingTask {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AnonymousDecoderTask, final)
AnonymousDecoderTask(RefPtr<Decoder>&& aDecoder,
ThreadSafeWeakPtr<AnonymousDecoder>&& aOwner)
: mDecoder(std::move(aDecoder)), mOwner(std::move(aOwner)) {}
bool ShouldPreferSyncRun() const final { return false; }
TaskPriority Priority() const final { return TaskPriority::eLow; }
bool IsValid() const {
return !AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdownFinal) &&
!mOwner.IsDead();
}
bool MaybeStart() {
if (!IsValid()) {
return false;
}
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderTask::Start -- queue", this));
DecodePool::Singleton()->AsyncRun(this);
return true;
}
void Resume() final {
if (!IsValid()) {
return;
}
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderTask::Resume -- queue", this));
DecodePool::Singleton()->AsyncRun(this);
}
void Run() final {
bool resume = true;
while (!mOwner.IsDead() && resume) {
LexerResult result = mDecoder->Decode(WrapNotNull(this));
if (result == LexerResult(Yield::NEED_MORE_DATA)) {
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderTask::Run -- need more data", this));
MOZ_ASSERT(result == LexerResult(Yield::NEED_MORE_DATA));
OnNeedMoreData();
return;
}
// Check if we have a new frame to process.
RefPtr<imgFrame> frame = mDecoder->GetCurrentFrame();
if (frame) {
RefPtr<gfx::SourceSurface> surface = frame->GetSourceSurface();
if (surface) {
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderTask::Run -- new frame %p", this,
frame.get()));
resume = OnFrameAvailable(std::move(frame), std::move(surface));
} else {
MOZ_ASSERT_UNREACHABLE("No surface from frame?");
}
}
if (result.is<TerminalState>()) {
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderTask::Run -- complete", this));
OnComplete(result == LexerResult(TerminalState::SUCCESS));
break;
}
MOZ_ASSERT(result == LexerResult(Yield::OUTPUT_AVAILABLE));
}
}
protected:
virtual ~AnonymousDecoderTask() = default;
virtual void OnNeedMoreData() {}
// Returns true if the caller should continue decoding more frames if
// possible.
virtual bool OnFrameAvailable(RefPtr<imgFrame>&& aFrame,
RefPtr<gfx::SourceSurface>&& aSurface) {
MOZ_ASSERT_UNREACHABLE("Unhandled frame!");
return true;
}
virtual void OnComplete(bool aSuccess) = 0;
RefPtr<Decoder> mDecoder;
ThreadSafeWeakPtr<AnonymousDecoder> mOwner;
};
class AnonymousMetadataDecoderTask final : public AnonymousDecoderTask {
public:
AnonymousMetadataDecoderTask(RefPtr<Decoder>&& aDecoder,
ThreadSafeWeakPtr<AnonymousDecoder>&& aOwner)
: AnonymousDecoderTask(std::move(aDecoder), std::move(aOwner)) {}
protected:
void OnComplete(bool aSuccess) override {
RefPtr<AnonymousDecoder> owner(mOwner);
if (!owner) {
return;
}
if (!aSuccess) {
owner->OnMetadata(nullptr);
return;
}
const auto& mdIn = mDecoder->GetImageMetadata();
owner->OnMetadata(&mdIn);
}
};
class AnonymousFrameCountDecoderTask final : public AnonymousDecoderTask {
public:
AnonymousFrameCountDecoderTask(RefPtr<Decoder>&& aDecoder,
ThreadSafeWeakPtr<AnonymousDecoder>&& aOwner)
: AnonymousDecoderTask(std::move(aDecoder), std::move(aOwner)) {}
protected:
void UpdateFrameCount(bool aComplete) {
RefPtr<AnonymousDecoder> owner(mOwner);
if (!owner) {
return;
}
const auto& mdIn = mDecoder->GetImageMetadata();
uint32_t frameCount = mdIn.HasFrameCount() ? mdIn.GetFrameCount() : 0;
owner->OnFrameCount(frameCount, aComplete);
}
void OnNeedMoreData() override { UpdateFrameCount(/* aComplete */ false); }
void OnComplete(bool aSuccess) override {
UpdateFrameCount(/* aComplete */ true);
}
};
class AnonymousFramesDecoderTask final : public AnonymousDecoderTask {
public:
AnonymousFramesDecoderTask(RefPtr<Decoder>&& aDecoder,
ThreadSafeWeakPtr<AnonymousDecoder>&& aOwner)
: AnonymousDecoderTask(std::move(aDecoder), std::move(aOwner)) {}
protected:
bool OnFrameAvailable(RefPtr<imgFrame>&& aFrame,
RefPtr<gfx::SourceSurface>&& aSurface) override {
RefPtr<AnonymousDecoder> owner(mOwner);
if (!owner) {
return false;
}
return owner->OnFrameAvailable(std::move(aFrame), std::move(aSurface));
}
void OnComplete(bool aSuccess) override {
RefPtr<AnonymousDecoder> owner(mOwner);
if (!owner) {
return;
}
owner->OnFramesComplete();
}
};
class AnonymousDecoderImpl final : public AnonymousDecoder {
public:
AnonymousDecoderImpl()
: mMutex("mozilla::image::AnonymousDecoderImpl::mMutex") {}
~AnonymousDecoderImpl() override { Destroy(); }
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
const char* typeName() const override {
return "mozilla::image::AnonymousDecoderImpl";
}
size_t typeSize() const override { return sizeof(*this); }
#endif
bool Initialize(RefPtr<Decoder>&& aDecoder) override {
MutexAutoLock lock(mMutex);
if (NS_WARN_IF(!aDecoder)) {
MOZ_LOG(sLog, LogLevel::Error,
("[%p] AnonymousDecoderImpl::Initialize -- bad decoder", this));
return false;
}
RefPtr<Decoder> metadataDecoder =
DecoderFactory::CloneAnonymousMetadataDecoder(aDecoder);
if (NS_WARN_IF(!metadataDecoder)) {
MOZ_LOG(sLog, LogLevel::Error,
("[%p] AnonymousDecoderImpl::Initialize -- failed clone metadata "
"decoder",
this));
return false;
}
DecoderFlags flags =
aDecoder->GetDecoderFlags() | DecoderFlags::COUNT_FRAMES;
RefPtr<Decoder> frameCountDecoder =
DecoderFactory::CloneAnonymousMetadataDecoder(aDecoder, Some(flags));
if (NS_WARN_IF(!frameCountDecoder)) {
MOZ_LOG(sLog, LogLevel::Error,
("[%p] AnonymousDecoderImpl::Initialize -- failed clone frame "
"count decoder",
this));
return false;
}
mMetadataTask = new AnonymousMetadataDecoderTask(
std::move(metadataDecoder), ThreadSafeWeakPtr<AnonymousDecoder>(this));
mFrameCountTask = new AnonymousFrameCountDecoderTask(
std::move(frameCountDecoder),
ThreadSafeWeakPtr<AnonymousDecoder>(this));
mFramesTask = new AnonymousFramesDecoderTask(
std::move(aDecoder), ThreadSafeWeakPtr<AnonymousDecoder>(this));
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::Initialize -- success", this));
return true;
}
void Destroy() override {
MutexAutoLock lock(mMutex);
DestroyLocked(NS_ERROR_ABORT);
}
void DestroyLocked(nsresult aResult) MOZ_REQUIRES(mMutex) {
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::Destroy", this));
mFramesToDecode = 0;
mMetadataTask = nullptr;
mFrameCountTask = nullptr;
mFramesTask = nullptr;
mPendingFramesResult.mFrames.Clear();
mPendingFramesResult.mFinished = true;
mMetadataPromise.RejectIfExists(aResult, __func__);
mFrameCountPromise.RejectIfExists(aResult, __func__);
mFramesPromise.RejectIfExists(aResult, __func__);
}
void OnMetadata(const ImageMetadata* aMetadata) override {
MutexAutoLock lock(mMutex);
// We must have already gotten destroyed before metadata decoding finished.
if (!mMetadataTask) {
return;
}
if (!aMetadata) {
MOZ_LOG(sLog, LogLevel::Error,
("[%p] AnonymousDecoderImpl::OnMetadata -- failed", this));
DestroyLocked(NS_ERROR_FAILURE);
return;
}
const auto size = aMetadata->GetSize();
mMetadataResult.mWidth = size.width;
mMetadataResult.mHeight = size.height;
mMetadataResult.mRepetitions = aMetadata->GetLoopCount();
mMetadataResult.mAnimated = aMetadata->HasAnimation();
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::OnMetadata -- %dx%d, repetitions %d, "
"animated %d",
this, size.width, size.height, mMetadataResult.mRepetitions,
mMetadataResult.mAnimated));
if (!mMetadataResult.mAnimated) {
mMetadataResult.mFrameCount = 1;
mMetadataResult.mFrameCountComplete = true;
mMetadataTask = nullptr;
mFrameCountTask = nullptr;
} else if (mFrameCountTask && !mFrameCountTaskRunning) {
MOZ_LOG(
sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::OnMetadata -- start frame count task",
this));
mFrameCountTaskRunning = mFrameCountTask->MaybeStart();
return;
}
mMetadataPromise.Resolve(mMetadataResult, __func__);
if (mFramesTask && mFramesToDecode > 0 && !mFramesTaskRunning) {
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::OnMetadata -- start frames task, "
"want %zu",
this, mFramesToDecode));
mFramesTaskRunning = mFramesTask->MaybeStart();
}
}
void OnFrameCount(uint32_t aFrameCount, bool aComplete) override {
MutexAutoLock lock(mMutex);
// We must have already gotten destroyed before frame count decoding
// finished.
if (!mFrameCountTask) {
return;
}
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::OnFrameCount -- frameCount %u, "
"complete %d",
this, aFrameCount, aComplete));
bool resolve = aComplete;
if (mFrameCount < aFrameCount) {
mFrameCount = aFrameCount;
resolve = true;
}
// If metadata completing is waiting on an updated frame count, resolve it.
mMetadataResult.mFrameCount = mFrameCount;
mMetadataResult.mFrameCountComplete = aComplete;
mMetadataPromise.ResolveIfExists(mMetadataResult, __func__);
if (mMetadataTask) {
mMetadataTask = nullptr;
if (mFramesTask && mFramesToDecode > 0 && !mFramesTaskRunning) {
MOZ_LOG(
sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::OnFrameCount -- start frames task, "
"want %zu",
this, mFramesToDecode));
mFramesTaskRunning = mFramesTask->MaybeStart();
}
}
if (resolve) {
mFrameCountPromise.ResolveIfExists(
DecodeFrameCountResult{aFrameCount, aComplete}, __func__);
}
if (aComplete) {
mFrameCountTask = nullptr;
}
}
bool OnFrameAvailable(RefPtr<imgFrame>&& aFrame,
RefPtr<gfx::SourceSurface>&& aSurface) override {
MutexAutoLock lock(mMutex);
MOZ_DIAGNOSTIC_ASSERT(mFramesTaskRunning);
// We must have already gotten destroyed before frame decoding finished.
if (!mFramesTask) {
mFramesTaskRunning = false;
return false;
}
// Filter duplicate frames.
if (mLastFrame == aFrame) {
return true;
}
mPendingFramesResult.mFrames.AppendElement(
DecodedFrame{std::move(aSurface), mMetadataResult.mAnimated
? aFrame->GetTimeout()
: FrameTimeout::Forever()});
mLastFrame = std::move(aFrame);
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::OnFrameAvailable -- want %zu, got %zu",
this, mFramesToDecode, mPendingFramesResult.mFrames.Length()));
// Check if we have satisfied the number of requested frames.
if (mFramesToDecode > mPendingFramesResult.mFrames.Length()) {
return true;
}
mFramesToDecode = 0;
if (!mFramesPromise.IsEmpty()) {
mFramesPromise.Resolve(std::move(mPendingFramesResult), __func__);
}
mFramesTaskRunning = false;
return false;
}
void OnFramesComplete() override {
MutexAutoLock lock(mMutex);
// We must have already gotten destroyed before frame decoding finished.
if (!mFramesTask) {
return;
}
MOZ_LOG(
sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::OnFramesComplete -- wanted %zu, got %zu",
this, mFramesToDecode, mPendingFramesResult.mFrames.Length()));
mFramesToDecode = 0;
mPendingFramesResult.mFinished = true;
if (!mFramesPromise.IsEmpty()) {
mFramesPromise.Resolve(std::move(mPendingFramesResult), __func__);
}
mLastFrame = nullptr;
mFramesTask = nullptr;
}
RefPtr<DecodeMetadataPromise> DecodeMetadata() override {
MutexAutoLock lock(mMutex);
if (!mMetadataTask) {
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::DecodeMetadata -- already complete",
this));
if (mMetadataResult.mWidth > 0 && mMetadataResult.mHeight > 0) {
return DecodeMetadataPromise::CreateAndResolve(mMetadataResult,
__func__);
}
return DecodeMetadataPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
if (!mMetadataTaskRunning) {
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::DecodeMetadata -- queue", this));
mMetadataTaskRunning = mMetadataTask->MaybeStart();
}
return mMetadataPromise.Ensure(__func__);
}
RefPtr<DecodeFrameCountPromise> DecodeFrameCount(
uint32_t aKnownFrameCount) override {
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mFrameCountPromise.IsEmpty());
// If we have finished, or we have an updated frame count, return right
// away. This may drive the frame decoder for the application as the data
// comes in from the network.
if (!mFrameCountTask || aKnownFrameCount < mFrameCount) {
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::DecodeFrameCount -- known %u, "
"detected %u, complete %d",
this, aKnownFrameCount, mFrameCount, !mFrameCountTask));
return DecodeFrameCountPromise::CreateAndResolve(
DecodeFrameCountResult{mFrameCount,
/* mFinished */ !mFrameCountTask},
__func__);
}
// mFrameCountTask is launching when metadata decoding is finished.
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::DecodeFrameCount -- waiting, known "
"%u, detected %u",
this, aKnownFrameCount, mFrameCount));
return mFrameCountPromise.Ensure(__func__);
}
RefPtr<DecodeFramesPromise> DecodeFrames(size_t aCount) override {
MutexAutoLock lock(mMutex);
// If we cleared our task reference, then we know we finished decoding.
if (!mFramesTask) {
mPendingFramesResult.mFinished = true;
return DecodeFramesPromise::CreateAndResolve(
std::move(mPendingFramesResult), __func__);
}
// If we are not waiting on any frames, then we know we paused decoding.
// If we still are metadata decoding, we need to wait.
if (mFramesToDecode == 0 && !mMetadataTask && !mFramesTaskRunning) {
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::DecodeFrames -- queue", this));
mFramesTaskRunning = mFramesTask->MaybeStart();
}
mFramesToDecode = std::max(mFramesToDecode, aCount);
return mFramesPromise.Ensure(__func__);
}
void CancelDecodeFrames() override {
MutexAutoLock lock(mMutex);
MOZ_LOG(sLog, LogLevel::Debug,
("[%p] AnonymousDecoderImpl::CancelDecodeFrames", this));
mFramesToDecode = 0;
mFramesPromise.RejectIfExists(NS_ERROR_ABORT, __func__);
}
private:
Mutex mMutex;
MozPromiseHolder<DecodeMetadataPromise> mMetadataPromise
MOZ_GUARDED_BY(mMutex);
MozPromiseHolder<DecodeFrameCountPromise> mFrameCountPromise
MOZ_GUARDED_BY(mMutex);
MozPromiseHolder<DecodeFramesPromise> mFramesPromise MOZ_GUARDED_BY(mMutex);
RefPtr<AnonymousFramesDecoderTask> mFramesTask MOZ_GUARDED_BY(mMutex);
RefPtr<AnonymousMetadataDecoderTask> mMetadataTask MOZ_GUARDED_BY(mMutex);
RefPtr<AnonymousFrameCountDecoderTask> mFrameCountTask MOZ_GUARDED_BY(mMutex);
RefPtr<imgFrame> mLastFrame MOZ_GUARDED_BY(mMutex);
DecodeMetadataResult mMetadataResult MOZ_GUARDED_BY(mMutex);
DecodeFramesResult mPendingFramesResult MOZ_GUARDED_BY(mMutex);
size_t mFramesToDecode MOZ_GUARDED_BY(mMutex) = 1;
uint32_t mFrameCount MOZ_GUARDED_BY(mMutex) = 0;
bool mMetadataTaskRunning MOZ_GUARDED_BY(mMutex) = false;
bool mFrameCountTaskRunning MOZ_GUARDED_BY(mMutex) = false;
bool mFramesTaskRunning MOZ_GUARDED_BY(mMutex) = false;
};
/* static */ already_AddRefed<AnonymousDecoder> ImageUtils::CreateDecoder(
SourceBuffer* aSourceBuffer, DecoderType aType,
SurfaceFlags aSurfaceFlags) {
if (NS_WARN_IF(!aSourceBuffer)) {
return nullptr;
}
if (NS_WARN_IF(aType == DecoderType::UNKNOWN)) {
return nullptr;
}
RefPtr<Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
aType, WrapNotNull(aSourceBuffer), Nothing(),
DecoderFlags::IMAGE_IS_TRANSIENT, aSurfaceFlags);
if (NS_WARN_IF(!decoder)) {
return nullptr;
}
auto anonymousDecoder = MakeRefPtr<AnonymousDecoderImpl>();
if (NS_WARN_IF(!anonymousDecoder->Initialize(std::move(decoder)))) {
return nullptr;
}
return anonymousDecoder.forget();
}
/* static */ DecoderType ImageUtils::GetDecoderType(
const nsACString& aMimeType) {
return DecoderFactory::GetDecoderType(aMimeType.Data());
}
} // namespace mozilla::image

View File

@ -1,141 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_image_ImageUtils_h
#define mozilla_image_ImageUtils_h
#include "FrameTimeout.h"
#include "mozilla/image/SurfaceFlags.h"
#include "mozilla/Assertions.h"
#include "mozilla/Maybe.h"
#include "mozilla/MozPromise.h"
#include "mozilla/RefPtr.h"
#include "mozilla/ThreadSafeWeakPtr.h"
#include "nsString.h"
#include "nsTArray.h"
namespace mozilla {
class ErrorResult;
namespace gfx {
class SourceSurface;
}
namespace image {
class Decoder;
class imgFrame;
class ImageMetadata;
class SourceBuffer;
/**
* The type of decoder; this is usually determined from a MIME type using
* DecoderFactory::GetDecoderType() or ImageUtils::GetDecoderType().
*/
enum class DecoderType {
PNG,
GIF,
JPEG,
BMP,
BMP_CLIPBOARD,
ICO,
ICON,
WEBP,
AVIF,
JXL,
UNKNOWN
};
struct DecodeMetadataResult {
int32_t mWidth = 0;
int32_t mHeight = 0;
int32_t mRepetitions = -1;
uint32_t mFrameCount = 0;
bool mAnimated = false;
bool mFrameCountComplete = true;
};
struct DecodeFrameCountResult {
uint32_t mFrameCount = 0;
bool mFinished = false;
};
struct DecodedFrame {
RefPtr<gfx::SourceSurface> mSurface;
FrameTimeout mTimeout;
};
struct DecodeFramesResult {
nsTArray<DecodedFrame> mFrames;
bool mFinished = false;
};
using DecodeMetadataPromise = MozPromise<DecodeMetadataResult, nsresult, true>;
using DecodeFrameCountPromise =
MozPromise<DecodeFrameCountResult, nsresult, true>;
using DecodeFramesPromise = MozPromise<DecodeFramesResult, nsresult, true>;
class AnonymousMetadataDecoderTask;
class AnonymousFrameCountDecoderTask;
class AnonymousFramesDecoderTask;
class AnonymousDecoder : public SupportsThreadSafeWeakPtr<AnonymousDecoder> {
public:
virtual RefPtr<DecodeMetadataPromise> DecodeMetadata() = 0;
virtual void Destroy() = 0;
virtual RefPtr<DecodeFrameCountPromise> DecodeFrameCount(
uint32_t aKnownFrameCount) = 0;
virtual RefPtr<DecodeFramesPromise> DecodeFrames(size_t aCount) = 0;
virtual void CancelDecodeFrames() = 0;
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
virtual const char* typeName() const = 0;
virtual size_t typeSize() const = 0;
#endif
virtual ~AnonymousDecoder();
protected:
AnonymousDecoder();
// Returns true if successfully initialized else false.
virtual bool Initialize(RefPtr<Decoder>&& aDecoder) = 0;
virtual void OnMetadata(const ImageMetadata* aMetadata) = 0;
virtual void OnFrameCount(uint32_t aFrameCount, bool aComplete) = 0;
// Returns true if the caller should continue decoding more frames if
// possible.
virtual bool OnFrameAvailable(RefPtr<imgFrame>&& aFrame,
RefPtr<gfx::SourceSurface>&& aSurface) = 0;
virtual void OnFramesComplete() = 0;
friend class AnonymousMetadataDecoderTask;
friend class AnonymousFrameCountDecoderTask;
friend class AnonymousFramesDecoderTask;
};
class ImageUtils {
public:
static already_AddRefed<AnonymousDecoder> CreateDecoder(
SourceBuffer* aSourceBuffer, DecoderType aType,
SurfaceFlags aSurfaceFlags);
static DecoderType GetDecoderType(const nsACString& aMimeType);
private:
ImageUtils() = delete;
~ImageUtils() = delete;
};
} // namespace image
} // namespace mozilla
#endif // mozilla_image_ImageUtils_h

View File

@ -269,9 +269,6 @@ void nsGIFDecoder2::EndImageFrame() {
if (WantsFrameCount()) {
mGIFStruct.pixels_remaining = 0;
mGIFStruct.images_decoded++;
mGIFStruct.delay_time = 0;
mColormap = nullptr;
mColormapSize = 0;
mCurrentFrameIndex = -1;
// Keep updating the count every time we find a frame.

View File

@ -64,10 +64,7 @@ EXPORTS.mozilla.image += [
"encoders/png/nsPNGEncoder.h",
"ICOFileHeaders.h",
"ImageMemoryReporter.h",
"ImageUtils.h",
"Resolution.h",
"SourceBuffer.h",
"SurfaceFlags.h",
"WebRenderImageProvider.h",
]
@ -89,7 +86,6 @@ UNIFIED_SOURCES += [
"ImageFactory.cpp",
"ImageMemoryReporter.cpp",
"ImageOps.cpp",
"ImageUtils.cpp",
"ImageWrapper.cpp",
"imgFrame.cpp",
"imgLoader.cpp",

View File

@ -3149,12 +3149,6 @@
value: @IS_NIGHTLY_BUILD@
mirror: always
# WebCodecs API - Image decoder
- name: dom.media.webcodecs.image-decoder.enabled
type: RelaxedAtomicBool
value: @IS_NIGHTLY_BUILD@
mirror: always
# Number of seconds of very quiet or silent audio before considering the audio
# inaudible.
- name: dom.media.silence_duration_for_audibility

View File

@ -131,7 +131,7 @@ class OpaqueResponseBlocker final : public nsIStreamListener {
nsILoadInfo* aLoadInfo);
void ResolveAndProcessData(HttpBaseChannel* aChannel, bool aAllowed,
Maybe<mozilla::ipc::Shmem>& aSharedData);
Maybe<ipc::Shmem>& aSharedData);
void MaybeRunOnStopRequest(HttpBaseChannel* aChannel);

View File

@ -1,4 +1,4 @@
prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enabled:true, media.ffmpeg.encoder.enabled:true]
prefs: [dom.media.webcodecs.enabled:true, media.ffmpeg.encoder.enabled:true]
tags: [webcodecs]
disabled:
if (os == "linux") and (bits == 32): Not implemented

View File

@ -1,14 +1,619 @@
prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enabled:true]
prefs: [dom.media.webcodecs.enabled:true]
[idlharness.https.any.html]
[VideoFrame interface: operation metadata()]
expected: FAIL
[VideoFrame interface: new VideoFrame(makeImageBitmap(32, 16), {timestamp: 100, duration: 33}) must inherit property "metadata()" with the proper type]
[ImageDecoder interface: existence and properties of interface object]
expected: FAIL
[ImageDecoder interface object length]
expected: FAIL
[ImageDecoder interface object name]
expected: FAIL
[ImageDecoder interface: existence and properties of interface prototype object]
expected: FAIL
[ImageDecoder interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[ImageDecoder interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[ImageDecoder interface: attribute type]
expected: FAIL
[ImageDecoder interface: attribute complete]
expected: FAIL
[ImageDecoder interface: attribute completed]
expected: FAIL
[ImageDecoder interface: attribute tracks]
expected: FAIL
[ImageDecoder interface: operation decode(optional ImageDecodeOptions)]
expected: FAIL
[ImageDecoder interface: operation reset()]
expected: FAIL
[ImageDecoder interface: operation close()]
expected: FAIL
[ImageDecoder interface: operation isTypeSupported(DOMString)]
expected: FAIL
[ImageTrackList interface: existence and properties of interface object]
expected: FAIL
[ImageTrackList interface object length]
expected: FAIL
[ImageTrackList interface object name]
expected: FAIL
[ImageTrackList interface: existence and properties of interface prototype object]
expected: FAIL
[ImageTrackList interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[ImageTrackList interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[ImageTrackList interface: attribute ready]
expected: FAIL
[ImageTrackList interface: attribute length]
expected: FAIL
[ImageTrackList interface: attribute selectedIndex]
expected: FAIL
[ImageTrackList interface: attribute selectedTrack]
expected: FAIL
[ImageTrack interface: existence and properties of interface object]
expected: FAIL
[ImageTrack interface object length]
expected: FAIL
[ImageTrack interface object name]
expected: FAIL
[ImageTrack interface: existence and properties of interface prototype object]
expected: FAIL
[ImageTrack interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[ImageTrack interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[ImageTrack interface: attribute animated]
expected: FAIL
[ImageTrack interface: attribute frameCount]
expected: FAIL
[ImageTrack interface: attribute repetitionCount]
expected: FAIL
[ImageTrack interface: attribute selected]
expected: FAIL
[idl_test setup]
expected: FAIL
[idl_test setup]
expected: FAIL
[idlharness.https.any.worker.html]
[VideoEncoder interface: existence and properties of interface object]
expected: FAIL
[VideoEncoder interface object length]
expected: FAIL
[VideoEncoder interface object name]
expected: FAIL
[VideoEncoder interface: existence and properties of interface prototype object]
expected: FAIL
[VideoEncoder interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[VideoEncoder interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[VideoEncoder interface: attribute state]
expected: FAIL
[VideoEncoder interface: attribute encodeQueueSize]
expected: FAIL
[VideoEncoder interface: attribute ondequeue]
expected: FAIL
[VideoEncoder interface: operation configure(VideoEncoderConfig)]
expected: FAIL
[VideoEncoder interface: operation encode(VideoFrame, optional VideoEncoderEncodeOptions)]
expected: FAIL
[VideoEncoder interface: operation flush()]
expected: FAIL
[VideoEncoder interface: operation reset()]
expected: FAIL
[VideoEncoder interface: operation close()]
expected: FAIL
[VideoEncoder interface: operation isConfigSupported(VideoEncoderConfig)]
expected: FAIL
[VideoFrame interface: operation metadata()]
expected: FAIL
[ImageDecoder interface: existence and properties of interface object]
expected: FAIL
[ImageDecoder interface object length]
expected: FAIL
[ImageDecoder interface object name]
expected: FAIL
[ImageDecoder interface: existence and properties of interface prototype object]
expected: FAIL
[ImageDecoder interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[ImageDecoder interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[ImageDecoder interface: attribute type]
expected: FAIL
[ImageDecoder interface: attribute complete]
expected: FAIL
[ImageDecoder interface: attribute completed]
expected: FAIL
[ImageDecoder interface: attribute tracks]
expected: FAIL
[ImageDecoder interface: operation decode(optional ImageDecodeOptions)]
expected: FAIL
[ImageDecoder interface: operation reset()]
expected: FAIL
[ImageDecoder interface: operation close()]
expected: FAIL
[ImageDecoder interface: operation isTypeSupported(DOMString)]
expected: FAIL
[ImageTrackList interface: existence and properties of interface object]
expected: FAIL
[ImageTrackList interface object length]
expected: FAIL
[ImageTrackList interface object name]
expected: FAIL
[ImageTrackList interface: existence and properties of interface prototype object]
expected: FAIL
[ImageTrackList interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[ImageTrackList interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[ImageTrackList interface: attribute ready]
expected: FAIL
[ImageTrackList interface: attribute length]
expected: FAIL
[ImageTrackList interface: attribute selectedIndex]
expected: FAIL
[ImageTrackList interface: attribute selectedTrack]
expected: FAIL
[ImageTrack interface: existence and properties of interface object]
expected: FAIL
[ImageTrack interface object length]
expected: FAIL
[ImageTrack interface object name]
expected: FAIL
[ImageTrack interface: existence and properties of interface prototype object]
expected: FAIL
[ImageTrack interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[ImageTrack interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[ImageTrack interface: attribute animated]
expected: FAIL
[ImageTrack interface: attribute frameCount]
expected: FAIL
[ImageTrack interface: attribute repetitionCount]
expected: FAIL
[ImageTrack interface: attribute selected]
expected: FAIL
[idl_test setup]
expected: FAIL
[idl_test setup]
expected: FAIL
[idlharness.https.any.worker.html]
[AudioDecoder interface: existence and properties of interface object]
expected: FAIL
[AudioDecoder interface object length]
expected: FAIL
[AudioDecoder interface object name]
expected: FAIL
[AudioDecoder interface: existence and properties of interface prototype object]
expected: FAIL
[AudioDecoder interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[AudioDecoder interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[AudioDecoder interface: attribute state]
expected: FAIL
[AudioDecoder interface: attribute decodeQueueSize]
expected: FAIL
[AudioDecoder interface: attribute ondequeue]
expected: FAIL
[AudioDecoder interface: operation configure(AudioDecoderConfig)]
expected: FAIL
[AudioDecoder interface: operation decode(EncodedAudioChunk)]
expected: FAIL
[AudioDecoder interface: operation flush()]
expected: FAIL
[AudioDecoder interface: operation reset()]
expected: FAIL
[AudioDecoder interface: operation close()]
expected: FAIL
[AudioDecoder interface: operation isConfigSupported(AudioDecoderConfig)]
expected: FAIL
[EncodedAudioChunk interface: existence and properties of interface object]
expected: FAIL
[EncodedAudioChunk interface object length]
expected: FAIL
[EncodedAudioChunk interface object name]
expected: FAIL
[EncodedAudioChunk interface: existence and properties of interface prototype object]
expected: FAIL
[EncodedAudioChunk interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[EncodedAudioChunk interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[EncodedAudioChunk interface: attribute type]
expected: FAIL
[EncodedAudioChunk interface: attribute timestamp]
expected: FAIL
[EncodedAudioChunk interface: attribute duration]
expected: FAIL
[EncodedAudioChunk interface: attribute byteLength]
expected: FAIL
[AudioData interface: existence and properties of interface object]
expected: FAIL
[AudioData interface object length]
expected: FAIL
[AudioData interface object name]
expected: FAIL
[AudioData interface: existence and properties of interface prototype object]
expected: FAIL
[AudioData interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[AudioData interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[AudioData interface: attribute format]
expected: FAIL
[AudioData interface: attribute sampleRate]
expected: FAIL
[AudioData interface: attribute numberOfFrames]
expected: FAIL
[AudioData interface: attribute numberOfChannels]
expected: FAIL
[AudioData interface: attribute duration]
expected: FAIL
[AudioData interface: attribute timestamp]
expected: FAIL
[AudioData interface: operation allocationSize(AudioDataCopyToOptions)]
expected: FAIL
[AudioData interface: operation clone()]
expected: FAIL
[AudioData interface: operation close()]
expected: FAIL
[VideoFrame interface: operation metadata()]
expected: FAIL
[ImageDecoder interface: existence and properties of interface object]
expected: FAIL
[ImageDecoder interface object length]
expected: FAIL
[ImageDecoder interface object name]
expected: FAIL
[ImageDecoder interface: existence and properties of interface prototype object]
expected: FAIL
[ImageDecoder interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[ImageDecoder interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[ImageDecoder interface: attribute type]
expected: FAIL
[ImageDecoder interface: attribute complete]
expected: FAIL
[ImageDecoder interface: attribute completed]
expected: FAIL
[ImageDecoder interface: attribute tracks]
expected: FAIL
[ImageDecoder interface: operation decode(optional ImageDecodeOptions)]
expected: FAIL
[ImageDecoder interface: operation reset()]
expected: FAIL
[ImageDecoder interface: operation close()]
expected: FAIL
[ImageDecoder interface: operation isTypeSupported(DOMString)]
expected: FAIL
[ImageTrackList interface: existence and properties of interface object]
expected: FAIL
[ImageTrackList interface object length]
expected: FAIL
[ImageTrackList interface object name]
expected: FAIL
[ImageTrackList interface: existence and properties of interface prototype object]
expected: FAIL
[ImageTrackList interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[ImageTrackList interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[ImageTrackList interface: attribute ready]
expected: FAIL
[ImageTrackList interface: attribute length]
expected: FAIL
[ImageTrackList interface: attribute selectedIndex]
expected: FAIL
[ImageTrackList interface: attribute selectedTrack]
expected: FAIL
[ImageTrack interface: existence and properties of interface object]
expected: FAIL
[ImageTrack interface object length]
expected: FAIL
[ImageTrack interface object name]
expected: FAIL
[ImageTrack interface: existence and properties of interface prototype object]
expected: FAIL
[ImageTrack interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[ImageTrack interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[ImageTrack interface: attribute animated]
expected: FAIL
[ImageTrack interface: attribute frameCount]
expected: FAIL
[ImageTrack interface: attribute repetitionCount]
expected: FAIL
[ImageTrack interface: attribute selected]
expected: FAIL
[idl_test setup]
expected: FAIL
[idl_test setup]
expected: FAIL
[EncodedAudioChunk interface: operation copyTo(AllowSharedBufferSource)]
expected: FAIL
[AudioData interface: operation copyTo(AllowSharedBufferSource, AudioDataCopyToOptions)]
expected: FAIL
[idlharness.https.any.worker.html]
[VideoFrame interface: operation metadata()]
expected: FAIL
[VideoFrame interface: new VideoFrame(makeImageBitmap(32, 16), {timestamp: 100, duration: 33}) must inherit property "metadata()" with the proper type]
[ImageDecoder interface: existence and properties of interface object]
expected: FAIL
[ImageDecoder interface object length]
expected: FAIL
[ImageDecoder interface object name]
expected: FAIL
[ImageDecoder interface: existence and properties of interface prototype object]
expected: FAIL
[ImageDecoder interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[ImageDecoder interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[ImageDecoder interface: attribute type]
expected: FAIL
[ImageDecoder interface: attribute complete]
expected: FAIL
[ImageDecoder interface: attribute completed]
expected: FAIL
[ImageDecoder interface: attribute tracks]
expected: FAIL
[ImageDecoder interface: operation decode(optional ImageDecodeOptions)]
expected: FAIL
[ImageDecoder interface: operation reset()]
expected: FAIL
[ImageDecoder interface: operation close()]
expected: FAIL
[ImageDecoder interface: operation isTypeSupported(DOMString)]
expected: FAIL
[ImageTrackList interface: existence and properties of interface object]
expected: FAIL
[ImageTrackList interface object length]
expected: FAIL
[ImageTrackList interface object name]
expected: FAIL
[ImageTrackList interface: existence and properties of interface prototype object]
expected: FAIL
[ImageTrackList interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[ImageTrackList interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[ImageTrackList interface: attribute ready]
expected: FAIL
[ImageTrackList interface: attribute length]
expected: FAIL
[ImageTrackList interface: attribute selectedIndex]
expected: FAIL
[ImageTrackList interface: attribute selectedTrack]
expected: FAIL
[ImageTrack interface: existence and properties of interface object]
expected: FAIL
[ImageTrack interface object length]
expected: FAIL
[ImageTrack interface object name]
expected: FAIL
[ImageTrack interface: existence and properties of interface prototype object]
expected: FAIL
[ImageTrack interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[ImageTrack interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[ImageTrack interface: attribute animated]
expected: FAIL
[ImageTrack interface: attribute frameCount]
expected: FAIL
[ImageTrack interface: attribute repetitionCount]
expected: FAIL
[ImageTrack interface: attribute selected]
expected: FAIL
[idl_test setup]
expected: FAIL

View File

@ -0,0 +1,3 @@
[image-decoder-disconnect-readable-stream-crash.https.html]
expected:
if (os == "win") and not debug and (processor == "x86_64"): [PASS, TIMEOUT]

View File

@ -1,5 +1,9 @@
prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enabled:true]
[image-decoder-image-orientation-none.https.html]
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[Test JPEG w/ EXIF orientation top-left on canvas w/o orientation]
expected: FAIL
[Test JPEG w/ EXIF orientation top-right on canvas w/o orientation.]
expected: FAIL
@ -21,6 +25,9 @@ prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enab
[Test JPEG w/ EXIF orientation left-bottom on canvas w/o orientation.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation top-left on canvas w/o orientation]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation top-right on canvas w/o orientation.]
expected: FAIL

View File

@ -0,0 +1,18 @@
[image-decoder.crossOriginIsolated.https.any.html]
expected:
if (os == "android") and debug: [OK, TIMEOUT]
[Test ImageDecoder decoding with a SharedArrayBuffer source]
expected: FAIL
[Test ImageDecoder decoding with a Uint8Array(SharedArrayBuffer) source]
expected: FAIL
[image-decoder.crossOriginIsolated.https.any.worker.html]
expected:
if (os == "android") and debug: [OK, TIMEOUT]
[Test ImageDecoder decoding with a SharedArrayBuffer source]
expected: FAIL
[Test ImageDecoder decoding with a Uint8Array(SharedArrayBuffer) source]
expected: FAIL

View File

@ -1,8 +1,41 @@
prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enabled:true]
[image-decoder.https.any.worker.html]
# 'Test invalid mime type rejects ...' variants don't catch us rejecting all
# of the promises.
expected: ERROR
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[Test JPEG image decoding.]
expected: FAIL
[Test JPEG w/ EXIF orientation top-left.]
expected: FAIL
[Test JPEG w/ EXIF orientation top-right.]
expected: FAIL
[Test JPEG w/ EXIF orientation bottom-right.]
expected: FAIL
[Test JPEG w/ EXIF orientation bottom-left.]
expected: FAIL
[Test JPEG w/ EXIF orientation left-top.]
expected: FAIL
[Test JPEG w/ EXIF orientation right-top.]
expected: FAIL
[Test JPEG w/ EXIF orientation right-bottom.]
expected: FAIL
[Test JPEG w/ EXIF orientation left-bottom.]
expected: FAIL
[Test PNG image decoding.]
expected: FAIL
[Test AVIF image decoding.]
expected: FAIL
[Test high bit depth HDR AVIF image decoding.]
expected: FAIL
[Test multi-track AVIF image decoding w/ preferAnimation=false.]
expected: FAIL
@ -10,6 +43,12 @@ prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enab
[Test multi-track AVIF image decoding w/ preferAnimation=true.]
expected: FAIL
[Test WEBP image decoding.]
expected: FAIL
[Test GIF image decoding.]
expected: FAIL
[Test JPEG image YUV 4:2:0 decoding.]
expected: FAIL
@ -31,17 +70,99 @@ prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enab
[Test invalid mime type rejects decodeMetadata() requests]
expected: FAIL
[Test out of range index returns RangeError]
expected: FAIL
[Test partial decoding without a frame results in an error]
expected: FAIL
[Test completed property on fully buffered decode]
expected: FAIL
[Test decode, decodeMetadata after no track selected.]
expected: FAIL
[Test track selection in multi track image.]
expected: FAIL
[Test ReadableStream of gif]
expected: FAIL
[Test that decode requests are serialized.]
expected: FAIL
[Test ReadableStream aborts promises on track change]
expected: FAIL
[Test ReadableStream aborts completed on close]
expected: FAIL
[Test ReadableStream resolves completed]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation top-left.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation top-right.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation bottom-right.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation bottom-left.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation left-top.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation right-top.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation right-bottom.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation left-bottom.]
expected: FAIL
[image-decoder.https.any.html]
# 'Test invalid mime type rejects ...' variants don't catch us rejecting all
# of the promises.
expected: ERROR
expected:
if (os == "android") and fission: [OK, TIMEOUT]
[Test JPEG image decoding.]
expected: FAIL
[Test JPEG w/ EXIF orientation top-left.]
expected: FAIL
[Test JPEG w/ EXIF orientation top-right.]
expected: FAIL
[Test JPEG w/ EXIF orientation bottom-right.]
expected: FAIL
[Test JPEG w/ EXIF orientation bottom-left.]
expected: FAIL
[Test JPEG w/ EXIF orientation left-top.]
expected: FAIL
[Test JPEG w/ EXIF orientation right-top.]
expected: FAIL
[Test JPEG w/ EXIF orientation right-bottom.]
expected: FAIL
[Test JPEG w/ EXIF orientation left-bottom.]
expected: FAIL
[Test PNG image decoding.]
expected: FAIL
[Test AVIF image decoding.]
expected: FAIL
[Test high bit depth HDR AVIF image decoding.]
expected: FAIL
[Test multi-track AVIF image decoding w/ preferAnimation=false.]
expected: FAIL
@ -49,6 +170,12 @@ prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enab
[Test multi-track AVIF image decoding w/ preferAnimation=true.]
expected: FAIL
[Test WEBP image decoding.]
expected: FAIL
[Test GIF image decoding.]
expected: FAIL
[Test JPEG image YUV 4:2:0 decoding.]
expected: FAIL
@ -70,8 +197,56 @@ prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enab
[Test invalid mime type rejects decodeMetadata() requests]
expected: FAIL
[Test out of range index returns RangeError]
expected: FAIL
[Test partial decoding without a frame results in an error]
expected: FAIL
[Test completed property on fully buffered decode]
expected: FAIL
[Test decode, decodeMetadata after no track selected.]
expected: FAIL
[Test track selection in multi track image.]
expected: FAIL
[Test ReadableStream of gif]
expected: FAIL
[Test that decode requests are serialized.]
expected: FAIL
[Test ReadableStream aborts promises on track change]
expected: FAIL
[Test ReadableStream aborts completed on close]
expected: FAIL
[Test ReadableStream resolves completed]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation top-left.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation top-right.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation bottom-right.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation bottom-left.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation left-top.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation right-top.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation right-bottom.]
expected: FAIL
[Test 4:2:0 JPEG w/ EXIF orientation left-bottom.]
expected: FAIL

View File

@ -1,4 +1,4 @@
prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enabled:true]
prefs: [dom.media.webcodecs.enabled:true]
[transfering.https.any.html]
[Test transfering ArrayBuffer to VideoFrame]
expected: FAIL
@ -18,6 +18,9 @@ prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enab
[Encoding from AudioData with transferred buffer]
expected: FAIL
[Test transfering ArrayBuffer to ImageDecoder.]
expected: FAIL
[transfering.https.any.worker.html]
[Test transfering ArrayBuffer to VideoFrame]
@ -37,3 +40,6 @@ prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enab
[Encoding from AudioData with transferred buffer]
expected: FAIL
[Test transfering ArrayBuffer to ImageDecoder.]
expected: FAIL

View File

@ -1187,8 +1187,6 @@ with modules["DOM_MEDIA"]:
errors["NS_ERROR_DOM_MEDIA_EXTERNAL_ENGINE_NOT_SUPPORTED_ERR"] = FAILURE(102)
errors["NS_ERROR_DOM_MEDIA_CDM_PROXY_NOT_SUPPORTED_ERR"] = FAILURE(103)
errors["NS_ERROR_DOM_MEDIA_DENIED_IN_NON_UTILITY"] = FAILURE(104)
errors["NS_ERROR_DOM_MEDIA_RANGE_ERR"] = FAILURE(105)
errors["NS_ERROR_DOM_MEDIA_TYPE_ERR"] = FAILURE(106)
# =======================================================================
# 42: NS_ERROR_MODULE_URL_CLASSIFIER