diff options
Diffstat (limited to 'dom/media/webcodecs/VideoDecoder.cpp')
-rw-r--r-- | dom/media/webcodecs/VideoDecoder.cpp | 97 |
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(); } |