The binary .sub file is an MPEG-2 program stream containing only the DVD
subpicture packets, copied from the disc’s VOB files. Each timestamp line
of the index gives the byte offset at which
one subtitle starts. In the published sample index, every such offset is a multiple of
2048, the size of a DVD sector.
Packet layout
Each sector holds an MPEG-2 pack followed by a PES packet on private stream 1.
| Size | Name | Value | Meaning |
|---|---|---|---|
| 4 | Pack start code | 00 00 01 BA | Starts the pack. |
| 10 | Pack header fields | System clock reference and multiplex rate, with stuffing given by the low 3 bits of the last byte. | |
| 4 | PES start code | 00 00 01 BD | Private stream 1. |
| 2 | Packet length | big-endian | Length of the rest of the PES packet. |
| 2 | Flags | The second byte shows whether a PTS follows. | |
| 1 | Header data length | Bytes of optional data that follow. | |
| variable | Header data | A 5-byte presentation time stamp when flagged, on the first packet of a subtitle. | |
| 1 | Substream ID | 20–3F | Which subpicture track: 20 plus the track number. |
| variable | Payload | Bytes of the subpicture unit. |
A subpicture unit larger than one packet continues in further packets. Only the first
has a presentation time. A padding stream (00 00 01 BE) fills any
remaining space in a sector.
Finding a track
A file holding several languages interleaves their packets. The substream number
matches the index of the track’s id: line in the index
file, and packets of a different substream are skipped.
Matroska stores this data differently: each subtitle’s subpicture unit goes in its own block, without the pack and PES headers, and each language becomes a separate track.
Not confirmed
This layout comes from the MPEG-2 systems standard, DVD practice and the observed files; VobSub’s documentation has not survived.