diff --git a/dom/base/StructuredCloneHolder.cpp b/dom/base/StructuredCloneHolder.cpp index 4eb485215706..0de10e7efa99 100644 --- a/dom/base/StructuredCloneHolder.cpp +++ b/dom/base/StructuredCloneHolder.cpp @@ -395,7 +395,7 @@ void StructuredCloneHolder::Read(nsIGlobalObject* aGlobal, JSContext* aCx, mWasmModuleArray.Clear(); mClonedSurfaces.Clear(); mInputStreamArray.Clear(); - mVideoFrameImages.Clear(); + mVideoFrames.Clear(); Clear(); } } @@ -1025,7 +1025,7 @@ JSObject* StructuredCloneHolder::CustomReadHandler( aTag == SCTAG_DOM_VIDEOFRAME && CloneScope() == StructuredCloneScope::SameProcess) { return VideoFrame::ReadStructuredClone(aCx, mGlobal, aReader, - VideoFrameImages()[aIndex]); + VideoFrames()[aIndex]); } return ReadFullySerializableObjects(aCx, aReader, aTag); diff --git a/dom/base/StructuredCloneHolder.h b/dom/base/StructuredCloneHolder.h index 6f00c44ebd37..e0c87415e220 100644 --- a/dom/base/StructuredCloneHolder.h +++ b/dom/base/StructuredCloneHolder.h @@ -166,7 +166,7 @@ class StructuredCloneHolderBase { class BlobImpl; class MessagePort; class MessagePortIdentifier; -struct VideoFrameImageData; +struct VideoFrameSerializedData; class StructuredCloneHolder : public StructuredCloneHolderBase { public: @@ -210,7 +210,7 @@ class StructuredCloneHolder : public StructuredCloneHolderBase { bool HasClonedDOMObjects() const { return !mBlobImplArray.IsEmpty() || !mWasmModuleArray.IsEmpty() || !mClonedSurfaces.IsEmpty() || !mInputStreamArray.IsEmpty() || - !mVideoFrameImages.IsEmpty(); + !mVideoFrames.IsEmpty(); } nsTArray>& BlobImpls() { @@ -266,9 +266,7 @@ class StructuredCloneHolder : public StructuredCloneHolderBase { return mClonedSurfaces; } - nsTArray& VideoFrameImages() { - return mVideoFrameImages; - } + nsTArray& VideoFrames() { return mVideoFrames; } // Implementations of the virtual methods to allow cloning of objects which // JS engine itself doesn't clone. @@ -368,7 +366,7 @@ class StructuredCloneHolder : public StructuredCloneHolderBase { nsTArray> mClonedSurfaces; // Used for cloning VideoFrame in the structured cloning algorithm. - nsTArray mVideoFrameImages; + nsTArray mVideoFrames; // This raw pointer is only set within ::Read() and is unset by the end. nsIGlobalObject* MOZ_NON_OWNING_REF mGlobal; diff --git a/dom/media/webcodecs/VideoFrame.cpp b/dom/media/webcodecs/VideoFrame.cpp index d7c71d8b1faa..51bf4c94dcb0 100644 --- a/dom/media/webcodecs/VideoFrame.cpp +++ b/dom/media/webcodecs/VideoFrame.cpp @@ -1051,10 +1051,10 @@ static Result, nsCString> CreateVideoFrameFromBuffer( // TODO: Spec should assign aInit.mFormat to inner format value: // https://github.com/w3c/webcodecs/issues/509. // This comment should be removed once the issue is resolved. - return MakeRefPtr( - aGlobal, data, aInit.mFormat, codedSize, parsedRect, - displaySize ? *displaySize : parsedRect.Size(), std::move(duration), - aInit.mTimestamp, colorSpace); + return MakeRefPtr(aGlobal, data, aInit.mFormat, codedSize, + parsedRect, + displaySize ? *displaySize : parsedRect.Size(), + duration, aInit.mTimestamp, colorSpace); } template @@ -1137,7 +1137,7 @@ InitializeFrameWithResourceAndSize( const VideoColorSpaceInit colorSpace{}; return MakeAndAddRef(aGlobal, image, format->PixelFormat(), image->GetSize(), visibleRect.value(), - displaySize.value(), std::move(duration), + displaySize.value(), duration, aInit.mTimestamp.Value(), colorSpace); } @@ -1171,8 +1171,8 @@ InitializeFrameFromOtherFrame(nsIGlobalObject* aGlobal, return MakeAndAddRef( aGlobal, aData.mImage, aData.mFormat.PixelFormat(), - aData.mImage->GetSize(), *visibleRect, *displaySize, std::move(duration), - timestamp, aData.mColorSpace); + aData.mImage->GetSize(), *visibleRect, *displaySize, duration, timestamp, + aData.mColorSpace); } /* @@ -1183,14 +1183,14 @@ VideoFrame::VideoFrame(nsIGlobalObject* aParent, const RefPtr& aImage, const VideoPixelFormat& aFormat, gfx::IntSize aCodedSize, gfx::IntRect aVisibleRect, gfx::IntSize aDisplaySize, - Maybe&& aDuration, int64_t aTimestamp, + const Maybe& aDuration, int64_t aTimestamp, const VideoColorSpaceInit& aColorSpace) : mParent(aParent), mResource(Some(Resource(aImage, VideoFrame::Format(aFormat)))), mCodedSize(aCodedSize), mVisibleRect(aVisibleRect), mDisplaySize(aDisplaySize), - mDuration(std::move(aDuration)), + mDuration(aDuration), mTimestamp(aTimestamp), mColorSpace(aColorSpace) { MOZ_ASSERT(mParent); @@ -1827,88 +1827,13 @@ void VideoFrame::Close() { // https://w3c.github.io/webcodecs/#ref-for-deserialization-steps%E2%91%A0 /* static */ -JSObject* VideoFrame::ReadStructuredClone(JSContext* aCx, - nsIGlobalObject* aGlobal, - JSStructuredCloneReader* aReader, - const VideoFrameImageData& aData) { - if (!IsSameOrigin(aGlobal, aData.mURI.get())) { +JSObject* VideoFrame::ReadStructuredClone( + JSContext* aCx, nsIGlobalObject* aGlobal, JSStructuredCloneReader* aReader, + const VideoFrameSerializedData& aData) { + if (!IsSameOrigin(aGlobal, aData.mPrincipalURI.get())) { return nullptr; } - VideoPixelFormat format; - if (NS_WARN_IF(!JS_ReadBytes(aReader, &format, 1))) { - return nullptr; - } - - uint32_t codedWidth = 0; - uint32_t codedHeight = 0; - if (NS_WARN_IF(!JS_ReadUint32Pair(aReader, &codedWidth, &codedHeight))) { - return nullptr; - } - - uint32_t visibleX = 0; - uint32_t visibleY = 0; - uint32_t visibleWidth = 0; - uint32_t visibleHeight = 0; - if (NS_WARN_IF(!JS_ReadUint32Pair(aReader, &visibleX, &visibleY)) || - NS_WARN_IF(!JS_ReadUint32Pair(aReader, &visibleWidth, &visibleHeight))) { - return nullptr; - } - - uint32_t displayWidth = 0; - uint32_t displayHeight = 0; - if (NS_WARN_IF(!JS_ReadUint32Pair(aReader, &displayWidth, &displayHeight))) { - return nullptr; - } - - uint8_t hasDuration = 0; - uint32_t durationLow = 0; - uint32_t durationHigh = 0; - if (NS_WARN_IF(!JS_ReadBytes(aReader, &hasDuration, 1)) || - NS_WARN_IF(!JS_ReadUint32Pair(aReader, &durationLow, &durationHigh))) { - return nullptr; - } - Maybe duration = - hasDuration ? Some(uint64_t(durationHigh) << 32 | durationLow) - : Nothing(); - - uint32_t timestampLow = 0; - uint32_t timestampHigh = 0; - if (NS_WARN_IF(!JS_ReadUint32Pair(aReader, ×tampLow, ×tampHigh))) { - return nullptr; - } - int64_t timestamp = int64_t(timestampHigh) << 32 | timestampLow; - - uint8_t colorSpaceFullRange = 0; - uint8_t colorSpaceMatrix = 0; - uint8_t colorSpacePrimaries = 0; - uint8_t colorSpaceTransfer = 0; - if (NS_WARN_IF(!JS_ReadBytes(aReader, &colorSpaceFullRange, 1)) || - NS_WARN_IF(!JS_ReadBytes(aReader, &colorSpaceMatrix, 1)) || - NS_WARN_IF(!JS_ReadBytes(aReader, &colorSpacePrimaries, 1)) || - NS_WARN_IF(!JS_ReadBytes(aReader, &colorSpaceTransfer, 1))) { - return nullptr; - } - VideoColorSpaceInit colorSpace{}; - if (colorSpaceFullRange < 2) { - colorSpace.mFullRange.Construct(colorSpaceFullRange > 0); - } - if (colorSpaceMatrix < - static_cast(VideoMatrixCoefficients::EndGuard_)) { - colorSpace.mMatrix.Construct( - static_cast(colorSpaceMatrix)); - } - if (colorSpacePrimaries < - static_cast(VideoColorPrimaries::EndGuard_)) { - colorSpace.mPrimaries.Construct( - static_cast(colorSpacePrimaries)); - } - if (colorSpaceTransfer < - static_cast(VideoTransferCharacteristics::EndGuard_)) { - colorSpace.mTransfer.Construct( - static_cast(colorSpaceTransfer)); - } - JS::Rooted value(aCx, JS::NullValue()); // To avoid a rooting hazard error from returning a raw JSObject* before // running the RefPtr destructor, RefPtr needs to be destructed before @@ -1917,10 +1842,9 @@ JSObject* VideoFrame::ReadStructuredClone(JSContext* aCx, // be safely destructed while the unrooted return JSObject* is on the stack. { RefPtr frame = MakeAndAddRef( - aGlobal, aData.mImage, format, gfx::IntSize(codedWidth, codedHeight), - gfx::IntRect(visibleX, visibleY, visibleWidth, visibleHeight), - gfx::IntSize(displayWidth, displayHeight), std::move(duration), - timestamp, colorSpace); + aGlobal, aData.mImage, aData.mFormat, aData.mCodedSize, + aData.mVisibleRect, aData.mDisplaySize, aData.mDuration, + aData.mTimestamp, aData.mColorSpace); if (!GetOrCreateDOMReflector(aCx, frame, &value) || !value.isObject()) { return nullptr; } @@ -1939,61 +1863,17 @@ bool VideoFrame::WriteStructuredClone(JSStructuredCloneWriter* aWriter, return false; } - const uint8_t format = BitwiseCast(mResource->mFormat.PixelFormat()); - - const uint32_t codedWidth = BitwiseCast(mCodedSize.Width()); - const uint32_t codedHeight = BitwiseCast(mCodedSize.Height()); - - const uint32_t visibleX = BitwiseCast(mVisibleRect.X()); - const uint32_t visibleY = BitwiseCast(mVisibleRect.Y()); - const uint32_t visibleWidth = BitwiseCast(mVisibleRect.Width()); - const uint32_t visibleHeight = BitwiseCast(mVisibleRect.Height()); - - const uint32_t displayWidth = BitwiseCast(mDisplaySize.Width()); - const uint32_t displayHeight = BitwiseCast(mDisplaySize.Height()); - - const uint8_t hasDuration = mDuration ? 1 : 0; - const uint32_t durationLow = mDuration ? uint32_t(*mDuration) : 0; - const uint32_t durationHigh = mDuration ? uint32_t(*mDuration >> 32) : 0; - - const uint32_t timestampLow = uint32_t(mTimestamp); - const uint32_t timestampHigh = uint32_t(mTimestamp >> 32); - - const uint8_t colorSpaceFullRange = - mColorSpace.mFullRange.WasPassed() ? mColorSpace.mFullRange.Value() : 2; - const uint8_t colorSpaceMatrix = BitwiseCast( - mColorSpace.mMatrix.WasPassed() ? mColorSpace.mMatrix.Value() - : VideoMatrixCoefficients::EndGuard_); - const uint8_t colorSpacePrimaries = BitwiseCast( - mColorSpace.mPrimaries.WasPassed() ? mColorSpace.mPrimaries.Value() - : VideoColorPrimaries::EndGuard_); - const uint8_t colorSpaceTransfer = - BitwiseCast(mColorSpace.mTransfer.WasPassed() - ? mColorSpace.mTransfer.Value() - : VideoTransferCharacteristics::EndGuard_); - // Indexing the image and send the index to the receiver. - const uint32_t index = aHolder->VideoFrameImages().Length(); + const uint32_t index = aHolder->VideoFrames().Length(); RefPtr image(mResource->mImage.get()); // The serialization is limited to the same process scope so it's ok to // serialize a reference instead of a copy. - aHolder->VideoFrameImages().AppendElement( - VideoFrameImageData{image.forget(), GetPrincipalURI()}); + aHolder->VideoFrames().AppendElement(VideoFrameSerializedData{ + image.forget(), mResource->mFormat.PixelFormat(), mCodedSize, + mVisibleRect, mDisplaySize, mDuration, mTimestamp, + VideoColorSpaceInit(mColorSpace), GetPrincipalURI()}); - return !( - NS_WARN_IF(!JS_WriteUint32Pair(aWriter, SCTAG_DOM_VIDEOFRAME, index)) || - NS_WARN_IF(!JS_WriteBytes(aWriter, &format, 1)) || - NS_WARN_IF(!JS_WriteUint32Pair(aWriter, codedWidth, codedHeight)) || - NS_WARN_IF(!JS_WriteUint32Pair(aWriter, visibleX, visibleY)) || - NS_WARN_IF(!JS_WriteUint32Pair(aWriter, visibleWidth, visibleHeight)) || - NS_WARN_IF(!JS_WriteUint32Pair(aWriter, displayWidth, displayHeight)) || - NS_WARN_IF(!JS_WriteBytes(aWriter, &hasDuration, 1)) || - NS_WARN_IF(!JS_WriteUint32Pair(aWriter, durationLow, durationHigh)) || - NS_WARN_IF(!JS_WriteUint32Pair(aWriter, timestampLow, timestampHigh)) || - NS_WARN_IF(!JS_WriteBytes(aWriter, &colorSpaceFullRange, 1)) || - NS_WARN_IF(!JS_WriteBytes(aWriter, &colorSpaceMatrix, 1)) || - NS_WARN_IF(!JS_WriteBytes(aWriter, &colorSpacePrimaries, 1)) || - NS_WARN_IF(!JS_WriteBytes(aWriter, &colorSpaceTransfer, 1))); + return !NS_WARN_IF(!JS_WriteUint32Pair(aWriter, SCTAG_DOM_VIDEOFRAME, index)); } // https://w3c.github.io/webcodecs/#ref-for-transfer-steps%E2%91%A0 diff --git a/dom/media/webcodecs/VideoFrame.h b/dom/media/webcodecs/VideoFrame.h index 2859df808423..1db9f65267bc 100644 --- a/dom/media/webcodecs/VideoFrame.h +++ b/dom/media/webcodecs/VideoFrame.h @@ -54,9 +54,16 @@ struct VideoFrameCopyToOptions; namespace mozilla::dom { -struct VideoFrameImageData { +struct VideoFrameSerializedData { const RefPtr mImage; - const nsCOMPtr mURI; + const VideoPixelFormat mFormat; + const gfx::IntSize mCodedSize; + const gfx::IntRect mVisibleRect; + const gfx::IntSize mDisplaySize; + const Maybe mDuration; + const int64_t mTimestamp; + const VideoColorSpaceInit mColorSpace; + const nsCOMPtr mPrincipalURI; }; class VideoFrame final : public nsISupports, public nsWrapperCache { @@ -68,7 +75,7 @@ class VideoFrame final : public nsISupports, public nsWrapperCache { VideoFrame(nsIGlobalObject* aParent, const RefPtr& aImage, const VideoPixelFormat& aFormat, gfx::IntSize aCodedSize, gfx::IntRect aVisibleRect, gfx::IntSize aDisplaySize, - Maybe&& aDuration, int64_t aTimestamp, + const Maybe& aDuration, int64_t aTimestamp, const VideoColorSpaceInit& aColorSpace); VideoFrame(const VideoFrame& aOther); @@ -146,7 +153,7 @@ class VideoFrame final : public nsISupports, public nsWrapperCache { // [Serializable] implementations: {Read, Write}StructuredClone static JSObject* ReadStructuredClone(JSContext* aCx, nsIGlobalObject* aGlobal, JSStructuredCloneReader* aReader, - const VideoFrameImageData& aImage); + const VideoFrameSerializedData& aData); bool WriteStructuredClone(JSStructuredCloneWriter* aWriter, StructuredCloneHolder* aHolder) const;