diff options
Diffstat (limited to 'dom/media/webcodecs/VideoFrame.h')
-rw-r--r-- | dom/media/webcodecs/VideoFrame.h | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/dom/media/webcodecs/VideoFrame.h b/dom/media/webcodecs/VideoFrame.h new file mode 100644 index 0000000000..0bef496b79 --- /dev/null +++ b/dom/media/webcodecs/VideoFrame.h @@ -0,0 +1,266 @@ +/* -*- 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_VideoFrame_h +#define mozilla_dom_VideoFrame_h + +#include "js/TypeDecls.h" +#include "mozilla/Attributes.h" +#include "mozilla/ErrorResult.h" +#include "mozilla/NotNull.h" +#include "mozilla/Span.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/TypedArray.h" +#include "mozilla/dom/VideoColorSpaceBinding.h" +#include "mozilla/dom/WorkerRef.h" +#include "mozilla/gfx/Point.h" +#include "mozilla/gfx/Rect.h" +#include "mozilla/media/MediaUtils.h" +#include "nsCycleCollectionParticipant.h" +#include "nsWrapperCache.h" + +class nsIGlobalObject; +class nsIURI; + +namespace mozilla { + +namespace layers { +class Image; +} // namespace layers + +namespace dom { + +class DOMRectReadOnly; +class HTMLCanvasElement; +class HTMLImageElement; +class HTMLVideoElement; +class ImageBitmap; +class MaybeSharedArrayBufferViewOrMaybeSharedArrayBuffer; +class OffscreenCanvas; +class OwningMaybeSharedArrayBufferViewOrMaybeSharedArrayBuffer; +class Promise; +class SVGImageElement; +class StructuredCloneHolder; +class VideoColorSpace; +class VideoFrame; +enum class VideoPixelFormat : uint8_t; +struct VideoFrameBufferInit; +struct VideoFrameInit; +struct VideoFrameCopyToOptions; + +} // namespace dom +} // namespace mozilla + +namespace mozilla::dom { + +struct VideoFrameData { + VideoFrameData(layers::Image* aImage, const Maybe<VideoPixelFormat>& aFormat, + gfx::IntRect aVisibleRect, gfx::IntSize aDisplaySize, + Maybe<uint64_t> aDuration, int64_t aTimestamp, + const VideoColorSpaceInit& aColorSpace); + VideoFrameData(const VideoFrameData& aData) = default; + + const RefPtr<layers::Image> mImage; + const Maybe<VideoPixelFormat> mFormat; + const gfx::IntRect mVisibleRect; + const gfx::IntSize mDisplaySize; + const Maybe<uint64_t> mDuration; + const int64_t mTimestamp; + const VideoColorSpaceInit mColorSpace; +}; + +struct VideoFrameSerializedData : VideoFrameData { + VideoFrameSerializedData(const VideoFrameData& aData, + gfx::IntSize aCodedSize); + + const gfx::IntSize mCodedSize; +}; + +class VideoFrame final : public nsISupports, public nsWrapperCache { + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(VideoFrame) + + public: + VideoFrame(nsIGlobalObject* aParent, const RefPtr<layers::Image>& aImage, + const Maybe<VideoPixelFormat>& aFormat, gfx::IntSize aCodedSize, + gfx::IntRect aVisibleRect, gfx::IntSize aDisplaySize, + const Maybe<uint64_t>& aDuration, int64_t aTimestamp, + const VideoColorSpaceInit& aColorSpace); + VideoFrame(nsIGlobalObject* aParent, const VideoFrameSerializedData& aData); + VideoFrame(const VideoFrame& aOther); + + protected: + ~VideoFrame(); + + public: + nsIGlobalObject* GetParentObject() const; + + JSObject* WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; + + static already_AddRefed<VideoFrame> Constructor( + const GlobalObject& aGlobal, HTMLImageElement& aImageElement, + const VideoFrameInit& aInit, ErrorResult& aRv); + static already_AddRefed<VideoFrame> Constructor( + const GlobalObject& aGlobal, SVGImageElement& aSVGImageElement, + const VideoFrameInit& aInit, ErrorResult& aRv); + static already_AddRefed<VideoFrame> Constructor( + const GlobalObject& aGlobal, HTMLCanvasElement& aCanvasElement, + const VideoFrameInit& aInit, ErrorResult& aRv); + static already_AddRefed<VideoFrame> Constructor( + const GlobalObject& aGlobal, HTMLVideoElement& aVideoElement, + const VideoFrameInit& aInit, ErrorResult& aRv); + static already_AddRefed<VideoFrame> Constructor( + const GlobalObject& aGlobal, OffscreenCanvas& aOffscreenCanvas, + const VideoFrameInit& aInit, ErrorResult& aRv); + static already_AddRefed<VideoFrame> Constructor(const GlobalObject& aGlobal, + ImageBitmap& aImageBitmap, + const VideoFrameInit& aInit, + ErrorResult& aRv); + static already_AddRefed<VideoFrame> Constructor(const GlobalObject& aGlobal, + VideoFrame& aVideoFrame, + const VideoFrameInit& aInit, + ErrorResult& aRv); + static already_AddRefed<VideoFrame> Constructor( + const GlobalObject& aGlobal, const ArrayBufferView& aBufferView, + const VideoFrameBufferInit& aInit, ErrorResult& aRv); + static already_AddRefed<VideoFrame> Constructor( + const GlobalObject& aGlobal, const ArrayBuffer& aBuffer, + const VideoFrameBufferInit& aInit, ErrorResult& aRv); + + Nullable<VideoPixelFormat> GetFormat() const; + + uint32_t CodedWidth() const; + + uint32_t CodedHeight() const; + + already_AddRefed<DOMRectReadOnly> GetCodedRect() const; + + already_AddRefed<DOMRectReadOnly> GetVisibleRect() const; + + uint32_t DisplayWidth() const; + + uint32_t DisplayHeight() const; + + Nullable<uint64_t> GetDuration() const; + + int64_t Timestamp() const; + + already_AddRefed<VideoColorSpace> ColorSpace() const; + + uint32_t AllocationSize(const VideoFrameCopyToOptions& aOptions, + ErrorResult& aRv); + + already_AddRefed<Promise> CopyTo( + const MaybeSharedArrayBufferViewOrMaybeSharedArrayBuffer& aDestination, + const VideoFrameCopyToOptions& aOptions, ErrorResult& aRv); + + already_AddRefed<VideoFrame> Clone(ErrorResult& aRv) const; + + void Close(); + bool IsClosed() const; + + // [Serializable] implementations: {Read, Write}StructuredClone + static JSObject* ReadStructuredClone(JSContext* aCx, nsIGlobalObject* aGlobal, + JSStructuredCloneReader* aReader, + const VideoFrameSerializedData& aData); + + bool WriteStructuredClone(JSStructuredCloneWriter* aWriter, + StructuredCloneHolder* aHolder) const; + + // [Transferable] implementations: Transfer, FromTransferred + using TransferredData = VideoFrameSerializedData; + + UniquePtr<TransferredData> Transfer(); + + static already_AddRefed<VideoFrame> FromTransferred(nsIGlobalObject* aGlobal, + TransferredData* aData); + + // Native only methods. + const gfx::IntSize& NativeCodedSize() const { return mCodedSize; } + const gfx::IntSize& NativeDisplaySize() const { return mDisplaySize; } + const gfx::IntRect& NativeVisibleRect() const { return mVisibleRect; } + already_AddRefed<layers::Image> GetImage() const; + + nsCString ToString() const; + + public: + // A VideoPixelFormat wrapper providing utilities for VideoFrame. + class Format final { + public: + explicit Format(const VideoPixelFormat& aFormat); + ~Format() = default; + const VideoPixelFormat& PixelFormat() const; + gfx::SurfaceFormat ToSurfaceFormat() const; + void MakeOpaque(); + + // TODO: Assign unique value for each plane? + // The value indicates the order of the plane in format. + enum class Plane : uint8_t { Y = 0, RGBA = Y, U = 1, UV = U, V = 2, A = 3 }; + nsTArray<Plane> Planes() const; + const char* PlaneName(const Plane& aPlane) const; + uint32_t SampleBytes(const Plane& aPlane) const; + gfx::IntSize SampleSize(const Plane& aPlane) const; + bool IsValidSize(const gfx::IntSize& aSize) const; + size_t SampleCount(const gfx::IntSize& aSize) const; + + private: + bool IsYUV() const; + VideoPixelFormat mFormat; + }; + + private: + // VideoFrame can run on either main thread or worker thread. + void AssertIsOnOwningThread() const { NS_ASSERT_OWNINGTHREAD(VideoFrame); } + + VideoFrameData GetVideoFrameData() const; + + // Below helpers are used to automatically release the holding Resource if + // VideoFrame is never Close()d by the users. + void StartAutoClose(); + void StopAutoClose(); + void CloseIfNeeded(); + + // A class representing the VideoFrame's data. + class Resource final { + public: + Resource(const RefPtr<layers::Image>& aImage, Maybe<Format>&& aFormat); + Resource(const Resource& aOther); + ~Resource() = default; + Maybe<VideoPixelFormat> TryPixelFormat() const; + uint32_t Stride(const Format::Plane& aPlane) const; + bool CopyTo(const Format::Plane& aPlane, const gfx::IntRect& aRect, + Span<uint8_t>&& aPlaneDest, size_t aDestinationStride) const; + + const RefPtr<layers::Image> mImage; + // Nothing() if mImage is not in VideoPixelFormat + const Maybe<Format> mFormat; + }; + + nsCOMPtr<nsIGlobalObject> mParent; + + // Use Maybe instead of UniquePtr to allow copy ctor. + // The mResource's existence is used as the [[Detached]] for [Transferable]. + Maybe<const Resource> mResource; // Nothing() after `Close()`d + + // TODO: Replace this by mResource->mImage->GetSize()? + gfx::IntSize mCodedSize; + gfx::IntRect mVisibleRect; + gfx::IntSize mDisplaySize; + + Maybe<uint64_t> mDuration; + int64_t mTimestamp; + VideoColorSpaceInit mColorSpace; + + // The following are used to help monitoring mResource release. + UniquePtr<media::ShutdownBlockingTicket> mShutdownBlocker = nullptr; + RefPtr<WeakWorkerRef> mWorkerRef = nullptr; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_VideoFrame_h |