HEVC學習(十八) —— NAL unit 的解碼過程之二
阿新 • • 發佈:2019-02-17
下面介紹實際完成NAL解析工作的函式:
/** * Parse an AVC AnnexB Bytestream bs to extract a single nalUnit * while accumulating bytestream statistics into stats. * * If EOF occurs while trying to extract a NALunit, an exception * of std::ios_base::failure is thrown. The contsnts of stats will * be correct at this point. */ static void _byteStreamNALUnit( InputByteStream& bs, vector<uint8_t>& nalUnit, AnnexBStats& stats) { /* At the beginning of the decoding process, the decoder initialises its * current position in the byte stream to the beginning of the byte stream. * It then extracts and discards each leading_zero_8bits syntax element (if * present), moving the current position in the byte stream forward one * byte at a time, until the current position in the byte stream is such * that the next four bytes in the bitstream form the four-byte sequence * 0x00000001. */ while ((bs.eofBeforeNBytes(24/8) || bs.peekBytes(24/8) != 0x000001) && (bs.eofBeforeNBytes(32/8) || bs.peekBytes(32/8) != 0x00000001)) { uint8_t leading_zero_8bits = bs.readByte(); //!< 提取並丟棄leading_zero_8bits句法元素 assert(leading_zero_8bits == 0); stats.m_numLeadingZero8BitsBytes++; } /* 1. When the next four bytes in the bitstream form the four-byte sequence * 0x00000001, the next byte in the byte stream (which is a zero_byte * syntax element) is extracted and discarded and the current position in * the byte stream is set equal to the position of the byte following this * discarded byte. */ /* NB, the previous step guarantees this will succeed -- if EOF was * encountered, an exception will stop execution getting this far */ if (bs.peekBytes(24/8) != 0x000001) { uint8_t zero_byte = bs.readByte(); //!< 提取並丟棄zero_byte句法元素 assert(zero_byte == 0); stats.m_numZeroByteBytes++; } /* 2. The next three-byte sequence in the byte stream (which is a * start_code_prefix_one_3bytes) is extracted and discarded and the current * position in the byte stream is set equal to the position of the byte * following this three-byte sequence. */ /* NB, (1) guarantees that the next three bytes are 0x00 00 01 */ uint32_t start_code_prefix_one_3bytes = bs.readBytes(24/8); //!< 提取並丟棄start_code_prefix_one_3bytes句法元素 assert(start_code_prefix_one_3bytes == 0x000001); stats.m_numStartCodePrefixBytes += 3; /* 3. NumBytesInNALunit is set equal to the number of bytes starting with * the byte at the current position in the byte stream up to and including * the last byte that precedes the location of any of the following * conditions: * a. A subsequent byte-aligned three-byte sequence equal to 0x000000, or * b. A subsequent byte-aligned three-byte sequence equal to 0x000001, or * c. The end of the byte stream, as determined by unspecified means. */ /* 4. NumBytesInNALunit bytes are removed from the bitstream and the * current position in the byte stream is advanced by NumBytesInNALunit * bytes. This sequence of bytes is nal_unit( NumBytesInNALunit ) and is * decoded using the NAL unit decoding process */ /* NB, (unsigned)x > 2 implies n!=0 && n!=1 */ while (bs.eofBeforeNBytes(24/8) || bs.peekBytes(24/8) > 2) { nalUnit.push_back(bs.readByte()); //!< 將NAL的負載部分儲存起來 } /* 5. When the current position in the byte stream is: * - not at the end of the byte stream (as determined by unspecified means) * - and the next bytes in the byte stream do not start with a three-byte * sequence equal to 0x000001 * - and the next bytes in the byte stream do not start with a four byte * sequence equal to 0x00000001, * the decoder extracts and discards each trailing_zero_8bits syntax * element, moving the current position in the byte stream forward one byte * at a time, until the current position in the byte stream is such that: * - the next bytes in the byte stream form the four-byte sequence * 0x00000001 or * - the end of the byte stream has been encountered (as determined by * unspecified means). */ /* NB, (3) guarantees there are at least three bytes available or none */ while ((bs.eofBeforeNBytes(24/8) || bs.peekBytes(24/8) != 0x000001) && (bs.eofBeforeNBytes(32/8) || bs.peekBytes(32/8) != 0x00000001)) { uint8_t trailing_zero_8bits = bs.readByte(); //!< 提取並丟棄trailing_zero_8bits句法元素 assert(trailing_zero_8bits == 0); stats.m_numTrailingZero8BitsBytes++; } }
實際上,程式碼中的註釋部分中,標記了1,2,3,4,5序號的註釋,對應於draft附錄B.2的5點,詳細判斷規則程式碼中已經說得很清楚了,這裡就不再羅嗦了。