天天看点

关于Android上ijkplayer-k0.8.8版本,播放rtsp延迟问题的一种解决方案

前言

我的应用场景是Android上播放一种可以提供rtsp码流的三方摄像头的视频画面

要求具有实时性,延迟不能太大,除开硬件本身性能和网络波动的因素的影响,先保障网络稳定,硬件配置足够的情况下,播放视频延迟符合要求

解决办法
  • 网上都是设置一些option,各位看着抄就行,无非是用硬解码,设置无缓存
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
// 支持硬解 1:开启 O:关闭
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-avc", 1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-mpeg4", 1);
// 自动旋屏
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"no-time-adjust",1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"infbuf",1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"packet-buffering",0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT,"fflags","nobuffer");
           
  • 后来发现还是有延迟,在网络稳定的情况下,找了一个cmake编译的ijkplayer版本,测试了一会儿发现,实际造成延迟的原因是,渲染速度跟不上解码速度

    查了下ff_fpaly.c中的视频渲染线程

static int video_refresh_thread(void *arg)
{
    FFPlayer *ffp = arg;
    VideoState *is = ffp->is;
    double remaining_time = 0.0;
    while (!is->abort_request) {
        if (remaining_time > 0.0)
            av_usleep((int)(int64_t)(remaining_time * 1000000.0));
        remaining_time = REFRESH_RATE;//这里有刷新速率限制
        if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh))
            video_refresh(ffp, &remaining_time);
    }

    return 0;
}
           

以上代码中,REFRESH_RATE速率限制会造成渲染线程有一定的睡眠时间

这里默认配置REFRESH_RATE为0.01,我们可以尝试调小这个值,在一定情况下可以解决延迟问题,但是这样修改也不彻底,我们继续查看渲染中的延迟计算

在static void video_refresh(FFPlayer *opaque, double *remaining_time)方法中

static void video_refresh(FFPlayer *opaque, double *remaining_time)
{
.......
			/* compute nominal last_duration */
            last_duration = vp_duration(is, lastvp, vp);
            delay = 0;//compute_target_delay(ffp, last_duration, is);//计算渲染延时
.......
}
           

实时流不需要做延时计算,因为码流是实时的,实际解码不会解得过多的frame,那么我们直接将上面的delay变量置0即可,通过以上修改即可解决播放rtsp码流的延迟问题