Bug 1128381: Part3. Handle on the fly video format change. r=cpearce

Add monitoring of the current SPS NAL and destroy/recreate H264 decoder as
required.

--HG--
extra : rebase_source : fbab04b0ae3b4be42eea34a1c6f1b19bf39ad2f0
This commit is contained in:
Jean-Yves Avenard 2015-03-12 11:07:19 +11:00
Родитель 06ae6e08e7
Коммит adf3e336a3
3 изменённых файлов: 34 добавлений и 2 удалений

Просмотреть файл

@ -44,6 +44,7 @@ private:
// will set mError accordingly.
nsresult CreateDecoder();
nsresult CreateDecoderAndInit(mp4_demuxer::MP4Sample* aSample);
nsresult CheckForSPSChange(mp4_demuxer::MP4Sample* aSample);
nsRefPtr<PlatformDecoderModule> mPDM;
mp4_demuxer::VideoDecoderConfig mCurrentConfig;
@ -92,18 +93,21 @@ AVCCMediaDataDecoder::Input(mp4_demuxer::MP4Sample* aSample)
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.
nsresult rv = CreateDecoderAndInit(aSample);
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 MP4Sample will be dropped.
return NS_OK;
}
NS_ENSURE_SUCCESS(rv, rv);
} else {
rv = CheckForSPSChange(aSample);
}
NS_ENSURE_SUCCESS(rv, rv);
aSample->extra_data = mCurrentConfig.extra_data;
@ -230,6 +234,23 @@ AVCCMediaDataDecoder::IsHardwareAccelerated() const
return MediaDataDecoder::IsHardwareAccelerated();
}
nsresult
AVCCMediaDataDecoder::CheckForSPSChange(mp4_demuxer::MP4Sample* aSample)
{
nsRefPtr<mp4_demuxer::ByteBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data) ||
mp4_demuxer::AnnexB::CompareExtraData(extra_data,
mCurrentConfig.extra_data)) {
return NS_OK;
}
// The SPS has changed, signal to flush the current decoder and create a
// new one.
mDecoder->Flush();
mDecoder->Shutdown();
return CreateDecoderAndInit(aSample);
}
// AVCCDecoderModule
AVCCDecoderModule::AVCCDecoderModule(PlatformDecoderModule* aPDM)

Просмотреть файл

@ -378,4 +378,12 @@ AnnexB::IsAnnexB(const MP4Sample* aSample)
return header == 0x00000001 || (header >> 8) == 0x000001;
}
bool
AnnexB::CompareExtraData(const ByteBuffer* aExtraData1,
const ByteBuffer* aExtraData2)
{
// Very crude comparison.
return aExtraData1 == aExtraData2 || *aExtraData1 == *aExtraData2;
}
} // namespace mp4_demuxer

Просмотреть файл

@ -39,6 +39,9 @@ public:
static bool IsAVCC(const MP4Sample* aSample);
// Returns true if format is AnnexB.
static bool IsAnnexB(const MP4Sample* aSample);
// Return true if both extradata are equal.
static bool CompareExtraData(const ByteBuffer* aExtraData1,
const ByteBuffer* aExtraData2);
private:
// AVCC box parser helper.