問題已解決(局域網(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