From 06ae6e08e7a20a44c8c7c1f5c0547a9a61cb5c73 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Thu, 12 Mar 2015 11:07:19 +1100 Subject: [PATCH] Bug 1128381: Part2. Properly extract extradata from AVC1 sample. r=rillian --HG-- extra : rebase_source : a67173bfcc4184211ab0b90e3b7634b1730288d5 --- media/libstagefright/binding/AnnexB.cpp | 32 +++++++++++++++---- .../binding/include/mp4_demuxer/AnnexB.h | 6 ++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/media/libstagefright/binding/AnnexB.cpp b/media/libstagefright/binding/AnnexB.cpp index c5f65e4e2c06..0a88e5092aa6 100644 --- a/media/libstagefright/binding/AnnexB.cpp +++ b/media/libstagefright/binding/AnnexB.cpp @@ -217,11 +217,9 @@ AnnexB::ConvertSampleToAVCC(MP4Sample* aSample) if (IsAVCC(aSample)) { return ConvertSampleTo4BytesAVCC(aSample); } - - uint32_t header = mozilla::BigEndian::readUint32(aSample->data); - if (header != 0x00000001 && (header >> 8) != 0x000001) { + if (!IsAnnexB(aSample)) { // Not AnnexB, can't convert. - return true; + return false; } mozilla::Vector nalu; @@ -236,7 +234,13 @@ already_AddRefed AnnexB::ExtractExtraData(const MP4Sample* aSample) { nsRefPtr extradata = new ByteBuffer; - if (!IsAVCC(aSample)) { + if (IsAVCC(aSample) && HasSPS(aSample->extra_data)) { + // We already have an explicit extradata, re-use it. + extradata = aSample->extra_data; + return extradata.forget(); + } + + if (IsAnnexB(aSample)) { return extradata.forget(); } // SPS content @@ -248,7 +252,14 @@ AnnexB::ExtractExtraData(const MP4Sample* aSample) ByteWriter ppsw(pps); int numPps = 0; - int nalLenSize = ((*aSample->extra_data)[4] & 3) + 1; + int nalLenSize; + if (IsAVCC(aSample)) { + nalLenSize = ((*aSample->extra_data)[4] & 3) + 1; + } else { + // We do not have an extradata, assume it's AnnexB converted to AVCC via + // ConvertSampleToAVCC. + nalLenSize = 4; + } ByteReader reader(aSample->data, aSample->size); // Find SPS and PPS NALUs in AVCC data @@ -357,5 +368,14 @@ AnnexB::IsAVCC(const MP4Sample* aSample) aSample->extra_data->Length() >= 7 && (*aSample->extra_data)[0] == 1; } +bool +AnnexB::IsAnnexB(const MP4Sample* aSample) +{ + if (aSample->size < 4) { + return false; + } + uint32_t header = mozilla::BigEndian::readUint32(aSample->data); + return header == 0x00000001 || (header >> 8) == 0x000001; +} } // namespace mp4_demuxer diff --git a/media/libstagefright/binding/include/mp4_demuxer/AnnexB.h b/media/libstagefright/binding/include/mp4_demuxer/AnnexB.h index 76f09ee559aa..5a4968ddd57c 100644 --- a/media/libstagefright/binding/include/mp4_demuxer/AnnexB.h +++ b/media/libstagefright/binding/include/mp4_demuxer/AnnexB.h @@ -28,11 +28,17 @@ public: // Parse an AVCC extradata and construct the Annex B sample header. static already_AddRefed ConvertExtraDataToAnnexB( const ByteBuffer* aExtraData); + // Extract SPS and PPS NALs from aSample, aSample must be in AVCC format. + // If aSample already contains an extradata with an SPS, it will be returned + // otherwise the SPS/PPS NALs are searched in-band. static already_AddRefed ExtractExtraData( const MP4Sample* aSample); static bool HasSPS(const MP4Sample* aSample); static bool HasSPS(const ByteBuffer* aExtraData); + // Returns true if format is AVCC and sample has valid extradata. static bool IsAVCC(const MP4Sample* aSample); + // Returns true if format is AnnexB. + static bool IsAnnexB(const MP4Sample* aSample); private: // AVCC box parser helper.