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

相关文章

MySQL字符串转数值的方法全解析

《MySQL字符串转数值的方法全解析》在MySQL开发中,字符串与数值的转换是高频操作,本文从隐式转换原理、显式转换方法、典型场景案例、风险防控四个维度系统梳理,助您精准掌握这一核心技能,需要的朋友可... 目录一、隐式转换:自动但需警惕的&ld编程quo;双刃剑”二、显式转换:三大核心方法详解三、典型场景

SQL 注入攻击(SQL Injection)原理、利用方式与防御策略深度解析

《SQL注入攻击(SQLInjection)原理、利用方式与防御策略深度解析》本文将从SQL注入的基本原理、攻击方式、常见利用手法,到企业级防御方案进行全面讲解,以帮助开发者和安全人员更系统地理解... 目录一、前言二、SQL 注入攻击的基本概念三、SQL 注入常见类型分析1. 基于错误回显的注入(Erro

C++ 多态性实战之何时使用 virtual 和 override的问题解析

《C++多态性实战之何时使用virtual和override的问题解析》在面向对象编程中,多态是一个核心概念,很多开发者在遇到override编译错误时,不清楚是否需要将基类函数声明为virt... 目录C++ 多态性实战:何时使用 virtual 和 override?引言问题场景判断是否需要多态的三个关

Springboot主配置文件解析

《Springboot主配置文件解析》SpringBoot主配置文件application.yml支持多种核心值类型,包括字符串、数字、布尔值等,文章详细介绍了Profile环境配置和加载位置,本文... 目录Profile环境配置配置文件加载位置Springboot主配置文件 application.ym

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

一文解析C#中的StringSplitOptions枚举

《一文解析C#中的StringSplitOptions枚举》StringSplitOptions是C#中的一个枚举类型,用于控制string.Split()方法分割字符串时的行为,核心作用是处理分割后... 目录C#的StringSplitOptions枚举1.StringSplitOptions枚举的常用

Python函数作用域与闭包举例深度解析

《Python函数作用域与闭包举例深度解析》Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,:本文主要介绍Python函数作用域与闭包的相关资料,文中通过代码... 目录1. 基础作用域访问示例1:访问全局变量示例2:访问外层函数变量2. 闭包基础示例3:简单闭包示例4

MyBatis延迟加载与多级缓存全解析

《MyBatis延迟加载与多级缓存全解析》文章介绍MyBatis的延迟加载与多级缓存机制,延迟加载按需加载关联数据提升性能,一级缓存会话级默认开启,二级缓存工厂级支持跨会话共享,增删改操作会清空对应缓... 目录MyBATis延迟加载策略一对多示例一对多示例MyBatis框架的缓存一级缓存二级缓存MyBat