TSReader |
Descriptor Decoding |
Introduction
Many MPEG, DVB, ATSC and DCII tables can contain descriptors which add to the information being sent on these tables. TSReader decodes almost all of these descriptors as shown below. Descriptors are decoded based on the network type that TSReader is currently processing. The following table explains how TSReader recognizes a network type:
MPEG-2 Transport Stream | Always assumed. |
DVB | A PMT entry for program 0 pointing to PID 0x0010 or NIT traffic on PID 0x0010. |
ATSC | A TVCT or CVCT being carried on PID 0x1ffe. |
DCII | A PMT entry for program 0 pointing to PID 0x0ffe. |
TSReader makes the decision about the network type the first time it sees one of the above conditions. We've seen a few (very few) networks carrying both DVB and ATSC tables so there's a special switch -D to force TSReader to operate in DVB mode on such networks.
The implications of the network type in TSReader alter the way in which descriptors are decoded. On DVB networks for example, descriptor tags have a value from 0x40 - 0x7f and anything above (0x80 - 0xff) are deemed user defined descriptors. On the other hand, DCII networks use descriptors from 0x80 - 0x90, so when TSReader is in DVB mode it'll decode descriptor 0x82 as a user-defined descriptor and output it in hex/ASCII. However, if TSReader is looking at a DCII network, descriptor 0x82 will be correctly decoded as a DCII frame-rate descriptor.
Descriptor List
Descriptor Tag | Descriptor Usage | Supported? |
MPEG-2 | ||
0x02 | Video Stream | Y |
0x03 | Audio Stream | Y |
0x04 | Hierarchy | Y |
0x05 | Registration | Y |
0x06 | Data Stream Alignment | Y |
0x07 | Target Background Grid | Y |
0x08 | Video Window | Y |
0x09 | Conditional Access | Y |
0x0a | ISO 639 Language | Y |
0x0b | System Clock | Y |
0x0c | Multiplex Buffer Utilization | Y |
0x0d | Copyright Descriptor | * 1 |
0x0e | Maximum Bitrate | Y |
0x0f | Private Data Indicator | * 1 |
0x10 | Smoothing Buffer | Y |
0x11 | STD | Y |
0x12 | IBP | Y |
DVB | ||
0x40 | Network Name | * 2 |
0x41 | Service List | Y |
0x42 | Stuffing | * 1 |
0x43 | Satellite Delivery | * 2 |
0x44 | Cable Delivery | * 2 |
0x45 | VBI Data | Y |
0x46 | VBI Teletext | Y |
0x47 | Bouquet Name | Y |
0x48 | Service | Y |
0x49 | Country Availability | Y |
0x4a | Linkage | Y |
0x4b | NVOD Reference | Y |
0x4c | Time Shifted Service | Y |
0x4d | Short Event | * 2 |
0x4e | Extended Event | * 2 |
0x4f | Time Shifted Event | Y |
0x50 | Component | Y |
0x51 | Mosaic | Y |
0x52 | Stream Indentifier | * 1 |
0x53 | Conditional Access | Y |
0x54 | Content | Y |
0x55 | Parental Rating | Y |
0x56 | Teletext | Y |
0x57 | Telephone | Y |
0x58 | Local Time Offset | Y |
0x59 | Subtitling | Y |
0x5a | Terrestrial Delivery | * 2 |
0x5b | Multi Lingual Network Name | Y |
0x5c | Multi Lingual Bouquet Name | Y |
0x5d | Multi Lingual Service Name | Y |
0x5e | Multi Lingual Component Name | Y |
0x5f | Private Data Specifier | Y |
0x60 | Service Move | Y |
0x61 | Short Smoothing Buffer | Y |
0x62 | Frequency List | Y |
0x63 | Partial Transport Stream | Y |
0x64 | Data Broadcast | Y |
0x65 | CA Systen | * 3 |
0x66 | Data Broadcast ID | Y |
0x67 | Transport Stream | * 1 |
0x68 | DSNG | * 1 |
0x69 | PDC | Y |
0x6a | AC-3 Audio | Y |
0x6b | Ancilliary Data | Y |
0x6c | Cell List | Y |
0x6d | Cell Frequency Link | Y |
0x6e | Announcement Support | Y |
0x73 | DTS Audio | Y |
0x83 | Logical Channel Number | Y |
DCII | ||
0x80 | Stuffing | * 1 |
0x81 | AC-3 Audio | Y |
0x82 | Frame Rate | Y |
0x83 | Extended Video | Y |
0x84 | Component Name | Y |
0x90 | Frequency Spec | |
0x91 | Modulation Parameters | |
0x92 | Transport Stream ID | |
0xc0 | Banner Override | |
ATSC | ||
0x80 | Stuffing | * 1 |
0x81 | AC-3 Audio | Y |
0x86 | Caption Service | Y |
0x87 | Content Advisory | Y |
0xa0 | Extended Channel Name | Y |
0xa1 | Service Location | Y |
0xa2 | Time-Shifted Service | Y |
0xa3 | Component Name | Y |
|
||
0x91 | Dish Network Compressed Short Event | * 2 |
0x92 | Dish Network Compressed Extended Event | * 2 |
Notes
1 | The descriptor has no defined value in the appropriate specification. For example the contents of the stuffing descriptor is user defined. In these cases, TSReader outputs the contents of the descriptor in hex and ASCII. |
2 | This descriptor is used internally by TSReader to tie various pieces of the transport stream together and therefore isn't handled the same way as other descriptors. It is decoded in context of the mux or network. |
3 | As per note 1, but this descriptor is from the DAVIC standard which isn't currently supported in TSReader. |
User Defined Descriptor Decoding in TSReader Professional
TSReader Professional has the ability for users to decode private descriptors via a special entry point in a standard MD plugin called On_Descriptor_Decode. There's a sample MD plugin provided in the TSReader folder.
The On_Descriptor_Decode function is defined as:
BOOL On_Descriptor_Decode(BOOL fWantDescription, int nNetworkPID, BYTE * pDescriptor, char * szDecoded)
When fWantDescription is TRUE, TSReader is attempting to get the name of the descriptor and pDescriptor points to just the descriptor tag. Conversely, when fWantDescription is FALSE, TSReader passes the full descriptor including the tag and length and the returned value should be a textual decode of the descriptor.
Here's an example of decoding a user-defined descriptor that announces the day of the week (yes, a silly application but possible). This descriptor has this syntax:
Syntax | No. of bits | Identifier |
day_of_week_descriptor(){ | ||
descriptor_tag | 8 | uimsbf (0xcd) |
descriptor_length | 8 | uimsbf |
day_of_week | 8 | uimsbf |
} |
day_of_week is 0 for Sunday, 1 for Monday and so on. So here's the code to handle decoding this descriptor in a plugin:
BOOL On_Descriptor_Decode(BOOL fWantDescription, int nNetworkPID, BYTE * pDescriptor, char * szDecoded) { if (fWantDescription) { switch(*pDescriptor) { case 0xcd: lstrcpy(szDecoded, "Day of Week"); return TRUE; } } else { switch(*pDescriptor) { case 0xcd: { char * szDayOfWeek = NULL; switch(pDescriptor[2]) { case 0: szDayOfWeek = "Sunday"; break; case 1: szDayOfWeek = "Monday"; break; case 2: szDayOfWeek = "Tuesday"; break; case 3: szDayOfWeek = "Wedensday"; break; case 4: szDayOfWeek = "Thursday"; break; case 5: szDayOfWeek = "Friday"; break; case 6: szDayOfWeek = "Saturday"; break; } if (szDayOfWeek != NULL) wsprintf(szDecoded, " Day of week: %s\r\n", szDayOfWeek); else wsprintf(szDecoded, " **Invalid day of week specified - value %02x **\r\n", pDescriptor[2]); return TRUE; } } } return FALSE; }