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表解释相关推荐

  1. ts包、表、子表、section的关系

    我们经常接触到创建 DEMUX,注册 Filter 过滤数据, 通过回调过滤出 section 数据,然后我们对 section 数据做具体的解析或者其他操作. 我们这里说的 section 就是段的 ...

  2. python颜色表_数据库表连接的简单解释 | 图文并茂,通俗易懂

    (点击上方公众号,可快速关注一起学Python) 作者:阮一峰       链接: http://www.ruanyifeng.com/blog/2019/01/table-join.html 关系型 ...

  3. 【Hive】Hive建表基本语法及解释

    Hive建表基本语法 CREATE [EXTERNAL] TABLE [IF NOT EXIST] table_name [(col_name data_type [COMMENT COL_COMME ...

  4. a连接带id转送不了数据_数据库表连接的简单解释

    关系型数据库最难的地方,就是建模(model). 错综复杂的数据,需要建立模型,才能储存在数据库.所谓"模型"就是两样东西:实体(entity)+ 关系(relationship) ...

  5. 便利贴--43{vue3+ts+setup+ArcoDesign 表格和表单 单页模板(整合)} --舍弃--不删--不更新

    便利贴--43{vue3+ts+setup+ArcoDesign 表格和表单 单页模板(整合)} --舍弃--不删--不更新 前言 tableOnce.vue affuxFormModal.vue 前 ...

  6. ffmpeg——TS流解析

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

  7. autojs遍历当前页面所有控件_HTML5表单和表单控件的使用

    哈喽大家好,我是作者"未来",本期分享的内容是Web前端系列课程,本系列总共29个阶段,坚持学习3个月蜕变为Web前端高手哦! 志同道合的小伙伴跟我一起学习交流哦! 第一阶段 HT ...

  8. (DML触发器)如何正确理解触发器的deleted表和inserted表(转)

    在触发器的设计当中,有很多的同学总是不了解怎样善用触发器来解决问题,其实问题在于他们不理解触发器最重要的两个表:inserted表和deleted表,假如你理解这两表的话,许多关于的触发器的问题就迎刃 ...

  9. MYSQL中的主表和父表_主表,从表,关联表,父表,子表

    一.前言 在数据库设计中,Hibernate,iBatis等ORM框架的使用中经常听说主键,外键,主表,从表,关联表,父表,子表之类的术语,弄懂它们之前的区别与联系对于数据库设计和ORM框架的学习使用 ...

最新文章

  1. 订单倒计时取消,nodejs 辅助实现倒计时任务
  2. 关于table和ul/ol还有span.
  3. 交换机配置软件_如何配置远程登陆交换机?最简单的解释方式,一看就懂
  4. ios 持续获取定位 高德地图_概述-iOS 定位SDK | 高德地图API
  5. Web SQL Database 之 SQLite语法
  6. vscode终端无法输入
  7. Jekyll 使用入门
  8. ctfshow-WEB-web14( 利用数据库读写功能读取网站敏感文件)
  9. 《Puppet实战手册》——2.5 使用标准的命名约定
  10. 跳槽后,获年薪300万,是跳槽还是跳坑
  11. sql优化-项目实战
  12. jQuery 中的 attr
  13. VOIP语音电话配置
  14. 信息学奥赛一本通pdf_信息学奥赛冠军的竞赛“秘籍”
  15. 读《三体》差点污了我的三观
  16. 深度学习技术在不同方向的应用及相关开源项目
  17. 【项目设计】基于OneNet平台的心率监测系统 -嵌入式 -物联网
  18. 第四章 Caché JSON 处理数据类型
  19. 小爱同学控制灯 局域网
  20. 蓝桥杯包子凑数java解析,蓝桥杯之包子凑数

热门文章

  1. Android studio Intent的使用
  2. 网络安全面试的HTTPS问题_HTTPS原理剖析
  3. 【机械萌新成长日志】DAY1:SolidWorks工程图遇到圆角如何标注?
  4. 安卓之实现一个简单的短信发送功能
  5. 学习记录—— java 求岁数
  6. 华为服务器gpu芯片,GPU云运算服务器方案
  7. 周小川最新演讲:Libra可能会导致“赢者通吃”的局面(万字长文)
  8. php退款系统设计思路,支付系统设计实现(1)——支付退款
  9. linux下使用usb转串口,Linux下使用USB转串口线
  10. Kotlin笔记9--无参构造函数