The first thing that service information has to describe is the organization of the transport stream. This is defined as part of the MPEG standard, and so these tables are common across all types of digital TV system, be it DVB or ATSC. The most important table is the Program Association Table (PAT). This is the entry point into the service information, and so it must be broadcast on a well-known PID within the transport stream – PID 0.
Programs in MPEG are the same as services in a digital TV context. The Program Association Table lists how many services there are in the transport stream, and provides pointers to more detailed descriptions of those services. Each service has an associated Program Map Table (PMT) that describes the elementary stream s that make up the service. For every elementary stream in the service, the PMT for that service contains information about the type of that stream (audio, video or data, and what type of audio, video or data) and the PID of that elementary stream. Since there are several instances of the PMT in a transport stream, these are broadcast on different PIDs. The PID for each PMT is carried in the PAT entry for that service.
The Virtual Channel Table
Now that the receiver knows how the network is organized at the stream level, some extra logical information is needed to make this more useful to the receiver. The PMT provides a list of how each service is organized in the transport stream, but it doesn’t actually give much information about how services are organized from the perspective of the viewer. The viewer cares specifically about TV channels, and shouldn’t even know about transport streams and elementary streams or any other part of the broadcasting system. To do this, ATSC uses another table called the Virtual Channel Table, or VCT. Cable, satellite and terrestrial networks all have slightly different versions of this table. Below, we can see the structure of the VCT in a terrestrial network:
Syntax | No. of bits | Format |
---|---|---|
terrestrial_virtual_channel_table_section () { | ||
table_id | 8 | 0xC8 |
section_syntax_indicator | 1 | ‘1’ |
private_indicator | 1 | ‘1’ |
reserved | 2 | ’11’ |
section_length | 12 | uimsbf |
transport_stream_id | 16 | uimsbf |
reserved | 2 | ’11’ |
version_number | 5 | uimsbf |
current_next_indicator | 1 | bslbf |
section_number | 8 | uimsbf |
last_section_number | 8 | uimsbf |
protocol_version | 8 | uimsbf |
num_channels_in_section | 8 | uimsbf |
for (i=0; i < num_channels_in_section; i++) { | ||
short_name | 7 * 16 | uimsbf |
reserved | 4 | ‘1111’ |
major_channel_number | 10 | uimsbf |
minor_channel_number | 10 | uimsbf |
modulation_mode | 6 | uimsbf |
carrier_frequency | 32 | uimsbf |
channel_TSID | 16 | uimsbf |
program_number | 16 | uimsbf |
ETM_location | 2 | uimsbf |
access_controlled | 1 | bslbf |
hidden | 1 | bslbf |
reserved | 2 | ’11’ |
hide_guide | 1 | bslbf |
reserved | 3 | ‘111’ |
service_type | 6 | uimsbf |
source_id | 16 | uimsbf |
reserved | 6 | ‘111111’ |
descriptors_length | 10 | uimsbf |
for (j = 0; j < N; j++) { | ||
descriptor() | ||
} | ||
} | ||
reserved | 6 | ‘111111’ |
additional_descriptors_length | 10 | uimsbf |
for (i=0; i < N; i++) { | ||
additional_descriptor() | ||
} | ||
CRC_32 | 32 | rpchof |
} |
For terrestrial VCTs, the table ID is 0xC8, and for cable VCTs, the table ID is 0xC9. For terrestrial and cable networks, a single VCT will be carried on PID number 0x1FFB (this is known as the base PID).
The only difference between VCTs in terrestrial and cable networks is the presence of two extra fields in a cable VCT. The reserved bits following the hidden
flag are replaced with two extra flags: the path_select
and out_of_band
flags.
Satellite networks, on the other hand, may contain several SVCT instances carried on any PID (and one PID may carry more than one SVCT instance). This is because a single satellite may carry signals from several different network operators. In this case, different instances of the SVCT will have a different SVCT ID in order to identify which SVCT the receiver should use. Exactly how the receiver knows which VCT to use isn’t standardized. This can be tied to the CA system, or it can be hard-coded into the receiver. In every case, the table ID for a satellite VCT is 0xDA. The structure of the VCT for a satellite ndtwork is as follows:
Syntax | No. of bits | Format |
---|---|---|
satellite_virtual_channel_table_section () { | ||
table_id | 8 | 0xDA |
section_syntax_indicator | 1 | ‘1’ |
private_indicator | 1 | ‘1’ |
reserved | 2 | ’11’ |
section_length | 12 | uimsbf |
if (satellite network) { | ||
satellite VCT subtype | 8 | uimsbf |
satellite VCT ID | 8 | uimsbf |
} else { | ||
transport_stream_id | 16 | uimsbf |
} | ||
reserved | 2 | ’11’ |
version_number | 5 | uimsbf |
current_next_indicator | 1 | bslbf |
section_number | 8 | uimsbf |
last_section_number | 8 | uimsbf |
protocol_version | 8 | uimsbf |
num_channels_in_section | 8 | uimsbf |
for (i=0; i < num_channels_in_section; i++) { | ||
if (satellite network) | ||
satellite channel description() | ||
} else { | ||
short_name | 7 * 16 | uimsbf |
reserved | 4 | ‘1111’ |
major_channel_number | 10 | uimsbf |
minor_channel_number | 10 | uimsbf |
modulation_mode | 6 | uimsbf |
carrier_frequency | 32 | uimsbf |
carrier_symbol_rate | 32 | uimsbf |
polarization | 2 | uimsbf |
FEC_inner | 8 | uimsbf |
channel_TSID | 16 | bslbf |
program_number | 16 | bslbf |
ETM_location | 2 | uimsbf |
reserved | 1 | ‘1’ |
hidden | 1 | bslbf |
reserved | 2 | ’11’ |
hide_guide | 1 | bslbf |
reserved | 3 | ‘111’ |
service_type | 6 | uimsbf |
source_id | 16 | uimsbf |
feed_id | 8 | uimsbf |
reserved | 6 | ‘111111’ |
descriptors_length | 10 | uimsbf |
for (j = 0; j < N; j++) { | ||
descriptor() | ||
} | ||
} | ||
reserved | 6 | ‘111111’ |
additional_descriptors_length | 10 | uimsbf |
for (k=0; k < N; k++) { | ||
additional_descriptor() | ||
} | ||
CRC_32 | 32 | rpchof |
} |
ATSC also imposes some restrictions on the transport stream packets that carry VCT sections – in particular, the transport_scrambling_control
field must have the value ’00’, and the adaptation_field_control
field must be set to the value ’01’.
Describing individual channels
Many of the basic elements that describe an individual channel are the same in each type of VCT. In practise, only those fields that refer to the type of modulation will change. Since satellite signals have a much greater number of parameters that control the way the signal is encoded, satellite VCTs need to carry this information so that the receiver can tune to a signal correctly. As well as the modulation mode and frequency, satellite VCTs also tell the receiver about the symbol rate, FEC coding and the feed ID of the transport stream. While the first two of these are pretty obvious, the feed ID may not be – this is used to identify the satellite containing the signal, or to carry some additional information about the frequency band or polarization that the receiver needs to know. The exact use of this value isn’t standardized, and so network operators can use this in the way that they see best.
There are two fields which may not appear useful at this stage. The program_number
field tells the which program in the transport stream this particular VCT entry refers to. This is not the same as the major and minor channel numbers, which tell the receiver where in the channel lineup the channel should appear.
The ETM_location
field tells the receiver where it can find an extended text description of the virtual channel. This field can take one of three values:
ETM location value | Description |
---|---|
0x00 | No extended description is available |
0x01 | Extended description available in the transport stream carrying the VTC |
0x02 | Extended description available in the transport stream specified by the channel_TSID field |
These extended text descriptions can contain several languages, and so it’s possible to provide multi-lingual names for channels using this mechanism.
One thing to notice when looking at the differences between satellite, terrestrial and cable VCTs is the length of the short_name
field. For satellite VCTs, this may be up to eight characters long, while for other network types it can only be seven characters (each character is 16-bit Unicode character). I’m not aware of any good reason why they are different, but it’s something that middleware developers and network operators need to be aware of.