From 509fefbffdadaff280cf1275f31967d80e338987 Mon Sep 17 00:00:00 2001 From: Andrew Osmond Date: Tue, 22 Oct 2024 13:45:36 +0000 Subject: [PATCH] Bug 1926249 - Implement support for desired width/height with WebCodecs ImageDecoder. r=media-playback-reviewers,padenot Differential Revision: https://phabricator.services.mozilla.com/D226498 --- dom/media/webcodecs/ImageDecoder.cpp | 24 ++++++-- dom/media/webcodecs/ImageDecoder.h | 4 +- dom/media/webcodecs/test/green.png | Bin 0 -> 255 bytes dom/media/webcodecs/test/mochitest.toml | 8 ++- .../test/test_imageDecoder_desiredSize.html | 57 ++++++++++++++++++ image/ImageUtils.cpp | 33 ++++++++-- image/ImageUtils.h | 2 +- 7 files changed, 115 insertions(+), 13 deletions(-) create mode 100644 dom/media/webcodecs/test/green.png create mode 100644 dom/media/webcodecs/test/test_imageDecoder_desiredSize.html diff --git a/dom/media/webcodecs/ImageDecoder.cpp b/dom/media/webcodecs/ImageDecoder.cpp index 007cc97fd3a8..a27249e36175 100644 --- a/dom/media/webcodecs/ImageDecoder.cpp +++ b/dom/media/webcodecs/ImageDecoder.cpp @@ -45,11 +45,14 @@ class ImageDecoder::ControlMessage { class ImageDecoder::ConfigureMessage final : public ImageDecoder::ControlMessage { public: - explicit ConfigureMessage(ColorSpaceConversion aColorSpaceConversion) - : mColorSpaceConversion(aColorSpaceConversion) {} + explicit ConfigureMessage(const Maybe& aOutputSize, + ColorSpaceConversion aColorSpaceConversion) + : mOutputSize(aOutputSize), + mColorSpaceConversion(aColorSpaceConversion) {} ConfigureMessage* AsConfigureMessage() override { return this; } + const Maybe mOutputSize; const ColorSpaceConversion mColorSpaceConversion; }; @@ -152,9 +155,10 @@ void ImageDecoder::Destroy() { } void ImageDecoder::QueueConfigureMessage( + const Maybe& aOutputSize, ColorSpaceConversion aColorSpaceConversion) { mControlMessageQueue.push( - MakeUnique(aColorSpaceConversion)); + MakeUnique(aOutputSize, aColorSpaceConversion)); } void ImageDecoder::QueueDecodeMetadataMessage() { @@ -239,8 +243,8 @@ MessageProcessedResult ImageDecoder::ProcessConfigureMessage( // 3. Otherwise, assign the [[codec implementation]] internal slot with an // implementation supporting init.type - mDecoder = - image::ImageUtils::CreateDecoder(mSourceBuffer, type, surfaceFlags); + mDecoder = image::ImageUtils::CreateDecoder(mSourceBuffer, type, + aMsg->mOutputSize, surfaceFlags); if (NS_WARN_IF(!mDecoder)) { MOZ_LOG(gWebCodecsLog, LogLevel::Error, ("ImageDecoder %p Initialize -- failed to create platform decoder", @@ -680,9 +684,17 @@ void ImageDecoder::Initialize(const GlobalObject& aGlobal, return; } + Maybe desiredSize; + if (aInit.mDesiredWidth.WasPassed() && aInit.mDesiredHeight.WasPassed()) { + desiredSize.emplace( + std::min(aInit.mDesiredWidth.Value(), static_cast(INT32_MAX)), + std::min(aInit.mDesiredHeight.Value(), + static_cast(INT32_MAX))); + } + // 10.2.2.17.3 / 10.2.2.18.6. // Queue a control message to configure the image decoder with init. - QueueConfigureMessage(aInit.mColorSpaceConversion); + QueueConfigureMessage(desiredSize, aInit.mColorSpaceConversion); // 10.2.10.2.2.18.7. Queue a control message to decode track metadata. // diff --git a/dom/media/webcodecs/ImageDecoder.h b/dom/media/webcodecs/ImageDecoder.h index d104d3a4e413..adff3fe43587 100644 --- a/dom/media/webcodecs/ImageDecoder.h +++ b/dom/media/webcodecs/ImageDecoder.h @@ -14,6 +14,7 @@ #include "mozilla/UniquePtr.h" #include "mozilla/dom/ImageDecoderBinding.h" #include "mozilla/dom/WebCodecsUtils.h" +#include "mozilla/gfx/Point.h" #include "nsCycleCollectionParticipant.h" #include "nsWrapperCache.h" @@ -113,7 +114,8 @@ class ImageDecoder final : public nsISupports, public nsWrapperCache { void Reset(const MediaResult& aResult); void Close(const MediaResult& aResult); - void QueueConfigureMessage(ColorSpaceConversion aColorSpaceConversion); + void QueueConfigureMessage(const Maybe& aOutputSize, + ColorSpaceConversion aColorSpaceConversion); void QueueDecodeMetadataMessage(); void QueueDecodeFrameMessage(); diff --git a/dom/media/webcodecs/test/green.png b/dom/media/webcodecs/test/green.png new file mode 100644 index 0000000000000000000000000000000000000000..7df25f33bdb26cc7f41138501ab399059839137d GIT binary patch literal 255 zcmeAS@N?(olHy`uVBq!ia0vp^DImFdgVmrY2>Os;yW$XlS$JWm(LkcwMxFBmd1FmNz0$ozjU>fm{HrGS|QSGZD6PEz%r zro*}k!eEMoFdB8hjHM3Kz>FXTpc + + + + + + + + + + diff --git a/image/ImageUtils.cpp b/image/ImageUtils.cpp index 0485f8c5fa0f..2602b52ec139 100644 --- a/image/ImageUtils.cpp +++ b/image/ImageUtils.cpp @@ -171,6 +171,12 @@ class AnonymousFramesDecoderTask final : public AnonymousDecoderTask { ThreadSafeWeakPtr&& aOwner) : AnonymousDecoderTask(std::move(aDecoder), std::move(aOwner)) {} + void SetOutputSize(const OrientedIntSize& aSize) { + if (mDecoder) { + mDecoder->SetOutputSize(aSize); + } + } + protected: bool OnFrameAvailable(RefPtr&& aFrame, RefPtr&& aSurface) override { @@ -194,8 +200,9 @@ class AnonymousFramesDecoderTask final : public AnonymousDecoderTask { class AnonymousDecoderImpl final : public AnonymousDecoder { public: - AnonymousDecoderImpl() - : mMutex("mozilla::image::AnonymousDecoderImpl::mMutex") {} + explicit AnonymousDecoderImpl(const Maybe& aOutputSize) + : mMutex("mozilla::image::AnonymousDecoderImpl::mMutex"), + mOutputSize(aOutputSize) {} ~AnonymousDecoderImpl() override { Destroy(); } @@ -298,6 +305,23 @@ class AnonymousDecoderImpl final : public AnonymousDecoder { this, size.width, size.height, mMetadataResult.mRepetitions, mMetadataResult.mAnimated)); + if (mOutputSize && !mMetadataResult.mAnimated && mFramesTask) { + if (mOutputSize->width <= size.width && + mOutputSize->height <= size.height) { + MOZ_LOG( + sLog, LogLevel::Debug, + ("[%p] AnonymousDecoderImpl::OnMetadata -- use output size %dx%d", + this, mOutputSize->width, mOutputSize->height)); + mFramesTask->SetOutputSize( + OrientedIntSize::FromUnknownSize(*mOutputSize)); + } else { + MOZ_LOG(sLog, LogLevel::Debug, + ("[%p] AnonymousDecoderImpl::OnMetadata -- cannot use output " + "size %dx%d, exceeds metadata size", + this, mOutputSize->width, mOutputSize->height)); + } + } + if (!mMetadataResult.mAnimated) { mMetadataResult.mFrameCount = 1; mMetadataResult.mFrameCountComplete = true; @@ -526,6 +550,7 @@ class AnonymousDecoderImpl final : public AnonymousDecoder { RefPtr mLastFrame MOZ_GUARDED_BY(mMutex); DecodeMetadataResult mMetadataResult MOZ_GUARDED_BY(mMutex); DecodeFramesResult mPendingFramesResult MOZ_GUARDED_BY(mMutex); + Maybe mOutputSize 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; @@ -535,7 +560,7 @@ class AnonymousDecoderImpl final : public AnonymousDecoder { /* static */ already_AddRefed ImageUtils::CreateDecoder( SourceBuffer* aSourceBuffer, DecoderType aType, - SurfaceFlags aSurfaceFlags) { + const Maybe& aOutputSize, SurfaceFlags aSurfaceFlags) { if (NS_WARN_IF(!aSourceBuffer)) { return nullptr; } @@ -551,7 +576,7 @@ class AnonymousDecoderImpl final : public AnonymousDecoder { return nullptr; } - auto anonymousDecoder = MakeRefPtr(); + auto anonymousDecoder = MakeRefPtr(aOutputSize); if (NS_WARN_IF(!anonymousDecoder->Initialize(std::move(decoder)))) { return nullptr; } diff --git a/image/ImageUtils.h b/image/ImageUtils.h index ccf34a27b38e..f5ed2387cfc7 100644 --- a/image/ImageUtils.h +++ b/image/ImageUtils.h @@ -126,7 +126,7 @@ class ImageUtils { public: static already_AddRefed CreateDecoder( SourceBuffer* aSourceBuffer, DecoderType aType, - SurfaceFlags aSurfaceFlags); + const Maybe& aOutputSize, SurfaceFlags aSurfaceFlags); static DecoderType GetDecoderType(const nsACString& aMimeType);