Bug 1313398: P4. Check that the out of band extradata hasn't changed. r?gerald
On android, where decoders can sometimes be recycled, the h264converter can be fed over its lifetime MediaRawData with different mExtraData.
So we need to ensure that not only, the inband ones don't change, but that the out of band one hasn't changed either.
This is a condition we could totally ignore on desktop, as when the resolution change the H264Converter is destroyed.
MozReview-Commit-ID: 7w6ku6by1Qi
--- a/dom/media/platforms/wrappers/H264Converter.cpp
+++ b/dom/media/platforms/wrappers/H264Converter.cpp
@@ -29,16 +29,21 @@ H264Converter::H264Converter(PlatformDec
, mDecoder(nullptr)
, mGMPCrashHelper(aParams.mCrashHelper)
, mLastError(NS_OK)
, mType(aParams.mType)
, mOnWaitingForKeyEvent(aParams.mOnWaitingForKeyEvent)
, mDecoderOptions(aParams.mOptions)
{
CreateDecoder(mOriginalConfig, aParams.mDiagnostics);
+ if (mDecoder) {
+ MOZ_ASSERT(mp4_demuxer::AnnexB::HasSPS(mOriginalConfig.mExtraData));
+ // The video metadata contains out of band SPS/PPS (AVC1) store it.
+ mOriginalExtraData = mOriginalConfig.mExtraData;
+ }
}
H264Converter::~H264Converter()
{
}
RefPtr<MediaDataDecoder::InitPromise>
H264Converter::Init()
@@ -323,19 +328,34 @@ H264Converter::DecodeFirstSample(MediaRa
->Track(mDecodePromiseRequest);
}
nsresult
H264Converter::CheckForSPSChange(MediaRawData* aSample)
{
RefPtr<MediaByteBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
- if (!mp4_demuxer::AnnexB::HasSPS(extra_data)
- || mp4_demuxer::AnnexB::CompareExtraData(extra_data,
- mCurrentConfig.mExtraData)) {
+ if (!mp4_demuxer::AnnexB::HasSPS(extra_data)) {
+ MOZ_ASSERT(mCanRecycleDecoder.isSome());
+ if (!*mCanRecycleDecoder) {
+ // If the decoder can't be recycled, the out of band extradata will never
+ // change as the H264Converter will be recreated by the MediaFormatReader
+ // instead. So there's no point in testing for changes.
+ return NS_OK;
+ }
+ // This sample doesn't contain inband SPS/PPS
+ // We now check if the out of band one has changed.
+ if (mp4_demuxer::AnnexB::HasSPS(aSample->mExtraData) &&
+ !mp4_demuxer::AnnexB::CompareExtraData(aSample->mExtraData,
+ mOriginalExtraData)) {
+ extra_data = mOriginalExtraData = aSample->mExtraData;
+ }
+ }
+ if (mp4_demuxer::AnnexB::CompareExtraData(extra_data,
+ mCurrentConfig.mExtraData)) {
return NS_OK;
}
RefPtr<MediaRawData> sample = aSample;
MOZ_ASSERT(mCanRecycleDecoder.isSome());
if (*mCanRecycleDecoder) {
// Do not recreate the decoder, reuse it.
UpdateConfigFromExtraData(extra_data);
--- a/dom/media/platforms/wrappers/H264Converter.h
+++ b/dom/media/platforms/wrappers/H264Converter.h
@@ -76,16 +76,18 @@ private:
bool CanRecycleDecoder() const;
void DecodeFirstSample(MediaRawData* aSample);
RefPtr<PlatformDecoderModule> mPDM;
const VideoInfo mOriginalConfig;
VideoInfo mCurrentConfig;
+ // Current out of band extra data (as found in metadata's VideoInfo).
+ RefPtr<MediaByteBuffer> mOriginalExtraData;
RefPtr<layers::KnowsCompositor> mKnowsCompositor;
RefPtr<layers::ImageContainer> mImageContainer;
const RefPtr<TaskQueue> mTaskQueue;
RefPtr<MediaRawData> mPendingSample;
RefPtr<MediaDataDecoder> mDecoder;
MozPromiseRequestHolder<InitPromise> mInitPromiseRequest;
MozPromiseRequestHolder<DecodePromise> mDecodePromiseRequest;
MozPromiseHolder<DecodePromise> mDecodePromise;