MPEG-TS
188-byte packets that interleave video, audio and tables into one stream.
A TS packet carrying the PAT
The 4-byte header, then the table of contents with a CRC computed for real.
Whole frame
A 4-byte header (sync, flags, PID, counter) and then the payload: here the table of contents. The rest of the 188 bytes is 0xFF filler.
| Field | Offset | Example value | Meaning |
|---|---|---|---|
| Sync byte | Byte 0 | 0x47 | Always 0x47 ('G'). Every TS packet is exactly 188 bytes, so a receiver finds packet boundaries by checking that 0x47 repeats every 188 bytes. That is how it recovers after a glitch. |
| Transport error | Byte 1, bit 7 | 0 | Set by a demodulator that could not correct errors in this packet. Decoders skip it. |
| Payload unit start | Byte 1, bit 6 | 1 | 1 = a new PES packet or table section begins in this packet's payload (the first byte is then a pointer_field for tables). It marks where a frame or table starts. |
| Transport priority | Byte 1, bit 5 | 0 | 1 = more important than other packets with the same PID. Rarely used. |
| PID | Bytes 1–2 | 0x0000 = PAT | Packet Identifier: which stream this packet belongs to. Many streams (video, several audios, subtitles, tables) are interleaved in one TS and told apart only by PID. PID 0 is always the PAT, the table of contents. |
| Scrambling | Byte 3, bits 7–6 | 00 | Encryption flag for pay TV. 00 = not scrambled. |
| Adaptation field | Byte 3, bits 5–4 | 01 = payload only | 01 = payload only, 10 = adaptation field only, 11 = both. The adaptation field carries the PCR clock and stuffing. |
| Continuity counter | Byte 3, bits 3–0 | 0 | Counts 0–15 for each PID, +1 per packet that has a payload. A skipped number tells the receiver that packets of this PID were lost. |
| Pointer field | Byte 4 | 0 | Present because PUSI = 1 on a table: how many bytes to skip before the section starts. 0 = right away. |
| Table ID | Byte 5 | 0x00 = PAT | 0x00 = PAT (Program Association Table), 0x02 = PMT, 0x42 = SDT... |
| Syntax indicator | Byte 6, bit 7 | 1 | 1 = the long section syntax, with a CRC. |
| Zero | Byte 6, bit 6 | 0 | Always 0 in PSI tables. |
| Reserved | Byte 6, bits 5–4 | 11 | Set to 1 1. |
| Section length | Bytes 6–7 | 13 | Bytes after this field up to the end of the CRC: 5 (fixed part) + 4 (one program) + 4 (CRC) = 13. |
| Transport stream ID | Byte 8–9 | 1 | An ID for this whole multiplex. |
| Reserved | Byte 10, bits 7–6 | 11 | Set to 1 1. |
| Version | Byte 10, bits 5–1 | 0 | Increments whenever the table's content changes, so receivers know to re-read it. |
| Current/next | Byte 10, bit 0 | 1 | 1 = this table is the one in effect now. |
| Section number | Byte 11 | 0 | Which piece of a multi-section table this is. |
| Last section | Byte 12 | 0 | The last piece's number. 0 = the table fits in one section. |
| Program number | Byte 13–14 | 1 | A program (a channel: its video + audio). Number 1 here. |
| Reserved | Byte 15, bits 7–5 | 111 | Set to 1 1 1. |
| PMT PID | Bytes 15–16 | 0x1000 | Where to find the Program Map Table of program 1: packets with this PID. The PMT then lists the PIDs of the video and audio streams. So decoding starts at PID 0 → PMT PID → video PID. |
| CRC-32 | Byte 17–20 | 0x2AB104B2 | A CRC-32/MPEG-2 over the section (polynomial 0x04C11DB7, initial value 0xFFFFFFFF, no reflection). Computed for real here: 0x2AB104B2. A receiver discards a table whose CRC does not match. |
Overview
MPEG transport stream (TS) was built for broadcasting over lossy links. Everything is cut into fixed 188-byte packets, each starting with 0x47 and labelled with a PID. Video, several audio tracks, subtitles and the tables that describe them travel interleaved in one stream, and a receiver can join at any moment.
Tables (PAT, PMT) tell the decoder which PIDs are video and audio. The media itself is wrapped in PES packets with timestamps, then split across TS packets. Digital TV, Blu-ray, IPTV and HLS segments all use it.
Key facts
- Packet size
- 188 bytes (204 with FEC)
- Header
- 4 bytes, sync 0x47
- PID
- 13 bits (8,192 streams)
- Clock
- PCR 27 MHz, PTS 90 kHz
- Tables
- PAT, PMT, SDT, ... + CRC-32
- Standard
- ISO/IEC 13818-1
A video frame in a PES packet
The PES header with a presentation timestamp, then the start of H.264 data.
Whole frame
Before each compressed frame sits a PES header with the one thing the player needs most: its presentation time. The PES packet is then chopped into 184-byte pieces and wrapped in TS packets.
| Field | Offset | Example value | Meaning |
|---|---|---|---|
| Start code prefix | Byte 0–2 | 00 00 01 | 00 00 01 can't occur inside properly escaped video data, so a decoder can find the start of a PES packet by scanning for it. |
| Stream ID | Byte 3 | 0xE0 = video stream 0 | What kind of elementary stream: 0xE0–0xEF video, 0xC0–0xDF audio. |
| PES packet length | Byte 4–5 | 0 (unbounded) | Bytes that follow. 0 is allowed for video and means 'unbounded': the packet ends where the next one starts (a whole frame is often bigger than 65,535 bytes). |
| Marker | Byte 6, bits 7–6 | 10 | Always 10. |
| PES flags | Byte 6, bits 5–0 | 000000 | Scrambling (2 bits), priority, data alignment, copyright, original: all 0 here. |
| PTS/DTS flags | Byte 7, bits 7–6 | 10 = PTS only | 10 = a PTS is present (without DTS); 11 = both; 00 = neither. Frames in order need only a PTS; B-frames also need a DTS because decode order differs from display order. |
| Other flags | Byte 7, bits 5–0 | 000000 | ESCR, ES rate, trick mode, copy info, CRC, extension: all absent. |
| Header data length | Byte 8 | 5 | Bytes of optional header fields before the payload: just the 5-byte PTS. |
| PTS | Byte 9–13 | 90000 = 1.000 s | Presentation Time Stamp: when to show this frame, in 90 kHz ticks, 33 bits wide, spread over 5 bytes with a marker bit after each group. Here 90000 ticks = 1.000 s. 33 bits at 90 kHz wrap after about 26.5 hours. |
| H.264 start code | Byte 14–17 | 00 00 00 01 | The compressed video begins here. In an H.264 byte stream every NAL unit starts with 00 00 00 01. |
| NAL header | Byte 18 | 0x09 = AUD | forbidden_zero 0, nal_ref_idc 0, type 9 = Access Unit Delimiter: 'a new frame starts'. |
| AUD data | Byte 19 | 0xF0 | primary_pic_type 7 (any slice type) plus the rbsp stop bit. |
Where you meet it
- Digital TV broadcast (DVB, ATSC, ISDB)
- IPTV and contribution links, often over UDP or SRT (7 TS packets = 1,316 bytes fit one datagram)
- HLS segments (.ts files) and Blu-ray discs (M2TS)
Watch out for
- Overhead is high on small streams: stuffing and 4 header bytes per 188.
- A continuity-counter jump is how receivers detect loss; it also fires on legitimate duplicates, which are allowed once.
- PTS wraps every ~26.5 hours: long recordings must handle the rollover.
Standards
- ISO/IEC 13818-1 (MPEG-2 Systems)
- ITU-T H.264 Annex B