音视频封装格式(3):TS格式学习

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

你可能感兴趣的:(音视频封装格式(3):TS格式学习)