PSI/SI Tables & Descriptors
The lookup tables you actually need at the keyboard: reserved PIDs, table_id values, and the descriptor tags that carry the detail. Values from ETSI EN 300 468 V1.19.1.
Where the tables live
| PID | table_id | Table | In one line |
|---|---|---|---|
0x0000 | 0x00 | PAT | Every service and where its PMT lives. Read first. |
0x0001 | 0x01 | CAT | EMM streams. Absent when nothing is scrambled. |
0x0002 | 0x03 | TSDT | Describes the TS as a whole. Rare. |
| from PAT | 0x02 | PMT | One service: PCR PID, every ES, descriptors, ECMs. |
0x0010 | 0x40 / 0x41 | NIT | Every TS in the network, with tuning parameters. |
0x0011 | 0x42 / 0x46 | SDT | Service names and metadata. |
0x0011 | 0x4A | BAT | Commercial bouquets. Shares the SDT PID. |
0x0012 | 0x4E / 0x4F | EIT p/f | Now and next banner. |
0x0012 | 0x50–0x6F | EIT schedule | The full EPG. Optional and expensive. |
0x0013 | 0x71 | RST | Event started or ended early. |
0x0014 | 0x70 | TDT | UTC. |
0x0014 | 0x73 | TOT | Local offset. Carries a CRC32, unusually for a short section. |
0x1FFF | — | null | Padding. |
0x0011; TDT and TOT share 0x0014. Only table_id tells them apart — filter on both.
Descriptor tags you will actually meet
| Tag | Descriptor | Why you look it up |
|---|---|---|
0x40 | network_name | Network name. NIT only. |
0x43 | satellite_delivery_system | Frequency, polarization, symbol rate, FEC. |
0x44 | cable_delivery_system | Cable tuning parameters. |
0x48 | service | The channel name lives here. |
0x4A | linkage | Points to another service or event. |
0x4D | short_event | EPG title and short text. |
0x4E | extended_event | Long EPG description. |
0x50 | component | Stream content and type. |
0x52 | stream_identifier | Component tag, so other tables can point at an ES. |
0x54 | content | Genre. |
0x55 | parental_rating | Minimum age by country. |
0x56 | teletext | Teletext page and language. PMT. |
0x58 | local_time_offset | DST change. TOT. |
0x59 | subtitling | Subtitle language, type, page. PMT. |
0x5A | terrestrial_delivery_system | DVB-T tuning parameters. |
0x5F | private_data_specifier | Scopes the private descriptors after it. |
0x62 | frequency_list | Alternative frequencies for the same TS. |
0x6A | AC-3 | How you know audio is AC-3. Not the stream type. |
0x79 | S2_satellite_delivery_system | DVB-S2 tuning parameters. |
0x7A | enhanced_AC-3 | E-AC-3 audio. |
0x7F | extension | Second tag byte extends the space. |
0x00–0x3F is MPEG's (ISO/IEC 13818-1). 0x40–0x7F is DVB's. 0x80+ is private and only meaningful inside the scope set by private_data_specifier (0x5F).
Three things that catch people
AC-3 is carried as a private stream type and identified by AC-3_descriptor (0x6A). Same for E-AC-3 (0x7A), subtitles (0x59) and teletext (0x56). Read the descriptor loop or you will mis-identify audio on a lot of European transponders.
Some are legal in exactly one table — network_name in the NIT, service in the SDT. A parser that ignores which table it is inside will decode something that has no business being there and report it confidently.
Right after tuning the tables may not have arrived yet. Ask by explicit PID list and you need no table knowledge; ask by program and you must wait for the PMT.
Repetition thresholds
| Table | Within | If late |
|---|---|---|
| PAT | 0.5 s | Nothing decodes. |
| PMT | 0.5 s | That service does not decode. |
| SDT actual | 2 s | No channel name. |
| EIT p/f | 2 s | No now-and-next. |
| NIT actual | 10 s | Scanning falls back to a band sweep. |
| TDT | 30 s | Clock cannot be set. |
pids=all for monitoring feeds.