はじめに
前回はTSヘッダを解析し、その結果をダンプするようにしました。今回は予告通りPCRを取り出してみます。
プログラムは以下を参照ください。
https://github.com/sagesagesagesagesage
PCRとは?
PCR(Program Clock Reference)はMPEG-2 TSの送信側と受信側で同期をとるためのクロックになります。PCRは重要なもので、これが送信側と受信側で同期がとれないと受信側で正しく映像が再生されません。
PCRは100ms以下の間隔で送信器から送信することが推奨されているようです。
PCRは42Bitのデータになりますが、Base 33Bit、Extension 9Bitで構成されており、BaseとExtensionを使用して以下の様に算出します。
PCR = PCR(Base) × 300 + PCR(Extension)
なお、PCRの27MHzのクロックとなるため、およそ26.5時間で巡回します。
2,576,980,377,811(PCRの最大値) ÷ 27,000,000 ÷ 3600 ≒ 26.5(時間)
PCRの取得方法
PCRはTSヘッダにAdaptation Filedが存在し、Adaptation Filed中のpcr_flagが1の場合に存在します。実際のデータを見た方が早いので、以下にあるTSパケットのヘッダを示します。
47,01,FF,20,B7,10,BD,F5,CC,EB,7E,D6,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,
上記データはsync_byte 0x47 で始まるTSパケットなり、adaptation_filed_controlが2(0x2)となるTSヘッダのみのTSパケットです。adaptation_filed_lengthは0xB7(183)となっていますが、実際にはPCRしか含まれておらず、残りは0xFFでパディングされています。pcr_flagはadaptation_filed_lengthの次のバイト、0x10に含まれており、第4ビット(LSBが第0ビット)がそれに該当します。今回、1が立っているのでPCRが含まれています。
PCRは「BD,F5,CC,EB,7E,D6」に含まれており、先頭の 33Bit がPCRのBase,6Bit reserved で、次の 9Bit がExtension となります。
実装時には以下の様なマクロを作成してみました。
#define GET_PCR_EXT( pcr_bin, pcr ) { \
uint64_t b, e; \
b = ( ( ( uint8_t* )pcr_bin )[ 0 ] << ( 3 * 8 ) ) & 0x00000000FF000000; \
b |= ( ( ( uint8_t* )pcr_bin )[ 1 ] << ( 2 * 8 ) ) & 0x0000000000FF0000; \
b |= ( ( ( uint8_t* )pcr_bin )[ 2 ] << ( 1 * 8 ) ) & 0x000000000000FF00; \
b |= ( ( ( uint8_t* )pcr_bin )[ 3 ] << ( 0 * 8 ) ) & 0x00000000000000FF; \
b <<= 1; \
b |= ( ( ( uint8_t* )pcr_bin )[ 4 ] >> ( 7 ) ) & 0x0000000000000001; \
e = ( ( ( uint8_t* )pcr_bin )[ 4 ] << ( 8 ) ) & 0x0000000000000100; \
e |= ( ( ( uint8_t* )pcr_bin )[ 5 ] << ( 0 ) ) & 0x00000000000000FF; \
pcr = b * 300 + e; \
} \
おわりに
今回はPCRを解析しました。次はPAT、PMTの解析をしたいと思います。