修复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 ...
随机推荐
- Visual studio 2017 未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage”包
装完win10更新 发现vs杯具了… 提示 未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage”包 可以尝试在vs命令行 ...
- C++ this指针
成员函数不能定义 this 形参,而是由编译器隐含地定义.成员函数的函数体可以显式使用 this 指针,但不是必须这么做.如果对类成员的引用没有限定,编译器会将这种引用处理成通过 this 指针的引用 ...
- 咸鱼入门到放弃10--javaweb的两种开发模式
(本篇是之前方法的综合使用,新东西不多,其中也涉及三层架构的问题.此处直接引用了大佬blog:https://www.cnblogs.com/xdp-gacl/p/3908610.html) SUN公 ...
- Spring 下使用Junit4 单元测试
package platform; import java.util.List; import java.util.UUID; import javax.annotation.Resource; im ...
- 10_30_unittest
1.断言 1).self.assertEqual(2,res)#期望值qian.结果值hou2)TextTestRunner 源码 必要的参数3)测试结果 上下文管理器 with open(" ...
- Alpha冲刺(2/10)——2019.4.24
作业描述 课程 软件工程1916|W(福州大学) 团队名称 修!咻咻! 作业要求 项目Alpha冲刺(团队) 团队目标 切实可行的计算机协会维修预约平台 开发工具 Eclipse 团队信息 队员学号 ...
- leetcode刷题正则表达式
题目链接:https://leetcode-cn.com/problems/regular-expression-matching/ 这道题用到了动态规划: 关于动态规划请参考这篇博文:https:/ ...
- vue中 v-show和v-if的区别?
v-show的操作元素的属性是display v-if的操作元素的移除和新建 还有一个就是权限的时候,v-show普通用户能看到,用v-if的时候普通用户看不到.
- CF741C.Arpa’s overnight party and Mehrdad’s silent entering [构造 二分图染色]
CF741C - Arpa's overnight party and Mehrdad's silent entering 题意: 有 n 对情侣坐成一个圈,有两种食物Kooft and Zahre- ...
- The frist email to myself by python
昨天用python模块给自己发了第一封电子邮件,真是激动 今天完善了一下. code: import smtplib from email.mime.text import MIMEText//ema ...