1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
|
/* -*- 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/ErrorResult.h"
#include "mozilla/Span.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/BufferSourceBindingFwd.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/VideoColorSpaceBinding.h"
#include "mozilla/dom/WebCodecsUtils.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/media/MediaUtils.h"
#include "nsCycleCollectionParticipant.h"
#include "nsTArrayForwardDeclare.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 OffscreenCanvas;
class Promise;
class SVGImageElement;
class StructuredCloneHolder;
class VideoColorSpace;
class VideoFrame;
enum class PredefinedColorSpace : uint8_t;
enum class VideoPixelFormat : uint8_t;
struct VideoFrameBufferInit;
struct VideoFrameCopyToOptions;
struct VideoFrameInit;
} // namespace dom
namespace webgpu {
class ExternalTexture;
} // namespace webgpu
} // 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 VideoColorSpaceInternal& 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 VideoColorSpaceInternal mColorSpace;
};
struct VideoFrameSerializedData : VideoFrameData {
VideoFrameSerializedData(const VideoFrameData& aData,
gfx::IntSize aCodedSize);
const gfx::IntSize mCodedSize;
};
class VideoFrame final : public nsISupports,
public nsWrapperCache,
public media::ShutdownConsumer {
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 VideoColorSpaceInternal& 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 bool PrefEnabled(JSContext* aCx, JSObject* aObj = nullptr);
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 AllowSharedBufferSource& aDestination,
const VideoFrameCopyToOptions& aOptions,
ErrorResult& aRv);
already_AddRefed<VideoFrame> Clone(ErrorResult& aRv) const;
void Close();
bool IsClosed() const;
void OnShutdown() override;
// [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;
// Track a WebGPU ExternalTexture as being imported from this video frame.
// This ensures it will be correctly expired when the video frame is closed.
void TrackWebGPUExternalTexture(
WeakPtr<webgpu::ExternalTexture> aExternalTexture);
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 ByteCount(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); }
already_AddRefed<VideoFrame> ConvertToRGBFrame(
const VideoPixelFormat& aFormat, const PredefinedColorSpace& aColorSpace);
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;
VideoColorSpaceInternal mColorSpace;
// The following are used to help monitoring mResource release.
RefPtr<media::ShutdownWatcher> mShutdownWatcher = nullptr;
// WebGPU external textures that were imported from this video frame. We must
// call `Expire()` on them when the video frame is closed.
nsTArray<WeakPtr<webgpu::ExternalTexture>> mWebGPUExternalTextures;
};
} // namespace mozilla::dom
#endif // mozilla_dom_VideoFrame_h
|