在局域網(wǎng)rtsp直播流場景下,播放延遲1~2s的問題

問題已解決(局域網(wǎng)已優(yōu)化到300ms左右),小結(jié)一下備忘:

1.播放器IJKFFOptions參數(shù)的設(shè)置

//丟幀閾值
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 30);
//視頻幀率
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "fps", 30);
//環(huán)路濾波
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
//設(shè)置無packet緩存
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0);
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fflags", "nobuffer");
//不限制拉流緩存大小
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", 1);
//設(shè)置最大緩存數(shù)量
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "max-buffer-size", 1024);
//設(shè)置最小解碼幀數(shù)
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "min-frames", 3);
//啟動(dòng)預(yù)加載
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 1);
//設(shè)置探測包數(shù)量
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probsize", "4096");
//設(shè)置分析流時(shí)長
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", "2000000");

值得注意的是,ijkPlayer默認(rèn)使用udp拉流,因?yàn)樗俣缺容^快。如果需要可靠且減少丟包,可以改為tcp協(xié)議: mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");

另外,可以這樣開啟硬解碼,如果打開硬解碼失敗,再自動(dòng)切換到軟解碼:

mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 0);

2.解碼器設(shè)為零延時(shí)

大家應(yīng)該聽過編碼器的零延時(shí)(zerolatency),但可能沒聽過解碼器零延時(shí)。其實(shí)解碼器內(nèi)部默認(rèn)會(huì)緩存幾幀數(shù)據(jù),用于后續(xù)關(guān)聯(lián)幀的解碼,大概是3-5幀。經(jīng)過反復(fù)測試,發(fā)現(xiàn)解碼器的緩存幀會(huì)帶來100多ms延時(shí)。也就是說,假如能夠去掉緩存幀,就可以減少100多ms的延時(shí)。而在avcodec.h文件的AVCodecContext結(jié)構(gòu)體有一個(gè)參數(shù)(flags)用來設(shè)置解碼器延時(shí):

typedef struct AVCodecContext {
......
int flags;
......
}

為了去掉解碼器緩存幀,我們可以把flags設(shè)置為CODEC_FLAG_LOW_DELAY。在初始化解碼器時(shí)進(jìn)行設(shè)置:

//set decoder as low deday
codec_ctx->flags |= CODEC_FLAG_LOW_DELAY;

通過以上1、2點(diǎn)的設(shè)置,我已經(jīng)將延遲控制在200ms左右的范圍,我們要求暫時(shí)沒有那么高,效果是可以接受的。
還有中間過程中遇到的其他解決方案,這里也備忘下

3.簡書-暴走大牙:ijkplay播放直播流延時(shí)控制小結(jié) http://www.itdecent.cn/p/d6a5d8756eec 4.ff_ffplay文件,read_thread函數(shù)中,ret = av_read_frame(ic, pkt);后添加根據(jù)緩存大小,倍速播放的邏輯

//延遲優(yōu)化:根據(jù)緩存大小設(shè)置倍速播放
            // 計(jì)算當(dāng)前緩存大小,通過 audioq 和 videoq 的 size 來計(jì)算緩存大小
            int current_cache_size = is->audioq.size + is->videoq.size;
            if (current_cache_size > CACHE_THRESHOLD*3) {
                av_log(ffp, AV_LOG_INFO, "wzt read_thread trible speed play size=%d\n", current_cache_size);
                set_playback_rate(ffp, Trible_PLAYBACK_RATE);
            } else
            if (current_cache_size > CACHE_THRESHOLD) {
                av_log(ffp, AV_LOG_INFO, "wzt read_thread double speed play size=%d\n", current_cache_size);
                set_playback_rate(ffp, DOUBLE_PLAYBACK_RATE);
            } else {
                av_log(ffp, AV_LOG_INFO, "wzt read_thread normal speed play size%d\n", current_cache_size);
                set_playback_rate(ffp, NORMAL_PLAYBACK_RATE);
            }

4.直播內(nèi)容保存為本地視頻

http://www.itdecent.cn/p/a346f93ddaff

5.Android IjkPlayer內(nèi)核編譯記(二)RTMP追幀優(yōu)化

https://juejin.cn/post/7395456322433105958

參考鏈接:

https://blog.csdn.net/u011686167/article/details/85256101
http://www.itdecent.cn/p/d6a5d8756eec

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容