PAT、PMT、SDT详解

http://blog.chinaunix.net/uid-24322243-id-2620180.html

下面针对解复用程序详细分析一下PAT,PMTSDT三类表格的格式.

PAT---Program Association Table,节目关联表 PAT表携带以下信息: 
(1) TS流ID--- transport_stream_id,该ID标志唯一的流ID
(2)
节目频道号-- program_number,该号码标志TS流中的一个频道,该频道可以包含很多的节目(即可以包含多个Video PIDAudio PID)
(3)
 PMTPID--- program_map_PID,表示本频道使用的哪个PID做为PMT的PID,因为可以有很多的频道,因此DVB规定PMTPID可以由用户自己定义.

PAT表定义如下: 各字段含义如下:

table_id:8 bits,标志本表格的类型,应该是0x00

section_syntax_indicator:1 bit,段语法标志,应该是''1'' ''0'':固定的''0'',这是为了防止和ISO13818Video流格式中的控制字冲突而设置的.

Reserved:保留的2bits,保留位一般都是''0''

section_length:12bits的段大小,单位是Bytes.

transport_stream_id:16bits的当前流ID,DVB内唯一.(事实上很多都是自定义的TS ID)version_number:5bits版本号码,标注当前节目的版本.这是个非常有用的参数,当检测到这个字段改变时,说明TS流中的节目已经变化 了,程序必须重新搜索节目.

current_next_indicator:1bit:当前还是未来使用标志符,一般情况下为''0''

section_number:8bits当前段号码

last_section_number:8bits最后段号码(section_number last_section_number的功能是当PAT内容>184字节时,PAT表会分成多个段(sections),解复用程序必须在全部接 收完成后再进行PAT的分析)

for()开始,就是描述了当前流中的频道数目(N),每一个频道对应的PMT PID是什么.解复用程序需要和上图类似的循环来接收所有的频道号码和对应的PMT PID,并把这些信息在缓冲区中保存起来.在后部的处理中需要使用到PMT PID.

CRC_32:本段的CRC校验值,一般是会忽略的.N是一个变量,计算方法是N=(section_length-9)/4.

从以上分析我们可以发现,PAT表主要包含频道号码和每一个频道对应的PMTPID号码,这些信息我们在处理PAT表格的时候会保存起来,以后会使用到 这些数据.例如我们可以定义这样的数据结构保存这些信息:

typedef struct

{

int channel_number;

int pmt_pid;

}PMT_ITEM;

PMT_ITEM pmt[64];

 

PMT, Program Map Table,节目影射表 如果一个TS流中含有多个频道,
那么就会包含多个PID不同的PMT.检测是否PMT的伪代码如下:
void Process_Packet(unsigned char*buff)
{ int I;

int PID=GETPID(buff);

if(PID==0x0000)

{

Process_PAT(buff+4);

 }

else if(PID==.....)
{ }

else

{ for(i=0;i<64;i++)
{ if(PID==pmt[i].pmt_pid)

{ Process_PMT(buff+4); break; }
} } }
PMT
表中包含的数据如下:

(1) 当前频道中包含的所有Video数据的PID

(2) 当前频道中包含的所有Audio数据的PID

(3) 和当前频道关联在一起的其他数据的PID(如数字广播,数据通讯等使用的PID)

 

PMT定义如下: 各字段含义如下:

table_id:8bitsID,应该是0x02

section_syntax_indicator:1bit的段语法标志,应该是''1'' ''0'':固定是''0'',如果不是说明数据有错.

reserved:2bits保留位,应该是''00''

section_length:16bits段长度,program_number开始,CRC_32(包含)的字节总数. program_number:16bits的频道号码,表示当前的PMT关联到的频道.换句话就是说,当前描述的是program_number频道的 信息.

reserved:2bits保留位,应该是''00''

version_number:版本号码,如果PMT内容有更新,version_number会递增1通知解复用程序需要重新接收节目信息,否则 version_number是固定不变的.

current_next_indicator:当前未来标志符,一般是0

section_number:当前段号码

last_section_number:最后段号码,含义和PAT中的对应字段相同,请参考PAT部分. reserved:3bits保留位,一般是''000''.

PCR_PID:13bitsPCR PID,具体请参考ISO13818-1,解复用程序不使用该参数.

reserved:4bits保留位,一般是''0000''

program_info_length:节目信息长度(之后的是N个描述符结构,一般可以忽略掉,这个字段就代表描述符总的长度,单位是Bytes) 紧接着就是频道内部包含的节目类型和对应的PID号码了.

stream_type:8bits流类型,标志是Video还是Audio还是其他数据.

reserved:3 bits保留位.

elementary_PID:13bits对应的数据PID号码(如果stream_typeVideo,那么这个PID就是Video PID,如果stream_type标志是Audio,那么这个PID就是Audio PID)

reserved:4 bits保留位.

ES_info_length:program_info_length类似的信息长度(其后是N2个描述符号) CRC_32:32bits段末尾是本段的CRC校验值,一般忽略.

 

从以上的分析可以看出,只要我们处理了PMT,那么我们就可以获取频道中所有的PID信息,例如当前频道包含多少个Video,共多少个Audio,和其 他数据,还能知道每种数据对应的PID分别是什么. 这样如果我们要选择其中一个VideoAudio收看,那么只需要把要收看的节目的Video PIDAudio PID保存起来,在处理Packet的时候进行过滤即可实现. 比较全面实现解复用的伪代码如下:

int Video_PID=0x07e5,Audio_PID=0x07e6;

void Process_Packet(unsigned char*buff)

{ int I; int PID=GETPID(buff);

if(PID==0x0000) { Process_PAT(buff+4); }

else if(PID==Video_PID) { SaveToVideoBuffer(buff+4); }

else if(PID==Audio_PID) { SaveToAudioBuffer(buff+4); }

else

{ for( i=0;i<64;i++)

{ if(PID==pmt[i].pmt_pid) { Process_PMT(buff+4); Break; }

} } }

以上伪代码可以实现基本的解复用:检测所有的频道,检测所有streamPID,选择特定的节目进行播放.只要读取每个Packet188字节的内 ,然后每次都调用Process_Packet()即可实现简单的解复用. 介绍到这里,我们就可以总结一下DVB搜台的原理了.(!洗耳恭听!)  顶盒先调整高频头到一个固定的频率(498MHZ),如果此频率有数字信号,COFDM芯片(MT352)会自动把TS流数据传送给MPEG- 2 decoder. MPEG-2 decoder先进行数据的同步,也就是等待完整的Packet的到来.然后循环查找是否出现PID== 0x0000Packet,如果出现了,则马上进入分析PAT的处理,获取了所有的PMTPID.接着循环查找是否出现PMT,如果发现了,则自动进 PMT分析,获取该频段所有的频道数据并保存.如果没有发现PAT或者没有发现PMT,说明该频段没有信号,进入下一个频率扫描. 从以上描述可以看出,机顶盒搜索频率是随机发生的,要使每次机顶盒都能搜索到信号,则要求TS流每隔一段时间就发送一 PATPMT.事实上DVB传输系统就是这么做的.因此无论何时接入终端系统,系统都能马上搜索到节目并正确解复用实现播放.不仅仅如此,其他数据也 都是交替传送的.比如第一个Packet可能是PAT,第二个Packet可能是PMT,而第三个Packet可能是Video 1,第四个Packet可能是Video 2, 只要系统传输速度足够快(就是称之为"码率"的东东),实现实时播放是没有任何问题的. 到这里虽然实现了解复用,但可以看出,使用的PID都是枯燥的数字,如果调台要用户自己输入数字那可是太麻烦了,而且还容易输入错 ,操作非常不直观,即使做成一个菜单让用户选择也是非常的呆板.针对这个问题,DVB系统提出了一个SDT表格,该表格标志一个节目的名称,并且能和 PMT中的PID联系起来,这样用户就可以通过直接选择节目名称来选择节目了.

 

SDT, Service description section,服务描述段

SDT可以提供的信息包括:

(1) 该节目是否在播放中

(2) 该节目是否被加密

(3) 该节目的名称

SDT定义如下: 各字段定义如下:

table_id:8bitsID,可以是0x42,表示描述的是当前流的信息,也可以是0x46,表示是其他流的信息(EPG使用此参数)

section_syntax_indicator:段语法标志,一般是''1''

reserved_future_used:2bits保留未来使用

reserved:1bit保留位,防止控制字冲突,一般是''0'',也有可能是''1''

section_length:12bits的段长度,单位是Bytes,transport_stream_id开始,CRC_32结束(包含)

transport_stream_id:16bits当前描述的流ID

reserved:2bits保留位

version_number:5bits的版本号码,如果数据更新则此字段递增1

current_next_indicator:当前未来标志,一般是''0'',表示当前马上使用. original_netword_id:16bits的原始网络ID

reserved_future_use:8bits保留未来使用位 接下来是N个节目信息的循环:

service_id:16 bits的服务器ID,实际上就是PMT段中的program_number. reserved_future_used:6bits保留未来使用位

EIT_schedule_flag:1bitEIT信息,1表示当前流实现了该节目的EIT传送 EIT_present_following_flag:1bitsEIT信息,1表示当前流实现了该节目的EIT传送 running_status:3bits的运行状态信息:1-还未播放 2-几分钟后马上开始,3-被暂停播出,4-正在播放,其他---保留

free_CA_mode:1bits的加密信息,''1''表示该节目被加密.  接着的是描述符,一般是Service descriptor,分析此描述符可以获取servive_id指定的节目的节目名称.具体格式请参考 EN300468中的Service descriptor部分.

 

分析完毕 , 则节目名称和节目号码已经联系起来了 . 机顶盒程序就可以用这些节目名称代替   PID 让用户选择 , 从而实现比较友好的用户界面 !   下面参考一下 <> 中的界面和显示信息 .     图是 <> 打开三个不同的码流文件 (*.ts) 形成的 PID 信息和节目名称 . 用户   可以通过切换节目名称的下拉列表框切换节目 , 也可以通过 " 视频流 " " 音频流 " 下拉列表框切换 Video Audio! 这些数据都是通过分析 PAT, PMT SDT 得到的 .   (转载自网路)


http://blog.csdn.net/blackboyofsnp/article/details/4665409

// 所有原创文章转载请注明作者及链接
//
 blackboycpp(AT)gmail.com
// QQ群: 135202158

对TS流的分析, 涉及到对PAT,PMT等等的分析, 具体内容见iso/iec 13838系列文档,

本文只给出自己写的一些和TS分析想关的代码, 简单的分析足够了, 不考虑复杂情况:

 

[cpp]  view plain copy
  1. //  
  2. //  
  3. //  TS流结构定义  
  4. //  
  5. //  
  6.   
  7. #ifndef ZZQ_TS_H_  
  8. #define ZZQ_TS_H_  
  9.   
  10. #include <vector>  
  11. using namespace std;  
  12. typedef  unsigned char  byte;  
  13. typedef  unsigned int   bits;  
  14.   
  15. #define  TSPKT_LENGTH  188  
  16.   
  17. //-----------------------------------------------------------------------------  
  18. // 结构体  
  19. //-----------------------------------------------------------------------------  
  20. // TS包构成伪代码  
  21.   
  22. // TS包头部  
  23. // WARNING!!!  暂时没有考虑修改区以及修改区内可选字段的处理  
  24. struct ts_header  
  25.  
  26.     bits  sync_byte                    8;  
  27.     bits  transport_error_indicator    1;  
  28.     bits  payload_unit_start_indicator 1;  
  29.     bits  transport_priority           1;  
  30.     bits  PID                          13;  
  31.     bits  transport_scrambling_control 2;  
  32.     bits  adaptation_field_control     2;  
  33.     bits  continuity_counter           4;  
  34. };  
  35. // TS包中的修改字段(adaptation field)  
  36. struct ts_adaptation_field  
  37.  
  38.     bits  adaptation_field_length 8;  
  39.     bits  discontinuity_idicator  1;  
  40.     bits  random_access_indicator 1;  
  41.     bits  elementary_stream_priority_indicator 1;  
  42.     bits  flags                   5; // flags  
  43. };  
  44.   
  45. // PAT中的可变段  
  46. struct ts_pat_section  
  47.  
  48.     bits  program_number 16;  
  49.     bits  reserved       3;  
  50.     bits  PID            13;  
  51. };  
  52. typedef vector<ts_pat_section>  vec_pat_section;  
  53. // PAT表, P138-PAT的结构, 文档P61  
  54. struct ts_pat  
  55.  
  56.     bits  table_id                 8;  // 0x00  
  57.     bits  section_syntax_indicator 1;  // 1  
  58.     bits  zero                     1;  // 0  
  59.     bits  reserved_1               2;  // 11  
  60.     bits  section_length           12;   
  61.     bits  transport_stream_id      16; // 传输数据流识别  
  62.     bits  reserved_2               2;  // "11"  
  63.     bits  version_number           5;  
  64.     bits  current_next_indicator   1;  
  65.     bits  section_number           8;  
  66.     bits  last_section_number      8;  
  67.     // .... TODO  
  68.     vec_pat_section network_section;  
  69.     vec_pat_section pmt_section;  
  70.     bits  crc32                    32;  
  71. };  
  72.   
  73. // Stream_type分配表, P85  
  74. #define  ST_Reserved        0x00 // ITU-T ISO/IEC Reserved  
  75. #define  ST_VIDEO_1         0x01 // ISO/IEC 11172 Video  
  76. #define  ST_VIDEO_2         0x02 // ITU-T Rec. H.262 ISO/IEC 13818-2 Video or ISO/IEC 11172-2 constrained parameter video stream  
  77. #define  ST_AUDIO_1         0x03 // ISO/IEC 11172 Audio  
  78. #define  ST_AUDIO_2         0x04 // ISO/IEC 13818-3 Audio  
  79. #define  ST_PRIVATE_SECTIONS        0x05 // ITU-T Rec. H.222.0 ISO/IEC 13818-1 private_sections  
  80. #define  ST_PES_PKT_PRIVATE_DATA    0x06 // ITU-T Rec. H.222.0 ISO/IEC 13818-1 PES packets containing private data  
  81. #define  ST_MHEG            0x07 // ISO/IEC 13522 MHEG  
  82. #define  ST_DSMCC           0x08 // ITU-T Rec. H.222.0 ISO/IEC 13818-1 Annex DSM CC  
  83. #define  ST_H2221           0x09 // ITU-T Rec. H.222.1  
  84. #define  ST_TYPEA           0x0A // ISO/IEC 13818-6 type A  
  85. #define  ST_TYPEB           0x0B // ISO/IEC 13818-6 type B  
  86. #define  ST_TYPEC           0x0C // ISO/IEC 13818-6 type C  
  87. #define  ST_TYPED           0x0D // ISO/IEC 13818-6 type D  
  88. #define  ST_AUXILIARY       0x0E // ISO/IEC 13818-1 auxiliary  
  89. // 0x0F-0x7F: ITU-T Rec. H.222.0 ISO/IEC 13818-1 Reserved  
  90. // 0x80-0xFF: User Private  
  91. // PMT表中的ES段  
  92. struct ts_pmt_es_section  
  93.  
  94.     bits  stream_type              8;  
  95.     bits  reserved_1               3;  
  96.     bits  elementary_PID           13;  
  97.     bits  reserved_2               4;  
  98.     bits  ES_info_length           12;  
  99. };  
  100. typedef vector<ts_pmt_es_section>  vec_pmt_section;  
  101.   
  102. // PMT表, 书P138 PMT的结构  
  103. struct ts_pmt  
  104.  
  105.     bits  table_id                 8;  // 0x02  
  106.     bits  section_syntax_indicator 1;  // 1  
  107.     bits  zero                     1;  // 0  
  108.     bits  reserved_1               2;  // 11  
  109.     bits  section_length           12;  
  110.     bits  program_number           16;  
  111.     bits  reserved_2               2;  // 11  
  112.     bits  version_number           5;  
  113.     bits  current_next_indicator   1;  
  114.     bits  section_number           8;  
  115.     bits  last_section_number      8;  
  116.     bits  reserved_3               3;  // 111  
  117.     bits  PCR_PID                  13;  
  118.     bits  reserved_4               4;  // 1111  
  119.     bits  program_info_length      12;  
  120.     vec_pmt_section  es_section;  
  121.     bits  crc32                    32;  
  122. };  
  123.   
  124. // PES包构成伪代码  P43  
  125.   
  126.   
  127. // Steam ID分配表,  文档P47  
  128. #define  SID_PROGRAM_STREAM_MAP     0xBC  
  129. #define  SID_PRIVATE_STREAM_1       0xBD  
  130. #define  SID_PADDING_STREAM         0xBE  
  131. #define  SID_PRIVATE_STREAM_2       0xBF  
  132. #define  SID_AUDIO_STREAM           0xC0 // 110x xxxx, stream number xxxx  
  133. #define  SID_VIDEO_STREAM           0xE0 // 1110 xxxx, stream number xxxx  
  134. #define  SID_ECM_STREAM             0xF0  
  135. #define  SID_EMM_STREAM             0xF1  
  136. #define  SID_DSMCC_STREAM           0xF2  
  137. #define  SID_13522_STREAM           0xF3  
  138. #define  SID_TYPEA                  0xF4  
  139. #define  SID_TYPEB                  0xF5  
  140. #define  SID_TYPEC                  0xF6  
  141. #define  SID_TYPED                  0xF7  
  142. #define  SID_TYPEE                  0xF8  
  143. #define  SID_ANCILLARY_STREAM       0xF9  
  144. // 1111 1010 1111 1110, reserved data stream  
  145. #define  SID_PROGRAM_STREAM_DIRECTORY   0xFF  
  146.   
  147. // PES包中的可选包头部  
  148. struct optional_pes_header  
  149.  
  150.     bits  prefix                   2; // "10"  
  151.     bits  pes_scrambling_control   2;  
  152.     bits  pes_priority             1;  
  153.     bits  data_alignment_indicator 1;  
  154.     bits  copyright                1;  
  155.     bits  original_or_copy         1;  
  156.     // flags start  
  157.     bits  PTS_DTS_flags            2;  
  158.     bits  ESCR_flag                1;  
  159.     bits  ES_rate_flag             1;  
  160.     bits  DSM_trick_mode_flag      1;  
  161.     bits  additional_copy_info_flag: 1;  
  162.     bits  PES_CRC_flag             1;  
  163.     bits  PES_extension_flag       1;  
  164.     // flags end  
  165.     bits  pes_header_data_length   8;  
  166.     // WARNING!!! 目前只使用 PTS, DTS  
  167.     bits  PTS_H                    3;  // 32..30  
  168.     bits  PTS_M                    15; // 29..15  
  169.     bits  PTS_L                    15; // 14..0  
  170.     bits  DTS_H                    3;  // 32..30  
  171.     bits  DTS_M                    15; // 29..15  
  172.     bits  DTS_L                    15; // 14..0  
  173. };  
  174.   
  175. // PES包头部, 文档P43, 书P131  
  176. struct pes_header  
  177.  
  178.     bits  packet_start_code_prefix 24;  
  179.     bits  stream_id                8;  
  180.     bits  pes_packet_length        16;  
  181.     // 之后是optional PES header, 即任意包头, 它的有无由stream_id决定  
  182.     bool  ophdr_flag;  
  183.     optional_pes_header ophdr;  // 如果声明为指针, 会带来一些内存问题  
  184.     //byte*  es_data;   // 实际数据指针  
  185.     int   offset;   // 实际数据偏移  
  186.       
  187.     pes_header()  
  188.      
  189.         ophdr_flag false 
  190.         offset -1;  
  191.      
  192.     ~pes_header()  
  193.     {}  
  194. };  
  195.   
  196. //-----------------------------------------------------------------------------  
  197. // 位段结构调整函数  
  198. //-----------------------------------------------------------------------------  
  199. int adjust_ts_header(ts_header* pkt, byte* buff);  
  200. int adjust_ts_pat(ts_pat* pkt, byte* buff);  
  201. int adjust_ts_pmt(ts_pmt* pkt, byte* buff);  
  202. int adjust_ts_pes_header(pes_header* pkt, byte* buff);  
  203. __int64  get_pts_from_pes(pes_header& pkt);  
  204. __int64  get_dts_from_pes(pes_header& pkt);  
  205. #endif  
 
[cpp]  view plain copy
  1. //  
  2. //  
  3. //  TS流相关函数  
  4. //  
  5. //  
  6. #include <stdio.h>  
  7. #include "zzq_TS.h"  
  8.   
  9. int adjust_ts_header(ts_header* pkt, byte* buff)  
  10.  
  11.     if(pkt == NULL || buff == NULL)  
  12.       return 1;    
  13.     pkt->sync_byte buff[0];  
  14.     pkt->transport_error_indicator buff[1] >> 7;  
  15.     pkt->payload_unit_start_indicator buff[1] >> 0x01;  
  16.     pkt->transport_priority buff[1] >> 0x01;  
  17.     pkt->PID (buff[1] 0x1f)<<8 buff[2];  
  18.     pkt->transport_scrambling_control buff[3] >> 6;  
  19.     pkt->adaptation_field_control buff[3] >> 0x03;  
  20.     pkt->continuity_counter buff[3] 0x03;  
  21.     return 0;  
  22.  
  23.   
  24. int adjust_ts_pat(ts_pat* pkt, byte* buff)  
  25.  
  26.     if(pkt == NULL || buff == NULL)  
  27.       return 1;    
  28.     pkt->table_id buff[0];  
  29.     pkt->section_syntax_indicator buff[1] >> 7;  
  30.     pkt->zero buff[1] >> 0x1;  
  31.     pkt->reserved_1 buff[1] >> 0x3;  
  32.     pkt->section_length (buff[1] 0x0f) << buff[2];  
  33.     pkt->transport_stream_id buff[3] << buff[4];  
  34.     pkt->reserved_2 buff[5] >> 6;  
  35.     pkt->version_number buff[5] >> 0x1f;  
  36.     pkt->current_next_indicator (buff[5] << 7) >> 7;  
  37.     pkt->section_number buff[6];  
  38.     pkt->last_section_number buff[7];  
  39.     // get crc32  
  40.     int len pkt->section_length;  
  41.     pkt->crc32 (buff[len-4] 0x000000ff) << 24  
  42.                  (buff[len-3] 0x000000ff) << 16  
  43.                  (buff[len-2] 0x000000ff) <<   
  44.                  (buff[len-1] 0x000000ff);  
  45.     // get variable section  
  46.     for(int i=0; i<pkt->section_length-4-8; i+=4  
  47.      
  48.         ts_pat_section sec;  
  49.         sec.program_number buff[8+i] << buff[9];  
  50.         sec.reserved buff[10+i] >> 5;  
  51.         sec.PID (buff[10+i] << 3) << buff[11+i];  
  52.         if(sec.program_number == 0x0)  
  53.             pkt->network_section.push_back(sec);  
  54.         else  
  55.             pkt->pmt_section.push_back(sec);  
  56.      
  57.     return 0;  
  58.  
  59.   
  60. int adjust_ts_pmt(ts_pmt* pkt, byte* buff)  
  61.  
  62.     if(pkt == NULL || buff == NULL)   
  63.       return 1;    
  64.     pkt->table_id buff[0];  
  65.     pkt->section_syntax_indicator buff[1] >> 7;  
  66.     pkt->zero buff[1] >> 6;  
  67.     pkt->reserved_1 buff[1] >> 4;  
  68.     pkt->section_length (buff[1] 0x0f) << buff[2];  
  69.     pkt->program_number buff[3] << buff[4];  
  70.     pkt->reserved_2 buff[5] >> 6;  
  71.     pkt->version_number buff[5] >> 0x1f;  
  72.     pkt->current_next_indicator (buff[5] << 7) >> 7;  
  73.     pkt->section_number buff[6];  
  74.     pkt->last_section_number buff[7];  
  75.     pkt->reserved_3 buff[8] >> 5;  
  76.     pkt->PCR_PID ((buff[8] << 8) buff[9]) 0x1fff;  
  77.     pkt->reserved_4 buff[10] >> 4;  
  78.     pkt->program_info_length (buff[10] 0x0f) << buff[11];  
  79.     // get crc32  
  80.     int len pkt->section_length 3;  
  81.     pkt->crc32 (buff[len-4] 0x000000ff) << 24  
  82.                  (buff[len-3] 0x000000ff) << 16  
  83.                  (buff[len-2] 0x000000ff) <<   
  84.                  (buff[len-1] 0x000000ff);  
  85.     // skip program description  
  86.     int pos 12 pkt->program_info_length;  
  87.     forpos <= (pkt->section_length-4); pos+=5)  
  88.      
  89.         ts_pmt_es_section sec;  
  90.         sec.stream_type buff[pos];  
  91.         sec.reserved_1 buff[pos+1] >> 5;  
  92.         sec.elementary_PID ((buff[pos+1] << 8) buff[pos+2]) 0x1fff;  
  93.         sec.ES_info_length (buff[pos+3] 0x0f) << buff[pos+4];  
  94.         pkt->es_section.push_back(sec);  
  95.         pos += sec.ES_info_length;  
  96.      
  97.     return 0;  
  98.  
  99.   
  100. int adjust_ts_pes_header(pes_header* pkt, byte* buff)  
  101.  
  102.     if(pkt == NULL || buff == NULL)   
  103.       return 1;    
  104.     // 0000 0000 0000 0000 0000 0001 0x000001  
  105.     pkt->packet_start_code_prefix (buff[0] 0x0000ff) << 16  
  106.                                     (buff[1] 0x0000ff) <<   
  107.                                     (buff[2] 0x0000ff);  
  108.     //if(pkt->packet_start_code_prefix != 0x000001)  return 2;  
  109.     byte sid buff[3]; // aux  
  110.     pkt->stream_id buff[3];  
  111.     pkt->pes_packet_length buff[4] << buff[5];  
  112.     if(sid != SID_PROGRAM_STREAM_MAP &&  
  113.        sid != SID_PADDING_STREAM &&  
  114.        sid != SID_PRIVATE_STREAM_2 &&  
  115.        sid != SID_ECM_STREAM &&  
  116.        sid != SID_EMM_STREAM &&  
  117.        sid != SID_PROGRAM_STREAM_DIRECTORY &&  
  118.        sid != SID_DSMCC_STREAM &&  
  119.        sid != SID_TYPEE  
  120.        
  121.      
  122.         pkt->ophdr_flag true 
  123.         pkt->ophdr.prefix buff[6] >> 6; // "10" 2  
  124.         //if(pkt->ophdr->prefix != 2) return 2;  
  125.         pkt->ophdr.pes_scrambling_control buff[6] >> 0x03;  
  126.         pkt->ophdr.pes_priority buff[6] >> 0x01;  
  127.         pkt->ophdr.data_alignment_indicator buff[6] >> 0x01;  
  128.         pkt->ophdr.copyright buff[6] >> 0x01;  
  129.         pkt->ophdr.original_or_copy buff[6] 0x01;  
  130.         pkt->ophdr.PTS_DTS_flags buff[7] >> 0x03;  
  131.         pkt->ophdr.ESCR_flag buff[7] >> 0x01;  
  132.         pkt->ophdr.ES_rate_flag buff[7] >> 0x01;  
  133.         pkt->ophdr.DSM_trick_mode_flag buff[7] >> 0x01;  
  134.         pkt->ophdr.additional_copy_info_flag buff[7] >> 0x01;  
  135.         pkt->ophdr.PES_CRC_flag buff[7] >> 0x01;  
  136.         pkt->ophdr.PES_extension_flag  buff[7] 0x01;  
  137.         pkt->ophdr.pes_header_data_length buff[8];  
  138.         if(pkt->ophdr.PTS_DTS_flags == 0x2) // "10"  
  139.          
  140.             // 以下移位操作, 都将各位串靠左对齐  
  141.             pkt->ophdr.PTS_H buff[9] << 0xe0; // bits  
  142.             pkt->ophdr.PTS_M (buff[10] << 8) (buff[11] 0xfe); // 15 bits  
  143.             pkt->ophdr.PTS_L (buff[12] << 8) (buff[13] 0xfe); // 15 bits  
  144.          
  145.         else if(pkt->ophdr.PTS_DTS_flags == 0x3) // "11"  
  146.          
  147.             // 以下移位操作, 都将各位串靠左对齐  
  148.             pkt->ophdr.PTS_H buff[9] << 0xe0; // bits  
  149.             pkt->ophdr.PTS_M (buff[10] << 8) (buff[11] 0xfe); // 15 bits  
  150.             pkt->ophdr.PTS_L (buff[12] << 8) (buff[13] 0xfe); // 15 bits  
  151.             pkt->ophdr.DTS_H buff[14] << 0xe0;  
  152.             pkt->ophdr.DTS_M (buff[15] << 8) (buff[16] 0xfe); // 15 bits  
  153.             pkt->ophdr.DTS_L (buff[17] << 8) (buff[18] 0xfe); // 15 bits  
  154.          
  155.         //  
  156.         //  ESCR, ES_rate之类的目前不处理  
  157.         // 3: (24+8+16) (2+2+1+1+1+1+8+8)  
  158.         pkt->offset pkt->ophdr.pes_header_data_length;  
  159.      
  160.     else if(sid == SID_PROGRAM_STREAM_MAP ||  
  161.             sid == SID_PRIVATE_STREAM_2 ||  
  162.             sid == SID_ECM_STREAM ||  
  163.             sid == SID_EMM_STREAM ||  
  164.             sid == SID_PROGRAM_STREAM_DIRECTORY ||  
  165.             sid == SID_DSMCC_STREAM ||  
  166.             sid == SID_TYPEE  
  167.             
  168.      
  169.         pkt->offset 6;  
  170.      
  171.     else if(sid == SID_PADDING_STREAM)  
  172.      
  173.         pkt->offset -1;  
  174.      
  175.       
  176.     return 0;  
  177.  
  178.   
  179. __int64  get_pts_from_pes(pes_header& pkt)  
  180.  
  181.     if(pkt.ophdr_flag == falsereturn -1;  
  182.     if(pkt.ophdr.PTS_DTS_flags != 0x2 && pkt.ophdr.PTS_DTS_flags != 0x3)  
  183.         return -1;  
  184.     __int64 0, 0, 0;  
  185.     pkt.ophdr.PTS_L >> pkt.ophdr.PTS_M << 14;  
  186.     pkt.ophdr.PTS_M >> pkt.ophdr.PTS_H << 13;  
  187.     pkt.ophdr.PTS_H >> 3;  
  188.     return (H<<32) (M<<16) L;  
  189.  
  190. __int64  get_dts_from_pes(pes_header& pkt)  
  191.  
  192.     if(pkt.ophdr_flag == falsereturn -1;  
  193.     if(pkt.ophdr.PTS_DTS_flags != 0x3)  
  194.         return -1;  
  195.     __int64 0, 0, 0;  
  196.     pkt.ophdr.DTS_L >> pkt.ophdr.DTS_M << 14;  
  197.     pkt.ophdr.DTS_M >> pkt.ophdr.DTS_H << 13;  
  198.     pkt.ophdr.DTS_H >> 3;  
  199.     return (H<<32) (M<<16) L;  

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值