tor-browser

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

commit f5986df439c7409c3d866ba3c516558065f8dec9
parent 729e32cb210d5aee6d8459bfbb715efbb706e65d
Author: Andrew Osmond <aosmond@gmail.com>
Date:   Thu,  8 Jan 2026 15:56:04 +0000

Bug 2008354 - Part 3. Handle AnnexB output from encoders when AVCC requested. r=media-playback-reviewers,jolin

On Android, the encoders produce AnnexB, so we need to extract the
extradata for the AVCC samples. Since the flag to indicate there was a
configuration change, AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG, is different
from that of a key frame, AMEDIACODEC_BUFFER_FLAG_KEY_FRAME, and we
cannot distinguish when the former happens, we check all frames, not
just the key frames.

This patch also converts the AnnexB frames themselves to AVCC.

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

Diffstat:
Mdom/media/platforms/ffmpeg/FFmpegVideoEncoder.cpp | 44++++++++++++++++++++++++++++++++++++--------
Mdom/media/platforms/ffmpeg/FFmpegVideoEncoder.h | 1+
2 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoEncoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoEncoder.cpp @@ -10,6 +10,7 @@ #include <algorithm> +#include "AnnexB.h" #include "BufferReader.h" #include "EncoderConfig.h" #include "FFmpegEncoderModule.h" @@ -733,6 +734,20 @@ FFmpegVideoEncoder<LIBAV_VER>::ToMediaRawData(AVPacket* aPacket) { e.Description().get()); } + if (mCodecID == AV_CODEC_ID_H264 && + mConfig.mCodecSpecific.is<H264Specific>() && + mConfig.mCodecSpecific.as<H264Specific>().mFormat == + H264BitStreamFormat::AVC && + !mCodecName.Equals("libx264"_ns) && AnnexB::IsAnnexB(*data)) { + if (data->mExtraData) { + mLastExtraData = std::move(data->mExtraData); + } + if (!AnnexB::ConvertSampleToAVCC(data, mLastExtraData)) { + return Err(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, + "Failed to convert to AVCC"_ns)); + } + } + // TODO(bug 1869560): The unit of pts, dts, and duration is time_base, which // is recommended to be the reciprocal of the frame rate, but we set it to // microsecond for now. @@ -773,18 +788,32 @@ FFmpegVideoEncoder<LIBAV_VER>::GetExtraData(AVPacket* aPacket) { MOZ_ASSERT(mTaskQueue->IsOnCurrentThread()); MOZ_ASSERT(aPacket); - // H264 Extra data comes with the key frame and we only extract it when - // encoding into AVCC format. + // We only extract the extra data when encoding into AVCC format. if (mCodecID != AV_CODEC_ID_H264 || !mConfig.mCodecSpecific.is<H264Specific>() || mConfig.mCodecSpecific.as<H264Specific>().mFormat != - H264BitStreamFormat::AVC || - !(aPacket->flags & AV_PKT_FLAG_KEY)) { + H264BitStreamFormat::AVC) { return Err( - MediaResult(NS_ERROR_NOT_AVAILABLE, "No available extra data"_ns)); + MediaResult(NS_ERROR_NOT_AVAILABLE, "Extra data unnecessary"_ns)); + } + + Span<const uint8_t> packetBuf(aPacket->data, + static_cast<size_t>(aPacket->size)); + if (!mCodecName.Equals("libx264"_ns) && AnnexB::IsAnnexB(packetBuf)) { + auto extraData = AnnexB::ExtractExtraDataForAVCC(packetBuf); + if (!extraData) { + return Err(MediaResult(NS_ERROR_NOT_AVAILABLE, + "Extra data missing from packet"_ns)); + } + return extraData.forget(); } - if (mCodecName != "libx264") { + if (!(aPacket->flags & AV_PKT_FLAG_KEY)) { + return Err(MediaResult(NS_ERROR_NOT_AVAILABLE, + "Extra data only comes with key frame"_ns)); + } + + if (!mCodecName.Equals("libx264"_ns)) { return Err(MediaResult( NS_ERROR_NOT_IMPLEMENTED, RESULT_DETAIL( @@ -805,8 +834,7 @@ FFmpegVideoEncoder<LIBAV_VER>::GetExtraData(AVPacket* aPacket) { Span<const uint8_t>(mCodecContext->extradata, static_cast<size_t>(mCodecContext->extradata_size)); } else { - buf = - Span<const uint8_t>(aPacket->data, static_cast<size_t>(aPacket->size)); + buf = packetBuf; } if (buf.empty()) { return Err(MediaResult(NS_ERROR_UNEXPECTED, diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoEncoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoEncoder.h @@ -86,6 +86,7 @@ class FFmpegVideoEncoder<LIBAV_VER> final int64_t mFakePts = 0; int64_t mCurrentFramePts = 0; PtsMap mPtsMap; + RefPtr<MediaByteBuffer> mLastExtraData; }; } // namespace mozilla