ljkplayer是一款做視頻直播的框架, 網(wǎng)上很多視頻項目都使用了這個框架。這里不再講如何集成ijkplayer,推薦一篇詳細(xì)的集成文章。
一、下載ijkplayer
下載地址:https://github.com/Bilibili/ijkplayer
下載完成后解壓,根據(jù)github上作者的說明下載ffmpeg,編譯ffmpeg:


二、不同步的解決方案
我在使用ijkplayer的時候主要遇到了3個問題
1. 音視頻不同步
在開始使用過程當(dāng)中對rtmp視頻流進(jìn)行播放,會出現(xiàn)嚴(yán)重的視頻音頻不同步現(xiàn)象,并且隨著播放的時間越長,視頻與音頻的差距越大。
解決方案
具體原因是CPU在處理視頻幀的時候處理得太慢,默認(rèn)的音視頻同步方案是視頻同步到音頻, 導(dǎo)致了音頻播放過快,視頻跟不上。

可以通過修改
framedrop 的數(shù)值來解決不同步的問題,framedrop 是在視頻幀處理不過來的時候丟棄一些幀達(dá)到同步的效果。具體設(shè)置:
IJKFFOptions *options = [IJKFFOptions optionsByDefault];
[options setPlayerOptionIntValue:5 forKey:@"framedrop"];
framedrop的具體大小根據(jù)實際情況而定, 我這邊改成5就已經(jīng)能夠正常播放了。
2. 硬解碼模式下, 重復(fù)推送同一部電影, 沒有畫面
客戶端在一直接收流進(jìn)行播放的狀態(tài)下,在硬解碼模式下,推流端的一部電影推流完成,然后繼續(xù)重新推送這部電影,發(fā)現(xiàn)無法顯示畫面,只有聲音
解決方案
原因是pts引起的,上一部電影推流完成時視頻的pts很大,而第二次推送的時候pts重新開始計算,在ijk內(nèi)部IJKVideoToolBox類里面有一個判斷阻擋了視頻的顯示:

我們只需要在里面簡單的處理以下就行了:
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過于太小,視頻幀仍然可以推進(jìn)幀隊列里。一個是如果前一個幀的大小是新的幀的幾十倍,仍然可以將視頻幀推進(jìn)幀隊列里進(jìn)行處理。這樣的話視頻就能正常播放了。
3. 硬解碼模式下, 改變推流端視頻分辨率的大小, 花屏的問題
客戶端在一直接收流進(jìn)行播放的狀態(tài)下,當(dāng)我在推流端切換了視頻的分辨率,或者換了一部參數(shù)不一樣的電影進(jìn)行推流,會出現(xiàn)花屏。
解決方案
這個問題在最新的版本里面作者已經(jīng)進(jìn)行了解決,不會在出現(xiàn)這個問題了,如果你是老版本的話,可以在IJKVideoToolBoxl類里面的 decode_video 函數(shù)里面將

改成
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;
}
}
這樣就能正常播放了
三、結(jié)束
在研發(fā)過程當(dāng)中可能會遇見各種問題,希望和大家相互交流,共同成長。最后推薦一個開源的視頻直播應(yīng)用:高仿<喵播APP>。這個用各種開源庫(ijkplayer, LFLiveKit, GPUImage)組成的APP再一次證明了輪子的重要性。
希望本文對大家有幫助,任何不足,望指正!