nsresult H264Converter::Input(MediaRawData* aSample) { if (!mNeedAVCC) { if (!mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample)) { return NS_ERROR_FAILURE; } } else { if (!mp4_demuxer::AnnexB::ConvertSampleToAVCC(aSample)) { return NS_ERROR_FAILURE; } } nsresult rv; if (!mDecoder) { // It is not possible to create an AVCC H264 decoder without SPS. // As such, creation will fail if the extra_data just extracted doesn't // contain a SPS. rv = CreateDecoderAndInit(aSample); if (rv == NS_ERROR_NOT_INITIALIZED) { // We are missing the required SPS to create the decoder. // Ignore for the time being, the MediaRawData will be dropped. return NS_OK; } } else { rv = CheckForSPSChange(aSample); } NS_ENSURE_SUCCESS(rv, rv); aSample->mExtraData = mCurrentConfig.mExtraData; return mDecoder->Input(aSample); }
nsresult H264Converter::Input(MediaRawData* aSample) { if (!mp4_demuxer::AnnexB::ConvertSampleToAVCC(aSample)) { // We need AVCC content to be able to later parse the SPS. // This is a no-op if the data is already AVCC. return NS_ERROR_FAILURE; } if (mInitPromiseRequest.Exists()) { mMediaRawSamples.AppendElement(aSample); return NS_OK; } nsresult rv; if (!mDecoder) { // It is not possible to create an AVCC H264 decoder without SPS. // As such, creation will fail if the extra_data just extracted doesn't // contain a SPS. rv = CreateDecoderAndInit(aSample); if (rv == NS_ERROR_NOT_INITIALIZED) { // We are missing the required SPS to create the decoder. // Ignore for the time being, the MediaRawData will be dropped. return NS_OK; } } else { rv = CheckForSPSChange(aSample); } NS_ENSURE_SUCCESS(rv, rv); if (!mNeedAVCC && !mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample)) { return NS_ERROR_FAILURE; } aSample->mExtraData = mCurrentConfig.mExtraData; return mDecoder->Input(aSample); }
void H264Converter::Input(MediaRawData* aSample) { if (!mp4_demuxer::AnnexB::ConvertSampleToAVCC(aSample)) { // We need AVCC content to be able to later parse the SPS. // This is a no-op if the data is already AVCC. mCallback->Error(MediaResult(NS_ERROR_OUT_OF_MEMORY, RESULT_DETAIL("ConvertSampleToAVCC"))); return; } if (mInitPromiseRequest.Exists()) { if (mNeedKeyframe) { if (!aSample->mKeyframe) { // Frames dropped, we need a new one. mCallback->InputExhausted(); return; } mNeedKeyframe = false; } mMediaRawSamples.AppendElement(aSample); return; } nsresult rv; if (!mDecoder) { // It is not possible to create an AVCC H264 decoder without SPS. // As such, creation will fail if the extra_data just extracted doesn't // contain a SPS. rv = CreateDecoderAndInit(aSample); if (rv == NS_ERROR_NOT_INITIALIZED) { // We are missing the required SPS to create the decoder. // Ignore for the time being, the MediaRawData will be dropped. mCallback->InputExhausted(); return; } } else { rv = CheckForSPSChange(aSample); if (rv == NS_ERROR_NOT_INITIALIZED) { // The decoder is pending initialization. mCallback->InputExhausted(); return; } } if (NS_FAILED(rv)) { mCallback->Error( MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, RESULT_DETAIL("Unable to create H264 decoder"))); return; } if (mNeedKeyframe && !aSample->mKeyframe) { mCallback->InputExhausted(); return; } if (!mNeedAVCC && !mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample, mNeedKeyframe)) { mCallback->Error(MediaResult(NS_ERROR_OUT_OF_MEMORY, RESULT_DETAIL("ConvertSampleToAnnexB"))); return; } mNeedKeyframe = false; aSample->mExtraData = mCurrentConfig.mExtraData; mDecoder->Input(aSample); }
RefPtr<MediaDataDecoder::DecodePromise> H264Converter::Decode(MediaRawData* aSample) { MOZ_RELEASE_ASSERT(mFlushPromise.IsEmpty(), "Flush operatin didn't complete"); MOZ_RELEASE_ASSERT(!mDecodePromiseRequest.Exists() && !mInitPromiseRequest.Exists(), "Can't request a new decode until previous one completed"); if (!AnnexB::ConvertSampleToAVCC(aSample)) { // We need AVCC content to be able to later parse the SPS. // This is a no-op if the data is already AVCC. return DecodePromise::CreateAndReject( MediaResult(NS_ERROR_OUT_OF_MEMORY, RESULT_DETAIL("ConvertSampleToAVCC")), __func__); } if (!AnnexB::IsAVCC(aSample)) { return DecodePromise::CreateAndReject( MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, RESULT_DETAIL("Invalid H264 content")), __func__); } MediaResult rv(NS_OK); if (!mDecoder) { // It is not possible to create an AVCC H264 decoder without SPS. // As such, creation will fail if the extra_data just extracted doesn't // contain a SPS. rv = CreateDecoderAndInit(aSample); if (rv == NS_ERROR_NOT_INITIALIZED) { // We are missing the required SPS to create the decoder. // Ignore for the time being, the MediaRawData will be dropped. return DecodePromise::CreateAndResolve(DecodedData(), __func__); } } else { // Initialize the members that we couldn't if the extradata was given during // H264Converter's construction. if (!mNeedAVCC) { mNeedAVCC = Some(mDecoder->NeedsConversion() == ConversionRequired::kNeedAVCC); } if (!mCanRecycleDecoder) { mCanRecycleDecoder = Some(CanRecycleDecoder()); } rv = CheckForSPSChange(aSample); } if (rv == NS_ERROR_DOM_MEDIA_INITIALIZING_DECODER) { // The decoder is pending initialization. RefPtr<DecodePromise> p = mDecodePromise.Ensure(__func__); return p; } if (NS_FAILED(rv)) { return DecodePromise::CreateAndReject(rv, __func__); } if (mNeedKeyframe && !aSample->mKeyframe) { return DecodePromise::CreateAndResolve(DecodedData(), __func__); } auto res = !*mNeedAVCC ? AnnexB::ConvertSampleToAnnexB(aSample, mNeedKeyframe) : Ok(); if (res.isErr()) { return DecodePromise::CreateAndReject( MediaResult(res.unwrapErr(), RESULT_DETAIL("ConvertSampleToAnnexB")), __func__); } mNeedKeyframe = false; aSample->mExtraData = mCurrentConfig.mExtraData; return mDecoder->Decode(aSample); }
RefPtr<MediaDataDecoder::DecodePromise> H264Converter::Decode(MediaRawData* aSample) { MOZ_RELEASE_ASSERT(!mDecodePromiseRequest.Exists() && !mInitPromiseRequest.Exists(), "Can't request a new decode until previous one completed"); if (!mp4_demuxer::AnnexB::ConvertSampleToAVCC(aSample)) { // We need AVCC content to be able to later parse the SPS. // This is a no-op if the data is already AVCC. return DecodePromise::CreateAndReject( MediaResult(NS_ERROR_OUT_OF_MEMORY, RESULT_DETAIL("ConvertSampleToAVCC")), __func__); } nsresult rv; if (!mDecoder) { // It is not possible to create an AVCC H264 decoder without SPS. // As such, creation will fail if the extra_data just extracted doesn't // contain a SPS. rv = CreateDecoderAndInit(aSample); if (rv == NS_ERROR_NOT_INITIALIZED) { // We are missing the required SPS to create the decoder. // Ignore for the time being, the MediaRawData will be dropped. return DecodePromise::CreateAndResolve(DecodedData(), __func__); } } else { rv = CheckForSPSChange(aSample); } if (rv == NS_ERROR_DOM_MEDIA_INITIALIZING_DECODER) { // The decoder is pending initialization. RefPtr<DecodePromise> p = mDecodePromise.Ensure(__func__); return p; } if (NS_FAILED(rv)) { return DecodePromise::CreateAndReject( MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, RESULT_DETAIL("Unable to create H264 decoder")), __func__); } if (mNeedKeyframe && !aSample->mKeyframe) { return DecodePromise::CreateAndResolve(DecodedData(), __func__); } if (!mNeedAVCC) { mNeedAVCC = Some(mDecoder->NeedsConversion() == ConversionRequired::kNeedAVCC); } if (!*mNeedAVCC && !mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample, mNeedKeyframe)) { return DecodePromise::CreateAndReject( MediaResult(NS_ERROR_OUT_OF_MEMORY, RESULT_DETAIL("ConvertSampleToAnnexB")), __func__); } mNeedKeyframe = false; aSample->mExtraData = mCurrentConfig.mExtraData; return mDecoder->Decode(aSample); }