Program Association Table :节目相关表 pid ==0x 00
有效载荷起始符: ptr [1] &=0x40 后>>4 即 看 47后面 0 4 6 0:没有pes头 else 有
步骤:
1. 解析 PAT 找到 PMT pid。
2. 找到 PMT pid 找到 视频pid 和 音频pid
。
3.依次读取ts 包 工具 pid不同做不同处理。
工具ts头,有效载荷起始符的状态判断 有没有pes头 再对具体数据处理
下面具体实例:
解析 Ts包头
u_int16_t pid=to_int((unsigned char *)ptr+1); // 解析 Ts头部 pid
u_int8_t flags=to_byte(ptr+3);
bool transport_error=pid&0x8000;
bool payload_unit_start_indicator=pid&0x4000; // 有效载荷起始符
bool adaptation_field_exist=flags&0x20;
bool payload_data_exist=flags&0x10; // 有无 调整字段 3:有 1:无
u_int8_t continuity_counter=flags&0x0f;
pid&=0x0fff;
因为PAT的pid 为00 所以找到这个包 即可在PAT表中找到 PMT pid
payload_data_exit 不为一时:即没有调整字符,调整指针指到 PAT表头
ptr+=4;
当 payload_data_exit 为一时 即 存在调整字符 ,
if(adaptation_field_exist)
{
ptr+=to_byte(ptr)+1;
}
然后 根据 PAT表的结构 找到 PMT pid
ptr+=11; // Find PMT pid pos 第十一字节
if(parse_pat_ft){ //设置标志位 解析了一次就不再解析
u_int16_t pid=to_int((unsigned char *)ptr);
pid&=0x0fff;
pmt_pid=pid;
parse_pat_ft=0;
printf("Pmt_Pid =%d\n",pmt_pid);
return 1;
}
二,根据之前找到的 PMT pid 找到 PMT表 解析 音频 pid 视频 pid
if(pid==pmt_pid){ // PMT
if(parse_pmt_ft){
ptr+=2;
int info_len=to_int(ptr);
info_len&=0x0fff; // 算出分段长度
ptr+=(info_len-11); // 移动指针到视频 pid
info_len=to_int(ptr);
info_len&=0x0fff;
video_pid=info_len;
printf("video pid =%d\n",video_pid);
ptr+=5; //移动指针到音频pid
info_len=to_int(ptr);
info_len&=0x0fff;
audio_pid=info_len;
printf("audio pid =%d\n",audio_pid);
parse_pmt_ft=0;
return 1;
}
三,分析Ts包头 判断是音频包 还是视频包
跳过pes head 处理:先看看 pes头格式:
if(payload_unit_start_indicator){
u_int8_t flags=to_int(ptr+7);
flags&=0x0fff; // PES head 长度
ptr+=9;
ptr+=flags; //跳过peshead
}
if(视频)
跳过PES头 找到sps pps 然后开始将数据保存到264文件中 即先找到 0x 00 00 00 01 67
// Find 0x 00 00 00 01 67
if(Find_Sps<1)
{
while(ptr<end_ptr)
{
if(Find_start(ptr)>0)
{
Find_Sps=1; // find sps pps
break;
}
ptr++;
}
}
int Find_start(const unsigned char *Buf)
{
if(Buf[0]!=0 || Buf[1]!=0 || Buf[2] !=0 || Buf[3] !=1 || Buf[4]!=0x67) return 0;//0x00000001?
else return 1;
}
当找到 sps pps 后 就可以将所有 数据总结保存至 h264中
if(音频)
跳过pes 头 保存
没有pes 头 直接保存。