Program-specific information (PSI) is a collection of standardized metadata tables embedded within an MPEG-2 transport stream that describes the structure, components, and access controls of individual programs (such as television channels), enabling receivers to demultiplex, synchronize, and decode the content automatically. Defined in the ISO/IEC 13818-1 standard for information technology—generic coding of moving pictures and associated audio information, PSI forms the foundational layer for program identification and delivery in digital broadcasting systems.[1]
The core components of PSI consist of three primary tables: the Program Association Table (PAT), transmitted on packet identifier (PID) 0x0000, which maps program numbers to the PIDs of their corresponding Program Map Tables (PMT) and indicates the PID for the Network Information Table (NIT) if present; the PMT, which for each program specifies the PIDs and types of elementary streams (e.g., video, audio, subtitles) along with descriptors for stream properties and synchronization via Program Clock References (PCR); and the Conditional Access Table (CAT), sent on PID 0x0001, which points to entitlement management and control message streams for decryption in pay-TV scenarios.[2][1] These tables are carried in sections within transport stream packets and are periodically repeated—typically every 0.1 to 1 second—to ensure rapid acquisition by decoders during channel changes or stream initialization.[2]
PSI plays a pivotal role in global digital television standards, including DVB (Digital Video Broadcasting) in Europe and Asia, and forms the basis for extensions like ATSC's Program and System Information Protocol (PSIP) in North America, where it is supplemented by additional tables for enhanced electronic program guides and virtual channel navigation.[1] By providing essential normative data for demultiplexing transport streams and regenerating programs, PSI ensures interoperability across set-top boxes, televisions, and streaming devices, while private data sections allow broadcasters to include custom information without violating the standard. Its design supports both free-to-air and conditional access services, making it indispensable for the reliable delivery of multiplexed audiovisual content over satellite, cable, and terrestrial networks.[2]
Introduction
Definition and Purpose
Program Specific Information (PSI) is defined as normative metadata within the MPEG-2 Systems standard (ISO/IEC 13818-1), serving as essential control data embedded in transport streams to describe the structure and contents of multiplexed programs and their constituent elementary streams, such as video, audio, and data components. This metadata is carried in specific packets of the transport stream, providing decoders with the necessary information to interpret the multiplex without requiring external configuration or prior knowledge of the stream's organization.[3]
The primary purposes of PSI include enabling the demultiplexing of individual programs from a shared transport stream, where multiple programs are combined for efficient transmission; identifying the types and locations of elementary streams associated with each program to facilitate their extraction and decoding; supporting conditional access mechanisms to control viewing permissions for scrambled content; and aiding receivers in navigating and selecting programs by mapping program identifiers to their respective components. These functions ensure that end-user devices, such as set-top boxes, can reliably process and present selected audiovisual content in real-time broadcasting scenarios.
At its core, PSI allows a receiver to locate, reconstruct, and synchronize a specific program from the multiplexed transport stream, which acts as the container for interleaved packets of multiple programs and PSI data, thereby enabling seamless program selection and playback without dependency on proprietary signaling.
Historical Context and Standards
Program-specific information (PSI) originated within the MPEG-2 standards as part of the systems layer, developed to facilitate digital television broadcasting by enabling the multiplexing and identification of multiple programs in a single stream. The Moving Picture Experts Group (MPEG), established under ISO/IEC JTC1/SC29/WG11 in 1988, initiated MPEG-2 work in 1991, culminating in the publication of ISO/IEC 13818-1 in July 1995, which formally defined PSI alongside transport and program streams.[3][4] This standard addressed the need for robust signaling in broadcast environments, supporting synchronization of video, audio, and data elementary streams for applications like high-definition television.[3] Subsequent editions, up to the tenth edition published in August 2025, have incorporated technical revisions and amendments to extend PSI functionality.[3]
The initial definition of PSI in ISO/IEC 13818-1 provided core tables for program association and mapping, marking a significant advancement over prior formats. In contrast to MPEG-1 program streams, defined in ISO/IEC 11172-1 (1993) and suited for single-program storage media like CD-ROMs without dedicated multiplexing metadata, MPEG-2 introduced PSI to handle multiple independent programs within transport streams, essential for error-prone broadcast channels.[3][4] These editions have incorporated adaptations for regional standards such as ATSC, DVB, and ISDB to meet diverse broadcasting requirements.[3]
Key standardization events in 1995 accelerated PSI's adoption: the International Organization for Standardization (ISO) approved ISO/IEC 13818-1, while the Advanced Television Systems Committee (ATSC) integrated it into A/53 for U.S. digital television, enabling efficient use of 6 MHz channels for HDTV and SDTV transmission.[5] The Digital Video Broadcasting (DVB) Project, founded in September 1993, built on MPEG-2 PSI with extensions specified in ETSI EN 300 468 for European terrestrial, cable, and satellite delivery.[1] Similarly, Japan's Integrated Services Digital Broadcasting (ISDB) standards, developed in the mid-1990s and formalized by ARIB in 1998, adopted and extended PSI for hierarchical transmission supporting mobile and fixed reception.[4] These integrations played a pivotal role in the global transition from analog to digital broadcasting during the late 1990s, standardizing infrastructure for over-the-air, cable, and satellite services worldwide.[5][6]
PSI in MPEG-2 Transport Streams
Relation to Transport Stream Structure
In the MPEG-2 transport stream, which serves as a multiplex of multiple packetized elementary streams (PES) representing audio, video, and data components from one or more programs, Program Specific Information (PSI) is integrated as a set of signaling sections rather than PES packets. These PSI sections are encapsulated directly into the payload of 188-byte fixed-length transport stream packets, without using PES headers, allowing for efficient demultiplexing and program identification across the stream. When a PSI section begins within a packet's payload, the payload_unit_start_indicator is set to '1', and a pointer_field specifies the offset to the section's start, ensuring seamless parsing even if sections span multiple packets; any unused space following a section is filled with stuffing bytes (0xFF) that decoders ignore.[7]
PSI occupies a foundational position in every transport stream, being mandatory to enable receivers to map program numbers—logical identifiers for broadcast programs—to specific Packet Identifiers (PIDs), which are 13-bit fields in transport packet headers that route data to appropriate buffers. This mapping is essential for isolating individual programs within the multiplexed stream, as without PSI, decoders cannot associate elementary streams with their intended programs. The standard mandates that PSI tables remain unscrambled, ensuring accessibility for initial stream acquisition regardless of content encryption.[7]
PSI data is organized into modular sections, each beginning with a header that includes fields such as the table_id, which uniquely identifies the type of PSI table (e.g., 0x00 for the Program Association Table), and the section_syntax_indicator, set to '1' to denote the long-form syntax used for PSI with CRC_32 error checking and optional private data. These sections are transmitted in transport packets assigned to reserved PIDs, with the Program Association Table (PAT) specifically carried on PID 0x0000, making it the entry point for all PSI parsing; other PSI tables, like the Program Map Table (PMT), use PIDs referenced within the PAT. This sectional structure allows PSI to be updated incrementally, with version numbers signaling changes to decoders without disrupting the entire stream.[7]
For decoding a transport stream, receivers must first acquire and process PSI to interpret the multiplexed content, as it provides the necessary PIDs for locating elementary streams and the Program Clock Reference (PCR), a time base embedded in adaptation fields of designated packets. The PCR_PID, specified in PSI tables, enables synchronization of program timelines across audio, video, and data, with PCR values transmitted at least every 0.1 seconds to maintain clock recovery via phase-locked loops in decoders. This dependency ensures that PSI not only structures the stream but also facilitates timed presentation, preventing desynchronization in multi-program environments.[7]
Transmission and Parsing Mechanisms
Program Specific Information (PSI) in MPEG-2 transport streams is transmitted by segmenting tables into sections that are carried within the payload of transport stream packets. These sections are assigned to specific packet identifiers (PIDs), such as PID 0x0000 for the Program Association Table (PAT) and PID 0x0001 for the Conditional Access Table (CAT), with Program Map Table (PMT) PIDs referenced in the PAT.[8] The transmission occurs continuously, with tables cycled and repeated to support decoder acquisition during channel changes or signal recovery, though the MPEG-2 standard does not mandate exact intervals.[8] Recommendations in broadcasting profiles, such as ITU-R BT.1300-3, suggest that each section of the PAT and PMT should be transmitted at least once every 100 ms to ensure timely availability. In practice, ATSC A/53 requires PAT transmission at least every 100 ms, while allowing up to 500 ms maximum cycles to avoid errors.[9]
Each PSI section follows a standardized syntax, beginning after a pointer field in packets where the payload_unit_start_indicator is set to 1, and concludes with a 32-bit cyclic redundancy check (CRC-32) for error detection.[8] The CRC-32 is computed using the polynomial x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1, ensuring the remainder is zero for valid sections.[8] Incomplete sections may include stuffing bytes (0xFF) to fill payloads, and sections are limited to a maximum length of 1021 bytes for standard PSI, excluding the CRC.[8]
Receivers parse PSI through a structured workflow to extract and process this data from the transport stream. The process begins with synchronization on the transport stream packet sync byte (0x47), which marks the start of each 188-byte packet.[8] Packets are then filtered by their PID to isolate relevant PSI data, such as PID 0x0000 for PAT sections.[8] When the payload_unit_start_indicator is 1, the pointer_field indicates the offset to the section header; otherwise, sections continue from prior packets. The receiver reassembles multi-packet sections using the section_length field and sequences them via the section_number (0-255), validating integrity with the CRC_32.[8] Finally, the table_id field (e.g., 0x00 for PAT, 0x02 for PMT) routes the data for interpretation, enabling program demultiplexing.[8]
Error handling in PSI transmission relies on versioning and discontinuity indicators to maintain reliability. The version_number field (5 bits, 0-31) increments modulo 32 upon table content changes, signaling decoders to acquire the updated version when the current_next_indicator is 1.[8] This allows efficient updates without full stream restarts. The discontinuity_indicator in the adaptation_field of transport packets flags interruptions in continuity counters or time bases, such as during splicing, prompting receivers to reset parsing states if needed.[8] Invalid CRCs result in section discard, with repetition ensuring recovery within the cycle interval.
PSI transmission imposes minimal bandwidth overhead on the transport stream, typically consuming 1-5% of the total bitrate depending on the number of programs and repetition rates.[8] Optimizations focus on cycling complete sections rather than incremental updates, with buffer models like the system target decoder (T-STD) removing PSI data at rates scaled to the transport bitrate (e.g., at least 80 kbit/s or 1/500th of the stream rate).[8]
Core PSI Tables
Program Association Table (PAT)
The Program Association Table (PAT) serves as the primary directory for programs within an MPEG-2 transport stream, associating each program with the packet identifier (PID) of its corresponding Program Map Table (PMT). Carried exclusively in transport stream packets with PID 0x0000, the PAT is a mandatory element of Program Specific Information (PSI) that facilitates program identification and selection by receivers.[8] A program_number value of 0 in the PAT reserves the entry for a network_PID pointing to network information tables, such as the Network Information Table (NIT), while nonzero values indicate program_map_PID entries for individual programs.[8]
The syntax of the PAT follows the generic section structure defined in ISO/IEC 13818-1, with specific fields tailored for program association:
program_association_section() {
table_id 8 uimsbf // 0x00
section_syntax_indicator 1 bslbf // 1
'0' 1 bslbf
reserved 2 bslbf // '11'
section_length 12 uimsbf
transport_stream_id 16 uimsbf
reserved 2 bslbf // '11'
version_number 5 uimsbf
current_next_indicator 1 bslbf
section_number 8 uimsbf
last_section_number 8 uimsbf
for (i = 0; i < N; i++) {
program_number 16 uimsbf
reserved 3 bslbf // '111'
if (program_number == 0) {
network_PID 13 uimsbf
} else {
program_map_PID 13 uimsbf
}
}
CRC_32 32 rpchof
}
program_association_section() {
table_id 8 uimsbf // 0x00
section_syntax_indicator 1 bslbf // 1
'0' 1 bslbf
reserved 2 bslbf // '11'
section_length 12 uimsbf
transport_stream_id 16 uimsbf
reserved 2 bslbf // '11'
version_number 5 uimsbf
current_next_indicator 1 bslbf
section_number 8 uimsbf
last_section_number 8 uimsbf
for (i = 0; i < N; i++) {
program_number 16 uimsbf
reserved 3 bslbf // '111'
if (program_number == 0) {
network_PID 13 uimsbf
} else {
program_map_PID 13 uimsbf
}
}
CRC_32 32 rpchof
}
This structure allows the PAT to be segmented into multiple sections if necessary, with the section_length field (12 bits) specifying the byte count from after this field to the end of the CRC_32, limited to a maximum of 1021 bytes per section.[8] The table_id is fixed at 0x00 to uniquely identify the PAT, while the transport_stream_id (16 bits) distinguishes the current transport stream from others.[8] Reserved bits are set to '1' for backward compatibility, and the CRC_32 provides error detection using the polynomial x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1.[8]
Key semantics of the PAT fields include:
| Field | Size (bits) | Semantics |
|---|
| table_id | 8 | Fixed value 0x00, indicating the Program Association Table.[8] |
| section_syntax_indicator | 1 | Set to 1, denoting adherence to the long-form section syntax.[8] |
| section_length | 12 | Length in bytes of the section (excluding the table_id through section_length fields but including CRC_32); first/last sections have nonzero length, pointer sections may have zero.[8] |
| transport_stream_id | 16 | Label identifying the transport stream; value 0 is reserved.[8] |
| version_number | 5 | Numbered 0–31; increments by 1 (modulo 32) when PAT contents change to notify receivers of updates.[8] |
| current_next_indicator | 1 | 1 indicates the section is currently applicable; 0 means it applies to the next transport stream version only.[8] |
| section_number | 8 | Identifies the section number within the PAT (0–255); increments for multi-section PATs.[8] |
| last_section_number | 8 | Number of the final section in the PAT.[8] |
| program_number | 16 | Assigns a unique number to each program (1–65535) or 0 for network information.[8] |
| program_map_PID | 13 | PID value (1–8190) for packets carrying the PMT of the associated program; excludes 0x0000 and 0x1FFF.[8] |
| network_PID | 13 | PID for network information sections when program_number is 0.[8] |
The PAT functions as the entry point for PSI demultiplexing, allowing decoders to locate PMTs and subsequently access elementary streams for desired programs.[8] It is mandatory in all transport streams and transmitted cyclically in PID 0x0000 packets to ensure reliable acquisition by receivers, typically with repetition intervals defined by application standards (e.g., ATSC requires at least every 100 ms).[8][10] For instance, an entry with program_number 1 might map to program_map_PID 0x0100, directing the receiver to the PMT packets at that PID for further stream details.[8] Updates to the PAT, such as adding or modifying programs, trigger an increment in the version_number (modulo 32), while the current_next_indicator determines the table's immediate validity.[8]
Program Map Table (PMT)
The Program Map Table (PMT) is a key component of Program Specific Information (PSI) in MPEG-2 transport streams, serving as a per-program table that lists the elementary streams comprising a specific program, including their types and associated Packet Identifiers (PIDs).[8] The PID for each PMT is obtained from the Program Association Table (PAT), which maps program numbers to their corresponding PMT locations.[8] This structure enables receivers to identify and demultiplex the components of individual programs within a multiplexed transport stream.[8]
The syntax of the PMT is defined in ISO/IEC 13818-1, Section 2.4.4.8, as a transport stream program map section with the following fields: an 8-bit table_id fixed at 0x02 to identify it as a PMT; a 12-bit section_length indicating the length of the section excluding the header; a 16-bit program_number specifying the program to which the PMT applies; a 13-bit PCR_PID identifying the PID carrying the Program Clock Reference for timing and synchronization; a 12-bit program_info_length followed by optional program-level descriptors; a loop for each elementary stream consisting of an 8-bit stream_type, a 13-bit elementary_PID, a 12-bit ES_info_length, and optional elementary stream descriptors; and a 32-bit CRC_32 for error detection.[8] The full syntax is as follows:
TS_program_map_section() {
table_id 8 uimsbf // value 0x02
section_syntax_indicator 1 bslbf // value 1
'0' 1 bslbf
reserved 2 bslbf
section_length 12 uimsbf
program_number 16 uimsbf
reserved 2 bslbf
version_number 5 uimsbf
current_next_indicator 1 bslbf
section_number 8 uimsbf // value 0x00
last_section_number 8 uimsbf // value 0x00
reserved 3 bslbf
PCR_PID 13 uimsbf
reserved 4 bslbf
program_info_length 12 uimsbf
for (i=0; i < N; i++) {
descriptor() // program descriptors
}
for (i=0; i < N1; i++) {
stream_type 8 uimsbf
reserved 3 bslbf
elementary_PID 13 uimsbf
reserved 4 bslbf
ES_info_length 12 uimsbf
for (j=0; j < N2; j++) {
descriptor() // ES descriptors
}
}
CRC_32 32 rpchof
}
TS_program_map_section() {
table_id 8 uimsbf // value 0x02
section_syntax_indicator 1 bslbf // value 1
'0' 1 bslbf
reserved 2 bslbf
section_length 12 uimsbf
program_number 16 uimsbf
reserved 2 bslbf
version_number 5 uimsbf
current_next_indicator 1 bslbf
section_number 8 uimsbf // value 0x00
last_section_number 8 uimsbf // value 0x00
reserved 3 bslbf
PCR_PID 13 uimsbf
reserved 4 bslbf
program_info_length 12 uimsbf
for (i=0; i < N; i++) {
descriptor() // program descriptors
}
for (i=0; i < N1; i++) {
stream_type 8 uimsbf
reserved 3 bslbf
elementary_PID 13 uimsbf
reserved 4 bslbf
ES_info_length 12 uimsbf
for (j=0; j < N2; j++) {
descriptor() // ES descriptors
}
}
CRC_32 32 rpchof
}
This syntax ensures the PMT remains compact while accommodating variable numbers of streams and descriptors.[8]
The primary function of the PMT is to enable the extraction and processing of a program's video, audio, subtitle, and other elementary streams by providing their stream types, PIDs, and associated metadata, thereby supporting the demultiplexing of multiple programs in a single transport stream.[8] For instance, in a PMT for program_number 1, a video elementary stream might be indicated by stream_type 0x02 (ITU-T Rec. H.262 | ISO/IEC 13818-2 Video, i.e., MPEG-2 video) with elementary_PID 0x0200, allowing a decoder to locate and synchronize that stream using the specified PCR_PID.[8]
Special cases in PMT handling include the placement of the PCR_PID, which is typically assigned to the video PID for efficiency but can alternatively use an audio PID or a dedicated PID if needed for synchronization across streams.[8] Descriptor loops at the program level provide overarching information such as conditional access details, while those at the elementary stream level offer stream-specific attributes like language codes or format parameters, enhancing flexibility without altering the core table structure.[8]
Conditional Access Table (CAT)
The Conditional Access Table (CAT) is a mandatory element of Program Specific Information (PSI) in MPEG-2 transport streams when conditional access is employed, transmitted exclusively in transport stream packets identified by the packet identifier (PID) 0x0001. It carries one or more conditional access (CA) descriptors that detail the systems used for scrambling content, including references to entitlement management message (EMM) streams necessary for authorizing subscriber access. These descriptors enable receivers to locate and process the appropriate EMM data for descrambling, supporting secure delivery in broadcast environments.[8]
The syntax of the CAT follows the private section structure defined in ISO/IEC 13818-1 with section_syntax_indicator set to 1 (long form), consisting of table_id=0x01 (8 bits), section_syntax_indicator=1 (1 bit), private_indicator=0 (1 bit), reserved=2 bits ('11'), section_length (12 bits, up to 1021 bytes excluding header and CRC), reserved=2 bits ('11'), version_number (5 bits), current_next_indicator (1 bit), section_number=0 (8 bits), last_section_number=0 (8 bits), followed by a loop of zero or more generic descriptors (where CA descriptors use tag 0x09, containing 16-bit CA_system_id, 13-bit CA_PID, and private data), and CRC_32 (32 bits). The full syntax is as follows:
CA_section() {
table_id 8 uimsbf // 0x01
section_syntax_indicator 1 bslbf // 1
private_indicator 1 bslbf // 0
reserved 2 bslbf // '11'
section_length 12 uimsbf
reserved 2 bslbf // '11'
version_number 5 uimsbf
current_next_indicator 1 bslbf
section_number 8 uimsbf // 0
last_section_number 8 uimsbf // 0
for (i = 0; i < N; i++) {
descriptor() // CA descriptors (tag 0x09)
}
CRC_32 32 rpchof
}
CA_section() {
table_id 8 uimsbf // 0x01
section_syntax_indicator 1 bslbf // 1
private_indicator 1 bslbf // 0
reserved 2 bslbf // '11'
section_length 12 uimsbf
reserved 2 bslbf // '11'
version_number 5 uimsbf
current_next_indicator 1 bslbf
section_number 8 uimsbf // 0
last_section_number 8 uimsbf // 0
for (i = 0; i < N; i++) {
descriptor() // CA descriptors (tag 0x09)
}
CRC_32 32 rpchof
}
In function, the CAT plays a critical role in access control by notifying compatible receivers of the active scrambling algorithms and the PIDs required to obtain long-term authorization keys via EMMs, which are essential for pay-TV and subscription-based services to prevent unauthorized viewing of encrypted content. It is particularly vital in multi-system environments where multiple CA vendors operate, allowing decoders to select the relevant EMM stream based on the CA_system_id. For example, in Digital Video Broadcasting (DVB) deployments, a CA_system_id of 0x0100 denotes the SECA Mediaguard (now Viaccess-Orca) system, with the CA_PID directing to an EMM stream such as 0x00B6 for entitlement processing. Without the CAT, receivers cannot initialize descrambling, even if program mapping details are available from other tables.[11][12]
The presence of the CAT is optional in unscrambled transport streams, where no access restrictions apply, but it must be included and periodically updated in secured streams to reflect changes in CA configurations. In application standards like DVB, transmission occurs with a maximum interval of 10 seconds and a maximum burst delay of 100 ms to ensure rapid acquisition by tuning receivers while conserving bandwidth.[13] This design balances efficiency with the security demands of conditional access, as specified in the MPEG-2 systems standard.[8]
Descriptors Within PSI
Descriptor Syntax and Usage
Descriptors in Program Specific Information (PSI) follow a standardized structure defined in the MPEG-2 Systems specification, consisting of a 2-byte header followed by variable-length data. The syntax begins with an 8-bit descriptor_tag field, which serves as an unsigned integer (uimsbf) to identify the descriptor type, followed by an 8-bit descriptor_length field indicating the number of subsequent bytes. The data portion then comprises a loop of descriptor_length bytes, each an 8-bit field (bslbf) containing the descriptor-specific content.[8]
This structure is embedded within descriptor loops in PSI tables such as the Program Map Table (PMT) and Conditional Access Table (CAT), where it appears in sections like program_info_length and ES_info_length for the PMT, or the descriptors_length loop for the CAT. Descriptors are optional and may be repeated within these loops to extend the base table information with additional attributes, such as audio language preferences or video aspect ratios, enhancing the flexibility of PSI without altering the core table syntax. The Program Association Table (PAT) does not typically include descriptor loops, limiting its extensibility compared to other PSI tables.[8]
Parsing of descriptors is designed for robustness, particularly with unknown or private tags; receivers read the descriptor_tag (ranging from 0x00 to 0xFF) and descriptor_length, then skip the entire data block by advancing the pointer accordingly, ensuring compatibility with future extensions. The example loop syntax in pseudocode illustrates this process:
for (i = 0; i < N; i++) {
descriptor_tag 8 uimsbf
descriptor_length 8 uimsbf
for (j = 0; j < descriptor_length; j++) {
descriptor_data_byte 8 bslbf
}
}
for (i = 0; i < N; i++) {
descriptor_tag 8 uimsbf
descriptor_length 8 uimsbf
for (j = 0; j < descriptor_length; j++) {
descriptor_data_byte 8 bslbf
}
}
Here, N represents the number of descriptors in the loop, determined by the enclosing length field.[8]
Constraints on descriptors ensure efficient transmission within the transport stream; the 8-bit length field limits each descriptor's data to a maximum of 255 bytes, while the overall PSI section sizes—up to 4095 bytes of data (total section up to approximately 4100 bytes including header) for tables like PMT and private sections—further bound the total descriptor space. Descriptors are never transmitted standalone but are always encapsulated within PSI sections, which are carried in transport stream packets and recommended to repeat at intervals not exceeding 0.1 seconds for timely availability to decoders.[8]
Program-Level and Stream-Level Descriptors
In MPEG-2 transport streams, descriptors within the Program Map Table (PMT) are categorized into program-level and stream-level based on their placement and scope of application. Program-level descriptors appear in the program_info loop of the PMT, providing metadata that applies to the entire program, such as access control or service identification. These descriptors follow the program_info_length field and are essential for configuring decoders to handle the program as a cohesive unit.
Stream-level descriptors, in contrast, are located in the ES_info loop associated with each elementary stream within the PMT, offering details specific to individual components like video or audio tracks. This separation allows for granular control over stream attributes while maintaining program-wide consistency. The descriptor syntax, as defined in the MPEG-2 systems standard, serves as the foundational structure for both levels, consisting of a tag, length, and data payload.
Program-level descriptors in the PMT's program_info loop include the conditional_access descriptor (tag 0x09), which specifies scrambling mechanisms and associated elementary stream PIDs for entitlement control messages to secure the entire program. For instance, the registration descriptor (tag 0x05) can identify private data formats at the program level. Another example from extensions like DVB is the service descriptor (tag 0x48), which conveys the service name and type, enabling receivers to display program identifiers like "digital television service" or "radio service" across all streams in the program. Additionally, the program clock reference (PCR) is managed at the program level through the PCR_PID field in the PMT header, which designates a single PID for the transport stream packets carrying the PCR in their adaptation fields to synchronize the whole program, rather than individual streams. These descriptors ensure unified program handling, such as applying conditional access to all components without per-stream repetition.[14]
Stream-level descriptors in the ES_info loop target specific elementary streams, for instance, the ISO_639_language_code descriptor (tag 0x0A), which identifies the primary language of an audio or subtitle stream using three-letter codes from ISO 639-2, allowing multilingual selection for that stream alone. The video_stream_descriptor (tag 0x02) provides format details, such as multiple frame rate flags or aspect ratio information, applicable only to the associated video elementary stream. This level enables tailored processing, like language-specific audio decoding, without impacting other program elements.[14]
The scope differs fundamentally: program-level descriptors influence the multiplexed program holistically, affecting synchronization and access for all streams, whereas stream-level descriptors operate on isolated elementary streams, supporting diverse configurations within a single program. Not all PSI tables employ both levels; the Program Association Table (PAT) rarely includes descriptors, focusing instead on program number to PID mappings, while the Conditional Access Table (CAT) primarily carries CA_system_ID descriptors centered on global access types rather than program or stream specifics. This structured application enhances efficient parsing and rendering in broadcast receivers.
PSI Coding and Identifiers
Table Identifiers
The table_id field is an 8-bit unsigned integer located in the header of each PSI section, serving as a primary identifier to distinguish the type of table being transmitted within the MPEG-2 transport stream.[8] This field enables receivers to route incoming sections to the appropriate parsing logic during demultiplexing.[8]
The assigned values for core PSI tables are fixed as follows: 0x00 for the Program Association Table (PAT), which maps program numbers to their corresponding Program Map Tables; 0x01 for the Conditional Access Table (CAT), which provides details on entitlement management messages; and 0x02 for the Program Map Table (PMT), which describes the elementary streams comprising each program.[8] All sections of a given PMT share the table_id value of 0x02, with section numbering set to 0x00 since each program's PMT is typically contained in a single section.[8] 0x03 is assigned to the Transport Stream Description Section (TS_description_section); values from 0x04 to 0x3F are reserved for future PSI extensions or specific PSI sections. PSI sections use table_id values from 0x00 to 0x3F, with values 0x08 to 0x3F reserved for future PSI extensions. Service Information (SI) tables in related standards like DVB use the private section syntax with table_id values from 0x40 to 0xFF.[8][15]
Private sections, identifiable by table_id values in the range 0x40 to 0xFF (excluding 0xFF, which is reserved for stuffing bytes), allow broadcasters to transmit custom data structured similarly to PSI sections, such as proprietary signaling or additional metadata, without conflicting with standard tables.[8] These private identifiers extend the PSI framework for application-specific needs while maintaining compatibility with the transport stream's section syntax.[8]
During reception and parsing, the table_id undergoes validation to ensure section integrity; any mismatch with the expected value for a given PID triggers discard or error handling, and alterations in table_id across versions can indicate updates to the PSI structure.[8] This mechanism supports efficient, real-time processing in decoders by preventing misinterpretation of section contents.[8]
| Table_id (Hex) | Table Name | Purpose |
|---|
| 0x00 | Program Association Table (PAT) | Associates program numbers with PMT PIDs. |
| 0x01 | Conditional Access Table (CAT) | Specifies PIDs for entitlement management messages. |
| 0x02 | Program Map Table (PMT) | Defines elementary streams, PCR PID, and descriptors for a program. |
| 0x03 | Transport Stream Description Section (TS_description_section) | Describes transport stream properties. |
| 0x04–0x3F | Reserved | For future PSI table extensions or specific PSI sections. |
| 0x40–0xFE | Private Sections | Custom data transmission in PSI-like format. |
In the Program Specific Information (PSI) of MPEG-2 transport streams, the descriptor_tag field is an 8-bit unsigned integer that uniquely identifies the type of each descriptor within descriptor loops of PSI tables such as the Program Map Table (PMT) or Conditional Access Table (CAT).[16] This field allows decoders to interpret the associated descriptor data correctly, with values ranging from 0x00 to 0xFF. The standard range of 0x00 to 0x7F is reserved for descriptors defined by ISO/IEC 13818-1, ensuring interoperability across MPEG-2 systems.[17] In contrast, the range 0x80 to 0xFF is designated for private use, enabling extensions by standards bodies like ATSC, DVB, or vendors without conflicting with core ISO definitions.[18]
Key descriptor tags in the ISO-defined range include 0x02 for the video_stream_descriptor, which specifies properties of video elementary streams; 0x03 for the audio_stream_descriptor, detailing audio stream characteristics; 0x09 for the CA_descriptor, providing conditional access parameters; and 0x0A for the ISO_639_language_descriptor, indicating language codes per ISO 639-2.[17] In the private range, tag 0x48 identifies the service_descriptor, used in ATSC PSIP tables to describe service attributes like type and name; while 0x5F denotes a private_data_specifier_descriptor for vendor-specific extensions.[18] These tags are exemplified in usage such as the 0x09 CA_descriptor within the CAT, where it carries the CA_system_id to specify the conditional access system.[16]
Assignment of descriptor tags is centrally registered by ISO to maintain global consistency, with new tags allocated through amendments to ISO/IEC 13818-1.[16] Private tags in the 0x80-0xFF range are managed by regional bodies to avoid overlap with ISO allocations; for instance, ATSC coordinates tags like 0x48 to extend PSI functionality in terrestrial broadcasting.[18] Standards updates, such as those in ATSC A/65:2013, introduce or revise private tags to support evolving features like enhanced service metadata, ensuring backward compatibility by reserving unused values in the private range.[18]
| Descriptor Tag | Name | Range | Usage Example |
|---|
| 0x02 | video_stream_descriptor | ISO (0x00-0x7F) | Video properties in PMT stream loops |
| 0x03 | audio_stream_descriptor | ISO (0x00-0x7F) | Audio properties in PMT stream loops |
| 0x09 | CA_descriptor | ISO (0x00-0x7F) | CA_system_id in CAT |
| 0x0A | ISO_639_language_descriptor | ISO (0x00-0x7F) | Language codes in PMT or service descriptors |
| 0x48 | service_descriptor | Private (0x80-0xFF) | Service type in ATSC VCT |
| 0x5F | private_data_specifier_descriptor | Private (0x80-0xFF) | Vendor extensions in PSI tables |
Elementary Stream Types
The stream_type field is an 8-bit value located within the elementary stream loop of the Program Map Table (PMT) in Program-Specific Information (PSI). It specifies the format and codec of the associated elementary stream, enabling receivers to identify and invoke the correct decoder for processing Packetized Elementary Stream (PES) packets or sections carried on the stream's Packet Identifier (PID).[19]
Defined in ISO/IEC 13818-1, the stream_type values range from 0x00 (reserved) to 0xFF, with 0x00–0x7F allocated for internationally standardized types and 0x80–0xFF designated for user private use, allowing customization by organizations like ATSC or DVB without conflicting with core MPEG definitions.[19] This classification ensures interoperability across transport streams while accommodating proprietary or application-specific extensions.
The original values established in early editions of ISO/IEC 13818-1 (MPEG-2 Systems) focused on foundational codecs from the 1990s, such as MPEG-1 and MPEG-2. Subsequent amendments and new editions have incorporated support for advanced formats through ISO/IEC extensions. For instance, values like 0x1B for H.264/AVC video (added via Amendment 3 in 2003) and 0x24 for HEVC/H.265 video (introduced in later revisions) reflect the evolution toward higher-efficiency compression standards.[19]
Representative stream_type values are summarized in the following table, highlighting key standardized and private examples used in PMTs to classify common elementary streams:
| Hex Value | Decimal | Description |
|---|
| 0x01 | 1 | ISO/IEC 11172-2 Video (MPEG-1 Video)[19] |
| 0x02 | 2 | ITU-T Rec. H.262 | ISO/IEC 13818-2 Video (MPEG-2 Video)[19] |
| 0x03 | 3 | ISO/IEC 11172-3 Audio (MPEG-1 Audio, Layer I/II/III)[19] |
| 0x04 | 4 | ISO/IEC 13818-3 Audio (MPEG-2 Audio, BC/SY/2)[19] |
| 0x06 | 6 | PES packets containing private data (e.g., non-MPEG content)[19] |
| 0x0F | 15 | ISO/IEC 13818-7 Audio with ADTS transport syntax (AAC)[19] |
| 0x10 | 16 | ISO/IEC 14496-3 Audio with LATM transport syntax (MPEG-4 AAC)[19] |
| 0x11 | 17 | ISO/IEC 14496-2 Visual (MPEG-4 Part 2 Video)[19] |
| 0x1B | 27 | ITU-T Rec. H.264 | ISO/IEC 14496-10 Video (AVC/H.264)[19] |
| 0x24 | 36 | ISO/IEC 23008-2 Video (HEVC/H.265)[19] |
| 0x81 | 129 | AC-3 Audio (ATSC private use) |
In practice, the stream_type guides decoder instantiation; for example, a PMT entry with stream_type 0x1B signals an H.264 video stream, prompting the receiver to use an AVC-compatible decoder while ignoring incompatible ones.[19] Mismatches between stream_type and stream content can lead to decoding failures, underscoring its role in robust stream demultiplexing.