rtmp时间戳pts、dts矫正解决卡顿快放慢放问题与倍速播放的实现

  • 问题分析与解决思路
    • 控流思路
    • 倍速播放思路
  • 实现方式
    • 1.控流,矫正pts、dts来解决播放卡顿,画面抖动等问题。匀速推流
    • 2.倍速播放

码云(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回调函数的音视频数据源等。下面对这些源如何控流进行逐一分析。

  1. rtsp源:因为rtsp是直播源,所以拉rtsp的流时,拉流速度播放速度是一定保持一致的,而推流速度依赖于拉流速度,因此rtsp的源无需做特殊处理,一般情况下拉流速度推流速度播放速度是恒定的。
  2. rtmp源:与rtsp源同理,一般情况下无需特殊处理,默认保持三个速度是一致的。
  3. mp4/flv等文件源:这些数据源在进行转码或转封装时,首先需要使用I/O流循环读取文件的数据,然而I/O流无法做到精准控制每帧视频数据的读取速度,故拉流速度是不可控的,默认情况下是由I/O读取速度控制的。而播放速度依赖于推流速度,推流速度过快,数据会缓冲到如nginx等流媒体中,播放器根据缓冲的数据的PTS来进行播放的,会一点点读取缓冲的数据来进行画面渲染;而推流速度过慢,导致nginx中没有缓冲的数据,播放器就会造成卡顿,等待下一帧的数据推送过来才会渲染。此类文件源只需控制推流速度,即可影响到拉流速度播放速度推流速度保持一致。
  4. 回调的码流数据:与mp4/flv等文件源情况类似,除非可以精准控制回调每一帧数据的速度,否则也只能控制推流速度来间接控制拉流速度。

倍速播放思路

倍速播放的实现方式有以下两种:

  1. 改变dts、pts:假如1s的视频含25帧,设置1s播50帧即可实现2倍速播放,4倍速,8倍速同理,让播放器播放1s内播放更多的帧。但是上文提到,播放器播放时是根据pts时间戳来进行播放的,所以即使推了再多的帧,每帧的pts间隔不变,播放器任然是匀速播放。因此例如2倍速播放需要满足以下两个条件:

1.每秒推送的帧翻倍
2.每帧的pts时间戳间隔减半
其他倍速同理

  1. 抽帧:改变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 && err_index < 5;) {pkt = grabber.grabPacket();// 空包if (pkt == null || pkt.size() <= 0 || pkt.data() == null) {                                       no_pkt_index++;continue;}// 获取到的pkt的dts,pts异常,将此包丢弃掉。if (pkt.dts() == avutil.AV_NOPTS_VALUE && pkt.pts() == avutil.AV_NOPTS_VALUE || pkt.pts() < dts) {err_index++;av_packet_unref(pkt);continue;}// 矫正pkt的dts,pts每次不从0开始累加所导致的播放器无法续播问题pkt.pts(pts);pkt.dts(dts);err_index += (recorder.recordPacket(pkt) ? 0 : 1);// 帧数加1pktindex++;// eg: 每秒25帧,如果推第1帧到第25的时间差小于1秒,则休眠1000-时间差;pktindex,firstpkttime重置,以保证每秒都能退出相应的帧数// 如果大于1秒,则继续执行if (pktindex >= framerate) {long nowtime = System.currentTimeMillis();if (nowtime - firstpkttime  < 1000) {Thread.sleep(1000 - (nowtime - firstpkttime ));}firstpkttime = System.currentTimeMillis();pktindex = 0;}// 计算出pts、dts时间戳间隔timebase = grabber.getFormatContext().streams(pkt.stream_index()).time_base().den();// pts,dts累加pts += (timebase / (int) framerate);dts += (timebase / (int) framerate);// 将缓存空间的引用计数-1,并将Packet中的其他字段设为初始值。如果引用计数为0,自动的释放缓存空间。av_packet_unref(pkt);}

2.倍速播放

         // 每一秒第一帧的时间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 && err_index < 5;) {// 暂停开关,改变标志位if (playstatus) {Thread.sleep(100);continue;}// 记录获取每一包的时间starttime = System.currentTimeMillis();pkt = grabber.grabPacket();// 空包if (pkt == null || pkt.size() <= 0 || pkt.data() == null) {                                      no_pkt_index++;continue;}// 获取到的pkt的dts,pts异常,将此包丢弃掉。if (pkt.dts() == avutil.AV_NOPTS_VALUE && pkt.pts() == avutil.AV_NOPTS_VALUE || pkt.pts() < dts) {err_index++;av_packet_unref(pkt);continue;}             // 矫正sdk回调数据的dts,pts每次不从0开始累加所导致的播放器无法续播问题pkt.pts(pts);pkt.dts(dts);err_index += (recorder.recordPacket(pkt) ? 0 : 1);
// 帧数加1pktindex++;// eg: 每秒25帧,如果推第1帧到第25的时间差小于1秒,则休眠1000-时间差;pktindex,firstpkttime重置,以保证每秒都能退出相应的帧数// 如果大于1秒,则继续执行if (pktindex >= framerate / speed) {long nowtime = System.currentTimeMillis();if (nowtime - firstpkttime  < 1000) {Thread.sleep(1000 - (nowtime - firstpkttime ));}firstpkttime = System.currentTimeMillis();pktindex = 0;}// 计算出pts、dts时间戳间隔timebase = grabber.getFormatContext().streams(pkt.stream_index()).time_base().den();// pts,dts累加,倍速播放时,dts、pts相应翻倍或减半,使播放器没s播对应数量的帧pts += (timebase / (int) framerate) / speed;dts += (timebase / (int) framerate) / speed;// 将缓存空间的引用计数-1,并将Packet中的其他字段设为初始值。如果引用计数为0,自动的释放缓存空间。av_packet_unref(pkt);}

rtmp时间戳pts、dts矫正解决卡顿快放慢放问题与倍速播放的实现相关推荐

  1. android8卡顿,看完就明白为什么安卓手机卡顿,这个技巧教你解决卡顿

    原标题:看完就明白为什么安卓手机卡顿,这个技巧教你解决卡顿 Android由源代码开放,所以安卓手机拥有更多的黑科技功能.很多安卓用户觉得手机卡顿,其实是没有好好利用这些神奇功能.下面笔者就为大家介绍 ...

  2. Macbook 安装Android Studio以及解决卡顿问题

    安装JDK,参考文章 http://blog.csdn.net/lzp2015/article/details/78307623 1. 下载AndroidStudio及SDK 下载地址:http:// ...

  3. Premiere高分辨率视频代理加速预览解决卡顿ProxyPresets v3版PR预设下载

    Premiere高分辨率视频代理加速预览解决卡顿ProxyPresets v3版PR预设下载 200多个Premiere pro cc代理预设,85种摄像机.只需在列表中选择您的代理预设,然后开始创建 ...

  4. 卡顿严重_魔兽怀旧服:安其拉开门二测结果出炉,暴雪依然无法解决卡顿问题...

    前言:上周魔兽世界怀旧服安其拉开门压力测试结束之后,暴雪便宣布将会在今天开启第二轮压力测试,然而这一次的压力测试结果同样不太理想. 安其拉开门二次压力测试结果 暴雪在今天如期开放了安其拉开门的第二次压 ...

  5. Android App解决卡顿慢之内存抖动及内存泄漏(发现和定位)

    内存抖动是指在短时间内有大量的对象被创建或者被回收的现象,内存抖动出现原因主要是频繁(很重要)在循环里创建对象(导致大量对象在短时间内被创建,由于新对象是要占用内存空间的而且是频繁,如果一次或者两次在 ...

  6. lolfps高但画面不流畅_你吃鸡卡吗,超详细和平精英画面设置教程,解决卡顿,主播都在用...

    相信很多人玩吃鸡的时候都会遇到手机卡顿,画面不流畅等问题,有时候正在和人钢枪,但总感觉慢人一步. 这个时候就会想是不是自己手机性能太差了,但又不是很想为了玩游戏专门花四五千买个手机. 怎么办呢? 其实 ...

  7. 安卓手机玩游戏卡顿怎么解决_手机卡顿怎么办?教你3个实用解决方法,两分钟解决卡顿难题!...

    相信更多人都知道这种情况,手机越使越卡,其中最严重的就是当属安卓手机,在使用一两年之后,有的时候会卡死机,这时候相信很多人都在想改换新手机了.今天小编教大家几个小技巧,让你的手机如新机般流畅. 一.更 ...

  8. idea卡顿的解决方法_lt;绝地求生/PUBG/解决卡顿方法(停机9小时)维护gt;9月16日(星期三) 08点30分amp;崩溃...

    [正式服不停机维护公告] 我们将在北京时间10月7日(星期三) 10点开始正式服的不停机维护. - 维护开始时间:10月7日(星期三) 10点 - 维护内容:优化服务器以及BUG修复 1. 修复了在四 ...

  9. 【来自项目的技术点】— 聊聊键盘长按的时候解决卡顿方案

    当我们做游戏的时候,很多时候遇用到键盘事件长按的的时候第一下卡顿的情况,怎么解决呢? 以下是我的解决方案,建议复制到编辑器上直接调试 代码里面有我思考的过程,大家可以参考 思考过程 //当按下的时候改 ...

最新文章

  1. Python分析离散心率信号(下)
  2. python进程监控 supervisor_python supervisor进程监控工具的使用
  3. kafka修改分区数_Kafka笔记
  4. 【Java反射】反射机制性能问题、反射操作泛型
  5. Java、Mysql、MyBatis 中枚举 enum 的使用
  6. 《云计算:概念、技术与架构》一1.5 书写惯例
  7. 计算机等级的判断,计算机等级考试一级WPS判断题及答案
  8. BPSK调制解调matlab仿真
  9. SHOPNC 插件机制的实现记录
  10. tomcat 配置文件 conf/server.xml 中的 appBase和docBase
  11. 蚂蚁金服副总裁蒋国飞:技术全面开放,与合作伙伴共发展
  12. 公务员没考上……我做了投资
  13. Linux下串口编程
  14. ajax和axios封装
  15. Tosca:定义元宇宙世界的时尚生活方式
  16. 详解基于罗德里格斯(Rodrigues)公式由旋转向量到旋转矩阵的 Python 实现
  17. 云原生CAx软件:多租户的认证
  18. 行楷练习5 回折撇、连撇
  19. 没有公网IP,怎样远程查看视频监控?
  20. 软件安装管家——pr2019安装包及教程

热门文章

  1. ufo末日余晖java下载_幽浮:末日余晖
  2. OpenCV的下载、安装与配置
  3. 第十一届蓝桥杯 ——数青蛙
  4. 光的反射与折射的向量计算
  5. unity shader立方体纹理中的反射以及折射效果的实现
  6. 理科生可以报湖师大计算机系吗,2020湖南师范大学冷门专业排名:湖师大数学系好就业吗?...
  7. 证券行业成功案例:国都证券网上交易容错系统(转)
  8. 个人觉得这篇cxf的文章还不错
  9. 爱不释手!2014年最佳的20个优秀网页设计
  10. 一步一步学linux操作系统: 32 输入与输出系统_ 块设备二_直接 I/O,缓存 I/O 与 块设备数据写入请求