leixiaohua使用的开源项目地址为:https://github.com/clark15b/tsdemuxer
这个开源工程有的地方写的不怎么好。
比如,他没有给PAT, PMT等数据结构做定义,所以需要你自己把这几个结构的定义写上去,方便自己查看。
同时它在int ts::demuxer::demux_ts_packet(const char* ptr)里面解析PAT, PMT的时候,直接移动指针,这样如果你不熟悉PST, PAT, PMT结构的话,会非常的困惑。
我就是这样的,不得已我查询了这几个结构才明白。
但是现在还有一个问题没有解决。
网上的“节目映射表PAT, PMT”结构我文档化后,如下:
// add by oldmtn, 共4个字节
// TS表头结构定于
typedef struct tagTS_Header
{
// sync_byte (同步字节):固定为0100 0111 (0x47);该字节由解码器识别,使包头和有效负载可相互分离。
unsigned sync_byte : 8;
// transport_error_indicator(传输错误指示):‘1’表示在相关的传输包中至少有一个不可纠正的错误位。当被置1后,在错误被纠正之前不能重置为0。
unsigned transport_error_indicator : 1;
// payload_unit_start_indicator(开始指示):为1时,在前4个字节之后会有一个调整字节,其的数值为后面调整字段的长度length。因此有效载荷开始的位置应再偏移1+[length]个字节。
unsigned payload_unit_start_indicator : 1;
// transport_priority(传输优先级):‘1’表明优先级比其他具有相同PID 但此位没有被置‘1’的分组高。
unsigned transport_priority : 1;
// PID:指示存储与分组有效负载中数据的类型。PID 值 0x0000—0x000F 保留。其中0x0000为PAT保留;0x0001为CAT保留;0x1fff为分组保留,即空包。
unsigned PID : 13;
// transport_scrambling_control(加扰控制):表示TS流分组有效负载的加密模式。空包为‘00’,如果传输包包头中包括调整字段,不应被加密。
unsigned transport_scrambling_control : 2;
/* adaptation_field_control(适配域控制):表示包头是否有调整字段或有效负载。‘00’为ISO/IEC未来使用保留;‘01’仅含有效载荷,无调整字段;‘10’ 无有效载荷,
仅含调整字段;‘11’ 调整字段后为有效载荷,调整字段中的前一个字节表示调整字段的长度length,有效载荷开始的位置应再偏移[length]个字节。空包应为‘10’。*/
unsigned adaption_field_control : 2;
// continuity_counter(连续性计数器):随着每一个具有相同PID的TS流分组而增加,当它达到最大值后又回复到0。范围为0~15。
unsigned continuity_counter : 4;
} TS_Header;
// PAT表结构定义
typedef struct tagTS_PAT_Program
{
unsigned short patChannel; // program number
unsigned short reserved_3 : 3; // 保留位
unsigned short network_PID : 13; // 网络信息表(NIT)的PID, 节目号为0时对应的PID为network_PID
} TS_PAT_Program;
typedef struct tagTS_PAT
{
// 开头的5个字节
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是当前有效还是下一个有效
unsigned section_number : 8; // 分段的号码。PAT可能分为多段传输, 第一段为00, 以后每个分段加1, 最懂可能有256个分段
unsigned last_section_number : 8; // 最后一个分段的号码
std::vector<TS_PAT_Program> program;
unsigned int CRC_32; // CRC32校验码
} TS_PAT;
// PMT表结构定义
typedef struct tagTS_PMT_ELEMENTARY
{
unsigned stream_type : 8;
unsigned reserved_5 : 3;
unsigned elementary_PID : 13;
unsigned reserved_6 : 4;
unsigned ES_info_length : 12;
} TS_PMT_ELEMENTARY;
typedef std::list<TS_PMT_ELEMENTARY> CArrayPmtElementary;
typedef struct tagTS_PMT
{
// 这部分和PAT表开头是一样的, 共8个字节
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_sectoin_number : 8;
unsigned reserved_3 : 3;
unsigned PCR_PID : 13;
// 将ptr加7后, ptr指向的位置为reserved_4
unsigned reserved_4 : 4;
unsigned program_info_length : 12;
CArrayPmtElementary m_arrPmtElementary;
//
unsigned CRC_32 : 32;
} TS_PMT;
在demux_ts_packet中,有
// PMT
ptr += 7; 但是理论上,应该偏移的是10个字节,而实际只要偏移7个字节。
这是目前还不明白的地方,后期碰到了再说吧。。
参考
1.http://blog.csdn.net/liangxiaozhang/article/details/17762531
2.http://blog.csdn.net/occupy8/article/details/43115765
3.http://blog.sina.com.cn/s/blog_6ca8ed170100qjvd.html
4.http://blog.csdn.net/leixiaohua1020/article/details/17973587 |