ljkplayer是一款做视频直播的框架, 网上很多视频项目都使用了这个框架。这里不再讲如何集成ijkplayer,推荐一篇详细的集成文章。
一、下载ijkplayer
下载地址:https://github.com/Bilibili/ijkplayer
下载完成后解压,根据github上作者的说明下载ffmpeg,编译ffmpeg:
二、不同步的解决方案
我在使用ijkplayer的时候主要遇到了3个问题
1. 音视频不同步
在开始使用过程当中对rtmp视频流进行播放,会出现严重的视频音频不同步现象,并且随着播放的时间越长,视频与音频的差距越大。
解决方案
具体原因是CPU在处理视频帧的时候处理得太慢,默认的音视频同步方案是视频同步到音频, 导致了音频播放过快,视频跟不上。
可以通过修改
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再一次证明了轮子的重要性。
希望本文对大家有帮助,任何不足,望指正!
网友评论