解析TS流PAT和PMT 代码
- 格式:doc
- 大小:58.00 KB
- 文档页数:10
TR101-290三级错误、PSI/SI、PCR分析描述DVB系统测量标准之一TR 101-290定义的三个优先级,是码流监测的一项主要内容。
通过这三个优先级的监测,可以检验被监测的码流是否符合MPEG-2和DVB标准。
这三个优先级都包含许多不同的参数。
一、TR 101-290的第一优先级1、同步错误(TS Sync Loss)同步错误是衡量传输流质量的最重要的指标。
传输流失去同步,表明传输过程中有一部分数据丢失,将直接影响画面显示的质量。
严重的同步丢失现象则表明传输中断,同步字节出现错误。
2、同步字节错误(Sync Byte Error)同步字节错误和同步错误的区别在于传输数据包长为188字节或204字节,但同步字头的标准值为0×47,当出现同步字节错误时,同步字头的值为其他数值,表明在传输过程中部分数据出现错误,可能导致接收时出现马赛克,严重时导致解码器和DISPLAY软件解不出信号。
3、包识别丢失(PID Mssing)检测数据流中各套电视节目的图像/声音数据是否正确。
PID丢失,将导致DISPLAY软件无法正确解码这套节目。
4、节目相关表(PAT)PAT在DVB标准中用于指示当前节目及其在数据流中的位置。
PA T丢失,将导致解码器无法搜索到相应的节目包,使得接收端收不到图像。
如果PA T超时,则解码器工作时间延长。
5、节目对照表(PMT)PMT在DVB标准中用于指示该套节目视/音频数据在传输流中的位置。
某一套节目的PMT丢失,将导致解码器找不到该套节目视/音频数据,使得接收端收不到图像或声音。
PMT 传输超时,DISPLAY软件无法显示这套节目。
6、连续计数错误(Cont Count Error)对于每一套节目的视/音频数据包而言,连续计数错误是一个很重要的指标。
传输流包头连续计数不正确,表明当前传输流有丢包、错包、包重叠等现象,将导致解码器或DISPLAY 软件不能正确解码,图像出现马赛克等现象。
[ts 码流解析 ] ETSI TR101 290 监测的三种级别错误对于码流解析仪所供应 ETSI TR101 290 监测的三种级别错误,接收端将会出现以下现象。
级别 错误种类接收端现象同步丧失错 黑屏、静帧和马赛克、画面不流畅现 一象级 同步字节错 黑屏、静帧和马赛克、画面不流畅现 错 象误PAT 错误 找寻不到节目或节目找寻错误 连续计数错 马赛克PMT 间隔错误 找寻不到节目或节目找寻错误 PMT 加扰错误 找寻不到节目或节目找寻错误PID 错误 黑屏、静帧、马赛克等所有异常现象 传达错误黑屏、静帧和马赛克、画面不流畅现象二 CRC 错误黑屏、静帧和马赛克、画面不流畅现 级象错 PCR 间隔错误 视音频不相同步或图象颜色丧失 误PCR 非连续标志错 视音频不相同步或图象颜色丧失 PCR 抖动错误 视音频不相同步或图象颜色丧失 PTS 错误音视频不相同步TS 包加扰错 只对加扰节目有影响,为略微错误 CAT 错误无法正确办理 CA 信息,为略微错误NIT ID 错误 无异常现象,码流解析仪的三级错误 三NIT 间隔错误为略微错误。
级 NIT 其他错误错SI 重复率错误缓冲器错非指定 PID 错SDT ID 错SDT 当前间隔错SDT 其他间隔错 EIT ID 错EIT 当前间隔错 EIT 其他间隔错EIT PF 错 RST 错误TDT 错误空缓冲器错误数据延缓错误TR101-290: DVB系统测量标准TR101-290: DVB系统测量标准。
TR 101-290定义的三个优先级,是码流监测的一项主要内容。
经过这三个优先级的监测,能够检验被监测的码流可否吻合MPEG-2和DVB标准。
这三个优先级都包含好多不相同的参数。
PSI/SI: 数字电视业务信息,由 PSI 和 SI 两局部组成。
PSI 是 MPEG-2规定的,它由PAT 、 PMT 、CAT 和 NIT 4个表组成,其中PAT 、PMT 表最为重要。
PMT (Program Map Table) 节目映射表Meaning of PMT - "Program Map Table". A Program Specific Information table that supplies basic information about the services present in an Moving Pictures Experts Group 2 (MPEG-2) transport stream. The PMT lists all of the packet IDs (PID) for packets containing elements of a particular program such as audio, video, aux data, and Program Clock Reference (PCR). Packets in the same elementary stream all have the same PID and the decoder can select the elementary stream or streams it wants and reject the remainder. Also carried in the metadata is the information that some programs will be open and some may be subject to encryption节目映射表:数字电视与传统模拟电视节目选择的方式完全不同,传统电视的每一个频道对应一个节目,只要调到相应的频率,就可以看到节目。
而在数字电视信号中,一路码流对应多路节目,使用复用技术就可以做到了。
一个物理的频道只能给出包含多路节目的一路传输流。
要观看其中的某一路节目,还必须从该传输流中提取出该路节目的压缩包,然后再进行解码。
ts码流结构分析TS(Transport Stream)是一种常用的音视频码流传输格式,用于在数字广播系统和互联网传输中对音视频数据进行分组和传输。
TS码流结构分析指的是对TS码流的组成部分进行分析,了解各部分的作用和关系。
以下是对TS码流结构的详细分析。
TS码流由多个188字节的包(Packet)组成,每个包都包含了一部分音视频数据。
一个TS包由4个字节的同步字节(Sync Byte)开头,用于标识包的开始。
接下来的4位为传输误码纠正(Error Correction)信息,用于保证传输数据的完整性和准确性。
再接下来的1位为负荷优先级(Payload Unit Start Indicator),用于标识包中是否包含了新的数据单元。
然后是13位的PID(Packet Identifier),用于标识包中所包含的数据单元的类型。
接下来的2位为传输加密(Transport Scrambling Control),用于指定包中数据的加密方式。
再接下来的2位为控制报文(Adaptation Field Control),用于指定包中的控制信息是否存在。
最后的184字节为有效数据(Payload),用于传输音视频数据。
每个TS包中的PID用于标识包中所包含的数据单元的类型,常见的PID值有0x0000(PAT:Program Association Table)、0x0001(CAT:Conditional Access Table)、0x0010(NIT:Network Information Table)、0x0011(SDT:Service Description Table)等。
PAT表包含了整个TS流的所有节目以及对应的PMT(Program Map Table)的PID值。
CAT表用于传递整个TS流中的加密和访问控制信息。
NIT表用于传递整个TS流中的网络信息,包括网络ID和传输参数。
SDT表用于传递整个TS流中的节目信息,包括节目名称和节目号码。
#include <stdio.h>#include <stdlib.h>#include<string.h>int parse_TS(unsigned char *buffer, int FileSize);void parse_PAT(unsigned char *buffer, int len);unsigned char* Find_PMT(unsigned short pmt_pid);void parse_PMT(unsigned char *buffer, int len, unsigned short pmt_pid); void Read_Ts_Packet(FILE *file_handle ,unsigned char *packet_buf, int len); void pronum_pmtid_printf();void printf_prog_list();typedef struct {unsigned short program_num; //节目编号unsigned short pmt_pid; //节目对应的PMT表的PID}PROGRAM;typedef struct{unsigned char stream_type; //节目元素包类型unsigned short elementary_pid; //元素对应的pid}PRO_LIST;PROGRAM programs[10] = { {0,0} };unsigned int num = 0; //总的节目数PRO_LIST program_list[20] = { {0,0} };unsigned int p_list_num = 0;FILE *file_handle;unsigned int FileSize = 0;int main(){unsigned char buffer[188] = {0};unsigned char *pmt_buffer = NULL;unsigned int i = 0, j =0, ret = 0;file_handle = fopen("435.ts", "rb");if(file_handle == NULL){printf("open file error!\n");return 0;}elseprintf("open file success!\n");fseek( file_handle, 0, SEEK_END );FileSize = ftell( file_handle ); //求文件的长度(字节)。
传送流(TS)的基础知识数字电视的TS包和TS流的组成和功能综合考虑⼏下⼏个因素:(1)包的长度不能过短,否则包头开销所占⽐例过⼤,导致传输效率下降(2)包的长度不能过长,否则在丢失同步的情况下恢复同步的周期过长,导致较多的信息丢失(3)其他环境相适配,如纠错编码,宽带⽹等。
TS包按功能分为链接头,适配域,净荷。
链接头的长度固定,4个字节适配域的长度从0字节到184字节可变,可以没有,也可以扩展到整个TS包净荷数据的长度从0字节到184字节可变。
整个TS流是由许多长度为188字节的TS包周期性的排列⽽形成的。
ts包头包含4个字节的内容,主要负责TS包的同步、各种ES流的表⽰、TS包传输差错的检测和条件接收等功能。
(1)包同步(syn_bate)是包中的第⼀个字节,TS包以固定的8bit的同步字节开始,所有的TS传送包,同步字都是唯⼀的OX47,⽤于建⽴发送端和接收端包的同步。
(2)包差错指⽰(transport_error_indicator)⽤于从解码器向分接器指⽰传输误码。
若这个⽐特被设置,表⽰此TS包中所携带的净荷信息有错误,⽆法使⽤。
(3)净荷单元起始指⽰(payload_uint_start_indicator)标志PES包头以及包含节⽬特定信息的表(PMT,PAT)的头是否出现在该包中,在失步后的重新同步中起着重要的作⽤。
(4)传送优先级(transport_priority)⽤于表⽰包中含有重要数据,应予以优先传送。
(6)加扰控制(transport_scrambling_control)传送信息通过加⼊扰码来加密,各个基本码流可以独⽴进⾏加扰。
加扰控制字段说明TS包中的净荷数据是否加扰。
如果加扰,标志出解扰的密匙。
(5)包标识符PID(pid)PID是识别TS包的重要参数,⽤来识别TS包所承载的数据。
在TS码流⽣成时,每⼀类业务(视频,⾳频,数据)的基本码流均被赋予⼀个不同的识别号PID,解码器借助于PID判断某⼀个TS包属于哪⼀类业务的基本码流。
便携式IPTV测试仪TS码流解析的实现便携式IPTV测试仪是一种用于测试和分析IPTV系统性能的设备。
它可以通过对传输流中的TS码流进行解析和分析,提供关于传输质量、视频质量、音频质量等方面的信息。
下面将介绍便携式IPTV测试仪TS码流解析的实现过程。
首先,便携式IPTV测试仪需要具备对TS码流解析的功能,这需要通过硬件和软件的结合来实现。
硬件方面,测试仪需要具备高性能的处理器和足够的存储空间来处理和存储大量的数据。
同时,测试仪需要具备支持高速数据传输的接口,例如千兆以太网接口。
软件方面,测试仪需要具备强大的编解码功能,能够对TS码流进行解析和分析。
在实现过程中,首先需要从IPTV系统中获取到传输的TS码流。
通常,这可以通过测试仪的网络接口连接到IPTV系统中的交换机或路由器上,然后通过ARP、DHCP等协议获取到IPTV系统分配给测试仪的IP地址和相关配置信息。
获取到IP地址后,测试仪就可以通过该地址与IPTV系统建立TCP/IP连接,并获取到传输的TS码流。
获取到TS码流后,测试仪需要对其进行解析。
TS码流是一种多路复用的码流格式,其中包含多个音视频流、字幕、EPG等信息。
测试仪需要通过解析TS码流,将其中的各个流分离出来,并进行相应的解码处理。
这可以通过测试仪上的解码器来实现,解码器可以将TS码流中的音视频数据进行解码,并输出为可播放的音视频信号。
在解析TS码流的过程中,测试仪可以获取到各个流的相关信息。
例如,测试仪可以通过解析PAT(Program Association Table)和PMT (Program Map Table)信息,获取到TS码流中包含的节目信息。
同时,测试仪还可以通过解析PCR(Program Clock Reference)信息,获取到TS码流的传输时钟参考,用于判断流的同步状态。
除了对TS码流的解析,测试仪还可以对解析后的音视频数据进行质量分析。
通过分析视频数据的码率、帧率、分辨率等参数,测试仪可以评估视频的质量。
TS协议解析范文TS协议(Transport Stream Protocol)是一种用于传输音频、视频和数据的通信协议。
它是MPEG(Moving Picture Experts Group)组织制定的一种传输标准,广泛用于数字广播和数字电视等领域。
TS协议主要通过分组方式将音视频数据进行打包、传输和解析,下面将对TS协议的解析进行详细介绍。
一、TS协议概述TS协议是一种基于分组传输的协议,它将音视频数据进行分组打包,每个分组的大小为188字节。
每个分组都包含了一个称为PacketIdentifier(PID)的标识符,用于标识不同的流。
TS协议可以同时传输多个音视频流和数据流,每个流对应一个唯一的PID。
其中,音频流和视频流采用连续的PID进行标识,数据流则可以采用任意的PID。
TS协议还支持通过PAT(Program Association Table)和PMT(Program Map Table)来描述和管理不同的音视频流。
二、TS协议分组结构TS协议的分组结构非常重要,它决定了数据的组织方式和传输方式。
每个TS分组由4字节的同步字节开始,之后是连续的184字节的有效数据和4字节的错误检测码(CRC32)。
TS分组的有效数据包括了多个TS数据包。
TS数据包由4字节的同步字节和184字节的有效负载组成。
同步字节用于标识分组的开始,有效负载则包含了音视频数据和控制信息。
三、TS协议的传输和解析TS协议的传输过程分为打包、传输和解析三个步骤。
首先,音视频数据被打包成TS分组的形式。
在打包过程中,音频和视频流被分别编码和打包,并通过不同的PID进行标识。
每个分组的PID决定了数据的类型和对应的解析方式。
然后,打包后的TS分组通过传输媒介进行传输。
常用的传输媒介包括卫星、有线和无线网络等。
TS分组通过传输媒介被传输到接收端,并进行解析。
最后,接收端根据TS分组的PID进行解析。
首先,接收端解析PAT 表,获取各个音视频流的PID。
视频播放的基本原理当初看VLC代码花了不少时间,其中很大的原因是不太了解视频播放的基本原理。
现在看来,几乎所有的视频播放器,如VLC、MPlayer、Xine,包括DirectShow,在播放视频的原理和架构上都是非常相似的,理解这个对理解VLC的源码会有事半功倍的效果。
大致的来说,播放一个视频分为4个步骤:1. acess 访问,或者理解为接收、获取、得到2. demux 解复用,就是把通常合在一起的音频和视频分离(还有可能的字幕)3. decode 解码,包括音频和视频的解码4. output 输出,也分为音频和视频的输出(aout和vout)拿播放一个UDP组播的MPEG TS流来说吧,access部分负责从网络接收组播流,放到VLC的内存缓冲区中,access模块关注IP协议,如是否IPv6、组播地址、组播协议、端口等信息;如果检测出来是RTP协议(RTP协议在UDP头部简单得加上了固定12个字节的信息),还要分析RTP头部信息。
这部分可以参看VLC源码/modules/access/udp.c 。
在同目录下还可以看到大量的access模块,如file、http、dvd、ftp、smb、tcp、dshow、mms、v4l…等等而demux部分首先要解析TS流的信息。
TS格式是MPEG2协议的一部分,概括地说,TS通常是固定188字节的一个packet,一个TS流可以包含多个program(节目),一个program 又可以包含多个视频、音频、和文字信息的ES流;每个ES流会有不同的PID标示。
而又为了可以分析这些ES流,TS有一些固定的PID用来间隔发送program和es流信息的表格:PA T和PMT表。
关于TS格式的详细信息可以去google一下。
VLC专门做了一个独立的库libdvbpsi来解析和编码TS流,而调用它的代码可以参见VLC源码/modules/demux/ts.c。
其实之所以需要demux,是因为音视频在制作的时候实际上都是独立编码的,得到的是分开的数据,为了传输方便必须要用某种方式合起来,这就有了各种封装格式也就有了demux。
介绍DVB-S码流,PAT,PMT,NIT,CAT摘要本文介绍了电子节目指南信息的构成以及MPEG-2 PSI和DVB-SI信息规范,提出了一种EPG信息的存储结构和节目数据库的生成方案,并据此讲述了如何在数字有线电视机顶盒中生成电子节目指南EPG。
关键词机顶盒 MPEG-2 PSI节目专用信息 DVB-SI业务信息电子节目指南1 引言目前数字电视已经进入快速发展阶段,与数字电视相关的业务也将大幅度增长。
当节目运营商将大量的节目信息通过有线网络提供给用户,用户在欣赏高质量节目源的同时如何才能方便快捷地找到这些业务或信息就成了开发者们需要解决的一个关键问题。
电子节目指南(EPG,Electronic Program Guide)正是为了方便用户对信息的获取而制作的运行于用户端综合接收解码器(IRD,Integrated Receiver Decoder)的应用程序,它通过电视屏幕向用户提供由文字、图形、图像组成的人机交互界面,负责电视节目和各种业务的导航[1]。
用户通过电子节目指南,能够了解到节目的相关信息(包括节目时间、播放时间、内容梗概等),并且实现对节目的快速检索和访问。
EPG的形成依赖于节目播出前端将符合DVB(Digital Video Broadcasting)标准的业务信息(SI,Service Information)插入到承载节目信息的传送流(TS,Transport Stream)中,这些SI信息携带了EPG所需的全部数据。
2 电子节目指南信息的组成和传输电子节目指南信息(以下简称EPG信息)由两部分组成:基本EPG信息和扩展EPG信息。
基本EPG信息是指完全可以用《数字广播业务信息规范(GY/Z174-2001)》中的网络信息表NIT、业务群关联表BAT、业务描述表SDT、事件信息表EIT等进行描述的EPG信息。
扩展EPG信息是指在基本EPG信息之外,通过数据轮播传递的EPG信息,这些信息的入口采用EPG映射表EMT进行描述,信息的内容被封装成具有多级目录结构的文件系统,称为扩展EPG内容信息(XECI)。
HLS,Http Live Streaming是由Apple公司定义的用于实时流传输的协议,HLS基于HTTP 协议实现,传输内容包括两部分,一是M3U8描述文件,二是TS媒体文件。
1、M3U8文件用文本方式对媒体文件进行描述,由一系列标签组成。
#EXTM3U#EXT-X-TARGETDURATION:5#EXTINF:5,./0.ts#EXTINF:5,./1.ts#EXTM3U:每个M3U8文件第一行必须是这个tag。
#EXT-X-TARGETDURATION:指定最大的媒体段时间长度(秒),#EXTINF中指定的时间长度必须小于或等于这个最大值。
该值只能出现一次。
#EXTINF:描述单个媒体文件的长度。
后面为媒体文件,如./0.ts2、ts文件ts文件为传输流文件,视频编码主要格式h264/mpeg4,音频为acc/MP3。
ts文件分为三层:ts层Transport Stream、pes层 Packet Elemental Stream、es层 Elementary Stream. es层就是音视频数据,pes层是在音视频数据上加了时间戳等对数据帧的说明信息,ts层就是在pes层加入数据流的识别和传输必须的信息注:详解如下(1)ts层ts包大小固定为188字节,ts层分为三个部分:ts header、adaptation field、payload。
ts header固定4个字节;adaptation field可能存在也可能不存在,主要作用是给不足188字节的数据做填充;payload是pes 数据。
ts headerts层的内容是通过PID值来标识的,主要内容包括:PAT表、PMT表、音频流、视频流。
解析ts流要先找到PAT表,只要找到PAT就可以找到PMT,然后就可以找到音视频流了。
PAT表的PID值固定为0。
PAT表和PMT表需要定期插入ts流,因为用户随时可能加入ts流,这个间隔比较小,通常每隔几个视频帧就要加入PAT和PMT。
更具体准确的信息请参考iso13818-1,都在里面定义的PAT的定义:Table_id:为8bit字段,该字段标识节目关联分段,对于PAT,置为0x00。
Section_syntax_indicator:1bit字段,对于PAT,置为0x01。
Reserved:2bit保留字段,用于将来扩展,置为11。
Section_length:12bit字段,指示当前section的长度,计数值从分段长度下一个字节开始,包括CRC校验的4个字节,开头两位置为00,因此其大小不超过1021。
Transport_stream_id:16bit字段,当前TS流的ID,与网络中其他TS流相区别,由运营商指定。
Reserved:2bit保留字段,用于将来扩展,置为11。
Version_number:5bit字段,指出PAT表的版本号,一旦PAT表有变化,其版本号增1,当增至31时,恢复至0。
Current_next_indicator:1bit,置为1时,表示传送的PAT当前有效,置为0表示PAT下一次有效。
Section_number:8bit字段,表示section的数目,从0x00开始。
Last_section_number:8bit字段,指出最后一个section号,即PAT表section的最大数目。
Program_number:16bit字段,指出了节目对于哪一个PMTPID是可用的,当为0x00时,后面的PID对应于NIT。
Reserved:3bit保留字段,用于将来扩展,置为111。
Network_id:13bit字段,NIT PID。
Program_map_PID:13bit字段,对应于program_number所指定的节目的program_map_section的PID,从上面可看出:一个program用4字节来表示(包括16bit的program_number与13bit的PID)。
CRC:用来证实数据正确性的循环冗余校验码。
#include<stdio.h>#include<stdlib.h>#include<string.h>#define ts_path "/home/huohuo/huangwork/work/birds.ts" //TS文件的绝对路径void Read_Ts_Packet(FILE *file_handle,unsigned char *packet_buf,int len); //读一个TS流的packetint parse_TS(unsigned char *buffer,int FileSize); //分析TS流,并找出PA T的PID和PAT的tablevoid parse_PAT(unsigned char *buffer,int len); //分析PA T,并找出所含频道的数目和PMT的PIDvoid pronum_pmtid_printf(); //打印PMT的PID unsigned char* Find_PMT(unsigned short pmt_pid); //找出PMT的tablevoid parse_PMT(unsigned char *buffer,int len,unsigned short pmt_pid); //解析PMT,找出其中的Video和Audio的PIDvoid printf_program_list(); //打印PMT table中包含的stream的类型和PIDunsigned char* Find_video_audio(unsigned short program_pid,unsigned char type); //找出Video或者Audio的tabletypedef struct{unsigned short program_num; //program's numunsigned short pmt_pid; //}PROGRAM;typedef struct{unsigned char stream_type;unsigned short elementary_pid;}PRO_LIST;PROGRAM programs[10] = {{0,0}}; //用来存储PMT的PID和数量unsigned int num = 0; //total programPRO_LIST program_list[10] = {{0,0}}; //用来存储PMT中stream的类型和PIDunsigned int program_list_num = 0;FILE *file_handle; //指向TS流的指针unsigned int FileSize = 0;int main(){unsigned char buffer[188] = {0};unsigned char *pmt_buffer, *Video_or_Audio_buffer;unsigned int i=0,j=0,ret=0;pmt_buffer = (unsigned char*)malloc(sizeof(char)*188); //给buffer分配空间memset(pmt_buffer,0,sizeof(char)*188);//清空bufferVideo_or_Audio_buffer = (unsigned char*)malloc(sizeof(char)*188);memset(Video_or_Audio_buffer,0,sizeof(char)*188);file_handle = fopen(ts_path,"rb+"); //以二进制方式打开TS文件if(NULL == file_handle) //判断是否打开文件{perror("fopen");printf("open file error!\n");return 0;}elseprintf("open file success!\n");fseek(file_handle,0,SEEK_END); //指针file_handle将以SEEK_END位置偏移0个位置,即将指针移动到文件尾FileSize = ftell(file_handle); // 计算file_handle到文件头的偏移字节数,即计算文件的大小printf("file size = %d\n",FileSize);rewind(file_handle); // equivalent (void) feek(file_handle,0L,SEEK_SET) 将file_handle 指针移动到文件头位置printf("find PAT begin-------->\n");for(i=0;i<FileSize/188;i++){Read_Ts_Packet(file_handle,buffer,188); //读TS的packet函数,每次读188个字节到bufferret = parse_TS(buffer,188); //解析188个字节的TS's packet,并打印找到的PA T’s table。
如果解析成功即找到PA T,则返回1,否则返回0if(ret == 1){break;}else{printf("There is no PAT table!\n");}}if(ret == 1){parse_PAT(buffer,188); //解析PAT,并找出所含频道的数目和PMT的PID }pronum_pmtid_printf(); //打印PMT的PIDrewind(file_handle);printf("find PMT begin -------->\n");for(i=0;i<num;i++){pmt_buffer = Find_PMT(programs[i].pmt_pid); //根据PMT的PID找到PMT's tableprintf("PMT table -------->\n");for(j=0;j<188;j++){printf("0x%x ",pmt_buffer[j]); //打印PMT}if(pmt_buffer){parse_PMT(pmt_buffer,188,programs[i].pmt_pid); //解析找到的PMT,得到Video、Audio等的PID}memset(pmt_buffer,0,sizeof(char)*188);printf("\n");}printf_program_list(); //打印elementary 流的PID和type。
rewind(file_handle);printf("find Audio and Video begin-------->\n");for(i=0;i<program_list_num;i++){Video_or_Audio_buffer = Find_video_audio(program_list[i].elementary_pid,program_list[i].stream_type); //根据PID找到elementary流printf("the program's PID is 0x%x\n",program_list[i].elementary_pid);printf("the program's Table --------->\n");for(j=0;j<188;j++){printf("0x%x ",Video_or_Audio_buffer[j]); //打印elementary's table }memset(Video_or_Audio_buffer,0,sizeof(char)*188);printf("\n");}free(pmt_buffer);free(Video_or_Audio_buffer);pmt_buffer = NULL;Video_or_Audio_buffer = NULL;fclose(file_handle);printf("\n");return 1;}/*************************************************** read one TS packet's data* *************************************************/void Read_Ts_Packet(FILE *file_handle,unsigned char *packet_buf,int len){fread(packet_buf,188,1,file_handle);}int parse_TS(unsigned char *buffer,int FileSize){unsigned char *temp = buffer;short pat_pid;int i = 0;if(buffer[0] != 0x47){printf("it's not a ts packet!\n");return 0;}while(temp < buffer + FileSize){pat_pid = (temp[1] & 0x1f)<<8 | temp[2];if(pat_pid != 0)printf("finding PAT table ....\n");else{printf("already find the PA T table\n");printf("pat_pid = 0x%x\n",pat_pid);printf("pat table ------->\n");for(i=0;i<=187;i++){printf("0x%x ",buffer[i]);}printf("\n");return 1;}temp = temp + 188;}return 0;}/******************************************************** parse PAT table, get the PMT's PID* ********************************************************/ void parse_PAT(unsigned char *buffer,int len){unsigned char *temp, *p;char adaptation_control;int adaptation_length,i=0;unsigned short section_length,prg_No,PMT_Pid;temp = buffer;adaptation_control = temp[3] & 0x30;if(adaptation_control == 0x10)temp = buffer + 4 + 1;else if (adaptation_control == 0x30){adaptation_length = buffer[4];temp = buffer + 4 + 1 +adaptation_length + 1; }else{return ;}section_length = (temp[1]&0x0f)<<8 | temp[2];p = temp + 1 +section_length;temp = temp + 8;while(temp < p - 4){prg_No = (temp[0]<<8) | (temp[1]);if(prg_No == 0){temp = temp + 4;continue;}else{PMT_Pid = (temp[2]&0x1f)<<8 | temp[3];programs[num].program_num = prg_No;programs[num].pmt_pid = PMT_Pid;// printf("pmt_pid is ox%x\n", PMT_Pid);num ++;temp = temp + 4;}}}void pronum_pmtid_printf(){unsigned int i;printf("PAT table's program_num and PMT's PID:\n");for(i=0;i<num;i++){printf("program_num = 0x%x (%d),PMT_Pid = 0x%x (%d)\n",programs[i].program_num,programs[i].program_num,programs[i].pmt_pid,programs[i].pmt_pid);}}void printf_program_list(){unsigned int i;printf("All PMT Table's program list: \n");for(i=0;i<program_list_num;i++){printf("stream_type = 0x%x, elementary_pid = 0x%x\n",program_list[i].stream_type,program_list[i].elementary_pid);}printf("\n");}unsigned char* Find_PMT(unsigned short pmt_pid){unsigned int i=0,j=0;int pid;unsigned char *buffer;buffer = (unsigned char *)malloc(sizeof(char)*188);memset(buffer,0,sizeof(char)*188);rewind(file_handle);for(j=0;j<FileSize/188;j++){Read_Ts_Packet(file_handle,buffer,188);if(buffer[0] != 0x47){printf("It's not TS packet !\n");}else{pid = (buffer[1] & 0x1f)<< 8 | buffer[2];if(pid == pmt_pid){printf("PMT Table already find!\n");return buffer;}elseprintf("finding PMT table.......\n");}}}unsigned char* Find_video_audio(unsigned short program_pid,unsigned char type) {unsigned int i = 0, j = 0 ;int pid;unsigned char *buffer;buffer = (unsigned char *)malloc(sizeof(char)*188);memset(buffer,0,sizeof(char)*188);rewind(file_handle);for(j=0;j<FileSize/188;j++){Read_Ts_Packet(file_handle,buffer,188);if(buffer[0] != 0x47){printf("It's not TS packet !\n");}else{pid = (buffer[1] & 0x1f)<< 8 | buffer[2];if(program_pid == pid){if(type == 0x02)printf("Find a program and this program is Video type!\n");else if(type == 0x03)printf("Find a program and this program is Audio type!\n");elseprintf("Find a program but this program is other type !\n");return buffer;}elseprintf("finding Video or Audio table.....\n ");}}}void parse_PMT(unsigned char *buffer,int len,unsigned short pmt_pid){unsigned char *temp, *p;char adaptation_control;int adaptation_length,i=0;int program_info_length;int ES_info_length;unsigned short section_length,pid;temp = buffer;adaptation_control = temp[3] & 0x30;if(adaptation_control == 0x10){temp = buffer + 4 +1;}else if (adaptation_control == 0x30){adaptation_length = buffer[4];temp = buffer + 5 + adaptation_length + 1;}elsereturn;section_length = (temp[1]&0x0f)<<8 | temp[2];p = temp + 1 + section_length;// temp = temp + 10;program_info_length = (temp[10] & 0x0f) << 8 | temp[11];temp = temp + 12 + program_info_length ;for(;temp < p - 4;){program_list[program_list_num].stream_type = temp[0],program_list[program_list_num].elementary_pid = (temp[1]&0x1f) << 8 | temp[2];ES_info_length = (temp[3]&0x0f) << 8 | temp[4];temp = temp + 4 + ES_info_length + 1;program_list_num ++ ;}}。