зеркало из https://github.com/mozilla/gecko-dev.git
307 строки
9.8 KiB
C++
307 строки
9.8 KiB
C++
/* -*- 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 "WebCodecsUtils.h"
|
|
|
|
#include "VideoUtils.h"
|
|
#include "js/experimental/TypedData.h"
|
|
#include "mozilla/Assertions.h"
|
|
#include "mozilla/CheckedInt.h"
|
|
#include "mozilla/dom/ImageBitmapBinding.h"
|
|
#include "mozilla/dom/VideoColorSpaceBinding.h"
|
|
#include "mozilla/dom/VideoFrameBinding.h"
|
|
#include "mozilla/gfx/Types.h"
|
|
#include "nsDebug.h"
|
|
|
|
namespace mozilla::dom {
|
|
|
|
/*
|
|
* The followings are helpers for VideoDecoder methods
|
|
*/
|
|
|
|
nsTArray<nsCString> GuessContainers(const nsAString& aCodec) {
|
|
if (IsAV1CodecString(aCodec)) {
|
|
return {"mp4"_ns, "webm"_ns};
|
|
}
|
|
|
|
if (IsVP9CodecString(aCodec)) {
|
|
return {"mp4"_ns, "webm"_ns, "ogg"_ns};
|
|
}
|
|
|
|
if (IsVP8CodecString(aCodec)) {
|
|
return {"webm"_ns, "ogg"_ns, "3gpp"_ns, "3gpp2"_ns, "3gp2"_ns};
|
|
}
|
|
|
|
if (IsH264CodecString(aCodec)) {
|
|
return {"mp4"_ns, "3gpp"_ns, "3gpp2"_ns, "3gp2"_ns};
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
/*
|
|
* The below are helpers to operate ArrayBuffer or ArrayBufferView.
|
|
*/
|
|
|
|
template <class T>
|
|
Result<Span<uint8_t>, nsresult> GetArrayBufferData(const T& aBuffer) {
|
|
// Get buffer's data and length before using it.
|
|
aBuffer.ComputeState();
|
|
|
|
CheckedInt<size_t> byteLength(sizeof(typename T::element_type));
|
|
byteLength *= aBuffer.Length();
|
|
if (NS_WARN_IF(!byteLength.isValid())) {
|
|
return Err(NS_ERROR_INVALID_ARG);
|
|
}
|
|
|
|
return Span<uint8_t>(aBuffer.Data(), byteLength.value());
|
|
}
|
|
|
|
Result<Span<uint8_t>, nsresult> GetSharedArrayBufferData(
|
|
const MaybeSharedArrayBufferViewOrMaybeSharedArrayBuffer& aBuffer) {
|
|
if (aBuffer.IsArrayBufferView()) {
|
|
return GetArrayBufferData(aBuffer.GetAsArrayBufferView());
|
|
}
|
|
|
|
MOZ_ASSERT(aBuffer.IsArrayBuffer());
|
|
return GetArrayBufferData(aBuffer.GetAsArrayBuffer());
|
|
}
|
|
|
|
Result<Span<uint8_t>, nsresult> GetSharedArrayBufferData(
|
|
const OwningMaybeSharedArrayBufferViewOrMaybeSharedArrayBuffer& aBuffer) {
|
|
if (aBuffer.IsArrayBufferView()) {
|
|
return GetArrayBufferData(aBuffer.GetAsArrayBufferView());
|
|
}
|
|
|
|
MOZ_ASSERT(aBuffer.IsArrayBuffer());
|
|
return GetArrayBufferData(aBuffer.GetAsArrayBuffer());
|
|
}
|
|
|
|
static std::tuple<JS::ArrayBufferOrView, size_t, size_t> GetArrayBufferInfo(
|
|
JSContext* aCx,
|
|
const OwningMaybeSharedArrayBufferViewOrMaybeSharedArrayBuffer& aBuffer) {
|
|
if (aBuffer.IsArrayBuffer()) {
|
|
const ArrayBuffer& buffer = aBuffer.GetAsArrayBuffer();
|
|
buffer.ComputeState();
|
|
CheckedInt<size_t> byteLength(buffer.Length());
|
|
byteLength *= sizeof(JS::ArrayBuffer::DataType);
|
|
return byteLength.isValid()
|
|
? std::make_tuple(
|
|
JS::ArrayBufferOrView::fromObject(buffer.Obj()), (size_t)0,
|
|
byteLength.value())
|
|
: std::make_tuple(JS::ArrayBufferOrView::fromObject(nullptr),
|
|
(size_t)0, (size_t)0);
|
|
}
|
|
|
|
MOZ_ASSERT(aBuffer.IsArrayBufferView());
|
|
const ArrayBufferView& view = aBuffer.GetAsArrayBufferView();
|
|
bool isSharedMemory;
|
|
JS::Rooted<JSObject*> obj(aCx, view.Obj());
|
|
return std::make_tuple(
|
|
JS::ArrayBufferOrView::fromObject(
|
|
JS_GetArrayBufferViewBuffer(aCx, obj, &isSharedMemory)),
|
|
JS_GetTypedArrayByteOffset(obj), JS_GetTypedArrayByteLength(obj));
|
|
}
|
|
|
|
Result<Ok, nsresult> CloneBuffer(
|
|
JSContext* aCx,
|
|
OwningMaybeSharedArrayBufferViewOrMaybeSharedArrayBuffer& aDest,
|
|
const OwningMaybeSharedArrayBufferViewOrMaybeSharedArrayBuffer& aSrc) {
|
|
std::tuple<JS::ArrayBufferOrView, size_t, size_t> info =
|
|
GetArrayBufferInfo(aCx, aSrc);
|
|
JS::Rooted<JS::ArrayBufferOrView> abov(aCx);
|
|
abov.set(std::get<0>(info));
|
|
size_t offset = std::get<1>(info);
|
|
size_t len = std::get<2>(info);
|
|
if (NS_WARN_IF(!abov)) {
|
|
return Err(NS_ERROR_UNEXPECTED);
|
|
}
|
|
|
|
JS::Rooted<JSObject*> obj(aCx, abov.asObject());
|
|
JS::Rooted<JSObject*> cloned(aCx,
|
|
JS::ArrayBufferClone(aCx, obj, offset, len));
|
|
if (NS_WARN_IF(!cloned)) {
|
|
return Err(NS_ERROR_OUT_OF_MEMORY);
|
|
}
|
|
|
|
JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*cloned));
|
|
if (NS_WARN_IF(!aDest.Init(aCx, value))) {
|
|
return Err(NS_ERROR_UNEXPECTED);
|
|
}
|
|
return Ok();
|
|
}
|
|
|
|
/*
|
|
* The following are utilities to convert between VideoColorSpace values to
|
|
* gfx's values.
|
|
*/
|
|
|
|
gfx::ColorRange ToColorRange(bool aIsFullRange) {
|
|
return aIsFullRange ? gfx::ColorRange::FULL : gfx::ColorRange::LIMITED;
|
|
}
|
|
|
|
gfx::YUVColorSpace ToColorSpace(VideoMatrixCoefficients aMatrix) {
|
|
switch (aMatrix) {
|
|
case VideoMatrixCoefficients::Rgb:
|
|
return gfx::YUVColorSpace::Identity;
|
|
case VideoMatrixCoefficients::Bt709:
|
|
case VideoMatrixCoefficients::Bt470bg:
|
|
return gfx::YUVColorSpace::BT709;
|
|
case VideoMatrixCoefficients::Smpte170m:
|
|
return gfx::YUVColorSpace::BT601;
|
|
case VideoMatrixCoefficients::Bt2020_ncl:
|
|
return gfx::YUVColorSpace::BT2020;
|
|
case VideoMatrixCoefficients::EndGuard_:
|
|
break;
|
|
}
|
|
MOZ_ASSERT_UNREACHABLE("unsupported VideoMatrixCoefficients");
|
|
return gfx::YUVColorSpace::Default;
|
|
}
|
|
|
|
gfx::TransferFunction ToTransferFunction(
|
|
VideoTransferCharacteristics aTransfer) {
|
|
switch (aTransfer) {
|
|
case VideoTransferCharacteristics::Bt709:
|
|
case VideoTransferCharacteristics::Smpte170m:
|
|
return gfx::TransferFunction::BT709;
|
|
case VideoTransferCharacteristics::Iec61966_2_1:
|
|
return gfx::TransferFunction::SRGB;
|
|
case VideoTransferCharacteristics::Pq:
|
|
return gfx::TransferFunction::PQ;
|
|
case VideoTransferCharacteristics::Hlg:
|
|
return gfx::TransferFunction::HLG;
|
|
case VideoTransferCharacteristics::Linear:
|
|
case VideoTransferCharacteristics::EndGuard_:
|
|
break;
|
|
}
|
|
MOZ_ASSERT_UNREACHABLE("unsupported VideoTransferCharacteristics");
|
|
return gfx::TransferFunction::Default;
|
|
}
|
|
|
|
gfx::ColorSpace2 ToPrimaries(VideoColorPrimaries aPrimaries) {
|
|
switch (aPrimaries) {
|
|
case VideoColorPrimaries::Bt709:
|
|
return gfx::ColorSpace2::BT709;
|
|
case VideoColorPrimaries::Bt470bg:
|
|
return gfx::ColorSpace2::BT601_625;
|
|
case VideoColorPrimaries::Smpte170m:
|
|
return gfx::ColorSpace2::BT601_525;
|
|
case VideoColorPrimaries::Bt2020:
|
|
return gfx::ColorSpace2::BT2020;
|
|
case VideoColorPrimaries::Smpte432:
|
|
return gfx::ColorSpace2::DISPLAY_P3;
|
|
case VideoColorPrimaries::EndGuard_:
|
|
break;
|
|
}
|
|
MOZ_ASSERT_UNREACHABLE("unsupported VideoTransferCharacteristics");
|
|
return gfx::ColorSpace2::UNKNOWN;
|
|
}
|
|
|
|
bool ToFullRange(const gfx::ColorRange& aColorRange) {
|
|
return aColorRange == gfx::ColorRange::FULL;
|
|
}
|
|
|
|
Maybe<VideoMatrixCoefficients> ToMatrixCoefficients(
|
|
const gfx::YUVColorSpace& aColorSpace) {
|
|
switch (aColorSpace) {
|
|
case gfx::YUVColorSpace::BT601:
|
|
return Some(VideoMatrixCoefficients::Smpte170m);
|
|
case gfx::YUVColorSpace::BT709:
|
|
return Some(VideoMatrixCoefficients::Bt709);
|
|
case gfx::YUVColorSpace::BT2020:
|
|
return Some(VideoMatrixCoefficients::Bt2020_ncl);
|
|
case gfx::YUVColorSpace::Identity:
|
|
return Some(VideoMatrixCoefficients::Rgb);
|
|
}
|
|
MOZ_ASSERT_UNREACHABLE("unsupported gfx::YUVColorSpace");
|
|
return Nothing();
|
|
}
|
|
|
|
Maybe<VideoTransferCharacteristics> ToTransferCharacteristics(
|
|
const gfx::TransferFunction& aTransferFunction) {
|
|
switch (aTransferFunction) {
|
|
case gfx::TransferFunction::BT709:
|
|
return Some(VideoTransferCharacteristics::Bt709);
|
|
case gfx::TransferFunction::SRGB:
|
|
return Some(VideoTransferCharacteristics::Iec61966_2_1);
|
|
case gfx::TransferFunction::PQ:
|
|
return Some(VideoTransferCharacteristics::Pq);
|
|
case gfx::TransferFunction::HLG:
|
|
return Some(VideoTransferCharacteristics::Hlg);
|
|
}
|
|
MOZ_ASSERT_UNREACHABLE("unsupported gfx::TransferFunction");
|
|
return Nothing();
|
|
}
|
|
|
|
Maybe<VideoColorPrimaries> ToPrimaries(const gfx::ColorSpace2& aColorSpace) {
|
|
switch (aColorSpace) {
|
|
case gfx::ColorSpace2::UNKNOWN:
|
|
case gfx::ColorSpace2::SRGB:
|
|
return Nothing();
|
|
case gfx::ColorSpace2::DISPLAY_P3:
|
|
return Some(VideoColorPrimaries::Smpte432);
|
|
case gfx::ColorSpace2::BT601_525:
|
|
return Some(VideoColorPrimaries::Smpte170m);
|
|
case gfx::ColorSpace2::BT709:
|
|
return Some(VideoColorPrimaries::Bt709);
|
|
case gfx::ColorSpace2::BT2020:
|
|
return Some(VideoColorPrimaries::Bt2020);
|
|
}
|
|
MOZ_ASSERT_UNREACHABLE("unsupported gfx::ColorSpace2");
|
|
return Nothing();
|
|
}
|
|
|
|
/*
|
|
* The following are utilities to convert from gfx's formats to
|
|
* VideoPixelFormats.
|
|
*/
|
|
|
|
Maybe<VideoPixelFormat> SurfaceFormatToVideoPixelFormat(
|
|
gfx::SurfaceFormat aFormat) {
|
|
switch (aFormat) {
|
|
case gfx::SurfaceFormat::B8G8R8A8:
|
|
return Some(VideoPixelFormat::BGRA);
|
|
case gfx::SurfaceFormat::B8G8R8X8:
|
|
return Some(VideoPixelFormat::BGRX);
|
|
case gfx::SurfaceFormat::R8G8B8A8:
|
|
return Some(VideoPixelFormat::RGBA);
|
|
case gfx::SurfaceFormat::R8G8B8X8:
|
|
return Some(VideoPixelFormat::RGBX);
|
|
case gfx::SurfaceFormat::YUV:
|
|
return Some(VideoPixelFormat::I420);
|
|
case gfx::SurfaceFormat::NV12:
|
|
return Some(VideoPixelFormat::NV12);
|
|
case gfx::SurfaceFormat::YUV422:
|
|
return Some(VideoPixelFormat::I422);
|
|
default:
|
|
break;
|
|
}
|
|
return Nothing();
|
|
}
|
|
|
|
Maybe<VideoPixelFormat> ImageBitmapFormatToVideoPixelFormat(
|
|
ImageBitmapFormat aFormat) {
|
|
switch (aFormat) {
|
|
case ImageBitmapFormat::RGBA32:
|
|
return Some(VideoPixelFormat::RGBA);
|
|
case ImageBitmapFormat::BGRA32:
|
|
return Some(VideoPixelFormat::BGRA);
|
|
case ImageBitmapFormat::YUV444P:
|
|
return Some(VideoPixelFormat::I444);
|
|
case ImageBitmapFormat::YUV422P:
|
|
return Some(VideoPixelFormat::I422);
|
|
case ImageBitmapFormat::YUV420P:
|
|
return Some(VideoPixelFormat::I420);
|
|
case ImageBitmapFormat::YUV420SP_NV12:
|
|
return Some(VideoPixelFormat::NV12);
|
|
default:
|
|
break;
|
|
}
|
|
return Nothing();
|
|
}
|
|
|
|
} // namespace mozilla::dom
|