ffmpeg关于mpegts码流解析部分:

1、  首先来看main函数

通过av_register_all()来注册所有的编解码器、解复用器(这里只用到mpegts_demuxer)、注册所使用的协议(这里用到文件打开的协议file_protocol,类似的还有http_protocal,pipe_protocol,rtp_protocol,tcp_protocol,udp_protocol).

代码如下:

Void av_register_all()

{

Avcodec_register_all();// 注册所有的编解码器

REGISTER_MUXDEMUX(MPEGTS,mpegts);//注册的实质是把所有的解复用器也好还是复//用器也好都加入到一个链表里面

REGISTER_PROTOCOL(FILE,file);//协议的注册也是如此,都是加入到一个链表里面

}

2、  调用av_open_input_file(&ic,filename,iformat,0,ap);

a)         只是传参一个filename,其他的内容会根据不同的数据内容自动填充

b)         通过url_fopen(&pb,filename,URL_RDONLY)打开文件,在url_fopen中调用了url_open()来判断打开的流是文件流还是网络流,会根据不同的内容自动匹配协议xxx_protocol,然后会根据不同的协议会调用相应的url_open打开流。

这里用到URLProtocol file_protocol = {

"file",

file_open,

file_read,

file_write,

file_seek,

file_close,

};

c)      这里用到一个重要的结构体ByteIOContext封装了媒体流的细节,用它来承载媒体流信息。

d)      接着来探测文件格式。首先通过get_buffer()为pb->buf得到数据,然后通过av_probe_input_format2(pb,1,&score)来探测输入流格式,并返回得到的格式fmt。

这里得到的文件格式为AVInputFormat mpegts_demuxer = {

"mpegts",

NULL_IF_CONFIG_SMALL("MPEG-2 transport stream format"),

sizeof(MpegTSContext),

mpegts_probe,

mpegts_read_header,

mpegts_read_packet,

mpegts_read_close,

read_seek,

mpegts_get_pcr,

AVFMT_SHOW_IDS|AVFMT_TS_DISCONT,

};

e)      调用av_open_input_stream(ic_ptr,pb,filename,fmt,ap)来解析包头信息。

在其中调用ic->iformat->read_header(ic, ap)实质上是调用mpegts_read_header(ic,ap);

现在程序进入到核心的部分mpegts.c中,下面来依次分析mpegts.c中的各个函数。

1.在mpegts_read_header中,先读取1024字节来得到包大小

pos = url_ftell(pb);

len = get_buffer(pb, buf, sizeof(buf));

if (len != sizeof(buf))

goto fail;

ts->raw_packet_size = get_packet_size(buf, sizeof(buf));

2.然后通过if(s->iformat==&mpegts_demuxer)来判断是解复用还是复用。先看解复用的情况。程序先挂载sdt表和pat表。

Mpegts_scan_sdt(ts);//挂在sdt表到ts->pids[pid]

Mpegts_set_service(ts);//挂在pat表到ts->pids[pid]

Handle_packets(ts,s->probesize);//真正处理包信息的地方在这里

3.进入到handle_packets()中来看。

For(;;)

{

Read_packet(pb,packet,ts->raw_packet_size);//得到一个包到packet

Handle_packet(ts,packet);//对包进行解析

}

4.下面分析handle_packets()

static void handle_packet(MpegTSContext *ts, const uint8_t *packet)

{

pid = AV_RB16(packet + 1) & 0x1fff;//得到pid,pid=0代表是pat表

if(pid && discard_pid(ts, pid))

return;

is_start = packet[1] & 0x40;

tss = ts->pids[pid];

if (ts->auto_guess && tss == NULL && is_start) {

add_pes_stream(ts, pid, -1, 0);

tss = ts->pids[pid];

}

if (!tss)

return;

cc = (packet[3] & 0xf);

cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc));

tss->last_cc = cc;

afc = (packet[3] >> 4) & 3;

p = packet + 4;

if (afc == 0)

return;

if (afc == 2)

return;

if (afc == 3) {

p += p[0] + 1;

}

p_end = packet + TS_PACKET_SIZE;

if (p >= p_end)//指针到到负载部分

return;

ts->pos47= url_ftell(ts->stream->pb) % ts->raw_packet_size;

if (tss->type == MPEGTS_SECTION) {//如果包类型是section

if (is_start) {

len = *p++;

if (p + len > p_end)

return;

if (len && cc_ok) {

write_section_data(s, tss,

p, len, 0);

if (!ts->pids[pid])

return;

}

p += len;

if (p < p_end) {

write_section_data(s, tss,//对section段进行解析

p, p_end - p, 1);

}

} else {

if (cc_ok) {

write_section_data(s, tss,

p, p_end - p, 0);

}

}

} else {

tss->u.pes_filter.pes_cb(tss,//这里先对section进行解析完之后才能进到这里对pes进行解析

p, p_end - p, is_start);

}

}

3.进入到write_section_data()

static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1,

const uint8_t *buf, int buf_size, int is_start)

{

if (tss->section_h_size == -1 && tss->section_index >= 3) {

len = (AV_RB16(tss->section_buf + 1) & 0xfff) + 3;//得到段长度

}

if (tss->section_h_size != -1 && tss->section_index >= tss->section_h_size) {

tss->end_of_section_reached = 1;

if (!tss->check_crc ||

av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1,

tss->section_buf, tss->section_h_size) == 0)

{

tss->section_cb(tss1, tss->section_buf, tss->section_h_size);//这是个重要的函数,是对一个包中的负载进行解析,section_cb会根据包类型的不同来调用不同的函数

}

}

}

Section_cb是一个回调函数,调用的函数有pat_cb,sdt_cb,pmt_cb,

Table_id 00代表pat表,02代表pmt表

关于ffmpeg程序的结构层次关系:

URLProtocol、URLContext和ByteIOContext是ffmpeg文件操作的结构,

AVFormatContext是相当于容器之类的东西,会把解析到的信息都记录在这里

AVFormatContext{

AVInputFormat

ByteIOContext{

URLContext{

URLProtocol;

}

}

Void *priv_data//指向MpegtsContext结构体

}

对TS码流分析:

第一个包  负载为pat表

00000000h: 04 CA 63 A0 包头:47 4pid0 00 afc10 00 00 B0 section_length11 00 01 C1 00 ; .蔯燝@....?..?

00000010h: 00 sid00 00 network_pidE0 1F sid00 01 Epmt_pid1 00 24 AC 48 84 FF FF FF ; ...?..?$琀?

00000020h: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ; 后面的省略

分析:pid=0,表明后面跟的负载为pat表

Afc=01,表明没有适应段

Section_length=17,表明此段后有17个字节,包括crc

Sid为节目

第二个包  负载为pmt表

000000c0h: 04 CA 63 A0 包头47 4pid1 00 10 00 段开始:table_id:02 B0 section_length:46program_number00 01 C1 section_number00 ; .蔯燝A....癋..?

000000d0h: last_sec_number00 F PCR_PID0 01 F0 program_info_length0C tag05 len04 bytes48 44 4D 56tag88 len04 0F FF FC ; .??..HDMV?.?

000000e0h: FC stream_type1B es_pidF0 11 Fes_info_len0 06 desc_tag28 desc_len04 64 00 29 BFstream_type81 es_pidF1 00 Fes_info_len0 ; ???(.d.)縼??

000000f0h: 12 desc_tag05 desc_len04 41 43 2D 33 desc_tag81 desc_len04 08 48 0E 00 desc_tag0Adesc_len04 6A ; ...AC-3?.H....j

00000100h: 70 6E 00 stream_type90 Fes_pid2 00 Fes_info_len0 06 desc_tag0A desc_len04 7A 68 6F 004C 3A ; pn.愹.?..zho.L:

00000110h: EA 06 FF FF FF FF FF FF FF FF FF FF FF FF FF FF ; ?未完待续。。。。

TS流解析 ffmpeg相关推荐

  1. 数字电视之TS流解析

    做了这么久的TV方案,对数字电视也很了解,今天来总结一下,MPEG-2 TS流解析的细节: TS流中有两种标识符,一种是包标识符,一种是表标识符.具有相同PID的不用信息表由表标识符table Id来 ...

  2. ffmpeg——TS流解析

    RTSP(Real Time Streaming Protocol),实时流传输协议,是TCP/IP协议体系中的一个应用层协议,该协议定义了一对多应用程序如何有效地通过IP网络传送多媒体数据.RTSP ...

  3. TS流解析之PMT表格解析

    from:http://blog.csdn.net/xioahw/article/details/4093491 PMT结构定义: typedef struct TS_PMT_Stream {  un ...

  4. TS流解析之PAT表格解析

    from: http://blog.csdn.net/xioahw/article/details/4093488 PAT表格定义如下: typedef struct TS_PAT_Program { ...

  5. TS流解析 二 *****

    1.TS格式介绍 TS:全称为MPEG2-TS.TS即"Transport Stream"的缩写.它是分包发送的,每一个包长为188字节(还有192和204个字节的包).包的结构为 ...

  6. TS流解析【PCR】自己的总结

    http://www.cnblogs.com/ztteng/articles/3166025.html http://blog.csdn.net/liuhongxiangm/article/detai ...

  7. c语言解析ts流文件,TS流解析

    1. 介绍:​TS即是"Transport Stream"的缩写.他是分包发送的,每一个包长为188字节或者是204的字节(204字节的就是在后面添加了16字节主要用于高清解码), ...

  8. python处理ts_[python]TS流解析

    据说TS包长度是188个字节,真的是这样?实验一下(原理:0x47是TS包头的第一个字节,作为同步字段): file = open('test.ts', 'rb') offset = 0 start ...

  9. DVB中TS流数据解析

    引  言 数字生活方式是现代文明的一个重要标志.在与人们工作生活密切相关的电脑.手机和电视三大信息平台中,电脑和手机已实现了数字化和网络化,为人们带来了多姿多彩的资讯和娱乐服务,也为相关企业带来了巨额 ...

最新文章

  1. 关于java线程同步的笔记_线程同步(JAVA笔记-线程基础篇)
  2. stringBuffer、StringBuilder、排序、Arrays、Jdk1.5新特性(java基础知识十三)
  3. 计算机专业 毕业论文 百度云,计算机专业毕业论文.pdf
  4. 安全性配置-定义任务流节点
  5. php分页类示例下载,PHP 通用分页类的简单示例
  6. ROS学习笔记1(配置ROS环境和创建工作空间)
  7. IM系统中聊天记录模块的设计与实现
  8. 实验室双显示屏安装使用记录
  9. hane nfs win 配置_win7下搭建nfs-server的方法
  10. mac vs 返回上一步_mac 后退一步 快捷键
  11. xutils中dbutils的使用
  12. Using ‘UTF-8‘ encoding to copy filtered resources. skip non existing resourceDirectory
  13. 华为云sql工程师评测答题[青铜+白银]
  14. 最小生成树——克鲁斯卡尔(Kruskal)算法
  15. command not found: conda
  16. 【java】java中输出字符串中的单个字符及获得其长度
  17. Android 9 (P)版本解决VNDK library: XXX‘s ABI has EXTENDING CHANGES
  18. 同轴连接器有哪些种类?
  19. html网页中在一个表格中去除部分表格线
  20. 【机器人学习】三自由度康复机器人运动学分析()

热门文章

  1. 可重复读隔离级别如何解决脏读、不可重复读
  2. 第二期:百度AI开发者大会;蚂蚁金服投资雪球|互联网行业公会
  3. 全志android平台下的SDK快速移植
  4. android五层系统架构,Android系统的五层架构、Dalvik与ART、最后有个奇怪的问题请教orz...
  5. 中国中药提取物市场深度研究分析报告
  6. 为欧陆词典安装词典库
  7. 内网渗透之CFS三层靶机搭建
  8. 【学习总结】Apsara Clouder云计算技能认证:网站建设:简单动态网站搭建+思维导图
  9. 强化学习系列4:蛇棋的例子
  10. 【虹科案例】智能工控屏eX707在水下遥控机器人中的应用