rtmp推流时间戳兼容问题
一直用简单的librtmp或者其他开源推流实现方式。没有太关注细节问题。
直到最近一次测试长时间推流。遇到了3字节时间戳溢出问题,即时间戳超过0xffffff,服务器断开。
复现方式:
用yasea推流到SRS或者Nginx-rtmp。
yasea版本要求2017-08-30以及以前的版本。
SRS不做特殊要求,本次使用v2.0.243 release版。
Nginx-rtmp版本不做特殊要求,本次使用Nginx: 1.13.3。
yasea推流到srs,超过4.5小时,当时间戳超过0xffffff,srs报错:
chunk stream is fresh, fmt must be , actual is . cid=, ret=(Resource temporarily unavailable)
read message header failed. ret=(Resource temporarily unavailable)
recv interlaced message failed. ret=(Resource temporarily unavailable)
thread process message failed. ret=(Resource temporarily unavailable)
thread recv cycle failed, ignored and retry, ret=
recv thread failed. ret=(Resource temporarily unavailable)
cleanup when unpublish
stream service cycle failed. ret=(Resource temporarily unavailable)
yasea推流到Nginx-rtmp,超过4.5小时,没问题。
第一反应不禁怀疑,srs兼容性有问题。随后用obs推流到srs和Nginx-rtmp,超过5个小时都没问题。
仔细阅读rtmp_specification_1.0.pdf 6.1.2 Chunk Message Header
page16开始。
yasea只发送了Type=0和Type=3的Chunks。
唯一不确定的环节就是extended timestamp的使用。
于是查看yasea代码和srs代码,既然是时间戳溢出处理的问题,就专注于这个角度。
每次测试都要等待4.5个小时,实在不应该。
于是找到对应时间戳的地方,加一个初始值。对应于:
audio.getHeader().setAbsoluteTimestamp(dts+0x00ffefff);
video.getHeader().setAbsoluteTimestamp(dts+0x00ffefff);
rtmpPacket.getHeader().setAbsoluteTimestamp((int) chunkStreamInfo.markAbsoluteTimestampTx()+0x00ffefff);
这样很快就运行到ffffff了。几分钟。
在分包发送的接口处打印时间戳日志,extended timestamp对应于:
com/github/faucamp/simplertmp/packets/RtmpHeader.java中writeTo()中
case TYPE_0_FULL: 和 case TYPE_3_RELATIVE_SINGLE_BYTE:
第一次尝试:
去掉Type=3中,Util.writeUnsignedInt32(out, extendedTimestamp);
注释掉下面一行:
Util.writeUnsignedInt32(out, extendedTimestamp);
推流时间戳超过0xffffff,推srs正常,推Nginx-rtmp报错。
第二次尝试:
Type=3的extended timestamp保证在Type=0后使用
只需要更改下面一句:
if (absoluteTimestamp >= 0xffffff)
改成
if (extendedTimestamp >= 0)
推流时间戳超过0xffffff,推srs偶尔报错,推Nginx-rtmp正常。
偶尔还是会出现问题。原因未明。
第三次尝试:
Type=3的时间戳和同一包分chunk时Type=0的时间戳,保持一致。
在上一次基础上改Type=3的代码如下:
推流时间戳超过0xffffff,推srs正常,推Nginx-rtmp正常。
然而在rtmp_specification_1.0.pdf文档中确实没有明确的规定。这个时间戳应该怎么做。
微信群里和srs、yasea两个项目的作者沟通,发现确实是这个问题。
srs大神winlin科普了一下,考虑周全的话,两种做法都要兼容。
如果Type=3有时间戳,这个时间戳就应该等于同一包中Type=0的时间戳。
如果Type=3没有时间戳。就用同一包中Type=0的传上来的时间戳。
实际上ffmpeg是这么做的,srs也是这么做的,Nginx-rtmp并没有兼容两者。
为了简单实用Type=1或者2,就不要发了。
所以是yasea引用的faucamp/simplertmp库有bug。
相关的问题,winlin的博客也有提到。参考:http://blog.csdn.net/win_lin/article/details/13363699
rtmp推流时间戳兼容问题的更多相关文章
- ffmpeg+EasyDSS流媒体服务器实现稳定的rtmp推流直播
本文转自EasyDarwin团队成员Alex的博客:http://blog.csdn.net/cai6811376/article/details/74783269 需求 在做EasyDSS开发时,总 ...
- EasyRTMP实现的rtmp推流的基本协议流程
EasyRTMP介绍 EasyRTMP是结合了多种音视频缓存及网络技术的一个rtmp直播推流端,包括:圆形缓冲区(circular buffer).智能丢帧.自动重连.rtmp协议等等多种技术,能够非 ...
- 3款知名RTMP推流模块比较:OBS VS SmartPublisher VS Flash Media Live Encoder
OBS 功能强大,几乎所有你想要的场景它都有,用起来很顺手.可以将桌面.摄像头.程序窗口通过rtmp推送到流媒体服务器上. 当然如果你是开发者,想基于OBS做二次开发,实现二次产品化的化,难度比较大, ...
- 安卓直播开源: RTMP 推流SDK
前些日子在github上提交了基于GPUImage的IOS直播推流SDK(https://github.com/runner365/GPUImageRtmpPush) 最近整理了android直播推流 ...
- C++ 实现的netstat -an 的功能<转>-目的为获取rtmp推流地址如果是域名的话查看1935的ip
目的可能是为了获取rtmp真正的推流ip 如果rtmp推流地址是域名,往CDN推流的话,需要nslookup 的那种DNS解析,然后获取的几个ip 可以使用netstat -n 等命令查看 1935 ...
- 前端多媒体(7)—— 在浏览器中实现rtmp推流
示例:https://young-cowboy.github.io/gallery/rtmp_client/index.html 在国内的直播场景中通常使用,rtmp协议作为推流协议.RTMP是Rea ...
- win10下一分钟快速搭建rtmp推流服务器
为了让大家少踩笔者踩过的坑,目前将工作中搭建rtmp推流服务器的步骤总结如下: 步骤1: 下载 nginx 1.7.11.3 Gryphon 下载链接: http://nginx-win.ecsds. ...
- Android 安卓直播开源: RTMP 推流SDK
前些日子在github上提交了基于GPUImage的iOS直播推流SDK(https://github.com/runner365/GPUImageRtmpPush) 最近整理了Android直播推流 ...
- 命令行利用ffmpeg实现rtmp推流《转》
ffmpeg在以前介绍过,是一个相当强大的工具,我们这次利用它实现rtmp推流(最终推流地址统一为rtmp://127.0.0.1:1935/live/123). 1.首先下载ffmpeg和ffpla ...
随机推荐
- HDU 1874 畅通工程续【Floyd算法实现】
畅通工程续 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- UVA11039-Building designing
Building designing Time limit: 3.000 seconds An architect wants to design a very high building. The ...
- io流读取文件
package test; import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import ...
- C#面试题整理(1)
最近在看CLR VIA C#,发现了一些案例很适合来做面试题.特此整理: 1,System.Object里的GetType方法是否为虚函数?说出理由. 答案:不是,因为C#是一种类型安全的语言,如果覆 ...
- VMware workstation 虚拟机中安装乌班图及其兼容性问题
之前我在虚拟机中安装乌班图,是先安装好虚拟机,然后将预先下载好的乌班图镜像文件导入安装,这样安装起来还是有些繁琐的,中间要设置好多东西.今天领导给我拷了个虚拟机,还有乌班图的安装文件,是这样的. 对于 ...
- Vue2反向代理
前一段时间写了一个vue2的小项目,用的是vue-cli脚手架搭建的项目,项目里需要跨域,但又不能使用jsonp,上网查了一下,发现有一个之前没接触过的词语--反向代理. 什么是"反向代 ...
- lnmp一键安装的卸载
http://blog.csdn.net/lansetiankong12/article/details/48130507 如果是lnmp一键安装的 进入安装包目录 [root@www home]# ...
- 把织梦安装到子目录,不读取CSS 没有样式?
我在A5上找的一个模板,照着说明安装到根目录就正常,我想安装到子目录下面,结果很乱 应该是不读取CSS. {dede:global.cfg_templets_skin/}/style/about.cs ...
- 修改DeDe标签Pagelist分页样式,自定义分页样式
我们在用dede仿站的时候,调用文章列表页的分页时,我们会用到: {dede:pagelist listitem="info,index,end,pre,next,pageno" ...
- iOS开发中一些有用的小代码
1.判断邮箱格式是否正确的代码: //利用正则表达式验证 -(BOOL)isValidateEmail:(NSString *)email { NSString *emailRegex = @&q ...