TS协议解析第二部分(PMT)

2024-02-05 09:58
文章标签 协议 解析 第二 部分 ts pmt

本文主要是介绍TS协议解析第二部分(PMT),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://blog.csdn.net/u013354805/article/details/51586086


1. PMT:

PMT(Program Map Table):节目映射表,该表的PID是由PAT提供给出的。通过该表可以得到一路节目中包含的信息,例如,该路节目由哪些流构成和这些流的类型(视频,音频,数据),指定节目中各流对应的PID,以及该节目的PCR所对应的PID。

PMT表中包含的数据如下:

(1) 当前频道中包含的所有Video数据的PID
(2) 当前频道中包含的所有Audio数据的PID
(3) 和当前频道关联在一起的其他数据的PID(如数字广播,数据通讯等使用的PID)

2. 分析MPT包:

2.1 PMT包数据:


2.2 包头:

TS包头只有4个字节(47 60 81 10),除掉第一个字节0x47,剩下就3个,重新分组如下:

0    1    1  0000010000001    00    01    0000

sync_byte

同步字节

0x47:

transport_error_indicator

传输错误标识

0:

payload_unit_start_indicator

负载单元开始标识

1:

transport_priority

传输优先级

1:

pid

PID

0x81:因为在PAT中查找到program_map_PID为0x81,因此就查找到PMT。

transport_scrambling_control

传输扰乱控制

00:

adaptation_field_control

自适应区域控制

01:

00是保留值。
01负载中只有有效载荷。
10负载中只有自适应字段。
11先有自适应字段,再有有效载荷。

continuity_counter

连续计数器

0x0:

2.3 TS包:

1) 在payload_unit_start_indicator为1时,在前4个字节后会有一个调整字节。所以实际数据应该为去除第一个字节00后的数据。(47 60 81 10 00 02 B0 17 00 01 C1 00 00 E8 10 F0 00 1B E8 10 F0 00 03 E8 14 F0 00 66 74 A4 2D

2) 02 B0 17:0000 0010 1011 0000 0001 0111
section_length:23 47 60 81 10 00 02 B0 17 00 01 C1 00 00 E8 10 F0 00 1B E8 10 F0 00 03 E8 14 F0 00 66 74 A4 2D

3)
00 01:0000 0000 0000 0001
C1:1100 0001
00 00:0000 0000 0000 0000
E8 10:1110 1000 0001 0000
F0 00:1111 0000 0000 0000
1B E8 10 F0 00:0001 1011 1110 1000 0001 0000 1111 0000 0000 0000
03 E8 14 F0 00:0000 0011 1110 1000 0001 0100 1111 0000 0000 0000

table_id

0x02:对于PMT,该字段置为0x02

section_syntax_indicator

1:对于PMT,该字段置为1

0

0:

reserved

11:

section_length

0000 0001 0111:前两位置为00,该字段指示分段的字节数,由分段长度字段开始,包括CRC,其值不超过1021。

Program_number

0x 00 01:对应于PAT中的Program_nmuber。

reserved

11:

version_number

00000:该字段指出了TS中program_map_section的版本号。

current_next_indicator

1:当该字段置为1时,表示当前传送的program_map_section可用;当该字段置0时,表示当前传送的program_map_section不可用,下一个TS的program_map_section有效。

section_number

0x00:section_number:该字段值总是置0x00

last_section_number

0x00:该字段值总是置0x00

reserved

111:

PCR_PID

0x810:该字段指示TS包的PID值。该TS包含有PCR字段,而PCR值对应于有节目好指定的节目。

reserved

1111:

Program_info_length

0x000:

stream_type

1B:表示这个流时h264格式的,通俗点就是视频

reserved

111:

Elementary_pid

0x810:表示PID时810的TS包就是用来装h264数据的

reserved

1111:

es_info_length

0x000:

Stream_type:

0x03:

reserved:

111:

Elementary_pid

0x814

reserved

1111:

Es_info_lenth

0x000:

Crc_32

0x 03 E8 14 F0 00:


PMT

table_id

8

1个字节

section_syntax_indicator

1

 

2个字节

‘0’

1

reserved

2

section_length

12

program_number

16

2个字节

reserved

2

 

1个字节

version_number

5

current_next_indicator

1

section_number

8

1个字节

last_section_number

8

1个字节

reserved

3

 

2个字节

PCR_PID

13

reserved

4

2个字节

program_info_length

12

循环:descriptor()(0-N)

循环开始(0-N1)

stream_type

8

1个字节

reserved

3

2个字节

elementary_PID

13

reserved

4

2个字节

ES_info_length

12

循环:descriptor()(0-N2)

循环结束

CRC_32

32

4个字节


3. 实现:

3.1 PMT表格定义如下:

[cpp]  view plain copy
  1. typedef struct TS_PMT_Stream  
  2. {  
  3.  unsigned stream_type     : 8; //指示特定PID的节目元素包的类型。该处PID由elementary PID指定  
  4.  unsigned elementary_PID  : 13; //该域指示TS包的PID值。这些TS包含有相关的节目元素  
  5.  unsigned ES_info_length  : 12; //前两位bit为00。该域指示跟随其后的描述相关节目元素的byte数  
  6.  unsigned descriptor;  
  7. }TS_PMT_Stream;  


3.2 PMT表结构体:
[cpp]  view plain copy
  1. typedef struct TS_PMT  
  2. {  
  3.     unsigned table_id                   : 8; //固定为0x02, 表示PMT表  
  4.     unsigned section_syntax_indicator    : 1; //固定为0x01  
  5.    unsigned zero                       : 1; //0x01  
  6.    unsigned reserved_1                 : 2; //0x03  
  7.    unsigned section_length : 12;//首先两位bit置为00,它指示段的byte数,由段长度域开始,包含CRC  
  8.    unsigned program_number             : 16;// 指出该节目对应于可应用的Program map PID  
  9.    unsigned reserved_2                 : 2; //0x03  
  10.    unsigned version_number             : 5; //指出TS流中Program map section的版本号  
  11.     unsigned current_next_indicator  : 1; //当该位置1时,当前传送的Program map section可用  
  12.      //当该位置0时,指示当前传送的Program map section不可用,下一个TS流的Program map section有效  
  13.    unsigned section_number            : 8; //固定为0x00  
  14.    unsigned last_section_number      : 8; //固定为0x00  
  15.    unsigned reserved_3               : 3; //0x07  
  16.    nsigned PCR_PID                   : 13; //指明TS包的PID值,该TS包含有PCR域,  
  17.       //该PCR值对应于由节目号指定的对应节目,如果对于私有数据流的节目定义与PCR无关,这个域的值将为0x1FFF。  
  18.    unsigned reserved_4            : 4;  //预留为0x0F  
  19.    unsigned program_info_length  : 12; //前两位bit为00。该域指出跟随其后对节目信息的描述的byte数。  
  20.       
  21.  std::vector<TS_PMT_Stream> PMT_Stream;  //每个元素包含8位, 指示特定PID的节目元素包的类型。该处PID由elementary PID指定  
  22.     unsigned reserved_5                : 3; //0x07  
  23.    unsigned reserved_6                : 4; //0x0F  
  24.    unsigned CRC_32                    : 32;   
  25. } TS_PMT;   


3.3 解析代码:

[cpp]  view plain copy
  1. HRESULT CTS_Stream_Parse::adjust_PMT_table ( TS_PMT * packet, unsigned char * buffer )  
  2. {   
  3.     packet->table_id                         = buffer[0];  
  4.     packet->section_syntax_indicator         = buffer[1] >> 7;  
  5.     packet->zero                             = buffer[1] >> 6 & 0x01;   
  6.     packet->reserved_1                       = buffer[1] >> 4 & 0x03;  
  7.     packet->section_length                   = (buffer[1] & 0x0F) << 8 | buffer[2];      
  8.     packet->program_number                   = buffer[3] << 8 | buffer[4];  
  9.     packet->reserved_2                       = buffer[5] >> 6;  
  10.     packet->version_number                   = buffer[5] >> 1 & 0x1F;  
  11.     packet->current_next_indicator           = (buffer[5] << 7) >> 7;  
  12.     packet->section_number                   = buffer[6];  
  13.     packet->last_section_number              = buffer[7];  
  14.     packet->reserved_3                       = buffer[8] >> 5;  
  15.     packet->PCR_PID                          = ((buffer[8] << 8) | buffer[9]) & 0x1FFF;  
  16.   
  17.     PCRID = packet->PCR_PID;  
  18.   
  19.     packet->reserved_4                       = buffer[10] >> 4;  
  20.     packet->program_info_length              = (buffer[10] & 0x0F) << 8 | buffer[11];   
  21.     // Get CRC_32  
  22.     int len = 0;  
  23.     len = packet->section_length + 3;      
  24.     packet->CRC_32                = (buffer[len-4] & 0x000000FF) << 24  
  25.       | (buffer[len-3] & 0x000000FF) << 16  
  26.       | (buffer[len-2] & 0x000000FF) << 8  
  27.       | (buffer[len-1] & 0x000000FF);   
  28.   
  29.   int pos = 12;  
  30.   // program info descriptor  
  31.   if ( packet->program_info_length != 0 )  
  32.         pos += packet->program_info_length;      
  33.   // Get stream type and PID      
  34.   for ( ; pos <= (packet->section_length + 2 ) -  4; )  
  35.   {  
  36.     TS_PMT_Stream pmt_stream;  
  37.     pmt_stream.stream_type =  buffer[pos];  
  38.     packet->reserved_5  =  buffer[pos+1] >> 5;  
  39.     pmt_stream.elementary_PID = ((buffer[pos+1] << 8) | buffer[pos+2]) & 0x1FFF;  
  40.     packet->reserved_6    =  buffer[pos+3] >> 4;  
  41.     pmt_stream.ES_info_length =  (buffer[pos+3] & 0x0F) << 8 | buffer[pos+4];  
  42.     
  43.     pmt_stream.descriptor = 0x00;  
  44.     if (pmt_stream.ES_info_length != 0)  
  45.     {  
  46.        pmt_stream.descriptor = buffer[pos + 5];  
  47.      
  48.        forint len = 2; len <= pmt_stream.ES_info_length; len ++ )  
  49.        {  
  50.          pmt_stream.descriptor = pmt_stream.descriptor<< 8 | buffer[pos + 4 + len];  
  51.        }  
  52.        pos += pmt_stream.ES_info_length;  
  53.     }  
  54.     pos += 5;  
  55.     packet->PMT_Stream.push_back( pmt_stream );  
  56.     TS_Stream_type.push_back( pmt_stream );  
  57.    }  
  58.    return 0;  
  59. }  


1
0





这篇关于TS协议解析第二部分(PMT)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/680549

相关文章

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

HTTP 与 SpringBoot 参数提交与接收协议方式

《HTTP与SpringBoot参数提交与接收协议方式》HTTP参数提交方式包括URL查询、表单、JSON/XML、路径变量、头部、Cookie、GraphQL、WebSocket和SSE,依据... 目录HTTP 协议支持多种参数提交方式,主要取决于请求方法(Method)和内容类型(Content-Ty

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Java Scanner类解析与实战教程

《JavaScanner类解析与实战教程》JavaScanner类(java.util包)是文本输入解析工具,支持基本类型和字符串读取,基于Readable接口与正则分隔符实现,适用于控制台、文件输... 目录一、核心设计与工作原理1.底层依赖2.解析机制A.核心逻辑基于分隔符(delimiter)和模式匹

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装

深度解析Python yfinance的核心功能和高级用法

《深度解析Pythonyfinance的核心功能和高级用法》yfinance是一个功能强大且易于使用的Python库,用于从YahooFinance获取金融数据,本教程将深入探讨yfinance的核... 目录yfinance 深度解析教程 (python)1. 简介与安装1.1 什么是 yfinance?