How to Parse AV1 OBU Size with Bitwise Operations
In the AV1 video codec specification, Open Bitstream Units (OBUs)
utilize a variable-length integer encoding called LEB128 (Little Endian
Base 128) to indicate their payload size when the header's
obu_has_size_field flag is set. Parsing this field requires
a sequence of specific bit-level operations—primarily bitwise AND,
bitwise left shift, and bitwise OR—to reconstruct the integer from a
stream of bytes. This article explains how these bitwise operations
function together to extract the final size value from an AV1
bitstream.
LEB128 Byte Structure in AV1
Each byte in an AV1 LEB128 sequence is split into two distinct parts:
- Bit 7 (MSB): The continuation flag. If set to
1, another byte follows. If set to0, this is the final byte of the size indicator. - Bits 0–6: The 7-bit data payload carrying the actual numerical value.
According to the AV1 specification, an OBU size indicator can span up to 8 bytes, producing an integer up to 56 bits wide (though practically bounded by standard integer limits).
Key Bit-Level Operations Used in Parsing
Decoding the variable-length size requires four core bitwise operations applied in a loop across the input bytes.
1. Bitwise AND
for Continuation Detection (& 0x80)
To check whether more bytes must be read, the parser tests the Most
Significant Bit (bit 7) using a bitwise AND with the hexadecimal mask
0x80 (10000000 in binary):
bool has_next_byte = (current_byte & 0x80) != 0;If the result is zero, the loop terminates after processing the current byte's payload.
2. Bitwise AND for
Payload Extraction (& 0x7F)
To isolate the lower 7 bits containing the numerical value, the
parser uses a bitwise AND with the mask 0x7F
(01111111 in binary):
uint64_t payload = current_byte & 0x7F;This clears the continuation bit, preventing it from corrupting the accumulated size value.
3. Bitwise Left Shift for
Alignment (<<)
Because LEB128 stores data in little-endian order, the first byte
represents the least significant 7 bits, the second byte represents bits
7 to 13, and so on. The parser aligns the extracted 7-bit payload to its
correct power-of-two position using a left shift by (i * 7)
bits, where i is the zero-based index of the current
byte:
uint64_t shifted_payload = payload << (i * 7);4. Bitwise OR for
Accumulation (| or |=)
To merge the shifted 7-bit segment into the total accumulated integer, the parser performs a bitwise OR operation against the target variable:
obu_size |= shifted_payload;Complete Implementation Example
Combining these bit-level operations yields the standard AV1
leb128() parsing routine:
uint64_t obu_size = 0;
for (int i = 0; i < 8; i++) {
uint8_t byte = read_byte();
// Extract lower 7 bits and shift into place, then accumulate
obu_size |= ((uint64_t)(byte & 0x7F)) << (i * 7);
// Check continuation bit
if ((byte & 0x80) == 0) {
break;
}
}Constraints and Validation
During parsing, implementations must enforce two AV1-specific bitstream constraints:
- Length Limit: If the continuation bit is still
1after reading 8 bytes, the bitstream is malformed and must trigger a decode error. - Value Padding: Bitstreams can pad small integers
across multiple bytes by leaving unused bits as
0while setting the continuation bit. However, the resulting shifted value must not exceed(1ULL << 32) - 1if the decoder enforces 32-bit maximum OBU sizes.