直播技术总结(三)ijkplayer的一些问题优化记录

转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/57075026

前言:ijkplayer中一些问题记录优化,看下Agenda:

  • 在弱网时如何优化
  • ijkplayer播放卡顿如何优化
  • 如何支持https链接播放?
  • 如何降低ijkplayer延迟效应
  • ijkplayer中音视频同步,是如何做的?

一、在弱网时如何优化

好的网络下视音频能够得到及时的发送,不会造成视音频数据在本地的堆积,直播效果流畅,延时较小。而在弱网网络环境下,视音频数据发送不出去,则需要我们对视音频数据进行处理。差网络环境下对视音频数据一般有四种处理方式:缓存区设计、网络检测、丢帧处理、降码率处理。

1、缓冲区设计

视音频数据传入缓冲区,发送者从缓冲区获取数据进行发送,这样就形成了一个异步的生产者消费者模式。生产者只需要将采集、编码后的视音频数据推送到缓冲区,而消费者则负责从这个缓冲区里面取出数据发送。

视音频缓冲区

上图中只显示了视频帧,显然里面也有相应的音频帧。要构建异步的生产者消费者模式,java中使用LinkedBlockingQueue,可以对之后进行丢帧、插入、取出等处理。

2、网络检测

差网络处理过程中一个重要的过程是网络检测,当网络变差的时候能够快速地检测出来,然后进行相应的处理,这样对网络反应就比较灵敏,效果就会好很多。通过实时计算每秒输入缓冲区的数据和发送出去数据,如果发送出去的数据小于输入缓冲区的数据,那么说明网络带宽不行,这时候缓冲区的数据会持续增多,这时候就要启动相应的机制。

3、丢帧处理

当检测到网络变差的时候,丢帧是一个很好的应对机制。视频经过编码后有关键帧和非关键帧,关键帧也就是一副完整的图片,而非关键帧描述图像的相对变化。

丢帧策略多钟多样,可以自行定义,一个需要注意的地方是:如果要丢弃P帧(非关键帧),那么需要丢弃两个关键帧之间的所有非关键帧,不然的话会出现马赛克。对于丢帧策略的设计因需求而异,可以自行进行设计。如下我一个丢帧实例:

当CPU在处理视频帧的时候处理得太慢,默认的音视频同步方案是视频同步到音频, 导致了音频播放过快,视频跟不上。

在ff_ffplay_options.h中,找到如下代码:

可以通过修改 framedrop 的值来解决不同步的问题,framedrop 是在视频帧处理不过来的时候丢弃一些帧达到同步的效果。具体设置,在上层Java层中IjkVideoView中:

默认ijkplayer中是1,你可以自行,修改这个值。

4、降码率

在Android中,如果使用了硬编进行编码,在差网络环境下,我们可以实时改变硬编的码率,从而使直播更为流畅。当检测到网络环境较差的时候,在丢帧的同时,我们也可以降低视音频的码率。在Android sdk版本大于等于19的时候,可以通过传递参数给MediaCodec,从而改变硬编编码器出来数据的码率。

Bundle bitrate = new Bundle();bitrate.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, bps * 1024);
mMediaCodec.setParameters(bitrate);

二、ijkplayer播放卡顿如何优化

在做音频播放的时候,使用的是开源的ijkplayer播放器,ijkplayer解码使用的是ffmpeg,声音输出使用的是audiotrack,在某机型上面播放遇到锁屏、返回后台、点击home键的时候会出现声音卡顿的现象,会输出下面的log

W/AudioTrack: releaseBuffer() track 0xcce8b600 disabled due to previous underrun, restarting

我实现播放调用步骤是在AsyncTask中,查阅资料发现是因为在线程中播放造成的问题,经过查看asynctask构造方法发现,asynctask会把线程的优先级设置为THREAD_PRIORITY_BACKGROUND后台线程,于是我将线程的优先级设置为THREAD_PRIORITY_URGENT_AUDIO,解决了播放卡顿的问题,我猜测播放线程优先级降低,系统分配时间片会减少,会导致底层ijk读数据输出数据时得不到及时的回应,audiotrack频繁的releasebuffer,restarting声道,造成卡顿。

本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/57075026

三、如何支持https链接播放?

如果你的项目要进行加密播放HLS协议的视频,要想支持https,须要在普通编译的基础上,进行一些配置。

接下来我们来编译openssl

1.init openssl

$ cd ..    进入到ijkplayer的目下
$ ./init-android-openssl.sh   去远程仓库拉取openssl的远程代码,如果是iOS的,这里是init-ios-openssl.h

2.compile openssl

$ cd android/contrib
$ ./compile-openssl.sh clean
$ ./compile-openssl.sh all

经过以上步骤已经编译好openssl了,然后我们执行一下方法

$./compile-ffmpeg.sh clean
     编译ffmpeg软解码库,这个过程会生成各种架构的ffmpeg 这个过程比较耗时
$./compile-ffmpeg.sh all

四、如何降低ijkplayer延迟效应

通过修改源文件,因为ijkplayer实际上是基于ffplay.c实现的:

ijkmedia>ijkplayer>ff_ffplay.c这个文件

static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) {
    if(vp->serial == nextvp->serial) {
        doubleduration = nextvp->pts - vp->pts;
    if(isnan(duration) || duration <=0|| duration > is->max_frame_duration)
        return vp->duration;
      else
       return duration;
   }else{
    return 0.0;
  }
}

直接换成:

static double vp_duration(VideoState*is,Frame*vp,Frame*nextvp) {
     return vp->duration;
}

2、接着改staticintffplay_video_thread这个方法:

static int ffplay_video_thread(void*arg){
    FFPlayer*ffp = arg;
    VideoState*is = ffp->is;
    AVFrame*frame =av_frame_alloc();
    doublepts;
    doubleduration;
    intret;
    AVRationaltb = is->video_st->time_base;
    //注释如下一行代码
    //AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL);

    //......省略部分代码

    //注释如下一行代码
    //duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational)  {frame_rate.den, frame_rate.num}) : 0);
    //直接这里写出
    duration=0.01;

   //........
}

改完后发现延迟明显降低,高分辨率开启硬解码,不支持的话会自动切换到软解,就算开启mediacodec,如果设备不支持,显示的解码器也是avcodec软解。

本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/57075026

五、ijkplayer中音视频同步,是如何做的?

对于播放器来说,音视频同步是一个关键点,同时也是一个难点,同步效果的好坏,直接决定着播放器的质量。通常音视频同步的解决方案就是选择一个参考时钟(主 clock),播放时读取音视频帧上的时间戳,同时参考当前时钟参考时钟(主 clock)上的时间来安排播放。如下图所示:

  • 如果音视频帧的播放时间大于当前参考时钟上的时间,则不急于播放该帧,直到参考时钟达到该帧的时间戳;
  • 如果音视频帧的时间戳小于当前参考时钟上的时间,则需要“尽快”播放该帧或丢弃,以便播放进度追上参考时钟。

参考时钟的选择也有多种方式:

  • 选取视频时间戳作为参考时钟源
  • 选取音频时间戳作为参考时钟源
  • 选取外部时间作为参考时钟源

考虑人对视频、和音频的敏感度,在存在音频的情况下,优先选择音频作为主时钟源。

ijkplayer在默认情况下也是使用音频作为参考时钟源,我们可以找到ff_ffplay.c文件中,处理同步的过程主要在视频渲染video_refresh_thread的线程中:

从上述实现可以看出,该方法中主要循环做两件事情:

  • 休眠等待,remaining_time的计算在video_refresh中
  • 调用video_refresh方法,刷新视频帧

可见同步的重点是在video_refresh中,下面看该方法一些关键部分:

lastvp是上一帧,vp是当前帧,last_duration则是根据当前帧和上一帧的pts(Presentation Time Stamp。PTS主要用于度量解码后的视频帧什么时候被显示出来),计算出来上一帧的显示时间,经过compute_target_delay方法,计算出显示当前帧需要等待的时间。

在compute_target_delay函数中,如果发现当前主Clock源不是video,则计算当前视频时钟与主时钟的差值:

  • 如果当前视频帧落后于主时钟源,则需要减小下一帧画面的等待时间;
  • 如果视频帧超前,并且该帧的显示时间大于显示更新门槛,则显示下一帧的时间为超前的时间差加上上一帧的显示时间
  • 如果视频帧超前,并且上一帧的显示时间小于显示更新门槛,则采取加倍延时的策略。

回到video_refresh函数中,有如下逻辑:

frame_timer实际上就是上一帧的播放时间,而frame_timer + delay实际上就是当前这一帧的播放时间,如果系统时间还没有到当前这一帧的播放时间,直接跳转至display,而此时is->force_refresh变量为0,不显示当前帧,进入video_refresh_thread中下一次循环,并睡眠等待。

如果当前这一帧的播放时间已经过了,并且其和当前系统时间的差值超过了AV_SYNC_THRESHOLD_MAX,则将当前这一帧的播放时间改为系统时间,并在后续判断是否需要丢帧,其目的是为后面帧的播放时间重新调整frame_timer,如果缓冲区中有更多的数据,并且当前的时间已经大于当前帧的持续显示时间,则丢弃当前帧,尝试显示下一帧。

否则进入正常显示当前帧的流程,调用video_display2开始渲染。

第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。

如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易

时间: 2024-10-11 07:11:26

直播技术总结(三)ijkplayer的一些问题优化记录的相关文章

HLS直播技术方案及踩过的坑

关于老码农的个人信息,请看这里:http://www.koulianbing.com/?page_id=12 一.为什么是IJKPlayer 在基础技术方面,后端有比较成熟的系统,就不再说了,这里说说客户端方面. 有直播就会有弹幕,基本上是标配了. 字幕方面bilibili开源了一个Android的项目,不过IOS却没有,这个只能自己写了,不过本身这个东西技术方案没有什么太高深的东西,建立一个HTTP连接,不停地读数据就好了,如果关闭字幕,就把连接断掉.在显示方面可能要考虑一些细节问题,像速度.

直播技术简单介绍(非原创)

文章大纲 一.视频直播原理介绍二.视频直播代码演示(Android)三.项目源码下载四.参考文章 一.视频直播原理介绍 1. 视频直播技术流程 视频直播的流程可以分为如下几步:采集 —>处理—>编码和封装—>推流到服务器—>服务器流分发—>播放器流播放 2. 采集 采集是整个视频推流过程中的第一个环节,它从系统的采集设备中获取原始视频数据,将其输出到下一个环节.视频的采集涉及两方面数据的采集:音频采集和图像采集,它们分别对应两种完全不同的输入源和数据格式. 2.1 音频采集音

移动直播技术秒开优化经验

现今移动直播技术上的挑战要远远难于传统设备或电脑直播,其完整的处理环节包括但不限于:音视频采集.美颜/滤镜/特效处理.编码.封包.推流.转码.分发.解码/渲染/播放等. 直播常见的问题包括 主播在不稳定的网络环境下如何稳定推流? 偏远地区的观众如何高清流畅观看直播? 直播卡顿时如何智能切换线路? 如何精确度量直播质量指标并实时调整? 移动设备上不同的芯片平台如何高性能编码和渲染视频? 美颜等滤镜特效处理怎么做? 如何实现播放秒开? 如何保障直播持续播放流畅不卡顿? 视频.直播等基础知识什么是视频

HTTP Live Streaming直播(iOS直播)技术分析与实现

http://www.cnblogs.com/haibindev/archive/2013/01/30/2880764.html 不经意间发现,大半年没写博客了,自觉汗颜.实则2012后半年,家中的事一样接着一样发生,实在是没有时间.快过年了,总算忙里偷闲,把最近的一些技术成果,总结成了文章,与大家分享. 前些日子,也是项目需要,花了一些时间研究了HTTP Live Streaming(HLS)技术,并实现了一个HLS编码器HLSLiveEncoder,当然,C++写的.其功能是采集摄像头与麦克

视频直播技术-视频-编码-传输-秒开等&lt;转&gt;

转载地址:http://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=2653547042&idx=1&sn=26d8728548a6b5b657079eeab121e283&scene=21#wechat_redirect 现今移动直播技术上的挑战要远远难于传统设备或电脑直播,其完整的处理环节包括但不限于:音视频采集.美颜/滤镜/特效处理.编码.封包.推流.转码.分发.解码/渲染/播放等. 视频.直播等基础知识 什么是视频?

转: HTTP Live Streaming直播(iOS直播)技术分析与实现

http://www.cnblogs.com/haibindev/archive/2013/01/30/2880764.html HTTP Live Streaming直播(iOS直播)技术分析与实现 不经意间发现,大半年没写博客了,自觉汗颜.实则2012后半年,家中的事一样接着一样发生,实在是没有时间.快过年了,总算忙里偷闲,把最近的一些技术成果,总结成了文章,与大家分享. 前些日子,也是项目需要,花了一些时间研究了HTTP Live Streaming(HLS)技术,并实现了一个HLS编码器

「视频直播技术详解」系列之四:推流和传输

关于直播的技术文章不少,成体系的不多.我们将用七篇文章,更系统化地介绍当下大热的视频直播各环节的关键技术,帮助视频直播创业者们更全面.深入地了解视频直播技术,更好地技术选型. 在上一期中,我们介绍了讲解编码和封装. 本篇是<解密视频直播技术>系列之四:推流和传输.推流是直播的第一公里,直播的推流对这个直播链路影响非常大,如果推流的网络不稳定,无论我们如何做优化,观众的体验都会很糟糕.所以也是我们排查问题的第一步,如何系统地解决这类问题需要我们对相关理论有基础的认识. 本系列文章大纲如下: (一

直播技术(从服务端到客户端)二

播放 在上一篇文章中,我们叙述了直播技术的环境配置(包括服务端nginx,nginx-rtmp-module, ffmpeg, android编译,ios编译).从本文开始,我们将叙述播放相关的东西,播放是直播技术中关键的一步,它包括很多技术如:解码,缩放,时间基线选择,缓存队列,画面渲染,声音播放等等.我将分为三个部分为大家讲述整个播放流程: Android 第一部分是基于NativeWindow的视频渲染,主要使用的OpenGL ES2通过传入surface来将视频数据渲染到surface上

直播技术简介--简进祥

一.前言 随着时代的改变,人们对于内容的需求也不断提高,从文字到图片到音频.视频,可能到以后的 VR 直播是一个非常烧钱的项目,需要足够多的带宽,足够好的服务器,比如负载均衡,这里还会扯到云等等,保证大数据并发,百万人同时访问等等 涉及到一些专业的视频相关的知识,也需要很长时间的学习,如解码(硬解.软解).编码.转码,还有底层的 ffmpeg(录制.转换以及流化音视频的完整解决方案) 涉及到 即时通讯 和 美颜处理,其中美颜涉及到 OpenGL ,以及基于 OpenGL 的图像/视频处理框架 G