tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 42990f5ce6d52b0a0d9453cbc16637d1ad1b9498
parent f65aafb263bdbc2bbd89988a061302fbc28c7447
Author: Andrew Osmond <aosmond@gmail.com>
Date:   Tue, 25 Nov 2025 20:31:32 +0000

Bug 2001774 - Part 2. Update FFmpegVideoDecoder configuration for decrypting. r=media-playback-reviewers,azebrowski

This makes sure we call MaybeAttachCDM to provide the AMediaCrypto
pointer to ffmpeg when it is creating the underlying AMediaCodec. This
is necessary to be able to decrypt content. Also now take advantage of
the new ffvpx plumbing to have better matched AMediaCodecCryptoInfo
lifetimes.

Differential Revision: https://phabricator.services.mozilla.com/D273708

Diffstat:
Mdom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp | 62+++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Mdom/media/platforms/ffmpeg/FFmpegDataDecoder.h | 7++++++-
Mdom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp | 26+++++++++++---------------
3 files changed, 70 insertions(+), 25 deletions(-)

diff --git a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp @@ -109,10 +109,54 @@ MediaResult FFmpegDataDecoder<LIBAV_VER>::InitSWDecoder( return InitDecoder(codec, aOptions); } +#if defined(MOZ_WIDGET_ANDROID) && defined(USING_MOZFFVPX) +/* static */ +void FFmpegDataDecoder<LIBAV_VER>::CryptoInfoAddRef(void* aCryptoInfo) { + reinterpret_cast<MediaDrmCryptoInfo*>(aCryptoInfo)->AddRef(); +} + +/* static */ +void FFmpegDataDecoder<LIBAV_VER>::CryptoInfoRelease(void* aCryptoInfo) { + reinterpret_cast<MediaDrmCryptoInfo*>(aCryptoInfo)->Release(); +} + +MediaResult FFmpegDataDecoder<LIBAV_VER>::MaybeAttachCryptoInfo( + MediaRawData* aSample, AVPacket* aPacket) { + if (!aSample->mCrypto.IsEncrypted()) { + return NS_OK; + } + + if (NS_WARN_IF(!mCDM)) { + return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, + RESULT_DETAIL("missing CDM for encrypted sample")); + } + + RefPtr<MediaDrmCryptoInfo> cryptoInfo = mCDM->CreateCryptoInfo(aSample); + if (NS_WARN_IF(!cryptoInfo)) { + return MediaResult( + NS_ERROR_DOM_MEDIA_FATAL_ERR, + RESULT_DETAIL("missing MediaDrmCryptoInfo for encrypted sample")); + } + + aPacket->moz_ndk_crypto_info = cryptoInfo->GetNdkCryptoInfo(); + if (NS_WARN_IF(!aPacket->moz_ndk_crypto_info)) { + return MediaResult( + NS_ERROR_DOM_MEDIA_FATAL_ERR, + RESULT_DETAIL("missing AMediaCodecCryptoInfo for encrypted sample")); + } + + aPacket->moz_crypto_info = cryptoInfo.forget().take(); + aPacket->moz_crypto_info_addref = CryptoInfoAddRef; + aPacket->moz_crypto_info_release = CryptoInfoRelease; + + FFMPEG_LOG(" encrypted packet, ndk_crypto_info=%p", + aPacket->moz_ndk_crypto_info); + return NS_OK; +} + MediaResult FFmpegDataDecoder<LIBAV_VER>::MaybeAttachCDM() { MOZ_ASSERT(mCodecContext); -#if defined(MOZ_WIDGET_ANDROID) && defined(FFVPX_VERSION) if (!mCDM) { return NS_OK; } @@ -120,20 +164,20 @@ MediaResult FFmpegDataDecoder<LIBAV_VER>::MaybeAttachCDM() { mCrypto = mCDM->GetCrypto(); if (NS_WARN_IF(!mCrypto)) { return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, - RESULT_DETAIL("missing crypto from cdm")); + RESULT_DETAIL("missing MediaDrmCrypto from CDM")); } - auto* ndkCrypto = mCrypto->GetNdkCrypto(); - MOZ_ASSERT(ndkCrypto); - - mCodecContext->moz_ndk_crypto = ndkCrypto; -#endif + mCodecContext->moz_ndk_crypto = mCrypto->GetNdkCrypto(); + if (NS_WARN_IF(!mCodecContext->moz_ndk_crypto)) { + return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, + RESULT_DETAIL("missing AMediaCrypto from CDM")); + } + FFMPEG_LOG(" attached CDM, ndk_crypto=%p", mCodecContext->moz_ndk_crypto); return NS_OK; } void FFmpegDataDecoder<LIBAV_VER>::MaybeDetachCDM() { -#if defined(MOZ_WIDGET_ANDROID) && defined(FFVPX_VERSION) if (mCodecContext) { mCodecContext->moz_ndk_crypto = nullptr; } @@ -141,8 +185,8 @@ void FFmpegDataDecoder<LIBAV_VER>::MaybeDetachCDM() { if (mCDM) { mCDM = nullptr; } -#endif } +#endif MediaResult FFmpegDataDecoder<LIBAV_VER>::InitDecoder(AVCodec* aCodec, AVDictionary** aOptions) { diff --git a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h @@ -15,7 +15,7 @@ #include "FFmpegLibs.h" namespace mozilla { -#if defined(MOZ_WIDGET_ANDROID) && defined(FFVPX_VERSION) +#if defined(MOZ_WIDGET_ANDROID) && defined(USING_MOZFFVPX) class MediaDrmCrypto; class MediaDrmRemoteCDMParent; #endif @@ -65,8 +65,13 @@ class FFmpegDataDecoder<LIBAV_VER> MediaResult DoDecode(MediaRawData* aSample, bool* aGotFrame, DecodedData& aResults); +#if defined(MOZ_WIDGET_ANDROID) && defined(USING_MOZFFVPX) + static void CryptoInfoAddRef(void* aCryptoInfo); + static void CryptoInfoRelease(void* aCryptoInfo); + MediaResult MaybeAttachCryptoInfo(MediaRawData* aSample, AVPacket* aPacket); MediaResult MaybeAttachCDM(); void MaybeDetachCDM(); +#endif FFmpegLibWrapper* mLib; // set in constructor diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp @@ -1200,21 +1200,9 @@ MediaResult FFmpegVideoDecoder<LIBAV_VER>::DoDecode( }); #if defined(MOZ_WIDGET_ANDROID) && defined(USING_MOZFFVPX) - RefPtr<MediaDrmCryptoInfo> cryptoInfo; - if (aSample->mCrypto.IsEncrypted()) { - if (NS_WARN_IF(!mCDM)) { - return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, - RESULT_DETAIL("Missing CDM for encrypted sample")); - } - - cryptoInfo = mCDM->CreateCryptoInfo(aSample); - if (NS_WARN_IF(!cryptoInfo)) { - return MediaResult( - NS_ERROR_DOM_MEDIA_DECODE_ERR, - RESULT_DETAIL("Failed to create CryptoInfo for encrypted sample")); - } - - packet->moz_ndk_crypto_info = cryptoInfo->GetNdkCryptoInfo(); + MediaResult ret = MaybeAttachCryptoInfo(aSample, packet); + if (NS_FAILED(ret)) { + return ret; } #endif @@ -2471,6 +2459,14 @@ MediaResult FFmpegVideoDecoder<LIBAV_VER>::InitMediaCodecDecoder() { return ret; } +# ifdef USING_MOZFFVPX + ret = MaybeAttachCDM(); + if (NS_FAILED(ret)) { + FFMPEG_LOG(" failed to attach CDM."); + return ret; + } +# endif + if (mLib->avcodec_open2(mCodecContext, codec, nullptr) < 0) { FFMPEG_LOG(" avcodec_open2 failed for MediaCodec decoder"); return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,