解析TS流数据的流程:查找PID为0x0的包,解析PAT,PAT包中的program_map_PID表示PMT的PID;查找PMT,PMT包中的elementary_PID表示音视频包的PID,PMT包中的PCR_PID表示PCR的PID,有的时候PCR的PID跟音频或者视频的PID相同,说明PCR会融进音视频的包,注意解析,有的时候PCR是自己单独的包;CAT、NIT、SDT、EIT的PID分别为: 0x01、0x10、0x11、0x12。
3.TS包头解析
TS包头有4个字节
//Transport Stream header
typedef struct TS_header
{
unsigned sync_byte :8; //同步字节,固定为0x47 ,表示后面的是一个TS分组,当然,后面包中的数据是不会出现0x47的
unsigned transport_error_indicator :1; //传输错误标志位,一般传输错误的话就不会处理这个包了
unsigned payload_unit_start_indicator :1; //有效负载的开始标志,根据后面有效负载的内容不同功能也不同
// payload_unit_start_indicator为1时,在前4个字节之后会有一个调整字节,它的数值决定了负载内容的具体开始位置。
unsigned transport_priority :1; //传输优先级位,1表示高优先级
unsigned PID :13; //有效负载数据的类型
unsigned transport_scrambling_control :2; //加密标志位,00表示未加密
unsigned adaption_field_control :2; //调整字段控制,。01仅含有效负载,10仅含调整字段,11含有调整字段和有效负载。为00的话解码器不进行处理。
unsigned continuity_counter :4; //一个4bit的计数器,范围0-15
} TS_header;
//特殊参数说明:
//sync_byte:0x47
//payload_unit_start_indicator:0x01表示含有PSI或者PES头
//PID:0x0表示后面负载内容为PAT,不同的PID表示不同的负载
//adaption_field_control:
// 0x0: // reserved for future use by ISO/IEC
// 0x1: // 无调整字段,仅含有效负载
// 0x2: // 仅含调整字段,无有效负载
// 0x3: // 调整字段后含有效负载
// Parse TS header
int Parse_TS_header(unsigned char *pTSBuf, TS_header *pheader)
{
pheader->sync_byte = pTSBuf[0];
if (pheader->sync_byte != 0x47)
return -1;
pheader->transport_error_indicator = pTSBuf[1] >> 7;
pheader->payload_unit_start_indicator = pTSBuf[1] >> 6 & 0x01;
pheader->transport_priority = pTSBuf[1] >> 5 & 0x01;
pheader->PID = (pTSBuf[1] & 0x1F) << 8 | pTSBuf[2];
pheader->transport_scrambling_control = pTSBuf[3] >> 6;
pheader->adaption_field_control = pTSBuf[3] >> 4 & 0x03;
pheader->continuity_counter = pTSBuf[3] & 0x0F;
return 0;
}
4.TS负载格式解析
4.1 PAT解析
TS_header包头中的PID值为0x0,表示当前负载为PAT(Program Association Table)。PAT数据的信息可以理解为整个TS流包含的节目信息。
// Program Association Table
typedef struct PAT_Packet_tag
{
unsigned table_id : 8; //固定为0x00 ,标志是该表是PAT
unsigned section_syntax_indicator : 1; //段语法标志位,固定为1
unsigned zero : 1; //0
unsigned reserved_1 : 2; // 保留位
unsigned section_length : 12;//表示这个字节后面有用的字节数,包括CRC32
unsigned transport_stream_id : 16;//该传输流的ID,区别于一个网络中其它多路复用的流
unsigned reserved_2 : 2; // 保留位
unsigned version_number : 5; //范围0-31,表示PAT的版本号
unsigned current_next_indicator : 1; //发送的PAT是当前有效还是下一个PAT有效
unsigned section_number : 8; //分段的号码。PAT可能分为多段传输,第一段为00,以后每个分段加1,最多可能有256个分段
unsigned last_section_number : 8; //最后一个分段的号码
// for(i=0; i 0)
{
iBeginlen += 1; // adaptation_field_length占8位
iBeginlen += adaptation_field_length; // + adaptation_field_length
}
else
{
iBeginlen += 1; // adaptation_field_length占8位
}
iBeginlen += pTSBuf[iBeginlen] + 1; // + pointer_field
break;
default:
break;
}
unsigned char *pPAT = pTSBuf + iBeginlen;
packet->table_id = pTSBuf[0];
packet->section_syntax_indicator = pTSBuf[1] >> 7;
packet->zero = pTSBuf[1] >> 6 & 0x1;
packet->reserved_1 = pTSBuf[1] >> 4 & 0x3;
packet->section_length = (pTSBuf[1] & 0x0F) << 8 | pTSBuf[2];
packet->transport_stream_id = pTSBuf[3] << 8 | pTSBuf[4];
packet->reserved_2 = pTSBuf[5] >> 6;
packet->version_number = pTSBuf[5] >> 1 & 0x1F;
packet->current_next_indicator = (pTSBuf[5] << 7) >> 7;
packet->section_number = pTSBuf[6];
packet->last_section_number = pTSBuf[7];
int len = 0;
len = 3 + packet->section_length;
packet->CRC_32 = (pTSBuf[len-4] & 0x000000FF) << 24
| (pTSBuf[len-3] & 0x000000FF) << 16
| (pTSBuf[len-2] & 0x000000FF) << 8
| (pTSBuf[len-1] & 0x000000FF);
int n = 0;
for ( n = 0; n < (packet->section_length - 12); n += 4 )
{
packet->program_number = pTSBuf[8 + n ] << 8 | pTSBuf[9 + n ];
packet->reserved_3 = pTSBuf[10 + n ] >> 5;
if ( packet->program_number == 0x00)
{
packet->network_PID = (pTSBuf[10 + n ] & 0x1F) << 8 | pTSBuf[11 + n ];
}
else
{
// 有效的PMT的PID,然后通过这个PID值去查找PMT包
program_map_PID = (pTSBuf[10 + n] & 0x1F) << 8 | pTSBuf[11 + n];
}
}
return 0;
}
}
return -1;
}
// Program Map Table
typedef struct PMT_Packet_tag
{
unsigned table_id : 8;
unsigned section_syntax_indicator : 1;
unsigned zero : 1;
unsigned reserved_1 : 2;
unsigned section_length : 12;
unsigned program_number : 16;
unsigned reserved_2 : 2;
unsigned version_number : 5;
unsigned current_next_indicator : 1;
unsigned section_number : 8;
unsigned last_section_number : 8;
unsigned reserved_3 : 3;
unsigned PCR_PID : 13;
unsigned reserved_4 : 4;
unsigned program_info_length : 12;
// for(i=0; i
unsigned long long Parse_PTS(unsigned *pBuf)
{
unsigned long long llpts = (((unsigned long long)(pBuf[0] & 0x0E)) << 29)
| (unsigned long long)(pBuf[1] << 22)
| (((unsigned long long)(pBuf[2] & 0xFE)) << 14)
| (unsigned long long)(pBuf[3] << 7)
| (unsigned long long)(pBuf[4] >> 1);
return llpts;
}
5.2 EasyICE
附件:ISO13818标准文件
http://braice.net/sites/default/files/iso13818-1.pdf