风波邪人

幸福,幸福就是心里有那么一个人,不管你走到哪儿,也不管她走到哪儿,心里永远想着她

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

TS 码流率计算总结

——By 风波邪人

1         transport_rate计算公式

 

其中, ,PCR字段编码在MPEG-2 TS包的自适应字段(Adaptation field)的6个Byte中,其中6 bits为预留位,42 bits为有效位,其在TS包中的编码位置见下图,PCR分两部分编码,一个以STC频率的1/300(90KHz)为单位,称为PCR_base,共33bit;另一个以STC频率(27MHz)为单位,称为PCR_ext,共9bit。

i指包含PCR_base 字段的最后一个bit的字节,PCR(i)表示这个字节到达TS系统目标解码器(T-STD)的时间,具体定义请参见参考文献1。通过PCR值不但可以获得正确的解码时间, 还可以计算TS速率等与时间有关的信息。这里的I’-I’’意思是连个包含PCR的数据包之间的字节差值。

 

图1  PCR字段编码在TS包中的位置

2         TS数据包分析

 

图2  Transport Packet

 

 

 

图3  TS包结构

 

TS流数据包是由:包头+自适应区(可选)+报数据(净荷)组成,Sync-byte同步字节为0x47。这里要用到pf(有效载荷标识), 因为它有效时 Table 2-6 Transport Stream adaptation field才有效,我们要抓取的PCR数据就在adaptation field中,接着往下看Table 2-6就会发现,只有PCR_flag == 1 时,我们要找的program_clock_reference_base 和 program_clock_reference_extension才有效。故,由此一连串的因果关系可以很明显的看出抓取PCR的过程了。

 

图4  Transport Stream Adaptation Field

 

图5  TS数据包内容

3         利用程序抓取PCR数据

在抓取PCR数据之前做一项工作,就是用程序读取 视频文件内容,在能正确读取文件内容的基础上才能抓取PCR数据。我是先根据TS包的结构特点和PCR数据存在的几个条件一起考虑写了一个简单的程序,提取出了PCR数据。通过一个小程序将得到的PCR数据处理成PCR_base和PCR_ext部分,在通过 公式将PCR(i)得到,从而得出transport_rate。

代码如下:

#include <iostream>

#include <iomanip>

using namespace std;

 

#define _FORMAT     0

 

#if _FORMAT == 1

#define FORMAT      dec

#else

#define FORMAT      hex

#endif

 

int PCR_OK = 0, OPCR_OK = 0, SP_CD_OK = 0;

 

// TS数据包

 

class TS{                                                   //Byte

private:

int sync_byte;                              //8bit

short ei;                                        //1bit

short pusi;                                             //1bit

short tpr;                                      //1bit

int PID;                                          //13bit

short scr_flags;                           //2bit

short af;                                        //1bit

short pf;                                        //1bit

short cc;                                        //4bit

int adpt_flength;                        //8bit

short flag;                                              //1bit

unsigned long PCR[2];               //48bit

unsigned long OPCR[2];            //48bit

int splice_countdown;               //8bit

unsigned char buf_data[179];     //179byte

public:

void display(int i);

int undecoder(FILE * fp);

 

};

 

//数据显示

 void TS::display(int i)

{

           cout<<setw(3)<<setiosflags(ios::right)<<dec<<i;

           cout<<"----"<<endl;

           cout<<"Item             "<<"Info"<<endl;

 

           //cout.setf(ios::showbase);

           cout.setf(ios::hex);

 

           cout<<"sync_byte       : "<<FORMAT<<sync_byte<<endl;

           cout<<"ei              : "<<ei<<endl;

           cout<<"pusi            : "<<pusi<<endl;

           cout<<"tpr             : "<<tpr<<endl;

           cout<<"PID             : "<<PID<<endl;

           cout<<"scr_flags       : "<<scr_flags<<endl;

           cout<<"af              : "<<af<<endl;

           cout<<"pf              : "<<pf<<endl;

           cout<<"cc              : "<<cc<<endl;

           cout<<"adpt_flength    : "<<adpt_flength<<endl;

          

           //output flag

           cout<<"flag            : "<<flag;

           cout<<"                binary :";

           int j;

           //output flag binary

           for(j = 0; j < 8; j++)

           {

                    if(!j)

                             cout<<dec<<((flag>>(7-j)) & 0x01);

                    else if(j%4 )

                             cout<<dec<<((flag>>(7-j)) & 0x01);

                    else

                    {       

                             cout<<'_';cout<<dec<<((flag>>(7-j)) & 0x01);

                    }

                   

           }

           cout<<endl;

          

           if(PCR_OK)

           {

                    PCR_OK = 0;

                    //output PCR

                    cout<<"PCR             : "<<FORMAT<<PCR[0]<<PCR[1]<<endl;

           }

 

           if(OPCR_OK)

           {

                    OPCR_OK = 0;

                    //output OPCR

                   cout<<"OPCR            : "<<FORMAT<<OPCR[0]<<OPCR[1]<<endl;

           }

 

           //output splice_countdown

           if(SP_CD_OK)

           {

                    SP_CD_OK = 0;

                    cout<<"splice_countdown: "<<FORMAT<<splice_countdown<<endl;

           }

}

 

int TS::undecoder(FILE * fp)

{

           unsigned char buf[6];

           int z=0;

           unsigned int ch, ch1;

 

           ch = fgetc(fp);

           sync_byte = ch;

           ch = fgetc(fp);

           ei = (ch & 0x80)>>7 ;                                                       //transport_error_indicator

 

           pusi = (ch & 0x40)>>6;                                                    //payload_unit_start_indicator

           tpr = (ch & 0x20)>>5;                                                      //transport_priority

 

           ch1 = fgetc(fp);                                                                

           PID = ((ch & 0x1f)<<8) | ch1;                               //PID

          

           ch = fgetc(fp);

           scr_flags = (ch & 0xc0)>>6;                                           //transport_scrambling_control

           af = (ch & 0x20)>>5;                                                        //adaptation_field_control

           pf = (ch & 0x10)>>4;

           cc = (ch & 0x0f);                                                               //continuity_counter

          

           ch = fgetc(fp);

           adpt_flength = ch;                                                           //adaptation_field_length

 

           ch = fgetc(fp);

           flag = ch;                                                                            //adaptation_field_flag

        //-------6B

 

           //adaptation field 有效

           //自适应区长度不为0

           if(af && adpt_flength )

           {

                    // 当 PCR_flag 有效时,读 PCR值到缓存  , 6B

                    if( flag &0x10)

                    {

                             for(z=0;z<6;z++)

                             {

                                       buf[z] = fgetc(fp);                                                             //读取PCR数据

                             }

 

                             PCR[0] = (buf[0]<<16) | (buf[1]<<8) | buf[2];

                             PCR[1] = (buf[3]<<16) | (buf[4]<<8) | buf[5];

                             PCR_OK = 1;                                                                                         //PCR数据读取完毕标志

                    }

                    else

                             fseek(fp, 6, 1);                                                                  //移动文件指针

 

                    // 当 OPCR_flag 有效时,读 OPCR值到缓存  ,6B

                    if(flag & 0x08)

                    {

                             for(z=0;z<6;z++)

                             {

                                       buf[z] = fgetc(fp);

                             }

                             OPCR[0] = (buf[0]<<16) | (buf[1]<<8) | buf[2];

                             OPCR[1] = (buf[3]<<16) | (buf[4]<<8) | buf[5];

                             OPCR_OK = 1;

                    }

                    else

                             fseek(fp, 6, 1);

 

                    if(flag & 0x04)     // 1B

                    {

                             ch  = fgetc(fp);                                                                //读取splice_countdown 数据

                             splice_countdown = ch;

                             SP_CD_OK = 1;

                    }

                    else

                             fseek(fp, 1, 1);

                   

                    //文件指针移到下一个TS包起始位置

                    fseek(fp, 0xbb - 0x12, 1);   //0 top position, 1 current position, 2 button position

           }

           else

                    fseek(fp, 0xbb - 0x05, 1);   //0 top position, 1 current position, 2 button position

 

           return 1;

}

 

void compute()

{

long pcr_in1,pcr_in2,pcr_base_H, pcr_base_L, pcr_base,pcr_base_header,pcr_ext;

    while(1)

{

           cout.setf(ios::hex);

           cout<<"input 0 end"<<endl;

           cin>>hex>>pcr_in1;

           if(pcr_in1 == 0)

                    return ;

           cin>>pcr_in2;

           pcr_base_H = pcr_in1;

 

           pcr_base_L = pcr_in2 >>15;

 

           if(pcr_base_H & 0x800000)

                    pcr_base_header = 1;

           else

                    pcr_base_header = 0;

           pcr_base = (pcr_base_H<<9) | pcr_base_L;

 

           pcr_ext = pcr_in2 & 0x0001ff;

 

           cout<<"PCR_BASE:"<<hex<<pcr_base_header<<hex<<pcr_base<<endl;

           cout<<"PCR_EXT:"<<hex<<pcr_ext<<endl;

          

 

 

}

}

 

 

void find()

{        

TS ts;

FILE * fp;

fp = fopen("ysgq.trp","rb");

 

if(fp != NULL)

           cout<<"FILE OPEN SUCCESS"<<endl;

else

{

           cout<<"FILE OPEN FAIL"<<endl;

           exit(0);

}

int count = 0;

for(int c = 0; !feof(fp) ; c++)               //读取TS流文件

{

 

           if(ts.undecoder(fp))                    //解码成功

           {

                    if(PCR_OK || OPCR_OK)           //找到PCR

                    {

                            

                             ts.display(c);                       //打印该包的信息

                             count ++;

                             if(count == 10)

                                       break;

                    }

                    else

                             ;

           }

           else

           {

                    cout<<"Read file fail!"<<endl;

                    break;

           }

 

}

 

fclose(fp);

}

 

 

int main()

{

// 数据类型显示

#if _FORMAT == 0

           cout<<"hex"<<endl;

#endif

#if _FORMAT == 1

           cout<<"dec"<<endl;

#endif

 

 

//===================================         

int sel;

while(1)

{

           cout<<"0:compute \n1:find"<<endl;

           cin>>sel;

 

           switch(sel)

           {

                    case 0:compute();break;                   //计算PCR(i)_base , PCR(i)_ext

                    case 1:find();break;                    //寻找PCR

                    default:break;

           }

}

 

//====================================

 

 

return 0;

}

在启动程序之后,会有一个菜单选项,0表示:计算PCR(i)值,加入用程序抓取到的PCR数据为A45D3456FE41,则先输入A45D34,按回车键再输入56FE41,回车即可得到PCR_base和PCR_ext。通过计算器求得PCR(i)。

 

4         利用公式计算transport_rate。

在以上工作做好之后利用公式计算是很容易的事情。

 

posted on 2011-12-26 14:56  风波邪人  阅读(5009)  评论(0编辑  收藏  举报