#はじめに
前回はTSファイルからPCRを取得して表示してみました。今回は、PATやPMTの解析をする予定でしたが、予定を変更してPCRを使用したTSファイルの解析を行いたいと思います。
とりあえずTSファイルの解析としてTSファイルのビットレートを算出してみます。TSファイルには複数のストリーム(サービス)が含まれている場合が有りますが、今回求めるのはそれを全て合算したものになります。
プログラムは以下を参照ください。
https://github.com/sagesagesagesagesage
ビットレートの計算方法
ビットレートの計算は以下の様に行います。
- TSファイルの先頭のPCR(s)を取得
- **一定個数(N)**のPCRを読み込むまでTSファイルを末尾に向けてシーク
- N個目のPCR(e)を読み込むまでのTSパケットのSizeをPCR(e)-PCR(s)で除算
- さらに27MHzで除算しビットレートbps(bit per second)を算出
ビットレート = Size ÷ ( PCR(e) - PCR(s) ) ÷ 27,000,000
イメージです。
プログラム
以下の様な関数を作成しました。N個は引数で与えるようにしています。また、PCRは最大値から最小値の0へ戻る場合が有る。その場合、簡易的にPCR(s)を再取得するようにした。
/**
* @brief Calculate bit rate of TS file
* @param[in] ts_file TS file path
* @param[in] use_pcr_count Sampling PCR count
* @return double bitrate. if error return 0.0
*/
static double ts_calc_bitrate( const char* ts_file, const uint32_t use_pcr_count )
{
FILE* ifp = NULL;
uint8_t ts_packet[ TS_PACKET_SIZE ];
uint64_t total_packet = 0;
uint64_t start_pcr = PCR_NONE;
uint64_t end_pcr = PCR_NONE;
int pcr_count = 0;
double bitrate = 0.0;
uint16_t pcr_pid = PID_NULL;
ifp = fopen( ts_file, "rb" );
total_packet = 0;
if( ifp ){
while( TS_PACKET_SIZE == fread( ts_packet, 1, sizeof( ts_packet ), ifp ) ){
if( TS_SYNC_BYTE != ts_packet[ 0 ] ){
break;
}
if( 0 < pcr_count ){
total_packet++;
}else{
total_packet = 0;
}
if( ts_packet[ 3 ] & TS_ADAPTATION_FIELD ){ // Is adaptaion_file ON ?
if( ts_packet[ 5 ] & ADAPTATION_FIELD_PCR ){ // PCR Flag ?
if( PID_NULL == pcr_pid ){
pcr_pid = GET_PID( ts_packet[ 1 ], ts_packet[ 2 ] );
}
if( pcr_pid != GET_PID( ts_packet[ 1 ], ts_packet[ 2 ] ) ){
continue;
}
if( 0 == pcr_count ){
GET_PCR_EXT( &ts_packet[ 6 ], start_pcr );
DEBUG_PRINT( "Start PCR = %lu\n", start_pcr );
pcr_count++;
}else if( 0 < pcr_count ){
GET_PCR_EXT( &ts_packet[ 6 ], end_pcr );
if( start_pcr > end_pcr ){
DEBUG_PRINT( "PCR RESET %lu => %lu\n", start_pcr, end_pcr );
pcr_count = 0;
total_packet = 0;
continue;
}
pcr_count++;
if( use_pcr_count < pcr_count ){
break;
}
}
}
}
}
fclose( ifp );
if( ( PCR_NONE != start_pcr )
&& ( PCR_NONE != end_pcr ) ){
DEBUG_PRINT("End PCR = %lu / Total = %lu\n", end_pcr, total_packet );
bitrate = ( total_packet * TS_PACKET_SIZE * 8 ) / ( ( end_pcr - start_pcr ) / ( double )PCR_CLOCK_EXT );
DEBUG_PRINT( "TS Bitrate = %lf\n", bitrate );
}
}
return bitrate;
}
おわりに
今回は予定を変更してPCRを使用してTSファイルのビットレートを算出してみました。ビットレートが求まるとTSファイルのシークや一定レートでの送出に使用できます。
次回こそPATやPMTの解析をする予定です。