summaryrefslogtreecommitdiffstats
path: root/dom/media/webcodecs/VideoDecoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/webcodecs/VideoDecoder.cpp')
-rw-r--r--dom/media/webcodecs/VideoDecoder.cpp97
1 files changed, 31 insertions, 66 deletions
diff --git a/dom/media/webcodecs/VideoDecoder.cpp b/dom/media/webcodecs/VideoDecoder.cpp
index 47ca5bb459..18855e5cea 100644
--- a/dom/media/webcodecs/VideoDecoder.cpp
+++ b/dom/media/webcodecs/VideoDecoder.cpp
@@ -15,11 +15,8 @@
#include "MediaData.h"
#include "VideoUtils.h"
#include "mozilla/Assertions.h"
-#include "mozilla/CheckedInt.h"
-#include "mozilla/DebugOnly.h"
#include "mozilla/Logging.h"
#include "mozilla/Maybe.h"
-#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/Try.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/EncodedVideoChunk.h"
@@ -31,7 +28,6 @@
#include "mozilla/dom/WebCodecsUtils.h"
#include "nsPrintfCString.h"
#include "nsReadableUtils.h"
-#include "nsThreadUtils.h"
#ifdef XP_MACOSX
# include "MacIOSurfaceImage.h"
@@ -97,9 +93,6 @@ VideoColorSpaceInit VideoColorSpaceInternal::ToColorSpaceInit() const {
return init;
};
-static Result<RefPtr<MediaByteBuffer>, nsresult> GetExtraData(
- const OwningMaybeSharedArrayBufferViewOrMaybeSharedArrayBuffer& aBuffer);
-
VideoDecoderConfigInternal::VideoDecoderConfigInternal(
const nsAString& aCodec, Maybe<uint32_t>&& aCodedHeight,
Maybe<uint32_t>&& aCodedWidth, Maybe<VideoColorSpaceInternal>&& aColorSpace,
@@ -129,7 +122,7 @@ UniquePtr<VideoDecoderConfigInternal> VideoDecoderConfigInternal::Create(
Maybe<RefPtr<MediaByteBuffer>> description;
if (aConfig.mDescription.WasPassed()) {
- auto rv = GetExtraData(aConfig.mDescription.Value());
+ auto rv = GetExtraDataFromArrayBuffer(aConfig.mDescription.Value());
if (rv.isErr()) { // Invalid description data.
LOGE(
"Failed to create VideoDecoderConfigInternal due to invalid "
@@ -168,12 +161,10 @@ nsString VideoDecoderConfigInternal::ToString() const {
if (mColorSpace.isSome()) {
rv.AppendPrintf("colorspace %s", "todo");
}
- if (mDescription.isSome()) {
+ if (mDescription.isSome() && mDescription.value()) {
rv.AppendPrintf("extradata: %zu bytes", mDescription.value()->Length());
}
- rv.AppendPrintf(
- "hw accel: %s",
- HardwareAccelerationValues::GetString(mHardwareAcceleration).data());
+ rv.AppendPrintf("hw accel: %s", GetEnumString(mHardwareAcceleration).get());
if (mOptimizeForLatency.isSome()) {
rv.AppendPrintf("optimize for latency: %s",
mOptimizeForLatency.value() ? "true" : "false");
@@ -217,24 +208,6 @@ static nsTArray<nsCString> GuessMIMETypes(const MIMECreateParam& aParam) {
return types;
}
-static bool IsSupportedCodec(const nsAString& aCodec) {
- // H265 is unsupported.
- if (!IsAV1CodecString(aCodec) && !IsVP9CodecString(aCodec) &&
- !IsVP8CodecString(aCodec) && !IsH264CodecString(aCodec)) {
- return false;
- }
-
- // Gecko allows codec string starts with vp9 or av1 but Webcodecs requires to
- // starts with av01 and vp09.
- // https://www.w3.org/TR/webcodecs-codec-registry/#video-codec-registry
- if (StringBeginsWith(aCodec, u"vp9"_ns) ||
- StringBeginsWith(aCodec, u"av1"_ns)) {
- return false;
- }
-
- return true;
-}
-
// https://w3c.github.io/webcodecs/#check-configuration-support
template <typename Config>
static bool CanDecode(const Config& aConfig) {
@@ -243,12 +216,7 @@ static bool CanDecode(const Config& aConfig) {
if (IsOnAndroid()) {
return false;
}
- if (!IsSupportedCodec(param.mParsedCodec)) {
- return false;
- }
- if (IsOnMacOS() && IsH264CodecString(param.mParsedCodec) &&
- !StaticPrefs::dom_media_webcodecs_force_osx_h264_enabled()) {
- // This will be fixed in Bug 1846796.
+ if (!IsSupportedVideoCodec(param.mParsedCodec)) {
return false;
}
// TODO: Instead of calling CanHandleContainerType with the guessed the
@@ -284,18 +252,9 @@ static nsTArray<UniquePtr<TrackInfo>> GetTracksInfo(
return {};
}
-static Result<RefPtr<MediaByteBuffer>, nsresult> GetExtraData(
- const OwningMaybeSharedArrayBufferViewOrMaybeSharedArrayBuffer& aBuffer) {
- RefPtr<MediaByteBuffer> data = MakeRefPtr<MediaByteBuffer>();
- if (!AppendTypedArrayDataTo(aBuffer, *data)) {
- return Err(NS_ERROR_OUT_OF_MEMORY);
- }
- return data->Length() > 0 ? data : nullptr;
-}
-
static Result<Ok, nsresult> CloneConfiguration(
RootedDictionary<VideoDecoderConfig>& aDest, JSContext* aCx,
- const VideoDecoderConfig& aConfig) {
+ const VideoDecoderConfig& aConfig, ErrorResult& aRv) {
DebugOnly<nsCString> str;
MOZ_ASSERT(VideoDecoderTraits::Validate(aConfig, str));
@@ -312,7 +271,7 @@ static Result<Ok, nsresult> CloneConfiguration(
if (aConfig.mDescription.WasPassed()) {
aDest.mDescription.Construct();
MOZ_TRY(CloneBuffer(aCx, aDest.mDescription.Value(),
- aConfig.mDescription.Value()));
+ aConfig.mDescription.Value(), aRv));
}
if (aConfig.mDisplayAspectHeight.WasPassed()) {
aDest.mDisplayAspectHeight.Construct(aConfig.mDisplayAspectHeight.Value());
@@ -334,8 +293,10 @@ static Maybe<VideoPixelFormat> GuessPixelFormat(layers::Image* aImage) {
// DMABUFSurfaceImage?
if (aImage->AsPlanarYCbCrImage() || aImage->AsNVImage()) {
const ImageUtils imageUtils(aImage);
+ Maybe<dom::ImageBitmapFormat> format = imageUtils.GetFormat();
Maybe<VideoPixelFormat> f =
- ImageBitmapFormatToVideoPixelFormat(imageUtils.GetFormat());
+ format.isSome() ? ImageBitmapFormatToVideoPixelFormat(format.value())
+ : Nothing();
// ImageBitmapFormat cannot distinguish YUV420 or YUV420A.
bool hasAlpha = aImage->AsPlanarYCbCrImage() &&
@@ -391,8 +352,6 @@ static VideoColorSpaceInternal GuessColorSpace(
// Make an educated guess based on the coefficients.
colorSpace.mPrimaries = colorSpace.mMatrix.map([](const auto& aMatrix) {
switch (aMatrix) {
- case VideoMatrixCoefficients::EndGuard_:
- MOZ_CRASH("This should not happen");
case VideoMatrixCoefficients::Bt2020_ncl:
return VideoColorPrimaries::Bt2020;
case VideoMatrixCoefficients::Rgb:
@@ -529,9 +488,6 @@ static VideoColorSpaceInternal GuessColorSpace(layers::Image* aImage) {
case VideoMatrixCoefficients::Bt2020_ncl:
colorSpace.mPrimaries = Some(VideoColorPrimaries::Bt2020);
break;
- case VideoMatrixCoefficients::EndGuard_:
- MOZ_ASSERT_UNREACHABLE("bad enum value");
- break;
};
}
}
@@ -794,6 +750,21 @@ bool VideoDecoderTraits::Validate(const VideoDecoderConfig& aConfig,
return false;
}
+ bool detached =
+ aConfig.mDescription.WasPassed() &&
+ (aConfig.mDescription.Value().IsArrayBuffer()
+ ? JS::ArrayBuffer::fromObject(
+ aConfig.mDescription.Value().GetAsArrayBuffer().Obj())
+ .isDetached()
+ : JS::ArrayBufferView::fromObject(
+ aConfig.mDescription.Value().GetAsArrayBufferView().Obj())
+ .isDetached());
+
+ if (detached) {
+ LOGE("description is detached.");
+ return false;
+ }
+
return true;
}
@@ -828,9 +799,7 @@ VideoDecoder::VideoDecoder(nsIGlobalObject* aParent,
LOG("VideoDecoder %p ctor", this);
}
-VideoDecoder::~VideoDecoder() {
- LOG("VideoDecoder %p dtor", this);
-}
+VideoDecoder::~VideoDecoder() { LOG("VideoDecoder %p dtor", this); }
JSObject* VideoDecoder::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
@@ -877,21 +846,17 @@ already_AddRefed<Promise> VideoDecoder::IsConfigSupported(
nsCString errorMessage;
if (!VideoDecoderTraits::Validate(aConfig, errorMessage)) {
p->MaybeRejectWithTypeError(nsPrintfCString(
- "VideoDecoderConfig is invalid: %s", errorMessage.get()));
+ "IsConfigSupported: config is invalid: %s", errorMessage.get()));
return p.forget();
}
- // TODO: Move the following works to another thread to unblock the current
- // thread, as what spec suggests.
-
RootedDictionary<VideoDecoderConfig> config(aGlobal.Context());
- auto r = CloneConfiguration(config, aGlobal.Context(), aConfig);
+ auto r = CloneConfiguration(config, aGlobal.Context(), aConfig, aRv);
if (r.isErr()) {
- nsresult e = r.unwrapErr();
- LOGE("Failed to clone VideoDecoderConfig. Error: 0x%08" PRIx32,
- static_cast<uint32_t>(e));
- p->MaybeRejectWithTypeError("Failed to clone VideoDecoderConfig");
- aRv.Throw(e);
+ // This can only be an OOM: all members to clone are known to be valid
+ // because this is check by ::Validate above.
+ MOZ_ASSERT(r.inspectErr() == NS_ERROR_OUT_OF_MEMORY &&
+ aRv.ErrorCodeIs(NS_ERROR_OUT_OF_MEMORY));
return p.forget();
}