From 9aea199da0312640208f3c0a6d47951fb9975984 Mon Sep 17 00:00:00 2001 From: trav90 Date: Mon, 15 Oct 2018 22:09:04 -0500 Subject: Add AOMDecoder Port the VPXDecoder interface to libaom which uses the same api with the names changed. --- dom/media/platforms/agnostic/AOMDecoder.cpp | 244 ++++++++++++++++++++++++++++ dom/media/platforms/agnostic/AOMDecoder.h | 62 +++++++ dom/media/platforms/moz.build | 8 + 3 files changed, 314 insertions(+) create mode 100644 dom/media/platforms/agnostic/AOMDecoder.cpp create mode 100644 dom/media/platforms/agnostic/AOMDecoder.h (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp new file mode 100644 index 000000000..30077ee03 --- /dev/null +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -0,0 +1,244 @@ +/* -*- 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 "AOMDecoder.h" +#include "MediaResult.h" +#include "TimeUnits.h" +#include "aom/aomdx.h" +#include "gfx2DGlue.h" +#include "mozilla/PodOperations.h" +#include "mozilla/SyncRunnable.h" +#include "nsError.h" +#include "prsystem.h" + +#include + +#undef LOG +#define LOG(arg, ...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, ("AOMDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) + +namespace mozilla { + +using namespace gfx; +using namespace layers; + +AOMDecoder::AOMDecoder(const CreateDecoderParams& aParams) + : mImageContainer(aParams.mImageContainer) + , mTaskQueue(aParams.mTaskQueue) + , mCallback(aParams.mCallback) + , mIsFlushing(false) + , mInfo(aParams.VideoConfig()) +{ + PodZero(&mCodec); +} + +AOMDecoder::~AOMDecoder() +{ +} + +void +AOMDecoder::Shutdown() +{ + aom_codec_destroy(&mCodec); +} + +RefPtr +AOMDecoder::Init() +{ + int decode_threads = 2; + aom_codec_iface_t* dx = aom_codec_av1_dx(); + if (aInfo.mDisplay.width >= 2048) { + decode_threads = 8; + } + else if (aInfo.mDisplay.width >= 1024) { + decode_threads = 4; + } + decode_threads = std::min(decode_threads, PR_GetNumberOfProcessors()); + + aom_codec_dec_cfg_t config; + PodZero(&config); + config.threads = decode_threads; + config.w = config.h = 0; // set after decode + + aom_codec_flags_t flags = 0; + + if (!dx || aom_codec_dec_init(aCtx, dx, &config, flags) { + return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); + } + return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__); +} + +void +AOMDecoder::Flush() +{ + MOZ_ASSERT(mCallback->OnReaderTaskQueue()); + mIsFlushing = true; + nsCOMPtr r = NS_NewRunnableFunction([this] () { + // nothing to do for now. + }); + SyncRunnable::DispatchToThread(mTaskQueue, r); + mIsFlushing = false; +} + +MediaResult +AOMDecoder::DoDecode(MediaRawData* aSample) +{ + MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); + +#if defined(DEBUG) + NS_ASSERTION(IsKeyframe(*aSample) == aSample->mKeyframe, + "AOM Decode Keyframe error sample->mKeyframe and si.si_kf out of sync"); +#endif + + if (aom_codec_err_t r = aom_codec_decode(&mCodec, aSample->Data(), aSample->Size(), nullptr, 0)) { + LOG("AOM Decode error: %s", aom_codec_err_to_string(r)); + return MediaResult( + NS_ERROR_DOM_MEDIA_DECODE_ERR, + RESULT_DETAIL("AOM error decoding AV1 sample: %s", aom_codec_err_to_string(r))); + } + + aom_codec_iter_t iter = nullptr; + aom_image_t *img; + + while ((img = aom_codec_get_frame(&mCodec, &iter))) { + NS_ASSERTION(img->fmt == AOM_IMG_FMT_I420 || + img->fmt == AOM_IMG_FMT_I444, + "WebM image format not I420 or I444"); + + // Chroma shifts are rounded down as per the decoding examples in the SDK + VideoData::YCbCrBuffer b; + b.mPlanes[0].mData = img->planes[0]; + b.mPlanes[0].mStride = img->stride[0]; + b.mPlanes[0].mHeight = img->d_h; + b.mPlanes[0].mWidth = img->d_w; + b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0; + + b.mPlanes[1].mData = img->planes[1]; + b.mPlanes[1].mStride = img->stride[1]; + b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0; + + b.mPlanes[2].mData = img->planes[2]; + b.mPlanes[2].mStride = img->stride[2]; + b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0; + + if (img->fmt == AOM_IMG_FMT_I420) { + b.mPlanes[1].mHeight = (img->d_h + 1) >> img->y_chroma_shift; + b.mPlanes[1].mWidth = (img->d_w + 1) >> img->x_chroma_shift; + + b.mPlanes[2].mHeight = (img->d_h + 1) >> img->y_chroma_shift; + b.mPlanes[2].mWidth = (img->d_w + 1) >> img->x_chroma_shift; + } else if (img->fmt == AOM_IMG_FMT_I444) { + b.mPlanes[1].mHeight = img->d_h; + b.mPlanes[1].mWidth = img->d_w; + + b.mPlanes[2].mHeight = img->d_h; + b.mPlanes[2].mWidth = img->d_w; + } else { + LOG("AOM Unknown image format"); + return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, + RESULT_DETAIL("AOM Unknown image format")); + } + + RefPtr v; + v = VideoData::CreateAndCopyData(mInfo, + mImageContainer, + aSample->mOffset, + aSample->mTime, + aSample->mDuration, + b, + aSample->mKeyframe, + aSample->mTimecode, + mInfo.ScaledImageRect(img->d_w, + img->d_h)); + + if (!v) { + LOG( + "Image allocation error source %ux%u display %ux%u picture %ux%u", + img->d_w, img->d_h, mInfo.mDisplay.width, mInfo.mDisplay.height, + mInfo.mImage.width, mInfo.mImage.height); + return MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__); + } + mCallback->Output(v); + } + return NS_OK; +} + +void +AOMDecoder::ProcessDecode(MediaRawData* aSample) +{ + MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); + if (mIsFlushing) { + return; + } + MediaResult rv = DoDecode(aSample); + if (NS_FAILED(rv)) { + mCallback->Error(rv); + } else { + mCallback->InputExhausted(); + } +} + +void +AOMDecoder::Input(MediaRawData* aSample) +{ + MOZ_ASSERT(mCallback->OnReaderTaskQueue()); + mTaskQueue->Dispatch(NewRunnableMethod>( + this, &AOMDecoder::ProcessDecode, aSample)); +} + +void +AOMDecoder::ProcessDrain() +{ + MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); + mCallback->DrainComplete(); +} + +void +AOMDecoder::Drain() +{ + MOZ_ASSERT(mCallback->OnReaderTaskQueue()); + mTaskQueue->Dispatch(NewRunnableMethod(this, &AOMDecoder::ProcessDrain)); +} + +/* static */ +bool +AOMDecoder::IsAV1(const nsACString& aMimeType) +{ + return aMimeType.EqualsLiteral("video/webm; codecs=av1") + || aMimeType.EqualsLiteral("video/av1"); +} + +/* static */ +bool +AOMDecoder::IsKeyframe(Span aBuffer) { + aom_codec_stream_info_t info; + PodZero(&info); + info.sz = sizeof(info); + + aom_codec_peek_stream_info(aom_codec_av1_dx(), + aBuffer.Elements(), + aBuffer.Length(), + &info); + + return bool(info.is_kf); +} + +/* static */ +nsIntSize +AOMDecoder::GetFrameSize(Span aBuffer) { + aom_codec_stream_info_t info; + PodZero(&info); + info.sz = sizeof(info); + + aom_codec_peek_stream_info(aom_codec_av1_dx(), + aBuffer.Elements(), + aBuffer.Length(), + &info); + + return nsIntSize(info.w, info.h); +} + +} // namespace mozilla +#undef LOG diff --git a/dom/media/platforms/agnostic/AOMDecoder.h b/dom/media/platforms/agnostic/AOMDecoder.h new file mode 100644 index 000000000..ec6b1f95a --- /dev/null +++ b/dom/media/platforms/agnostic/AOMDecoder.h @@ -0,0 +1,62 @@ +/* -*- 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/. */ + +#if !defined(AOMDecoder_h_) +#define AOMDecoder_h_ + +#include "PlatformDecoderModule.h" +#include "mozilla/Span.h" + +#include +#include "aom/aom_decoder.h" + +namespace mozilla { + +class AOMDecoder : public MediaDataDecoder +{ +public: + explicit AOMDecoder(const CreateDecoderParams& aParams); + + RefPtr Init() override; + void Input(MediaRawData* aSample) override; + void Flush() override; + void Drain() override; + void Shutdown() override; + const char* GetDescriptionName() const override + { + return "libaom (AV1) video decoder"; + } + + // Return true if aMimeType is a one of the strings used + // by our demuxers to identify AV1 streams. + static bool IsAV1(const nsACString& aMimeType); + + // Return true if a sample is a keyframe. + static bool IsKeyframe(Span aBuffer); + + // Return the frame dimensions for a sample. + static nsIntSize GetFrameSize(Span aBuffer); + +private: + ~AOMDecoder(); + void ProcessDecode(MediaRawData* aSample); + MediaResult DoDecode(MediaRawData* aSample); + void ProcessDrain(); + + const RefPtr mImageContainer; + const RefPtr mTaskQueue; + MediaDataDecoderCallback* mCallback; + Atomic mIsFlushing; + + // AOM decoder state + aom_codec_ctx_t mCodec; + + const VideoInfo& mInfo; +}; + +} // namespace mozilla + +#endif // AOMDecoder_h_ diff --git a/dom/media/platforms/moz.build b/dom/media/platforms/moz.build index 3fb0cc842..be13d31c4 100644 --- a/dom/media/platforms/moz.build +++ b/dom/media/platforms/moz.build @@ -55,6 +55,14 @@ if CONFIG['MOZ_FFMPEG']: 'ffmpeg', ] +if CONFIG['MOZ_AV1']: + EXPORTS += [ + 'agnostic/AOMDecoder.h', + ] + UNIFIED_SOURCES += [ + 'agnostic/AOMDecoder.cpp', + ] + if CONFIG['MOZ_APPLEMEDIA']: EXPORTS += [ 'apple/AppleDecoderModule.h', -- cgit v1.2.3 From 3e0443e4c1ea6612d722c3a5b38843e0da451e81 Mon Sep 17 00:00:00 2001 From: trav90 Date: Mon, 15 Oct 2018 22:10:46 -0500 Subject: Add AOMDecoder to AgnosticDecoderModule --- dom/media/platforms/agnostic/AgnosticDecoderModule.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp b/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp index 7bd75b7fe..4d4a90bd4 100644 --- a/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp +++ b/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp @@ -12,6 +12,10 @@ #include "WAVDecoder.h" #include "TheoraDecoder.h" +#ifdef MOZ_AV1 +#include "AOMDecoder.h" +#endif + namespace mozilla { bool @@ -20,6 +24,9 @@ AgnosticDecoderModule::SupportsMimeType(const nsACString& aMimeType, { bool supports = VPXDecoder::IsVPX(aMimeType) || +#ifdef MOZ_AV1 + AOMDecoder::IsAV1(aMimeType) || +#endif OpusDataDecoder::IsOpus(aMimeType) || VorbisDataDecoder::IsVorbis(aMimeType) || WaveDataDecoder::IsWave(aMimeType) || @@ -36,7 +43,13 @@ AgnosticDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams) if (VPXDecoder::IsVPX(aParams.mConfig.mMimeType)) { m = new VPXDecoder(aParams); - } else if (TheoraDecoder::IsTheora(aParams.mConfig.mMimeType)) { + } +#ifdef MOZ_AV1 + else if (AOMDecoder::IsAV1(aParams.mConfig.mMimeType)) { + m = new AOMDecoder(aParams); + } +#endif + else if (TheoraDecoder::IsTheora(aParams.mConfig.mMimeType)) { m = new TheoraDecoder(aParams); } -- cgit v1.2.3 From ee2cb65e248717b22104e802584cf1d7a4a916ad Mon Sep 17 00:00:00 2001 From: trav90 Date: Mon, 15 Oct 2018 22:11:24 -0500 Subject: Recognize AV1 in WebMDemuxer Call AOMDecoder to handle AV1 video tracks from the WebM container. The new decoder is very similar to VPXDecoder so we can use parallel calls. This codec is still build-time conditional. --- dom/media/webm/WebMDemuxer.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'dom') diff --git a/dom/media/webm/WebMDemuxer.cpp b/dom/media/webm/WebMDemuxer.cpp index b54739c06..013da9b2c 100644 --- a/dom/media/webm/WebMDemuxer.cpp +++ b/dom/media/webm/WebMDemuxer.cpp @@ -8,6 +8,9 @@ #include "MediaDecoderStateMachine.h" #include "AbstractMediaDecoder.h" #include "MediaResource.h" +#ifdef MOZ_AV1 +#include "AOMDecoder.h" +#endif #include "OpusDecoder.h" #include "VPXDecoder.h" #include "WebMDemuxer.h" @@ -320,6 +323,9 @@ WebMDemuxer::ReadMetadata() case NESTEGG_CODEC_VP9: mInfo.mVideo.mMimeType = "video/webm; codecs=vp9"; break; + case NESTEGG_CODEC_AV1: + mInfo.mVideo.mMimeType = "video/webm; codecs=av1"; + break; default: NS_WARNING("Unknown WebM video codec"); return NS_ERROR_FAILURE; @@ -651,6 +657,11 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl case NESTEGG_CODEC_VP9: isKeyframe = VPXDecoder::IsKeyframe(sample, VPXDecoder::Codec::VP9); break; +#ifdef MOZ_AV1 + case NESTEGG_CODEC_AV1: + isKeyframe = AOMDecoder::IsKeyframe(sample); + break; +#endif default: NS_WARNING("Cannot detect keyframes in unknown WebM video codec"); return NS_ERROR_FAILURE; @@ -658,10 +669,20 @@ WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSampl if (isKeyframe) { // For both VP8 and VP9, we only look for resolution changes // on keyframes. Other resolution changes are invalid. - auto codec = mVideoCodec == NESTEGG_CODEC_VP8 - ? VPXDecoder::Codec::VP8 - : VPXDecoder::Codec::VP9; - auto dimensions = VPXDecoder::GetFrameSize(sample, codec); + auto dimensions = nsIntSize(0, 0); + switch (mVideoCodec) { + case NESTEGG_CODEC_VP8: + dimensions = VPXDecoder::GetFrameSize(sample, VPXDecoder::Codec::VP8); + break; + case NESTEGG_CODEC_VP9: + dimensions = VPXDecoder::GetFrameSize(sample, VPXDecoder::Codec::VP9); + break; +#ifdef MOZ_AV1 + case NESTEGG_CODEC_AV1: + dimensions = AOMDecoder::GetFrameSize(sample); + break; +#endif + } if (mLastSeenFrameSize.isSome() && (dimensions != mLastSeenFrameSize.value())) { mInfo.mVideo.mDisplay = dimensions; -- cgit v1.2.3 From e5545e10a613bf0584ef8050856df1625551c0d7 Mon Sep 17 00:00:00 2001 From: trav90 Date: Mon, 15 Oct 2018 22:11:48 -0500 Subject: Add missing includes to WebMDemuxer --- dom/media/webm/WebMDemuxer.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'dom') diff --git a/dom/media/webm/WebMDemuxer.h b/dom/media/webm/WebMDemuxer.h index 09780e8d3..36d381e57 100644 --- a/dom/media/webm/WebMDemuxer.h +++ b/dom/media/webm/WebMDemuxer.h @@ -8,9 +8,13 @@ #include "nsTArray.h" #include "MediaDataDemuxer.h" +#include "MediaResource.h" #include "NesteggPacketHolder.h" #include "mozilla/Move.h" +#include +#include + typedef struct nestegg nestegg; namespace mozilla { -- cgit v1.2.3 From 26dc168e353d0e97f996371ddfed63140c864fb9 Mon Sep 17 00:00:00 2001 From: trav90 Date: Mon, 15 Oct 2018 22:47:27 -0500 Subject: Make AOMDecoder actually build --- dom/media/platforms/agnostic/AOMDecoder.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index 30077ee03..f3e8c7450 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -49,10 +49,10 @@ AOMDecoder::Init() { int decode_threads = 2; aom_codec_iface_t* dx = aom_codec_av1_dx(); - if (aInfo.mDisplay.width >= 2048) { + if (mInfo.mDisplay.width >= 2048) { decode_threads = 8; } - else if (aInfo.mDisplay.width >= 1024) { + else if (mInfo.mDisplay.width >= 1024) { decode_threads = 4; } decode_threads = std::min(decode_threads, PR_GetNumberOfProcessors()); @@ -64,7 +64,7 @@ AOMDecoder::Init() aom_codec_flags_t flags = 0; - if (!dx || aom_codec_dec_init(aCtx, dx, &config, flags) { + if (!dx || aom_codec_dec_init(&mCodec, dx, &config, flags)) { return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); } return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__); -- cgit v1.2.3 From 1036d1fa0b1fe0f1a7136ffe111f577aa35de21e Mon Sep 17 00:00:00 2001 From: trav90 Date: Wed, 17 Oct 2018 05:46:09 -0500 Subject: Remove aom_codec_stream_info_t sz field references Upstream has removed the requirement to set this when initializing the stream_info struct. --- dom/media/platforms/agnostic/AOMDecoder.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index f3e8c7450..3ab5004e3 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -215,7 +215,6 @@ bool AOMDecoder::IsKeyframe(Span aBuffer) { aom_codec_stream_info_t info; PodZero(&info); - info.sz = sizeof(info); aom_codec_peek_stream_info(aom_codec_av1_dx(), aBuffer.Elements(), @@ -230,7 +229,6 @@ nsIntSize AOMDecoder::GetFrameSize(Span aBuffer) { aom_codec_stream_info_t info; PodZero(&info); - info.sz = sizeof(info); aom_codec_peek_stream_info(aom_codec_av1_dx(), aBuffer.Elements(), -- cgit v1.2.3 From 0cc51bc106250988cc3b89cb5d743a5af52cd35a Mon Sep 17 00:00:00 2001 From: trav90 Date: Wed, 17 Oct 2018 05:54:22 -0500 Subject: Add av1 to MediaSource.isTypeSupported When av1 video playback is enabled, declare it as supported in the webm container in MediaSource.IsTypeSupported. Also support special mime types of the form video/webm; codecs=vp9.experimental. so test sites can verify playback support of particular encodings while the av1 bitstream is under development. --- dom/media/platforms/agnostic/AOMDecoder.cpp | 13 +++++++++++++ dom/media/platforms/agnostic/AOMDecoder.h | 3 +++ dom/media/webm/WebMDecoder.cpp | 8 ++++++++ 3 files changed, 24 insertions(+) (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index 3ab5004e3..d1b45cf7f 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -210,6 +210,19 @@ AOMDecoder::IsAV1(const nsACString& aMimeType) || aMimeType.EqualsLiteral("video/av1"); } +/* static */ +bool +AOMDecoder::IsSupportedCodec(const nsAString& aCodecType) +{ + // While AV1 is under development, we describe support + // for a specific aom commit hash so sites can check + // compatibility. + auto version = NS_ConvertASCIItoUTF16("av1.experimental."); + version.AppendLiteral("4d668d7feb1f8abd809d1bca0418570a7f142a36"); + return aCodecType.EqualsLiteral("av1") || + aCodecType.Equals(version); +} + /* static */ bool AOMDecoder::IsKeyframe(Span aBuffer) { diff --git a/dom/media/platforms/agnostic/AOMDecoder.h b/dom/media/platforms/agnostic/AOMDecoder.h index ec6b1f95a..1e2b76c2c 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.h +++ b/dom/media/platforms/agnostic/AOMDecoder.h @@ -34,6 +34,9 @@ public: // by our demuxers to identify AV1 streams. static bool IsAV1(const nsACString& aMimeType); + // Return true if aCodecType is a supported codec description. + static bool IsSupportedCodec(const nsAString& aCodecType); + // Return true if a sample is a keyframe. static bool IsKeyframe(Span aBuffer); diff --git a/dom/media/webm/WebMDecoder.cpp b/dom/media/webm/WebMDecoder.cpp index b41de6d40..d721a8ccc 100644 --- a/dom/media/webm/WebMDecoder.cpp +++ b/dom/media/webm/WebMDecoder.cpp @@ -5,6 +5,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/Preferences.h" +#ifdef MOZ_AV1 +#include "AOMDecoder.h" +#endif #include "MediaDecoderStateMachine.h" #include "WebMDemuxer.h" #include "WebMDecoder.h" @@ -65,6 +68,11 @@ WebMDecoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs, continue; } +#ifdef MOZ_AV1 + if (isVideo && AOMDecoder::IsSupportedCodec(codec)) { + continue; + } +#endif // Some unsupported codec. return false; } -- cgit v1.2.3 From df9477dfa60ebb5d31bc142e58ce46535c17abce Mon Sep 17 00:00:00 2001 From: trav90 Date: Wed, 17 Oct 2018 05:59:08 -0500 Subject: Update aom to slightly newer commit ID --- dom/media/platforms/agnostic/AOMDecoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index d1b45cf7f..7e78e1238 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -218,7 +218,7 @@ AOMDecoder::IsSupportedCodec(const nsAString& aCodecType) // for a specific aom commit hash so sites can check // compatibility. auto version = NS_ConvertASCIItoUTF16("av1.experimental."); - version.AppendLiteral("4d668d7feb1f8abd809d1bca0418570a7f142a36"); + version.AppendLiteral("aadbb0251996c8ebb8310567bea330ab7ae9abe4"); return aCodecType.EqualsLiteral("av1") || aCodecType.Equals(version); } -- cgit v1.2.3 From 4b5e2295672e2858d0e09a458f049772930db825 Mon Sep 17 00:00:00 2001 From: trav90 Date: Wed, 17 Oct 2018 22:40:32 -0500 Subject: Fix typo (build bustage) --- dom/media/webm/WebMDecoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'dom') diff --git a/dom/media/webm/WebMDecoder.cpp b/dom/media/webm/WebMDecoder.cpp index d721a8ccc..32feda6c0 100644 --- a/dom/media/webm/WebMDecoder.cpp +++ b/dom/media/webm/WebMDecoder.cpp @@ -69,7 +69,7 @@ WebMDecoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs, continue; } #ifdef MOZ_AV1 - if (isVideo && AOMDecoder::IsSupportedCodec(codec)) { + if (isWebMVideo && AOMDecoder::IsSupportedCodec(codec)) { continue; } #endif -- cgit v1.2.3 From dddc2aa9ec0bf7c70910f9846667da2691cd2c2f Mon Sep 17 00:00:00 2001 From: trav90 Date: Wed, 17 Oct 2018 22:49:24 -0500 Subject: Add missing includes to FFmpegLibWrapper --- dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp | 1 + dom/media/platforms/ffmpeg/FFmpegLibWrapper.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'dom') diff --git a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp index 6302882a6..e1c326818 100644 --- a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp @@ -7,6 +7,7 @@ #include "MediaPrefs.h" #include "mozilla/PodOperations.h" #include "mozilla/Types.h" +#include "PlatformDecoderModule.h" #include "prlink.h" #define AV_LOG_DEBUG 48 diff --git a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h index d6944a1d8..c6c43a4ae 100644 --- a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h +++ b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h @@ -5,6 +5,7 @@ #ifndef __FFmpegLibWrapper_h__ #define __FFmpegLibWrapper_h__ +#include "mozilla/Attributes.h" #include "mozilla/Types.h" struct AVCodec; @@ -91,4 +92,4 @@ private: } // namespace mozilla -#endif // FFmpegLibWrapper \ No newline at end of file +#endif // FFmpegLibWrapper -- cgit v1.2.3 From 7369c7d7a5eed32963d8af37658286617919f91c Mon Sep 17 00:00:00 2001 From: trav90 Date: Thu, 18 Oct 2018 06:04:57 -0500 Subject: Update aom to commit id f5bdeac22930ff4c6b219be49c843db35970b918 --- dom/media/platforms/agnostic/AOMDecoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index 7e78e1238..009654a5f 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -218,7 +218,7 @@ AOMDecoder::IsSupportedCodec(const nsAString& aCodecType) // for a specific aom commit hash so sites can check // compatibility. auto version = NS_ConvertASCIItoUTF16("av1.experimental."); - version.AppendLiteral("aadbb0251996c8ebb8310567bea330ab7ae9abe4"); + version.AppendLiteral("f5bdeac22930ff4c6b219be49c843db35970b918"); return aCodecType.EqualsLiteral("av1") || aCodecType.Equals(version); } -- cgit v1.2.3 From 4653be96093a65e8db08e29e10e13029fea861e7 Mon Sep 17 00:00:00 2001 From: trav90 Date: Thu, 18 Oct 2018 19:45:59 -0500 Subject: [aom] Resample high bit depth frames The libaom av1 decoder can return high bit depth frame data now. Handle those frames by downsampling them to 8 bits per channel so they can be passed to our normal playback pipeline. --- dom/media/platforms/agnostic/AOMDecoder.cpp | 84 ++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index 009654a5f..c2b62eaa4 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -8,6 +8,7 @@ #include "MediaResult.h" #include "TimeUnits.h" #include "aom/aomdx.h" +#include "aom/aom_image.h" #include "gfx2DGlue.h" #include "mozilla/PodOperations.h" #include "mozilla/SyncRunnable.h" @@ -82,6 +83,62 @@ AOMDecoder::Flush() mIsFlushing = false; } +// Ported from third_party/aom/tools_common.c. +static aom_codec_err_t +highbd_img_downshift(aom_image_t *dst, aom_image_t *src, int down_shift) { + int plane; + if (dst->d_w != src->d_w || dst->d_h != src->d_h) + return AOM_CODEC_INVALID_PARAM; + if (dst->x_chroma_shift != src->x_chroma_shift) + return AOM_CODEC_INVALID_PARAM; + if (dst->y_chroma_shift != src->y_chroma_shift) + return AOM_CODEC_INVALID_PARAM; + if (dst->fmt != (src->fmt & ~AOM_IMG_FMT_HIGHBITDEPTH)) + return AOM_CODEC_INVALID_PARAM; + if (down_shift < 0) + return AOM_CODEC_INVALID_PARAM; + switch (dst->fmt) { + case AOM_IMG_FMT_I420: + case AOM_IMG_FMT_I422: + case AOM_IMG_FMT_I444: + case AOM_IMG_FMT_I440: + break; + default: + return AOM_CODEC_INVALID_PARAM; + } + switch (src->fmt) { + case AOM_IMG_FMT_I42016: + case AOM_IMG_FMT_I42216: + case AOM_IMG_FMT_I44416: + case AOM_IMG_FMT_I44016: + break; + default: + return AOM_CODEC_UNSUP_BITSTREAM; + } + for (plane = 0; plane < 3; plane++) { + int w = src->d_w; + int h = src->d_h; + int x, y; + if (plane) { + w = (w + src->x_chroma_shift) >> src->x_chroma_shift; + h = (h + src->y_chroma_shift) >> src->y_chroma_shift; + } + for (y = 0; y < h; y++) { + uint16_t *p_src = + (uint16_t *)(src->planes[plane] + y * src->stride[plane]); + uint8_t *p_dst = + dst->planes[plane] + y * dst->stride[plane]; + for (x = 0; x < w; x++) *p_dst++ = (*p_src++ >> down_shift) & 0xFF; + } + } + return AOM_CODEC_OK; +} + +// UniquePtr dtor wrapper for aom_image_t. +struct AomImageFree { + void operator()(aom_image_t* img) { aom_img_free(img); } +}; + MediaResult AOMDecoder::DoDecode(MediaRawData* aSample) { @@ -101,11 +158,36 @@ AOMDecoder::DoDecode(MediaRawData* aSample) aom_codec_iter_t iter = nullptr; aom_image_t *img; + UniquePtr img8; while ((img = aom_codec_get_frame(&mCodec, &iter))) { + if (img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) { + // Downsample images with more than 8 bits per channel. + aom_img_fmt_t fmt8 = static_cast(img->fmt ^ AOM_IMG_FMT_HIGHBITDEPTH); + img8.reset(aom_img_alloc(NULL, fmt8, img->d_w, img->d_h, 16)); + if (img8 == nullptr) { + LOG("Couldn't allocate bitdepth reduction target!"); + return MediaResult( + NS_ERROR_OUT_OF_MEMORY, + RESULT_DETAIL("Couldn't allocate conversion buffer for AV1 frame")); + } + if (aom_codec_err_t r = highbd_img_downshift(img8.get(), img, img->bit_depth - 8)) { + LOG_RESULT(r, "Image downconversion failed"); + return MediaResult( + NS_ERROR_DOM_MEDIA_DECODE_ERR, + RESULT_DETAIL("Error converting AV1 frame to 8 bits: %s", + aom_codec_err_to_string(r))); + } + // img normally points to storage owned by mCodec, so it is not freed. + // To copy out the contents of img8 we can overwrite img with an alias. + // Since img is assigned at the start of the while loop and img8 is held + // outside that loop, the alias won't outlive the storage it points to. + img = img8.get(); + } + NS_ASSERTION(img->fmt == AOM_IMG_FMT_I420 || img->fmt == AOM_IMG_FMT_I444, - "WebM image format not I420 or I444"); + "AV1 image format not I420 or I444"); // Chroma shifts are rounded down as per the decoding examples in the SDK VideoData::YCbCrBuffer b; -- cgit v1.2.3 From 0c98b71659b728d80231af7c33214e03114f9a62 Mon Sep 17 00:00:00 2001 From: trav90 Date: Thu, 18 Oct 2018 19:47:53 -0500 Subject: [aom] Don't resample 8-bit images The libaom av1 decoder will return 16 bit per channel aom_image_t structures with only 8 significant bits. Detect this case and use the mSkip fields of PlanarYCbCrImage to handle the extra data instead of allocating and performing an extra copy to obtain the necessary 8 bit representation. --- dom/media/platforms/agnostic/AOMDecoder.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index c2b62eaa4..1571fe352 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -161,8 +161,10 @@ AOMDecoder::DoDecode(MediaRawData* aSample) UniquePtr img8; while ((img = aom_codec_get_frame(&mCodec, &iter))) { - if (img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) { - // Downsample images with more than 8 bits per channel. + // Track whether the underlying buffer is 8 or 16 bits per channel. + bool highbd = bool(img->fmt & AOM_IMG_FMT_HIGHBITDEPTH); + if (img->bit_depth > 8) { + // Downsample images with more than 8 significant bits per channel. aom_img_fmt_t fmt8 = static_cast(img->fmt ^ AOM_IMG_FMT_HIGHBITDEPTH); img8.reset(aom_img_alloc(NULL, fmt8, img->d_w, img->d_h, 16)); if (img8 == nullptr) { @@ -183,10 +185,13 @@ AOMDecoder::DoDecode(MediaRawData* aSample) // Since img is assigned at the start of the while loop and img8 is held // outside that loop, the alias won't outlive the storage it points to. img = img8.get(); + highbd = false; } NS_ASSERTION(img->fmt == AOM_IMG_FMT_I420 || - img->fmt == AOM_IMG_FMT_I444, + img->fmt == AOM_IMG_FMT_I42016 || + img->fmt == AOM_IMG_FMT_I444 || + img->fmt == AOM_IMG_FMT_I44416, "AV1 image format not I420 or I444"); // Chroma shifts are rounded down as per the decoding examples in the SDK @@ -195,17 +200,21 @@ AOMDecoder::DoDecode(MediaRawData* aSample) b.mPlanes[0].mStride = img->stride[0]; b.mPlanes[0].mHeight = img->d_h; b.mPlanes[0].mWidth = img->d_w; - b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0; + b.mPlanes[0].mOffset = 0; + b.mPlanes[0].mSkip = highbd ? 1 : 0; b.mPlanes[1].mData = img->planes[1]; b.mPlanes[1].mStride = img->stride[1]; - b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0; + b.mPlanes[1].mOffset = 0; + b.mPlanes[1].mSkip = highbd ? 1 : 0; b.mPlanes[2].mData = img->planes[2]; b.mPlanes[2].mStride = img->stride[2]; - b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0; + b.mPlanes[2].mOffset = 0; + b.mPlanes[2].mSkip = highbd ? 1 : 0; - if (img->fmt == AOM_IMG_FMT_I420) { + if (img->fmt == AOM_IMG_FMT_I420 || + img->fmt == AOM_IMG_FMT_I42016) { b.mPlanes[1].mHeight = (img->d_h + 1) >> img->y_chroma_shift; b.mPlanes[1].mWidth = (img->d_w + 1) >> img->x_chroma_shift; -- cgit v1.2.3 From ec910d81405c736a4490383a250299a7837c2e64 Mon Sep 17 00:00:00 2001 From: trav90 Date: Thu, 18 Oct 2018 21:53:44 -0500 Subject: Update aom to commit id e87fb2378f01103d5d6e477a4ef6892dc714e614 --- dom/media/platforms/agnostic/AOMDecoder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index 1571fe352..09ce54225 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -113,6 +113,7 @@ highbd_img_downshift(aom_image_t *dst, aom_image_t *src, int down_shift) { case AOM_IMG_FMT_I44016: break; default: + // We don't support anything that's not 16 bit return AOM_CODEC_UNSUP_BITSTREAM; } for (plane = 0; plane < 3; plane++) { @@ -174,7 +175,6 @@ AOMDecoder::DoDecode(MediaRawData* aSample) RESULT_DETAIL("Couldn't allocate conversion buffer for AV1 frame")); } if (aom_codec_err_t r = highbd_img_downshift(img8.get(), img, img->bit_depth - 8)) { - LOG_RESULT(r, "Image downconversion failed"); return MediaResult( NS_ERROR_DOM_MEDIA_DECODE_ERR, RESULT_DETAIL("Error converting AV1 frame to 8 bits: %s", @@ -309,7 +309,7 @@ AOMDecoder::IsSupportedCodec(const nsAString& aCodecType) // for a specific aom commit hash so sites can check // compatibility. auto version = NS_ConvertASCIItoUTF16("av1.experimental."); - version.AppendLiteral("f5bdeac22930ff4c6b219be49c843db35970b918"); + version.AppendLiteral("e87fb2378f01103d5d6e477a4ef6892dc714e614"); return aCodecType.EqualsLiteral("av1") || aCodecType.Equals(version); } -- cgit v1.2.3 From bbcc64772580c8a979288791afa02d30bc476d2e Mon Sep 17 00:00:00 2001 From: trav90 Date: Fri, 19 Oct 2018 21:52:15 -0500 Subject: Update aom to v1.0.0 Update aom to commit id d14c5bb4f336ef1842046089849dee4a301fbbf0. --- dom/media/platforms/agnostic/AOMDecoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index 09ce54225..9999aac8f 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -309,7 +309,7 @@ AOMDecoder::IsSupportedCodec(const nsAString& aCodecType) // for a specific aom commit hash so sites can check // compatibility. auto version = NS_ConvertASCIItoUTF16("av1.experimental."); - version.AppendLiteral("e87fb2378f01103d5d6e477a4ef6892dc714e614"); + version.AppendLiteral("d14c5bb4f336ef1842046089849dee4a301fbbf0"); return aCodecType.EqualsLiteral("av1") || aCodecType.Equals(version); } -- cgit v1.2.3 From ee1300453eb6e6d32962476351cf4e0391e8b4c4 Mon Sep 17 00:00:00 2001 From: trav90 Date: Fri, 19 Oct 2018 22:11:39 -0500 Subject: Updates to AOMDecoder for aom v1.0.0 This reflects the API changes to the aom_codec_decode function and the removal of I440. It also sets allow_lowbitdepth to give proper support for 8 bit video, and removes the git version from the mime type. --- dom/media/platforms/agnostic/AOMDecoder.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index 9999aac8f..d4ce299b4 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -62,6 +62,7 @@ AOMDecoder::Init() PodZero(&config); config.threads = decode_threads; config.w = config.h = 0; // set after decode + config.allow_lowbitdepth = true; aom_codec_flags_t flags = 0; @@ -101,7 +102,6 @@ highbd_img_downshift(aom_image_t *dst, aom_image_t *src, int down_shift) { case AOM_IMG_FMT_I420: case AOM_IMG_FMT_I422: case AOM_IMG_FMT_I444: - case AOM_IMG_FMT_I440: break; default: return AOM_CODEC_INVALID_PARAM; @@ -110,7 +110,6 @@ highbd_img_downshift(aom_image_t *dst, aom_image_t *src, int down_shift) { case AOM_IMG_FMT_I42016: case AOM_IMG_FMT_I42216: case AOM_IMG_FMT_I44416: - case AOM_IMG_FMT_I44016: break; default: // We don't support anything that's not 16 bit @@ -150,7 +149,7 @@ AOMDecoder::DoDecode(MediaRawData* aSample) "AOM Decode Keyframe error sample->mKeyframe and si.si_kf out of sync"); #endif - if (aom_codec_err_t r = aom_codec_decode(&mCodec, aSample->Data(), aSample->Size(), nullptr, 0)) { + if (aom_codec_err_t r = aom_codec_decode(&mCodec, aSample->Data(), aSample->Size(), nullptr)) { LOG("AOM Decode error: %s", aom_codec_err_to_string(r)); return MediaResult( NS_ERROR_DOM_MEDIA_DECODE_ERR, @@ -305,13 +304,7 @@ AOMDecoder::IsAV1(const nsACString& aMimeType) bool AOMDecoder::IsSupportedCodec(const nsAString& aCodecType) { - // While AV1 is under development, we describe support - // for a specific aom commit hash so sites can check - // compatibility. - auto version = NS_ConvertASCIItoUTF16("av1.experimental."); - version.AppendLiteral("d14c5bb4f336ef1842046089849dee4a301fbbf0"); - return aCodecType.EqualsLiteral("av1") || - aCodecType.Equals(version); + return aCodecType.EqualsLiteral("av1"); } /* static */ -- cgit v1.2.3 From 6ddf66542bfbc90056ca86023da7bdefcec31aa8 Mon Sep 17 00:00:00 2001 From: trav90 Date: Sat, 20 Oct 2018 08:24:28 -0500 Subject: Put AV1 codec behind a pref Disabled by default. --- dom/media/MediaPrefs.h | 3 +++ dom/media/platforms/agnostic/AgnosticDecoderModule.cpp | 8 ++++++-- dom/media/webm/WebMDecoder.cpp | 4 +++- 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'dom') diff --git a/dom/media/MediaPrefs.h b/dom/media/MediaPrefs.h index b237ecd3d..e67796edd 100644 --- a/dom/media/MediaPrefs.h +++ b/dom/media/MediaPrefs.h @@ -120,6 +120,9 @@ private: #ifdef MOZ_FFVPX DECL_MEDIA_PREF("media.ffvpx.enabled", PDMFFVPXEnabled, bool, true); #endif +#ifdef MOZ_AV1 + DECL_MEDIA_PREF("media.av1.enabled", AV1Enabled, bool, false); +#endif #ifdef XP_WIN DECL_MEDIA_PREF("media.wmf.enabled", PDMWMFEnabled, bool, true); DECL_MEDIA_PREF("media.wmf.skip-blacklist", PDMWMFSkipBlacklist, bool, false); diff --git a/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp b/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp index 4d4a90bd4..51ca4e9de 100644 --- a/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp +++ b/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AgnosticDecoderModule.h" +#include "MediaPrefs.h" #include "mozilla/Logging.h" #include "OpusDecoder.h" #include "VorbisDecoder.h" @@ -25,7 +26,9 @@ AgnosticDecoderModule::SupportsMimeType(const nsACString& aMimeType, bool supports = VPXDecoder::IsVPX(aMimeType) || #ifdef MOZ_AV1 - AOMDecoder::IsAV1(aMimeType) || + if (MediaPrefs::AV1Enabled()) { + supports |= AOMDecoder::IsAV1(aMimeType); + } #endif OpusDataDecoder::IsOpus(aMimeType) || VorbisDataDecoder::IsVorbis(aMimeType) || @@ -45,7 +48,8 @@ AgnosticDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams) m = new VPXDecoder(aParams); } #ifdef MOZ_AV1 - else if (AOMDecoder::IsAV1(aParams.mConfig.mMimeType)) { + else if (AOMDecoder::IsAV1(aParams.mConfig.mMimeType) && + MediaPrefs::AV1Enabled()) { m = new AOMDecoder(aParams); } #endif diff --git a/dom/media/webm/WebMDecoder.cpp b/dom/media/webm/WebMDecoder.cpp index 32feda6c0..5a32793ac 100644 --- a/dom/media/webm/WebMDecoder.cpp +++ b/dom/media/webm/WebMDecoder.cpp @@ -8,6 +8,7 @@ #ifdef MOZ_AV1 #include "AOMDecoder.h" #endif +#include "MediaPrefs.h" #include "MediaDecoderStateMachine.h" #include "WebMDemuxer.h" #include "WebMDecoder.h" @@ -69,7 +70,8 @@ WebMDecoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs, continue; } #ifdef MOZ_AV1 - if (isWebMVideo && AOMDecoder::IsSupportedCodec(codec)) { + if (isWebMVideo && MediaPrefs::AV1Enabled() && + AOMDecoder::IsSupportedCodec(codec)) { continue; } #endif -- cgit v1.2.3 From e5b30fc95e191a50da4b8735aaf52baa8d384a0e Mon Sep 17 00:00:00 2001 From: trav90 Date: Sat, 20 Oct 2018 14:49:17 -0500 Subject: Fix canPlayType/isTypeSupported for AV1 content --- dom/media/VideoUtils.cpp | 8 +++++ dom/media/VideoUtils.h | 5 +++ dom/media/platforms/agnostic/AOMDecoder.cpp | 41 +++++++++------------- dom/media/platforms/agnostic/AOMDecoder.h | 3 -- .../platforms/agnostic/AgnosticDecoderModule.cpp | 8 ++--- dom/media/webm/WebMDecoder.cpp | 3 +- 6 files changed, 35 insertions(+), 33 deletions(-) (limited to 'dom') diff --git a/dom/media/VideoUtils.cpp b/dom/media/VideoUtils.cpp index b1a202c03..2c8b67a9d 100644 --- a/dom/media/VideoUtils.cpp +++ b/dom/media/VideoUtils.cpp @@ -458,6 +458,14 @@ IsVP9CodecString(const nsAString& aCodec) aCodec.EqualsLiteral("vp9.0"); } +#ifdef MOZ_AV1 +bool +IsAV1CodecString(const nsAString& aCodec) +{ + return aCodec.EqualsLiteral("av1"); +} +#endif + template static bool StartsWith(const nsACString& string, const char (&prefix)[N]) diff --git a/dom/media/VideoUtils.h b/dom/media/VideoUtils.h index 441b63792..aaf0e9903 100644 --- a/dom/media/VideoUtils.h +++ b/dom/media/VideoUtils.h @@ -345,6 +345,11 @@ IsVP8CodecString(const nsAString& aCodec); bool IsVP9CodecString(const nsAString& aCodec); +#ifdef MOZ_AV1 +bool +IsAV1CodecString(const nsAString& aCodec); +#endif + // Try and create a TrackInfo with a given codec MIME type. UniquePtr CreateTrackInfoWithMIMEType(const nsACString& aCodecMIMEType); diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index d4ce299b4..7a5fba052 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -49,6 +49,7 @@ RefPtr AOMDecoder::Init() { int decode_threads = 2; + aom_codec_iface_t* dx = aom_codec_av1_dx(); if (mInfo.mDisplay.width >= 2048) { decode_threads = 8; @@ -231,23 +232,22 @@ AOMDecoder::DoDecode(MediaRawData* aSample) RESULT_DETAIL("AOM Unknown image format")); } - RefPtr v; - v = VideoData::CreateAndCopyData(mInfo, - mImageContainer, - aSample->mOffset, - aSample->mTime, - aSample->mDuration, - b, - aSample->mKeyframe, - aSample->mTimecode, - mInfo.ScaledImageRect(img->d_w, - img->d_h)); + RefPtr v = + VideoData::CreateAndCopyData(mInfo, + mImageContainer, + aSample->mOffset, + aSample->mTime, + aSample->mDuration, + b, + aSample->mKeyframe, + aSample->mTimecode, + mInfo.ScaledImageRect(img->d_w, + img->d_h)); if (!v) { - LOG( - "Image allocation error source %ux%u display %ux%u picture %ux%u", - img->d_w, img->d_h, mInfo.mDisplay.width, mInfo.mDisplay.height, - mInfo.mImage.width, mInfo.mImage.height); + LOG("Image allocation error source %ux%u display %ux%u picture %ux%u", + img->d_w, img->d_h, mInfo.mDisplay.width, mInfo.mDisplay.height, + mInfo.mImage.width, mInfo.mImage.height); return MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__); } mCallback->Output(v); @@ -296,15 +296,8 @@ AOMDecoder::Drain() bool AOMDecoder::IsAV1(const nsACString& aMimeType) { - return aMimeType.EqualsLiteral("video/webm; codecs=av1") - || aMimeType.EqualsLiteral("video/av1"); -} - -/* static */ -bool -AOMDecoder::IsSupportedCodec(const nsAString& aCodecType) -{ - return aCodecType.EqualsLiteral("av1"); + return aMimeType.EqualsLiteral("video/webm; codecs=av1") || + aMimeType.EqualsLiteral("video/av1"); } /* static */ diff --git a/dom/media/platforms/agnostic/AOMDecoder.h b/dom/media/platforms/agnostic/AOMDecoder.h index 1e2b76c2c..ec6b1f95a 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.h +++ b/dom/media/platforms/agnostic/AOMDecoder.h @@ -34,9 +34,6 @@ public: // by our demuxers to identify AV1 streams. static bool IsAV1(const nsACString& aMimeType); - // Return true if aCodecType is a supported codec description. - static bool IsSupportedCodec(const nsAString& aCodecType); - // Return true if a sample is a keyframe. static bool IsKeyframe(Span aBuffer); diff --git a/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp b/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp index 51ca4e9de..cf5ed3d22 100644 --- a/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp +++ b/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp @@ -25,15 +25,15 @@ AgnosticDecoderModule::SupportsMimeType(const nsACString& aMimeType, { bool supports = VPXDecoder::IsVPX(aMimeType) || + OpusDataDecoder::IsOpus(aMimeType) || + VorbisDataDecoder::IsVorbis(aMimeType) || + WaveDataDecoder::IsWave(aMimeType) || + TheoraDecoder::IsTheora(aMimeType); #ifdef MOZ_AV1 if (MediaPrefs::AV1Enabled()) { supports |= AOMDecoder::IsAV1(aMimeType); } #endif - OpusDataDecoder::IsOpus(aMimeType) || - VorbisDataDecoder::IsVorbis(aMimeType) || - WaveDataDecoder::IsWave(aMimeType) || - TheoraDecoder::IsTheora(aMimeType); MOZ_LOG(sPDMLog, LogLevel::Debug, ("Agnostic decoder %s requested type", supports ? "supports" : "rejects")); return supports; diff --git a/dom/media/webm/WebMDecoder.cpp b/dom/media/webm/WebMDecoder.cpp index 5a32793ac..9575d6e42 100644 --- a/dom/media/webm/WebMDecoder.cpp +++ b/dom/media/webm/WebMDecoder.cpp @@ -70,8 +70,7 @@ WebMDecoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs, continue; } #ifdef MOZ_AV1 - if (isWebMVideo && MediaPrefs::AV1Enabled() && - AOMDecoder::IsSupportedCodec(codec)) { + if (MediaPrefs::AV1Enabled() && IsAV1CodecString(codec)) { continue; } #endif -- cgit v1.2.3 From 070c2cb24ce1ff32a538346c7c1dbbe83fc7e171 Mon Sep 17 00:00:00 2001 From: trav90 Date: Sat, 20 Oct 2018 14:50:33 -0500 Subject: Downsample av1 images unconditionally Adding partial support for 10/12-bit video images seems to have broken the native pixel-stride support we were using to pass 8-bit AV1 frame data formatted in 16-bit pixel values, resulting in vertical green lines. Revert to the earlier behavior of always downsampling to 8 bit data. This is slower, but at least displays correctly. --- dom/media/platforms/agnostic/AOMDecoder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'dom') diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index 7a5fba052..b5d21375e 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -164,8 +164,8 @@ AOMDecoder::DoDecode(MediaRawData* aSample) while ((img = aom_codec_get_frame(&mCodec, &iter))) { // Track whether the underlying buffer is 8 or 16 bits per channel. bool highbd = bool(img->fmt & AOM_IMG_FMT_HIGHBITDEPTH); - if (img->bit_depth > 8) { - // Downsample images with more than 8 significant bits per channel. + if (highbd) { + // Downsample images with more than 8 bits per channel. aom_img_fmt_t fmt8 = static_cast(img->fmt ^ AOM_IMG_FMT_HIGHBITDEPTH); img8.reset(aom_img_alloc(NULL, fmt8, img->d_w, img->d_h, 16)); if (img8 == nullptr) { -- cgit v1.2.3 From 47a01617ea9bb51ecf40d155155299a0278f09f4 Mon Sep 17 00:00:00 2001 From: trav90 Date: Sat, 20 Oct 2018 14:53:15 -0500 Subject: Use larger stack for media decoder threads This increases the thread size for the platform decoder threads (to prevent stack overflows, particularly when decoding av1), while leaving the others at their default values. --- dom/media/VideoUtils.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'dom') diff --git a/dom/media/VideoUtils.cpp b/dom/media/VideoUtils.cpp index 2c8b67a9d..80d39a49f 100644 --- a/dom/media/VideoUtils.cpp +++ b/dom/media/VideoUtils.cpp @@ -207,8 +207,20 @@ already_AddRefed GetMediaThreadPool(MediaThreadType aType) name = "MediaPlayback"; break; } - return SharedThreadPool:: + RefPtr pool = SharedThreadPool:: Get(nsDependentCString(name), MediaPrefs::MediaThreadPoolDefaultCount()); + + // Ensure a larger stack for platform decoder threads + if (aType == MediaThreadType::PLATFORM_DECODER) { + const uint32_t minStackSize = 512*1024; + uint32_t stackSize; + MOZ_ALWAYS_SUCCEEDS(pool->GetThreadStackSize(&stackSize)); + if (stackSize < minStackSize) { + MOZ_ALWAYS_SUCCEEDS(pool->SetThreadStackSize(minStackSize)); + } + } + + return pool.forget(); } bool -- cgit v1.2.3 From 29f718ef78f1a25ca904c6438b59ffc8e365a750 Mon Sep 17 00:00:00 2001 From: trav90 Date: Sat, 20 Oct 2018 17:40:24 -0500 Subject: Add support for AV1 in MP4 --- dom/media/fmp4/MP4Decoder.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'dom') diff --git a/dom/media/fmp4/MP4Decoder.cpp b/dom/media/fmp4/MP4Decoder.cpp index fdd6f2c7e..5e288d63f 100644 --- a/dom/media/fmp4/MP4Decoder.cpp +++ b/dom/media/fmp4/MP4Decoder.cpp @@ -139,6 +139,14 @@ MP4Decoder::CanHandleMediaType(const MediaContentType& aType, NS_LITERAL_CSTRING("audio/flac"), aType)); continue; } +#ifdef MOZ_AV1 + if (IsAV1CodecString(codec)) { + trackInfos.AppendElement( + CreateTrackInfoWithMIMETypeAndContentTypeExtraParameters( + NS_LITERAL_CSTRING("video/av1"), aType)); + continue; + } +#endif // Note: Only accept H.264 in a video content type, not in an audio // content type. if (IsWhitelistedH264Codec(codec) && isMP4Video) { -- cgit v1.2.3 From 23013dda60af6191467a46ce73f1382bf69af01e Mon Sep 17 00:00:00 2001 From: trav90 Date: Sun, 21 Oct 2018 10:14:54 -0500 Subject: Ensure we correctly parse the finalized codec string for av1 --- dom/media/VideoUtils.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'dom') diff --git a/dom/media/VideoUtils.cpp b/dom/media/VideoUtils.cpp index 80d39a49f..c06ba9070 100644 --- a/dom/media/VideoUtils.cpp +++ b/dom/media/VideoUtils.cpp @@ -438,6 +438,16 @@ ParseMIMETypeString(const nsAString& aMIMEType, return ParseCodecsString(codecsStr, aOutCodecs); } +template +static bool +StartsWith(const nsACString& string, const char (&prefix)[N]) +{ + if (N - 1 > string.Length()) { + return false; + } + return memcmp(string.Data(), prefix, N - 1) == 0; +} + bool IsH264CodecString(const nsAString& aCodec) { @@ -474,20 +484,11 @@ IsVP9CodecString(const nsAString& aCodec) bool IsAV1CodecString(const nsAString& aCodec) { - return aCodec.EqualsLiteral("av1"); + return aCodec.EqualsLiteral("av1") || + StartsWith(NS_ConvertUTF16toUTF8(aCodec), "av01"); } #endif -template -static bool -StartsWith(const nsACString& string, const char (&prefix)[N]) -{ - if (N - 1 > string.Length()) { - return false; - } - return memcmp(string.Data(), prefix, N - 1) == 0; -} - UniquePtr CreateTrackInfoWithMIMEType(const nsACString& aCodecMIMEType) { -- cgit v1.2.3 From 192199b03fa2e56d2728b0de1dbe4bedfc1edc50 Mon Sep 17 00:00:00 2001 From: trav90 Date: Tue, 23 Oct 2018 05:47:41 -0500 Subject: Revert "Add support for AV1 in MP4" This commit was incomplete. Will re-land AV1 in MP4 support properly at a future date. This reverts commit 29f718ef78f1a25ca904c6438b59ffc8e365a750. --- dom/media/fmp4/MP4Decoder.cpp | 8 -------- 1 file changed, 8 deletions(-) (limited to 'dom') diff --git a/dom/media/fmp4/MP4Decoder.cpp b/dom/media/fmp4/MP4Decoder.cpp index 5e288d63f..fdd6f2c7e 100644 --- a/dom/media/fmp4/MP4Decoder.cpp +++ b/dom/media/fmp4/MP4Decoder.cpp @@ -139,14 +139,6 @@ MP4Decoder::CanHandleMediaType(const MediaContentType& aType, NS_LITERAL_CSTRING("audio/flac"), aType)); continue; } -#ifdef MOZ_AV1 - if (IsAV1CodecString(codec)) { - trackInfos.AppendElement( - CreateTrackInfoWithMIMETypeAndContentTypeExtraParameters( - NS_LITERAL_CSTRING("video/av1"), aType)); - continue; - } -#endif // Note: Only accept H.264 in a video content type, not in an audio // content type. if (IsWhitelistedH264Codec(codec) && isMP4Video) { -- cgit v1.2.3