ffmpeg ts section 表及pes表解释
ffmpeg ts section 表及pes表解释
1. sdt 表解释
例如下面的调用栈
0 in sdt_cb of libavformat/mpegts.c:2650
1 in write_section_data of libavformat/mpegts.c:466
2 in handle_packet of libavformat/mpegts.c:2819
3 in handle_packets of libavformat/mpegts.c:2984
4 in mpegts_read_header of libavformat/mpegts.c:3102
5 in avformat_open_input of libavformat/utils.c:609
6 in main of main.c:31
static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
1. section, section_len 信息是如何获得的?
在write_secton_data()中调用
tss->section_cb(tss1, cur_section_buf, tss->section_h_size)
其中 cur_section_buf 是指向当前section的数据指针
tss->section_h_size 是 从section 数据中读取的
tss->section_h_size = (AV_RB16(cur_section_buf + 1) & 0xfff) + 3;
只所以加3,是因为第1字节为tableID,第2,3字节是section的长度.
另:tss1 是tsfilter, tss是sectionfilter.
MpegTSSectionFilter *tss = &tss1->u.section_filter; // tss1是tsfilter, tss是sectionFilter, tss1更大一些.
2. sdt 表中有什么内容
sdt表,其pid是0x11,其tableID 是0x42, 后跟12bits 长度,后面还有16bits ts_ID(传输流id) 及3个bytes版本号,sec_num,last_sec_num为表头
后面一个16bits onID(origial network id),一个8bits val, 然后进入循环
后面一个16bits sid(服务id),一个8bits val, 一个16bits 长度再次进入循环
后面一个8bits tag, 一个8bits 长度.
如果tag 是0x48, 则后面数据包含一个8bits服务类型,提供商名称和服务名称.
onID,ts_ID,sid 构成3级定位
若存在该服务,则可以创建一个av_new_program(fmt_ctx,sid), 其传人参数是sid, 作为节目ID,并给这个program添加meta_data.
av_dict_set(&program->metadata, "service_name", name, 0);
av_dict_set(&program->metadata, "service_provider", provider_name, 0);
2. pat表解释
pat表,其pid是0x0,其tableID 是0x0, 后跟12bits 长度,后面还有16bits ts_ID(为传输流ID) 及3个bytes版本号,sec_num,last_sec_num为表头
后面进入循环:
16bits sid(服务id), 16bits pmt_pid
这里的sid 就是节目ID, 与sdt表中的sid 是一样的,都是节目ID或者说服务ID
每一个sid,都可以创建一个新节目av_new_program(fctx,sid),
这样program 就加了一个,一个流中(由ts_ID标识)可以有多个program(节目)
根据pmt_pid,可以创作一个Pmt filter, mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1);
就能过滤出pmt表了. 其中第一个ts 是上下文, 第二个ts是pmt_cb的参数.
每一个sid,pmt_pid构成pat表中的一项
pat 表的另一个作用是在 struct MpegTSContext 中添加sid, 并把pmt_pid加入其中
prg = add_program(ts, sid); //ts中有一个program 数组, ts->prg, 每个program包含一个ID数组及stream数组
add_pid_to_program(prg, pmt_pid);
3. pmt表解释
pmt表,其pid是pat表找到的,其tableID 是0x2, 后跟12bits 长度,后面还有16bits ID(为sid) 及3个bytes版本号,sec_num,last_sec_num为表头
这里的sid就是节目ID,和前面的sdt,pat中sid是一致的.每个表描述节目的一部分特性. sdt描述了服务名称,pat描述了pmt_pid,pmt中描述了播出流属性
一个节目,是包含节目ID和多个播出流pid, 例如音频流pid,视频流pid
首先,把当前流的pid(就是pmt表本身的PID) 加到program结构中
表头后面跟:
13bits pcr_pid, 把pcr_pid加到program结构中
12bits 节目信息长度,可能值为0, 后面进行循环,获取PMT项
获取8bits 流类型(stream_type), 13bits pid(这是基础流es的PID),12bits 基础流信息长度(可能为0)+基础流信息
例1: 1b e1 00 f0 00
0x1b(视频流,这是h264类型)+0x100(pid) ; e(1110),f(111)中的1都是1填充位
由stream_type 判定是否是pes 流, 除了0x13不能当pes流, 0x86有时候不能当pes流(配合另一参数),其它都可以作为基础流类型.
根据pid,pcr_pcd 可以创建一个pes 流,这就是基础流. 加上基础流过滤器,就可以过滤分析基础流了.
tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes);
其中ts 是上下文,pid是基础流id, mpegts_push_data 是回调函数,pes是回调函数的参数
然后在format 上创建一个新的stream
avformat_new_stream()
stream_type 就是codec_tag
stream 里有codec_param(stream_type,codec_type,codec_id), 有codec, 有time_base
看下面条目,就是定义0x1b流类型是视频h264
{ 0x1b, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 },
0x81 是audio,ac3类型
{ 0x81, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 },
在 struct MpegTSContext 中可以添加该stream
pes = add_pes_stream(ts, pid, pcr_pid) 其中会打开Pes 过滤器 mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes);
st = avformat_new_stream(pes->stream, NULL); //创建了一个stream, 但codec给的是空, 一个stream包含codec,codecpar,internal结构指针
st->id = pes->pid;
if (pes && !pes->stream_type) mpegts_set_stream_info(st, pes, stream_type, prog_reg_desc);
add_pid_to_program(prg, pid);
例2: 81 E1 01 F0 06 0A 04 65 6E 67 00
0x81(音频流,这是ac3类型)+0x101(pid)+6bytes 基础流信息,0A 为tag(这是描述语言类型的), 长度为4,内容为eng
4. pes 表头解释
固定的00 00 01开始加stream_id(8bits)+len(16bits), byte+标志位+长度(8bits) 构成9字节表头,
若flags & 0xc0==0xc0, 表示后跟pts(5B),dts(5B), 在后面是负载
参考: ffmpeg4.4 代码
ffmpeg ts section 表及pes表解释相关推荐
- ts包、表、子表、section的关系
我们经常接触到创建 DEMUX,注册 Filter 过滤数据, 通过回调过滤出 section 数据,然后我们对 section 数据做具体的解析或者其他操作. 我们这里说的 section 就是段的 ...
- python颜色表_数据库表连接的简单解释 | 图文并茂,通俗易懂
(点击上方公众号,可快速关注一起学Python) 作者:阮一峰 链接: http://www.ruanyifeng.com/blog/2019/01/table-join.html 关系型 ...
- 【Hive】Hive建表基本语法及解释
Hive建表基本语法 CREATE [EXTERNAL] TABLE [IF NOT EXIST] table_name [(col_name data_type [COMMENT COL_COMME ...
- a连接带id转送不了数据_数据库表连接的简单解释
关系型数据库最难的地方,就是建模(model). 错综复杂的数据,需要建立模型,才能储存在数据库.所谓"模型"就是两样东西:实体(entity)+ 关系(relationship) ...
- 便利贴--43{vue3+ts+setup+ArcoDesign 表格和表单 单页模板(整合)} --舍弃--不删--不更新
便利贴--43{vue3+ts+setup+ArcoDesign 表格和表单 单页模板(整合)} --舍弃--不删--不更新 前言 tableOnce.vue affuxFormModal.vue 前 ...
- ffmpeg——TS流解析
RTSP(Real Time Streaming Protocol),实时流传输协议,是TCP/IP协议体系中的一个应用层协议,该协议定义了一对多应用程序如何有效地通过IP网络传送多媒体数据.RTSP ...
- autojs遍历当前页面所有控件_HTML5表单和表单控件的使用
哈喽大家好,我是作者"未来",本期分享的内容是Web前端系列课程,本系列总共29个阶段,坚持学习3个月蜕变为Web前端高手哦! 志同道合的小伙伴跟我一起学习交流哦! 第一阶段 HT ...
- (DML触发器)如何正确理解触发器的deleted表和inserted表(转)
在触发器的设计当中,有很多的同学总是不了解怎样善用触发器来解决问题,其实问题在于他们不理解触发器最重要的两个表:inserted表和deleted表,假如你理解这两表的话,许多关于的触发器的问题就迎刃 ...
- MYSQL中的主表和父表_主表,从表,关联表,父表,子表
一.前言 在数据库设计中,Hibernate,iBatis等ORM框架的使用中经常听说主键,外键,主表,从表,关联表,父表,子表之类的术语,弄懂它们之前的区别与联系对于数据库设计和ORM框架的学习使用 ...
最新文章
- 订单倒计时取消,nodejs 辅助实现倒计时任务
- 关于table和ul/ol还有span.
- 交换机配置软件_如何配置远程登陆交换机?最简单的解释方式,一看就懂
- ios 持续获取定位 高德地图_概述-iOS 定位SDK | 高德地图API
- Web SQL Database 之 SQLite语法
- vscode终端无法输入
- Jekyll 使用入门
- ctfshow-WEB-web14( 利用数据库读写功能读取网站敏感文件)
- 《Puppet实战手册》——2.5 使用标准的命名约定
- 跳槽后,获年薪300万,是跳槽还是跳坑
- sql优化-项目实战
- jQuery 中的 attr
- VOIP语音电话配置
- 信息学奥赛一本通pdf_信息学奥赛冠军的竞赛“秘籍”
- 读《三体》差点污了我的三观
- 深度学习技术在不同方向的应用及相关开源项目
- 【项目设计】基于OneNet平台的心率监测系统 -嵌入式 -物联网
- 第四章 Caché JSON 处理数据类型
- 小爱同学控制灯 局域网
- 蓝桥杯包子凑数java解析,蓝桥杯之包子凑数
热门文章
- Android studio Intent的使用
- 网络安全面试的HTTPS问题_HTTPS原理剖析
- 【机械萌新成长日志】DAY1:SolidWorks工程图遇到圆角如何标注?
- 安卓之实现一个简单的短信发送功能
- 学习记录—— java 求岁数
- 华为服务器gpu芯片,GPU云运算服务器方案
- 周小川最新演讲:Libra可能会导致“赢者通吃”的局面(万字长文)
- php退款系统设计思路,支付系统设计实现(1)——支付退款
- linux下使用usb转串口,Linux下使用USB转串口线
- Kotlin笔记9--无参构造函数