简单解析PAT、PMT的程序
刚开始学习有关TS、PAT、PMT方面的内容,参考了别人的一些程序,然后写了一个简单的解析TS的小程序。如果有地方错误,请发邮件给我843036544@qq.com。
#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流的packet
int parse_TS(unsigned char *buffer,int FileSize); //分析TS流,并找出PAT的PID和PAT的table
void parse_PAT(unsigned char *buffer,int len); //分析PAT,并找出所含频道的数目和PMT的PID
void pronum_pmtid_printf(); //打印PMT的PID
unsigned char* Find_PMT(unsigned short pmt_pid); //找出PMT的table
void parse_PMT(unsigned char *buffer,int len,unsigned short pmt_pid); //解析PMT,找出其中的Video和Audio的PID
void printf_program_list(); //打印PMT table中包含的stream的类型和PID
unsigned char* Find_video_audio(unsigned short program_pid,unsigned char type); //找出Video或者Audio的table
typedef struct
{
unsigned short program_num; //program's num
unsigned 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 program
PRO_LIST program_list[10] = {{0,0}}; //用来存储PMT中stream的类型和PID
unsigned 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); //清空buffer
Video_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;
}
else
printf("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个字节到buffer
ret = parse_TS(buffer,188); //解析188个字节的TS's packet,并打印找到的PAT’s table。如果解析成功即找到PAT,则返回 1,否则返回0
if(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的PID
rewind(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 table
printf("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 PAT 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;
}
else
printf("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");
else
printf("Find a program but this program is other type !\n");
return buffer;
}
else
printf("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;
}
else
return;
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 ++ ;
}
}
非常感谢给予我帮助的大神们。
简单解析PAT、PMT的程序的更多相关文章
- 参考MySQL Internals手册,使用Golang写一个简单解析binlog的程序
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. MySQL作为最流行的开源关系型数据库,有大量的拥趸.其生态已经相当完善,各项特性在圈内都有大量研究.每次新特性发布,都会 ...
- TS流PAT/PMT详解
一 从TS流开始 从MPEG-2到DVB,看着看着突然就出现了一大堆表格,什么PAT.PMT.CAT……如此多的表该怎样深入了解呢? 我们知道,数字电视机顶盒接收到的是一段段的码流,我们称之为TS(T ...
- 对 cloudwu 简单的 cstring 进行简单解析
题外话 以前也用C写过字符串,主要应用的领域是,大字符串,文件读取方面.写的很粗暴,用的凑合着.那时候看见云风前辈的一个开源的 cstring 串. 当时简单观摩了一下,觉得挺好的.也没细看.过了较长 ...
- 第一个OC类、解析第一个OC程序
01第一个OC 类 本文目录 • 一.语法简介 • 二.用Xcode创建第一个OC的类 • 三.第一个类的代码解析 • 四.添加成员变量 • 五.添加方法 • 六.跟Java的比较 • 七.创建对象 ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)
深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...
- [ 转载 ] Java基础10--关于Object类下所有方法的简单解析
关于Object类下所有方法的简单解析 类Object是类层次结构的根类,是每一个类的父类,所有的对象包括数组,String,Integer等包装类,所以了解Object是很有必要的,话不多说,我们直 ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析
转自:https://www.cnblogs.com/FZfangzheng/p/8529132.html 深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每 ...
- Netty学习——基于netty实现简单的客户端聊天小程序
Netty学习——基于netty实现简单的客户端聊天小程序 效果图,聊天程序展示 (TCP编程实现) 后端代码: package com.dawa.netty.chatexample; import ...
- ThreadLocal 简单解析
ThreadLocal 简单解析 基于jdk1.8 ThreadLocal一定不陌生,开发中常用,也是面试里的常客了,但是往往我们可能只是知道该类的作用.学习该类对于个人的多线程编码能力是大有裨益的, ...
随机推荐
- vue-resource(搬运)
一.vue-resource特点vue-resource插件具有以下特点: 1. 体积小vue-resource非常小巧,在压缩以后只有大约12KB,服务端启用gzip压缩后只有4.5KB大小,这远比 ...
- 【Laravel】 常用的artisian命令
全局篇 查看artisian命令 php artisan php artisan list 查看某个帮助命令 php artisan help make:model 查看laravel版本 php a ...
- linux 命令行 拯救萌新精简版
装上linux 真机而不会命令行简直是太难了(这是什么人间疾苦) 于是,来几个非常基础的命令行,给(像我这样)的萌新们一点点前进的动力,也给奋斗在linux路上的大佬们一点点来自萌新的敬意吧. 一个非 ...
- luogu P5289 [十二省联考2019]皮配 背包
LINK:皮配 我承认是一道很难的题目. 不过对于这道题 部分分的提示显得尤为重要. 首先是 40分的暴力dp 很容易想 但是不容易写. 从40分可以发现我们只需要把蓝阵营和鸭派系的人数给存在起来就行 ...
- 6.3 省选模拟赛 Decompose 动态dp 树链剖分 set
LINK:Decompose 看起来很难 实际上也很难 考验选手的dp 树链剖分 矩阵乘法的能力. 容易列出dp方程 暴力dp 期望得分28. 对于链的情况 容易发现dp方程可以转矩阵乘法 然后利用线 ...
- electron开发 - 打印流程(仅支持6.0.0版本以上)
Electron打印 标签打印 标签打印一般有两种方式: 驱动打印,与普通打印机一样通过驱动方式打印. 通过指令打印,不同厂家的的打印机指令集不一样,可查看厂家提供的手册. electron 打印方式 ...
- Servlet容器启动过程
参考:https://blog.csdn.net/fredaq/article/details/9366043 一.概念 所谓Servlet容器其实说白了是符合Servlet规范的Java web容器 ...
- Jenkins总结1-部署jenkins
1. 介绍 jenkins是一个广泛用于持续构建的可视化web工具,持续构建说得更直白点,就是各种项目的"自动化"编译.打包.分发部署.jenkins可以很好的支持各种语言(比如: ...
- django--各个文件的含义
当你创建项目或者应用后你是不是发现多了很多个文件,现在我们来看看各代表什么意思 与你项目名相同的文件夹:是项目的管理功能目录,这个目录的名称因用户所创建的项目名称的不同而不同 在该目录下还有四个文件: ...
- LinuX操作系统基础------>了解文件结构和相关的文件操作
了解LinuX文件系统 熟悉LinuX的文件结构 熟悉LinuX的基本操作指令 利用所学指令进行指令组合操作 什么是文件?什么是目录? 文件:一般是一个独立的东西,可以通过某些工具将其打开 目录:可以 ...