修复FFMPEG 复用 PAT、PMT发送间隔小于25ms的错误
分析ffmpeg源码
分析问题
mpegtsenc.c
找到发送PAT、PMT的函数
/* send SDT, PAT and PMT tables regularly */
static void retransmit_si_info(AVFormatContext *s, int force_pat, int64_t dts)
{
MpegTSWrite *ts = s->priv_data;
int i;
if (++ts->sdt_packet_count == ts->sdt_packet_period ||
(dts != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) ||
(dts != AV_NOPTS_VALUE && dts - ts->last_sdt_ts >= ts->sdt_period*90000.0)
) {
ts->sdt_packet_count = 0;
if (dts != AV_NOPTS_VALUE)
ts->last_sdt_ts = FFMAX(dts, ts->last_sdt_ts);
mpegts_write_sdt(s);
}
if (++ts->pat_packet_count == ts->pat_packet_period ||
(dts != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) ||
(dts != AV_NOPTS_VALUE && dts - ts->last_pat_ts >= ts->pat_period*90000.0) ||
force_pat) {
ts->pat_packet_count = 0;
if (dts != AV_NOPTS_VALUE)
ts->last_pat_ts = FFMAX(dts, ts->last_pat_ts);
mpegts_write_pat(s);
for (i = 0; i < ts->nb_services; i++)
mpegts_write_pmt(s, ts->services[i]);
}
}
从源码分析,可以知道PAT、PMT的发送条件
if (++ts->pat_packet_count == ts->pat_packet_period ||
(dts != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) ||
(dts != AV_NOPTS_VALUE && dts - ts->last_pat_ts >= ts->pat_period*90000.0) ||
force_pat)
dts != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE
:第一次发送PAT、PMT用到的是这个条件。
++ts->pat_packet_count == ts->pat_packet_period
:这个条件是定时100ms发送PAT、PMT;ts->pat_packet_period 这个字段在函数mpegts_init
里面有定义。
ts->last_pat_ts >= ts->pat_period*90000.0
: 这个条件用户自定义发表间隔时会生效,ts->pat_period 这个字段默认值是INT_MAX。
ts->pat_period:这个字段可以通过如下接口进行用户自定义设置:
av_opt_set(ofmt_ctx->priv_data, "pat_period", "0.01", 0);
注:ffmpeg 巧妙的地方时,你用户自定义后,定时100ms发送的条件就会失效。
force_pat
: 强制发送PAT、PMT,这个参数是函数入参,故需要查看函数retransmit_si_info被谁调用。
搜索代码可知,只有mpegts_write_pes调用此函数。
static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
const uint8_t *payload, int payload_size,
int64_t pts, int64_t dts, int key, int stream_id)
{
MpegTSWriteStream *ts_st = st->priv_data;
MpegTSWrite *ts = s->priv_data;
uint8_t buf[TS_PACKET_SIZE];
uint8_t *q;
int val, is_start, len, header_len, write_pcr, is_dvb_subtitle, is_dvb_teletext, flags;
int afc_len, stuffing_len;
int64_t pcr = -1; /* avoid warning */
int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
int force_pat = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key;
av_assert0(ts_st->payload != buf || st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO);
if (ts->flags & MPEGTS_FLAG_PAT_PMT_AT_FRAMES && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
force_pat = 1;
}
is_start = 1;
while (payload_size > 0) {
retransmit_si_info(s, force_pat, dts);
force_pat = 0;
write_pcr = 0;
分析源码可知,force_pat遇到视频关键帧时,会被赋值为1。
由此分析可知,当定时发送完PAT、PMT后,25ms内来了一帧关键帧,也会发送PAT、PMT,导致出现PAT、PMT间隔小于25ms这个错误。
修改源码解决问题
修改函数retransmit_si_info:将发送PAT、PMT条件中的force_pat
去掉即可
/* send SDT, PAT and PMT tables regularly */
static void retransmit_si_info(AVFormatContext *s, int force_pat, int64_t dts)
{
MpegTSWrite *ts = s->priv_data;
int i;
if (++ts->sdt_packet_count == ts->sdt_packet_period ||
(dts != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) ||
(dts != AV_NOPTS_VALUE && dts - ts->last_sdt_ts >= ts->sdt_period*90000.0)
) {
ts->sdt_packet_count = 0;
if (dts != AV_NOPTS_VALUE)
ts->last_sdt_ts = FFMAX(dts, ts->last_sdt_ts);
mpegts_write_sdt(s);
}
#if 0
if (++ts->pat_packet_count == ts->pat_packet_period ||
(dts != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) ||
(dts != AV_NOPTS_VALUE && dts - ts->last_pat_ts >= ts->pat_period*90000.0) ||
force_pat)
#endif
if (++ts->pat_packet_count == ts->pat_packet_period ||
(dts != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) ||
(dts != AV_NOPTS_VALUE && dts - ts->last_pat_ts >= ts->pat_period*90000.0))
{
ts->pat_packet_count = 0;
if (dts != AV_NOPTS_VALUE)
ts->last_pat_ts = FFMAX(dts, ts->last_pat_ts);
mpegts_write_pat(s);
for (i = 0; i < ts->nb_services; i++)
mpegts_write_pmt(s, ts->services[i]);
}
}
修复FFMPEG 复用 PAT、PMT发送间隔小于25ms的错误的更多相关文章
- TS流PAT/PMT详解
一 从TS流开始 从MPEG-2到DVB,看着看着突然就出现了一大堆表格,什么PAT.PMT.CAT……如此多的表该怎样深入了解呢? 我们知道,数字电视机顶盒接收到的是一段段的码流,我们称之为TS(T ...
- ffmpeg 复用
aa 将mkv中的音视频复用成ts流: ffmpeg -i 32_mkv_h264_718x480_ac3.mkv -codec copy -bsf:v h264_mp4toannexb -f m ...
- 关于SetTimer间隔小于OmTimer执行时间的问题
如果SetTimer的时间间隔为t,其响应事件OnTimer代码执行一遍的时间为T,且T>t.这样,一次未执行完毕,下一次定时到,这时候程序会如何执行? 可能的情况:1.丢弃还未执行的代码,开始 ...
- 邮件发送,无尽的501错误。TCP发送邮件解决方案
先贴上错误信息,便于搜索引擎采集,也送给遇到此问题的技术朋友们. smtp 501 Syntax error (no parameters allowed) (#5.5.4) 背景描述: 使用TCP发 ...
- SpringMVC客户端发送json数据时报400错误
当测试客户端发送json数据给服务器时,找不到响应路径? 原来是参数类型不符,即使是json也要考虑参数的个数和类型 解决:将age请求参数由"udf"改为"3" ...
- duilib 修复padding属性导致其他控件自动计算宽高度错误的bug和导致自己宽高度错误的bug
转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/42950733 BUG 一:padding导致其他控件宽 ...
- vs2012 MinGW编译ffmpeg 出现libavdevice/avdevice.c(38) : error C2059: 语法错误:“.”
利用vs2012编译ffmpeg出现以下错误: libavdevice/avdevice.c(38) : error C2059: 语法错误:“.” libavdevice/avdevice.c(40 ...
- IE 浏览器在地址栏输入中文字符,发送get请求报400错误的问题
因为学校有JavaWeb的课程,所以才接触这方面.最近遇到了个小问题. 先看一段很简单的jsp代码例子 <%@ page language="java" import=&qu ...
- nRF24L01基于FIFO TX队列的发送性能优化
RF24项目代码分析 头文件 https://github.com/nRF24/RF24/blob/master/RF24.h 源文件 https://github.com/nRF24/RF24/bl ...
随机推荐
- Java使用线程池
多线程主函数 package UnitTest; import java.util.ArrayList; import java.util.List; import java.util.concurr ...
- HttpListener 实现web服务器
一.使用方法 1. Start()方法 允许此实例接受传入的请求.即开始监听 2. Stop()方法 处理完所有当前排队的请求后关闭HttpListener对象 3. GetContext()方法 ...
- Spark SQL UDF示例
UDF即用户自定函数,注册之后,在sql语句中使用. 基于scala-sdk-2.10.7,Spark2.0.0. package UDF_UDAF import java.util import o ...
- [原创]Xilinx Vivado 2017.4/2018.3/2016.4/2015.4/ISE14.7下载及其安装
最新版本Vivado 2018.3下载地址 链接:https://pan.baidu.com/s/17aE-vICRQYN27bD2sXCLxg提取码:ilg5 由于工程需要,下载VIVADO2018 ...
- outlook2013 关闭时最小化到任务栏的完美解决方法
使用 Keep Outlook Running 加载项 文件->选项->加载项 点击最下面的“转到”按钮 *用管理员身份运行Outlook才可以将 Keep Outlook Running ...
- 数据分析入门——Pandas类库基础知识
使用python进行数据分析时,经常会用Pandas类库处理数据,将数据转换成我们需要的格式.Pandas中的有两个数据结构和处理数据相关,分别是Series和DataFrame. Series Se ...
- event、fly.js、购物车特效
先总结下区别: #鼠标相对于浏览器窗口可视区域的X,Y坐标(窗口坐标),可视区域不包括工具栏和滚动条. event.clientX.event.clientY #鼠标相对于document文档区域的x ...
- idea通过mapper快速定位到xml文件
1.点击File找到设置(Settings) 2.点击Plugins下的 Browse respositories 3.在搜索栏搜索mybatis ,选中 Free Mybatis plugin——i ...
- Mix 导航
Mix 导航 一.程序员必备技能 Markdonw 使用 Git 常用命令 二.分析设计 UML 三.其他 博客园代码样式修改
- [Linux] 使用Yum在CentOS上安装MySQL
跟随官网上的安装教程:https://dev.mysql.com/doc/refman/8.0/en/linux-installation-yum-repo.html官网上还有一个QuickGuide ...