rtmp时间戳pts、dts矫正解决卡顿快放慢放问题与倍速播放的实现
码云(Gitee)主页:https://gitee.com/banmajio
github主页:https://github.com/banmajio
个人博客:banmajio’s blog
海康sdk二次开发系列文章
海康sdk捕获码流数据通过JavaCV推成rtmp流的实现思路(PS流转封装RTMP)
海康sdk进行历史回放时,码流数据回调过快问题的解决方法
海康sdk项目(java)部署Linux环境相关问题总结
海康sdk部署Linux环境下无法播放子码流的问题
海康sdk项目部署Linux系统时出现java.lang.UnstisfiedLinkError:jnidispatch(xxx)not found in resource path错误
通过海康sdk捕获码流数据实现抓图功能
通过海康sdk实现指定时间段内的录像文件下载
问题分析与解决思路
控流思路
在进行流媒体推rtmp无插件播放时,要想实现倍速播放和暂停播放、恢复播放与抓图功能时首先要保证的一点就是:拉流速度=推流速度=播放速度,只有这样才能保证当调用接口时生成的抓图图片时间点或者暂停恢复时间点与画面一致,也只有保证这三者的速度一致才能使倍速播放时播放器及时响应。而拉流视频源存在几种情况:rtsp源、rtmp源、mp4/flv等文件源、例如海康sdk回调函数的音视频数据源等。下面对这些源如何控流进行逐一分析。
- rtsp源:因为rtsp是直播源,所以拉rtsp的流时,拉流速度与播放速度是一定保持一致的,而推流速度依赖于拉流速度,因此rtsp的源无需做特殊处理,一般情况下拉流速度,推流速度,播放速度是恒定的。
- rtmp源:与rtsp源同理,一般情况下无需特殊处理,默认保持三个速度是一致的。
- mp4/flv等文件源:这些数据源在进行转码或转封装时,首先需要使用I/O流循环读取文件的数据,然而I/O流无法做到精准控制每帧视频数据的读取速度,故拉流速度是不可控的,默认情况下是由I/O读取速度控制的。而播放速度依赖于推流速度,推流速度过快,数据会缓冲到如nginx等流媒体中,播放器根据缓冲的数据的PTS来进行播放的,会一点点读取缓冲的数据来进行画面渲染;而推流速度过慢,导致nginx中没有缓冲的数据,播放器就会造成卡顿,等待下一帧的数据推送过来才会渲染。此类文件源只需控制推流速度,即可影响到拉流速度与播放速度与推流速度保持一致。
- 回调的码流数据:与mp4/flv等文件源情况类似,除非可以精准控制回调每一帧数据的速度,否则也只能控制推流速度来间接控制拉流速度。
倍速播放思路
倍速播放的实现方式有以下两种:
- 改变dts、pts:假如1s的视频含25帧,设置1s播50帧即可实现2倍速播放,4倍速,8倍速同理,让播放器播放1s内播放更多的帧。但是上文提到,播放器播放时是根据pts时间戳来进行播放的,所以即使推了再多的帧,每帧的pts间隔不变,播放器任然是匀速播放。因此例如2倍速播放需要满足以下两个条件:
1.每秒推送的帧翻倍
2.每帧的pts时间戳间隔减半
其他倍速同理
- 抽帧:改变dts、pts的方式实际是推送更多的帧以及让播放器播更多的帧。而抽帧的是指1倍速本来要播第1帧到第25帧;当两倍速的时候,1s要播第1帧到第50帧的视频,在不改变dts,pts的情况下,可以从50帧内每隔1个帧就丢一个帧出去。实际测试中发现画面跳帧严重,应该是丢了帧之后,播放区无法连贯显示其余的帧,只能显示关键帧,所以这种方式不考虑!!
实现方式
1.控流,矫正pts、dts来解决播放卡顿,画面抖动等问题。匀速推流
// 每一秒第一帧的时间
long firstpkttime = System.currentTimeMillis();
int pktindex = 0;
// dts\pts从0开始累加
long dts = 0;
long pts = 0;
for (int no_pkt_index = 0; no_pkt_index < 5