实际完成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点,详细判断规则代码中已经说得很清楚了,这里就不再罗嗦了。