Bug 1336431: P2. Asynchronously flush and shutdown decoder when SPS changes. r?cpearce
Those steps were missed in
bug 1319987.
This is an area of the code rarely used under normal circumstances, asadaptive playback is only used with MSE.
MozReview-Commit-ID: HZn3UxDy2GX
--- a/dom/media/platforms/wrappers/H264Converter.cpp
+++ b/dom/media/platforms/wrappers/H264Converter.cpp
@@ -130,19 +130,27 @@ H264Converter::Drain()
return mDecoder->Drain();
}
return DecodePromise::CreateAndResolve(DecodedData(), __func__);
}
RefPtr<ShutdownPromise>
H264Converter::Shutdown()
{
+ mInitPromiseRequest.DisconnectIfExists();
+ mDecodePromiseRequest.DisconnectIfExists();
+ mFlushRequest.DisconnectIfExists();
+ mShutdownRequest.DisconnectIfExists();
+ mPendingSample = nullptr;
+ if (mShutdownPromise) {
+ // We have a shutdown in progress, return that promise instead as we can't
+ // shutdown a decoder twice.
+ return mShutdownPromise.forget();
+ }
if (mDecoder) {
- mInitPromiseRequest.DisconnectIfExists();
- mDecodePromiseRequest.DisconnectIfExists();
RefPtr<MediaDataDecoder> decoder = mDecoder.forget();
return decoder->Shutdown();
}
return ShutdownPromise::CreateAndResolve(true, __func__);
}
bool
H264Converter::IsHardwareAccelerated(nsACString& aFailureReason) const
@@ -238,46 +246,46 @@ H264Converter::CreateDecoderAndInit(Medi
}
void
H264Converter::OnDecoderInitDone(const TrackType aTrackType)
{
mInitPromiseRequest.Complete();
RefPtr<MediaRawData> sample = mPendingSample.forget();
if (mNeedKeyframe && !sample->mKeyframe) {
- mDecodePromise.ResolveIfExists(DecodedData(), __func__);
+ mDecodePromise.Resolve(DecodedData(), __func__);
}
mNeedKeyframe = false;
if (!mNeedAVCC
&& !mp4_demuxer::AnnexB::ConvertSampleToAnnexB(sample, mNeedKeyframe)) {
- mDecodePromise.RejectIfExists(
+ mDecodePromise.Reject(
MediaResult(NS_ERROR_OUT_OF_MEMORY,
RESULT_DETAIL("ConvertSampleToAnnexB")),
__func__);
return;
}
RefPtr<H264Converter> self = this;
mDecoder->Decode(sample)
->Then(AbstractThread::GetCurrent()->AsTaskQueue(), __func__,
[self, this](const MediaDataDecoder::DecodedData& aResults) {
mDecodePromiseRequest.Complete();
- mDecodePromise.ResolveIfExists(aResults, __func__);
+ mDecodePromise.Resolve(aResults, __func__);
},
[self, this](const MediaResult& aError) {
mDecodePromiseRequest.Complete();
- mDecodePromise.RejectIfExists(aError, __func__);
+ mDecodePromise.Reject(aError, __func__);
})
->Track(mDecodePromiseRequest);
}
void
H264Converter::OnDecoderInitFailed(const MediaResult& aError)
{
mInitPromiseRequest.Complete();
- mDecodePromise.RejectIfExists(
+ mDecodePromise.Reject(
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Unable to initialize H264 decoder")),
__func__);
}
nsresult
H264Converter::CheckForSPSChange(MediaRawData* aSample)
{
@@ -293,19 +301,49 @@ H264Converter::CheckForSPSChange(MediaRa
&& mDecoder->SupportDecoderRecycling()) {
// Do not recreate the decoder, reuse it.
UpdateConfigFromExtraData(extra_data);
mNeedKeyframe = true;
return NS_OK;
}
// The SPS has changed, signal to flush the current decoder and create a
// new one.
- mDecoder->Flush();
- Shutdown();
- return CreateDecoderAndInit(aSample);
+ mPendingSample = aSample;
+ RefPtr<H264Converter> self = this;
+ mDecoder->Flush()
+ ->Then(AbstractThread::GetCurrent()->AsTaskQueue(),
+ __func__,
+ [self, this]() {
+ mFlushRequest.Complete();
+ mShutdownPromise = Shutdown();
+ mShutdownPromise
+ ->Then(AbstractThread::GetCurrent()->AsTaskQueue(),
+ __func__,
+ [self, this]() {
+ mShutdownRequest.Complete();
+ mShutdownPromise = nullptr;
+ RefPtr<MediaRawData> sample = mPendingSample.forget();
+ nsresult rv = CreateDecoderAndInit(sample);
+ if (rv == NS_ERROR_DOM_MEDIA_INITIALIZING_DECODER) {
+ // All good so far, will continue later.
+ return;
+ }
+ MOZ_ASSERT(NS_FAILED(rv));
+ mDecodePromise.Reject(rv, __func__);
+ return;
+ },
+ [] { MOZ_CRASH("Can't reach here'"); })
+ ->Track(mShutdownRequest);
+ },
+ [self, this](const MediaResult& aError) {
+ mFlushRequest.Complete();
+ mDecodePromise.Reject(aError, __func__);
+ })
+ ->Track(mFlushRequest);
+ return NS_ERROR_DOM_MEDIA_INITIALIZING_DECODER;
}
void
H264Converter::UpdateConfigFromExtraData(MediaByteBuffer* aExtraData)
{
mp4_demuxer::SPSData spsdata;
if (mp4_demuxer::H264::DecodeSPSFromExtraData(aExtraData, spsdata)
&& spsdata.pic_width > 0
--- a/dom/media/platforms/wrappers/H264Converter.h
+++ b/dom/media/platforms/wrappers/H264Converter.h
@@ -67,16 +67,20 @@ private:
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;
+ MozPromiseRequestHolder<FlushPromise> mFlushRequest;
+ MozPromiseRequestHolder<ShutdownPromise> mShutdownRequest;
+ RefPtr<ShutdownPromise> mShutdownPromise;
+
RefPtr<GMPCrashHelper> mGMPCrashHelper;
bool mNeedAVCC;
nsresult mLastError;
bool mNeedKeyframe = true;
const TrackInfo::TrackType mType;
MediaEventProducer<TrackInfo::TrackType>* const mOnWaitingForKeyEvent;
};