Detecting PES Packet Boundaries in VOB Streams
This article explains the technical process decoders use to locate and delineate Packetized Elementary Stream (PES) packet boundaries within an arbitrary DVD Video Object (VOB) file. Because a VOB file is fundamentally an implementation of the MPEG-2 Program Stream (PS) standard, decoders rely on unique 32-bit start code prefixes, the 16-bit PES packet length field, and DVD-specific 2,048-byte sector alignments to reliably isolate packets even when starting playback from an arbitrary byte position.
The Underlying VOB Structure
A VOB stream is a specialized MPEG-2 Program Stream structured into discrete 2,048-byte (2 KB) packs, matching the physical sector size of DVD media. Each pack starts with a Pack Header and contains one or more PES packets, which wrap the raw elementary stream data (such as MPEG-2 video, AC-3, DTS, or LPCM audio) alongside presentation timestamps (PTS) and decoding timestamps (DTS).
To extract audio, video, and sub-picture data, the decoder must continuously identify where a PES packet starts and where it terminates.
Step 1: Scanning for the 32-bit Start Code Prefix
When reading an arbitrary stream, the decoder maintains a sliding 4-byte buffer to identify synchronization markers. Every PES packet begins with a standard 32-bit start code:
- Prefix (24 bits):
0x00 0x00 0x01 - Stream ID (8 bits): A single byte identifying the payload type.
Valid PES stream IDs generally range from 0xBC to
0xFF. Common stream IDs found in VOB files include:
0xE0to0xEF: MPEG Video streams0xBD: Private Stream 1 (commonly used for AC-3, DTS, and Sub-picture streams)0xBF: Private Stream 2 (navigation data such as PCI and DSI packs)0xC0to0xDF: MPEG-1/2 Audio streams
Pack headers (0x00 0x00 0x01 0xBA) and System headers
(0x00 0x00 0x01 0xBB) share the same 24-bit prefix,
allowing the decoder's parser to distinguish PES packets from
higher-level stream structures based solely on the fourth byte.
Step 2: Reading the PES Packet Length
Immediately following the 1-byte stream_id, the MPEG-2
specification defines a 16-bit unsigned integer:
PES_packet_length.
+-----------------------------+-----------+-------------------+
| Start Code Prefix (24 bits) | Stream ID | PES Packet Length |
| 0x00 0x00 0x01 | (8 bits) | (16 bits) |
+-----------------------------+-----------+-------------------+
The boundary detection mechanism depends directly on this value:
- Non-Zero Length: The value specifies the exact
number of bytes remaining in the PES packet, counted immediately after
the length field. This count includes the optional PES header (flags,
PTS/DTS timestamps, stuffing bytes) and the elementary stream payload.
The decoder adds this length value to the byte offset directly following
the
PES_packet_lengthfield to pinpoint the exact terminating boundary of the packet. - Zero Length: While the MPEG-2 standard allows a
length of
0for video streams within Transport Streams (indicating an unconstrained size), the DVD-Video specification mandates that all PES packets within a VOB file explicitly declare their length via this 16-bit field.
Step 3: Utilizing Fixed 2,048-Byte Pack Alignment
VOB streams follow strict sector constraints that simplify boundary detection compared to generic MPEG-2 Program Streams:
- Fixed Sector Size: Every pack is aligned to a
2,048-byte boundary and begins with the Pack Header start code
(
0x00 0x00 0x01 0xBA). - Self-Contained Sectors: In DVD VOB authoring, PES packets do not span across pack boundaries. A single 2,048-byte pack typically contains the Pack Header, an optional System Header, and exactly one PES packet padded out to fill the remaining sector space.
- Stuffing Bytes: If the elementary payload does not
fill the 2,048-byte sector, the authoring pipeline inserts stuffing
bytes either within the PES header or by appending an explicit Padding
Stream packet (
stream_id = 0xBE).
Because of this rigid geometry, the end of a PES packet inside a VOB invariably coincides with either the end of the 2,048-byte sector or the beginning of a stuffing/padding sequence within that same sector.
Resynchronization on Corrupt or Arbitrary Streams
If a decoder begins reading at an arbitrary point within a VOB stream (such as during seeking or after packet loss), it executes a state-machine resynchronization:
- Byte Scan: The parser steps forward byte-by-byte
until it locates
0x00 0x00 0x01. - Start Code Evaluation: It checks if the succeeding
byte is a valid VOB stream ID or a Pack Header (
0xBA). - Length Validation: If a PES start code is identified, the decoder reads the 16-bit length. It then validates whether the end offset calculated from that length aligns with either the next valid start code prefix or the next 2,048-byte pack boundary.
- Acceptance: Once the calculated boundary correlates with the start of a new valid header, the decoder locks synchronization and begins routing payload data to the elementary decoders.