logo资料库

ts流中PAT表与PMT表详解.doc

第1页 / 共9页
第2页 / 共9页
第3页 / 共9页
第4页 / 共9页
第5页 / 共9页
第6页 / 共9页
第7页 / 共9页
第8页 / 共9页
资料共9页,剩余部分请下载后查看
TS 流也是由一个或多个 PES 组合而来的,他们可以具有相同的时间基准,也可以不同。其 基本的复用思想是,对具有相同时间基准[color="#000000"]的多个 PES 现进行节目复用,然 后再对相互有独立时间基准的各个 PS 进行传输复用,最终产生出 TS。 TS 包由包头和包数 据 2 部分组成,其中包头还可以包括扩展的自适用区。包头长度占 4bytes,自使用区和包数 据共占 184bytes,整个 TS 包长度相当于 4 个 ATM 包长。TS 包的包头由如下图摘录所示的同 步字节、传输误码指示符、有效载荷单元起始指示符、传输优先、包识别(PID-Packet Identification)、传输加扰控制、自适应区控制和连续计数器 8 个部分组成。 其中,可用同步字节位串的自动相关特性,检测数据流中的包限制,建立包同步;传输误码 指示符,是指有不能消除误码时,采用误码校正解码器可表示 1bit 的误码,但无法校正; 有效载荷单元起始指示符,表示该数据包是否存在确定的起始信息;传输优先,是给 TS 包 分配优先权;PID 值是由用户确定的,解码器根据 PID 将 TS 上从不同 ES 来的 TS 包区别出来, 以重建原来的 ES;传输加扰控制,可指示数据包内容是否加扰,但包头和自适应区永远不 加扰;自适应区控制,用 2 bit 表示有否自适应区,即(01)表示有有用信息无自适应区, (10)表示无有用信息有自适应区,(11)表示有有用信息有自适应区,(00)无定义;连续 计数器可对 PID 包传送顺序计数,据计数器读数,接收端可判断是否有包丢失及包传送顺序 错误。显然,包头对 TS 包具有同步、识别、检错及加密功能。 TS 包自适应区由自适应区长、各种标志指示符、与插入标志有关的信息和填充数据 4 部 分组成。其中标志部分由间断指示符、随机存取指示符、ES 优化指示符、PCR 标志、接点标 志、传输专用数据标志、原始 PCR 标志、自适应区扩展标志 8 个部分组成。重要的是标志 部分的 PCR 字段,可给编解码器的 27MHz 时钟提供同步资料,进行同步。其过程是,通过 PLL,用解码时本地用 PCR 相位与输入的瞬时 PCR 相位锁相比较,确定解码过程是否同步, 若不同步,则用这个瞬时 PCR 调整时钟频率。因为,数字图像采用了复杂而不同的压缩编 码算法,造成每幅图像的数据各不相同,使直接从压缩编码图像数据的开始部分获取时钟信 息成为不可能。为此,选择了某些(而非全部)TS 包的自适应区来传送定时信息。于是, 被选中的 TS 包的自适应区,可用于测定包信息的控制 bit 和重要的控制信息。自适应区无须 伴随每个包都发送,发送多少主要由选中的 TS 包的传输专用时标参数决定。标志中的随机 存取指示符和接点标志,在节目变动时,为随机进入 I 帧压缩的数据流提供随机进入点,也
为插入当地节目提供方便。自适应区中的填充数据是由于 PES 包长不可能正好转为 TS 包的 整数倍,最后的 TS 包保留一小部分有用容量,通过填充字节加以填补,这样可以防止缓存 器下溢,保持总码率恒定不变。 根据前一篇中各数据的定义及数据结构,对数据进行分别解析如下: TS 包头定义: typedef struct TS_packet_header { unsigned sync_byte unsigned transport_error_indicator unsigned payload_unit_start_indicator : 1; //传输误码指示符 : 1; //有效荷载单元起始指示符 : 8; //同步字节, 固定为 0x47,表示后面的是一个 TS 分组 unsigned transport_priority : 1; //传输优先, 1 表示高优先级,传输机制可能用到,解码 用不着 unsigned PID unsigned transport_scrambling_control unsigned adaption_field_control : 13; //PID : 2; //传输加扰控制 : 2; //自适应控制 01 仅含有效负载,10 仅含调整字 段,11 含有调整字段和有效负载。为 00 解码器不进行处理 unsigned continuity_counter : 4; //连续计数器 一个 4bit 的计数器,范围 0-15 } TS_packet_header; TS 包头解析代码: HRESULT CTS_Stream_Parse::adjust_TS_packet_header( TS_packet_header* TS_header ) { unsigned char buf[4]; = buf[1] >> 7; memcpy(buf, TS_header, 4); TS_header->transport_error_indicator TS_header->payload_unit_start_indicator = buf[1] >> 6 & 0x01; TS_header->transport_priority TS_header->PID TS_header->transport_scrambling_control = buf[3] >> 6; TS_header->adaption_field_control TS_header->continuity_counter = buf[1] >> 5 & 0x01; = (buf[1] & 0x1F) << 8 | buf[2]; = buf[3] >> 4 & 0x03; = buf[3] & 0x0F; // 四位数据,应为 0x0F xyy 09.03.18 return 0; } 如下为一个 TS 包数据: 0x47 0x40 0x00 0x12 0x00 0x00 0xb0 0x0d 0x00 0x00 0xc1 0x00 0x00 0x00 0x01 0xe3 0xe8 0xf0 0x0b 0xd7 0x79 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 分析知道前四位 0x47 0x40 0x00 0x12TS 头部即为 TS 包头数据,解析如下: sync_byte :0x47 transport_error_indicator: 0x00 payload_unit_start_indicator: 0x01 transport_priority : 0x00 PID :0x0000 transport_scrambling_control :0x00 adaptation_field_control :0x01 continuity_counter :0x02 PID = 0x0000,表示此 TS 包的内容为 PSI 信息表格的 PAT 表格数据,在 4 字节 的 TS 包头之后的第一个字节的 Point_field = 0x00, 表示偏移量为 0,即紧随其后 的即为 PAT 的数据信息。 TS 流解析之 PAT 表格解析 PAT 表格定义如下: typedef struct TS_PAT_Program { unsigned program_number unsigned program_map_PID :13; :16; //节目号 对应一个 }TS_PAT_Program; //PAT 表结构体 typedef struct TS_PAT { //节目映射表的 PID,节目号大于 0 时对应的 PID,每个节目 : 8; //固定为 0x00 ,标志是该表是 PAT : 1; //段语法标志位,固定为 1 : 2; // 保留位 : 12; //表示这个字节后面有用的字节数,包括 CRC32 : 16; //该传输流的 ID,区别于一个网络中其它多路复用 unsigned table_id unsigned section_syntax_indicator unsigned zero unsigned reserved_1 unsigned section_length unsigned transport_stream_id : 1; //0 的流 unsigned reserved_2 unsigned version_number : 2;// 保留位 : 5; //范围 0-31,表示 PAT 的版本号
unsigned current_next_indicator unsigned section_number : 1; //发送的 PAT 是当前有效还是下一个 PAT 有效 : 8; //分段的号码。PAT 可能分为多段传输,第一段为 00,以后每个分段加 1,最多可能有 256 个分段 unsigned last_section_number : 8; //最后一个分段的号码 std::vector program; unsigned reserved_3 unsigned network_PID : 3; // 保留位 : 13; //网络信息表(NIT)的 PID,节目号为 0 时对应的 PID 为 network_PID unsigned CRC_32 } TS_PAT; 解析代码如下: : 32; //CRC32 校验码 HRESULT CTS_Stream_Parse::adjust_PAT_table( TS_PAT * packet, unsigned char * buffer) { = buffer[0]; packet->table_id packet->section_syntax_indicator = buffer[1] >> 7; packet->zero = buffer[1] >> 6 & 0x1; packet->reserved_1 packet->section_length = buffer[1] >> 4 & 0x3; = (buffer[1] & 0x0F) << 8 | buffer[2]; packet->transport_stream_id = buffer[3] << 8 | buffer[4]; packet->reserved_2 packet->version_number packet->current_next_indicator packet->section_number packet->last_section_number int len = 0; len = 3 + packet->section_length; packet->CRC_32 = buffer[5] >> 6; = buffer[5] >> 1 & 0x1F; = (buffer[5] << 7) >> 7; = buffer[6]; = buffer[7]; = (buffer[len-4] & 0x000000FF) << 24 | (buffer[len-3] & 0x000000FF) << 16 | (buffer[len-2] & 0x000000FF) << 8 | (buffer[len-1] & 0x000000FF); int n = 0; for ( n = 0; n < packet->section_length - 12; n += 4 ) { unsigned program_num = buffer[8 + n ] << 8 | buffer[9 + n ]; packet->reserved_3 = buffer[10 + n ] >> 5;
packet->network_PID = 0x00; if ( program_num == 0x00) { packet->network_PID = (buffer[10 + n ] & 0x1F) << 8 | buffer[11 + n ]; TS_network_Pid = packet->network_PID; //记录该 TS 流的网络 PID TRACE(" packet->network_PID %0x \n\n", packet->network_PID ); } else { TS_PAT_Program PAT_program; PAT_program.program_map_PID = (buffer[10 + n] & 0x1F) << 8 | buffer[11 + n]; PAT_program.program_number = program_num; packet->program.push_back( PAT_program ); TS_program.push_back( PAT_program );//向全局 PAT 节目数组中添加 PAT 节目信息 } } return 0; } 因此,PAT 数据解析结果如下: //8 // 1 // 1 // 2 0x03 :0x00 PAT 数据 table_id :0x00 section_syntax_indicator :0x01 '0' reserved section_length :0x00d transport_stream_id :0x0000 :0x03 reserved version_number :0x00 current_next_indicator :0x01 :0x00 section_number last_section_number :0x00 program_number :0x0001 reserved program_map_PID :0x03e8 CRC :0x f0 0b d7 79 :0x07 // 12 // 16 // 2 // 5 // 1 // 8 // 8 // 16 // 3 // 13 由解析结构可知,该 PAT 表格中没有网络信息包信息,只包含一个节目,其 PID 为 0x03e8
TS 流解析之 PMT 表格解析 : 8; //指示特定 PID 的节目元素包的类型。该处 PID 由 : 13; //该域指示 TS 包的 PID 值。这些 TS 包含有相关的 : 12; //前两位 bit 为 00。该域指示跟随其后的描述相关节 typedef struct TS_PMT_Stream { unsigned stream_type elementary PID 指定 unsigned elementary_PID 节目元素 unsigned ES_info_length 目元素的 byte 数 unsigned descriptor; }TS_PMT_Stream; //PMT 表结构体 typedef struct TS_PMT { unsigned table_id unsigned section_syntax_indicator unsigned zero unsigned reserved_1 unsigned section_length : 8; //固定为 0x02, 表示 PMT 表 : 1; //固定为 0x01 : 1; //0x01 : 2; //0x03 : 12;//首先两位 bit 置为 00,它指示段的 byte 数,由段 长度域开始,包含 CRC。 unsigned program_number : 16;// 指出该节目对应于可应用的 Program map PID unsigned reserved_2 unsigned version_number unsigned current_next_indicator section 可用; : 2; //0x03 : 5; //指出 TS 流中 Program map section 的版本号 : 1; //当该位置 1 时,当前传送的 Program map //当该位置 0 时,指示当前传送的 Program map section 不可用,下一个 TS 流的 Program map section 有效。 unsigned section_number unsigned last_section_number unsigned reserved_3 unsigned PCR_PID : 8; //固定为 0x00 : 8; //固定为 0x00 : 3; //0x07 : 13; //指明 TS 包的 PID 值,该 TS 包含有 PCR 域, //该 PCR 值对应于由节目号指定的对应节目。 //如果对于私有数据流的节目定义与 PCR 无关,这个域的值将为 0x1FFF。 unsigned reserved_4 unsigned program_info_length : 4; //预留为 0x0F : 12; //前两位 bit 为 00。该域指出跟随其后对节目信息 的描述的 byte 数。 std::vector PMT_Stream; //每个元素包含 8 位, 指示特定 PID 的节目元素包 的类型。该处 PID 由 elementary PID 指定
unsigned reserved_5 unsigned reserved_6 unsigned CRC_32 : 3; //0x07 : 4; //0x0F : 32; } TS_PMT; 解析代码为: HRESULT CTS_Stream_Parse::adjust_PMT_table ( TS_PMT * packet, unsigned char * buffer ) { packet->table_id packet->section_syntax_indicator packet->zero packet->reserved_1 packet->section_length packet->program_number packet->reserved_2 packet->version_number packet->current_next_indicator packet->section_number packet->last_section_number packet->reserved_3 packet->PCR_PID PCRID = packet->PCR_PID; packet->reserved_4 packet->program_info_length // Get CRC_32 int len = 0; = buffer[0]; = buffer[1] >> 7; = buffer[1] >> 6 & 0x01; = buffer[1] >> 4 & 0x03; = (buffer[1] & 0x0F) << 8 | buffer[2]; = buffer[3] << 8 | buffer[4]; = buffer[5] >> 6; = buffer[5] >> 1 & 0x1F; = (buffer[5] << 7) >> 7; = buffer[6]; = buffer[7]; = buffer[8] >> 5; = ((buffer[8] << 8) | buffer[9]) & 0x1FFF; = buffer[10] >> 4; = (buffer[10] & 0x0F) << 8 | buffer[11]; len = packet->section_length + 3; packet->CRC_32 = (buffer[len-4] & 0x000000FF) << 24 | (buffer[len-3] & 0x000000FF) << 16 | (buffer[len-2] & 0x000000FF) << 8 | (buffer[len-1] & 0x000000FF); int pos = 12; // program info descriptor if ( packet->program_info_length != 0 ) pos += packet->program_info_length; // Get stream type and PID for ( ; pos <= (packet->section_length + 2 ) - 4; ) { TS_PMT_Stream pmt_stream;
pmt_stream.stream_type = buffer[pos]; packet->reserved_5 = buffer[pos+1] >> 5; pmt_stream.elementary_PID = ((buffer[pos+1] << 8) | buffer[pos+2]) & 0x1FFF; packet->reserved_6 pmt_stream.ES_info_length = (buffer[pos+3] & 0x0F) << 8 | buffer[pos+4]; = buffer[pos+3] >> 4; pmt_stream.descriptor = 0x00; if (pmt_stream.ES_info_length != 0) { pmt_stream.descriptor = buffer[pos + 5]; for( int len = 2; len <= pmt_stream.ES_info_length; len ++ ) { pmt_stream.descriptor = pmt_stream.descriptor<< 8 | buffer[pos + 4 + len]; } pos += pmt_stream.ES_info_length; } pos += 5; packet->PMT_Stream.push_back( pmt_stream ); TS_Stream_type.push_back( pmt_stream ); } return 0; } 举例如下: 0x47 0x43 0xe8 0x12 0x00 0x02 0xb0 0x12 0x00 0x01 0xc1 0x00 0x00 0xe3 0xe9 0xf0 0x00 0x1b 0xe3 0xe9 0xf0 0x00 0xf0 0xaf 0xb4 0x4f 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff TS 头部 sync_byte :0x47 transport_error_indicator: 0x00 payload_unit_start_indicator: 0x01 transport_priority : 0x00 PID :0x03e8 transport_scrambling_control :0x00 adaptation_field_control :0x01
分享到:
收藏