LoginSignup
3
0

More than 5 years have passed since last update.

MPEG-2 TSファイル処理 -PCRを使用したTSファイルの解析 ビットレートの算出-

Last updated at Posted at 2018-10-19

はじめに

前回は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

イメージです。

pcr.png

プログラム

以下の様な関数を作成しました。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の解析をする予定です。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0