ijkplayer音视频不同步解决方案

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

一、下载ijkplayer

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

ijkplayer音视频不同步解决方案_第1张图片
首先安装环境
ijkplayer音视频不同步解决方案_第2张图片
然后下载编译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 函数里面将

ijkplayer音视频不同步解决方案_第3张图片
老版本

改成

            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再一次证明了轮子的重要性。

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

你可能感兴趣的:(ijkplayer音视频不同步解决方案)