首先,ts主要是用于dvb的传输,ts可以理解成一种传输上的协议,要不怎么叫transport-stream,但是也可以理解成一种封装格式。
不管是ts文件,还是ts实时流,都可以这样来看,它由N个独立的packet构成,每个大小188Bytes。
每个packet都由两部分构成,header和data,header描述了一些关于这个packet的信息,而data就是这个packet所携带的音频数据,视频数据,字幕数据,当然也可能是节目信息数据。
typedef struct _tag_PACKET_HEADER {
//同步字节,总是0x47(0100 0111),表示这个包是正确的ts包
unsigned sync_byte: 8;
//传输错误指示符,1:暂且定义为本包有个无法修复的错误
unsigned transport_error_indicator: 1;
//负载单位开始指示符,1:PES或者PSI的开始部分,0:其他
unsigned payload_unit_start_indicator: 1;
//传输优先指示符,1:比相同PID的包有更高的优先级
unsigned transport_priority: 1;
//Packet ID
unsigned PID: 13;
//加扰控制指示符
//00:未加扰(俗称清流);01:留着等以后使用
//10:以even key方式加扰;11:以odd key方式加扰
unsigned scrambling_control: 2;
//适配区存在指示符
//00:留着等以后使用;
//01:本报不含适配区,只有负载区
//10:本包只含适配区,没有负载区
//11:本包不仅含有适配区,还含有负载区
//其实可以把这两bit分开来理解,第一个bit指示是否有适配区,第二个指示是否有负载区
unsigned adaptation_field_exist: 2;
//当本包目前有负载区时,它才回递增
//例如,当上面的字段为01or11时,本字段才回递增
unsigned continuity_counter: 4;
} PACKET_HEADER;
以上就是header的结构,可见sizeof(PACKET_HEADER) == 4 Bytes
根据header的情况,我可以推测出剩余的PACKET_DATA最长只有184Bytes了
typedef _tag_PACKET_DATA {
//0或者更长,依据PACKET_HEADER.adaptation_field_exist的第一bit而定
struct adaptation_field;
//0或者更长,依据PACKET_HEADER.adaptation_field_exist的第二bit而定
struct payload_data
}
下面请看adaptation_field的结构定义:
typedef struct adaptation_field {
//本区域除了本字节剩下的长度(不包含本字节!!!切记)
adaptation_field_length: 8;
//不连续指示符
//1:本ts包在continuity_counter或者PCR,是处于不连续状态的
discontinuity_indicator: 1;
//可随机访问指示符
//1:本包中的PES包可以启动一个视频/音频序列
//就是说如果是1,可以从这个包开始牵出该条ES流
random_access_indicator: 1;
//es流优先级指示符
//1:当同pid时,该es流有更高级的优先权
elementary_stream_priority_indicator: 1;
//Program Clock Reference,含有“节目时钟参考”标志
//1:适配区里面含有PCR field字段,0:不含有
PCR_flag: 1;
//1:适配区里面含有splice_countdown字段
splicing_point_flag: 1;
//1:适配区里面含有private_data_bytes字段
trasport_private_data_flag: 1;
//1:适配去里面含有adaptation_field_extension字段
adaptation_field_extension_flag: 1;
//下面几个字段依据上面几个指示器的值而存在与否
//Program Clock Reference,共6个字节,48bits,大端模式存储!
//33bits是基本的,6个填充bits,9个扩展bits
//时间参考,至少约100ms会确定一次audio和video之间的同步问题
PCR: 33+6+9;
//Original Program Clock Reference
//原始PCR,当一个ts包被复制到另一个包里面去了,这里保留其原始的PCR值
OPCR: 33+6+9
//分隔倒数器,我自己翻译的,求指点
//表示当一个分割点出现时,从这个ts包起,还剩多少个ts包(有可能是负数)
splice_countdown: 8;
//填充字节,全0xFF,目的是为了使得每一个packet的长度为188Bytes
//这个的结果可以使得码流为恒定值
//当然,如果一次想携带的内容超过184字节了怎么办?那就得分隔成多个ts packet了
stuffing_bytes: 不定长;
}
看完adaptation_field了,那struct payload_data呢?即使有,其实也没什么值得看的,payload_data结构就是所携带的纯粹的数据了,那个没什么好说的,但是还是遵守不足184Bytes就填充FF,超过184Bytes就分隔的原则啦。
所以ts包可以这样表示
【header】+【data】 == 【188Bytes】
【header】== 4 Bytes
【data】 == 184 Bytes == 【adaptation_field】+【payload_data+填充】
【adaptation_field】 == adaptation_field->adaptation_field_length
【payload_data+填充】 == 184 - field.adaptation_field_length
如果有兴趣,直接耐住性子看【http://mumudvb.braice.net/mumudrupal/sites/default/files/iso13818-1.pdf 】,会更加详细,透彻地了解mpeg2-ts