はじめに
前回はとりあえずMPEG-2 TSから1つのTSパケットを取り出し、それを1行でダンプしてみました。TSパケットを解析する場合、次にTSヘッダを解析します。TSパケットは大きく分けるとTSヘッダとペイロードの2つで構成されています。
下図の「header」と「payload」が該当します。
ISO/IEC 13818-1 より引用 「Transport Stream syntax diagram」
TSヘッダは通常4バイトになり、残りがペイロードとなります。ただし、adaptation fieldがある場合、4バイト+adaptation field長となります。
TSヘッダについて
TSヘッダに記述されているデータについては先ほどの図にあるようにsync byteからadaptation fieldとなります。
私がTSパケットを解析する際はsync byte(0x47)を始めに探し、次にPIDを探します。また別に記事を作成しますが、PIDからペイロードの中身が分かります。そのため、重要なデータとなります。また、ペイロードが複数のパケットに分割されている場合は、payload unit start indicatorが1となっているTSパケットを探してペイロードの始まりを確定します。
またとりあえずダンプしてみる
前回作成したプログラムに以下の様な処理を加えました。
static void ts_dump_header( const uint8_t* ts_packet, const uint8_t ts_packet_length )
{
TS_HEADER header;
static bool show_header = true;
assert( TS_PACKET_SIZE == ts_packet_length );
header.SyncByte = ts_packet[ 0 ];
header.TransportErrorIndicator = ( 0x80 & ts_packet[ 1 ] ) >> 7;
header.PayloadUnitStartIndicator = ( 0x40 & ts_packet[ 1 ] ) >> 6;
header.TransportPriority = ( 0x20 & ts_packet[ 1 ] ) >> 6;
header.Pid = GET_PID( ts_packet[ 1 ], ts_packet[ 2 ] );
header.TransportScramblingControl = ( ts_packet[ 3 ] & 0xC0 ) >> 6;
header.AdaptationFieldControl = ( ts_packet[ 3 ] & 0x30 ) >> 4;
header.ContinuityCounter = ts_packet[ 3 ] & 0x0F;
if( show_header ){
printf( "Sync byte,Transport Error Indicator,Payload Unit Start Indicator,"\
"Transport Priority,PID,Transport Scrambling Control,"\
"Adaptation field control,Continuity counter,Adaptation field,"\
"TS Packet raw data\n");
show_header = false;
}
printf( "0x%02X,%s,%s,%s,0x%X,%s,%s,%d,",
header.SyncByte,
( header.TransportErrorIndicator ) ? "NG" : "OK",
( header.PayloadUnitStartIndicator ) ? "ON" : "OFF",
( header.TransportPriority ) ? "Higher" : "Normal",
header.Pid,
( ( TS_SCRAMBLE_NONE == header.TransportScramblingControl )
?
"Not scrambled"
:
( ( TS_SCRAMBLE_EVEN == header.TransportScramblingControl )
?
"Scrambled with even key"
:
( ( TS_SCRAMBLE_EVEN == header.TransportScramblingControl )
?
"Scrambled with even key"
:
"Reserved for future use" )
)
),
( ( TS_ADAPTATION_FIELD_CONTROL_NONE == header.AdaptationFieldControl )
?
"Payload only"
:
( ( TS_ADAPTATION_FIELD_CONTROL_ONLY == header.AdaptationFieldControl )
?
"Adaptation field only"
:
( ( TS_ADAPTATION_FIELD_CONTROL_WITH_PAYLOAD == header.AdaptationFieldControl )
?
"Adaptation field followed by payload"
:
"Reserved for future use" )
)
),
header.ContinuityCounter
);
if( ( PID_NULL == header.Pid )
|| ( TS_ADAPTATION_FIELD_CONTROL_NONE == header.AdaptationFieldControl ) ){
printf( "-," );
}else{
int i;
for( i = 0 ; i < ts_packet[ 4 ] ; i++ ){
printf( "%02X ", ts_packet[ 4 + i ] );
}
printf( "," );
}
}
おわりに
今回はTSヘッダを解析しました(adaptation fieldを除く)。次は、adaptation fieldからPCRを取り出してみます。