From 862f8455eaacc1ffb5d8911f0bc7ecc3cf7ec46c Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Thu, 26 Jun 2014 19:55:23 -0700 Subject: [PATCH] handle emulation_prevention_three_bytes for AVC bug: 15917805 Change-Id: I824fe7eea807f8faba6b149c31890b7a5df87825 --- include/media/stagefright/foundation/ABitReader.h | 22 ++++++- .../nuplayer/NuPlayerDecoder.cpp | 4 +- media/libstagefright/foundation/ABitReader.cpp | 68 ++++++++++++++++++++++ 3 files changed, 89 insertions(+), 5 deletions(-) diff --git a/include/media/stagefright/foundation/ABitReader.h b/include/media/stagefright/foundation/ABitReader.h index 5510b12aee..c3bf0ff73d 100644 --- a/include/media/stagefright/foundation/ABitReader.h +++ b/include/media/stagefright/foundation/ABitReader.h @@ -25,8 +25,10 @@ namespace android { -struct ABitReader { +class ABitReader { +public: ABitReader(const uint8_t *data, size_t size); + virtual ~ABitReader(); uint32_t getBits(size_t n); void skipBits(size_t n); @@ -37,18 +39,32 @@ struct ABitReader { const uint8_t *data() const; -private: +protected: const uint8_t *mData; size_t mSize; uint32_t mReservoir; // left-aligned bits size_t mNumBitsLeft; - void fillReservoir(); + virtual void fillReservoir(); DISALLOW_EVIL_CONSTRUCTORS(ABitReader); }; +class NALBitReader : public ABitReader { +public: + NALBitReader(const uint8_t *data, size_t size); + + bool atLeastNumBitsLeft(size_t n) const; + +private: + int32_t mNumZeros; + + virtual void fillReservoir(); + + DISALLOW_EVIL_CONSTRUCTORS(NALBitReader); +}; + } // namespace android #endif // A_BIT_READER_H_ diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp index 5abfb71155..dd73cc4fd5 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp @@ -674,9 +674,9 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp &accessUnit) { bool hasCC = false; - ABitReader br(sei->data() + 1, sei->size() - 1); + NALBitReader br(sei->data() + 1, sei->size() - 1); // sei_message() - while (br.numBitsLeft() >= 16) { // at least 16-bit for sei_message() + while (br.atLeastNumBitsLeft(16)) { // at least 16-bit for sei_message() uint32_t payload_type = 0; size_t payload_size = 0; uint8_t last_byte; diff --git a/media/libstagefright/foundation/ABitReader.cpp b/media/libstagefright/foundation/ABitReader.cpp index 5499c32bba..beb5cc0739 100644 --- a/media/libstagefright/foundation/ABitReader.cpp +++ b/media/libstagefright/foundation/ABitReader.cpp @@ -27,6 +27,9 @@ ABitReader::ABitReader(const uint8_t *data, size_t size) mNumBitsLeft(0) { } +ABitReader::~ABitReader() { +} + void ABitReader::fillReservoir() { CHECK_GT(mSize, 0u); @@ -99,4 +102,69 @@ const uint8_t *ABitReader::data() const { return mData - (mNumBitsLeft + 7) / 8; } +NALBitReader::NALBitReader(const uint8_t *data, size_t size) + : ABitReader(data, size), + mNumZeros(0) { +} + +bool NALBitReader::atLeastNumBitsLeft(size_t n) const { + // check against raw size and reservoir bits first + size_t numBits = numBitsLeft(); + if (n > numBits) { + return false; + } + + ssize_t numBitsRemaining = n - mNumBitsLeft; + + size_t size = mSize; + const uint8_t *data = mData; + int32_t numZeros = mNumZeros; + while (size > 0 && numBitsRemaining > 0) { + bool isEmulationPreventionByte = (numZeros >= 2 && *data == 3); + + if (*data == 0) { + ++numZeros; + } else { + numZeros = 0; + } + + if (!isEmulationPreventionByte) { + numBitsRemaining -= 8; + } + + ++data; + --size; + } + + return (numBitsRemaining <= 0); +} + +void NALBitReader::fillReservoir() { + CHECK_GT(mSize, 0u); + + mReservoir = 0; + size_t i = 0; + while (mSize > 0 && i < 4) { + bool isEmulationPreventionByte = (mNumZeros >= 2 && *mData == 3); + + if (*mData == 0) { + ++mNumZeros; + } else { + mNumZeros = 0; + } + + // skip emulation_prevention_three_byte + if (!isEmulationPreventionByte) { + mReservoir = (mReservoir << 8) | *mData; + ++i; + } + + ++mData; + --mSize; + } + + mNumBitsLeft = 8 * i; + mReservoir <<= 32 - mNumBitsLeft; +} + } // namespace android -- 2.11.0