ijkplayer音视频不同步解决方案

作者: 耕地 | 来源:发表于2016-11-01 18:10 被阅读3815次

    ljkplayer是一款做视频直播的框架, 网上很多视频项目都使用了这个框架。这里不再讲如何集成ijkplayer,推荐一篇详细的集成文章

    一、下载ijkplayer

    下载地址:https://github.com/Bilibili/ijkplayer
    下载完成后解压,根据github上作者的说明下载ffmpeg,编译ffmpeg:

    首先安装环境 然后下载编译ffmpeg

    二、不同步的解决方案

    我在使用ijkplayer的时候主要遇到了3个问题
    1. 音视频不同步
    在开始使用过程当中对rtmp视频流进行播放,会出现严重的视频音频不同步现象,并且随着播放的时间越长,视频与音频的差距越大。

    解决方案

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

    framedorp 控制着允许丢帧的范围
    可以通过修改 framedrop 的数值来解决不同步的问题,framedrop 是在视频帧处理不过来的时候丢弃一些帧达到同步的效果。具体设置:
    IJKFFOptions *options = [IJKFFOptions optionsByDefault];
    [options setPlayerOptionIntValue:5      forKey:@"framedrop"];
    

    framedrop的具体大小根据实际情况而定, 我这边改成5就已经能够正常播放了。

    2. 硬解码模式下, 重复推送同一部电影, 没有画面
    客户端在一直接收流进行播放的状态下,在硬解码模式下,推流端的一部电影推流完成,然后继续重新推送这部电影,发现无法显示画面,只有声音

    解决方案

    原因是pts引起的,上一部电影推流完成时视频的pts很大,而第二次推送的时候pts重新开始计算,在ijk内部IJKVideoToolBox类里面有一个判断阻挡了视频的显示:

    新帧的pts小于之前帧的pts

    我们只需要在里面简单的处理以下就行了:

            if (ctx->m_sort_queue && newFrame->pic.pts < ctx->m_sort_queue->pic.pts) {
                
                if (newFrame->pic.pts < 500) {
                    
                    QueuePicture(ctx);
                    goto successed;
                }
                else if (ctx->m_sort_queue->pic.pts > newFrame->pic.pts * 20) {
                    QueuePicture(ctx);
                    goto successed;
                }
                
                goto failed;
            }
    

    里面做了两个简单的判断,一个是如果pts过于太小,视频帧仍然可以推进帧队列里。一个是如果前一个帧的大小是新的帧的几十倍,仍然可以将视频帧推进帧队列里进行处理。这样的话视频就能正常播放了。

    3. 硬解码模式下, 改变推流端视频分辨率的大小, 花屏的问题
    客户端在一直接收流进行播放的状态下,当我在推流端切换了视频的分辨率,或者换了一部参数不一样的电影进行推流,会出现花屏。

    解决方案

    这个问题在最新的版本里面作者已经进行了解决,不会在出现这个问题了,如果你是老版本的话,可以在IJKVideoToolBoxl类里面的 decode_video 函数里面将

    老版本
    改成
                ret = avcodec_decode_video2(new_avctx, frame, &got_picture, avpkt);
                if (ret < 0) {
                    avcodec_free_context(&new_avctx);
                    return ret;
                } else {
                    if (context->codecpar->width  != new_avctx->width &&
                        context->codecpar->height != new_avctx->height) {
                        avcodec_parameters_from_context(context->codecpar, new_avctx);
                        context->refresh_request = true;
                    }
                }
    

    这样就能正常播放了

    三、结束

    在研发过程当中可能会遇见各种问题,希望和大家相互交流,共同成长。最后推荐一个开源的视频直播应用:高仿<喵播APP>。这个用各种开源库(ijkplayer, LFLiveKit, GPUImage)组成的APP再一次证明了轮子的重要性。

    希望本文对大家有帮助,任何不足,望指正!

    相关文章

      网友评论

      • 84f77ede544e:请问有android的解决方案吗?
      • 03a1a28bc074:新版本硬解推流端切换分辨率依然花屏
      • 科了个技:作者,请问下ijkplayer怎么播放https协议的视频
        耕地:@科了个技 目前没有
        科了个技:@耕地 嗯 我现在正在编译openssl,我就想问下作者你有成功编译过,并且播放过https协议的视频没有
        耕地:@科了个技 ijkplayer作者原话是 "https needs ffmpeg built with openssl support." https://github.com/Bilibili/ijkplayer/issues/1829
      • Captian_Jack:太感谢, 终于找到ijk音视频不同步的文章了 :sob:

      本文标题:ijkplayer音视频不同步解决方案

      本文链接:https://www.haomeiwen.com/subject/gmvmuttx.html