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