前言
我的應用場景是Android上播放一種可以提供rtsp碼流的三方攝像頭的視訊畫面
要求具有實時性,延遲不能太大,除開硬體本身性能和網絡波動的因素的影響,先保障網絡穩定,硬體配置足夠的情況下,播放視訊延遲符合要求
解決辦法
- 網上都是設定一些option,各位看着抄就行,無非是用硬解碼,設定無緩存
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
// 支援硬解 1:開啟 O:關閉
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-avc", 1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-mpeg4", 1);
// 自動旋屏
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"no-time-adjust",1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"infbuf",1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"packet-buffering",0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT,"fflags","nobuffer");
-
後來發現還是有延遲,在網絡穩定的情況下,找了一個cmake編譯的ijkplayer版本,測試了一會兒發現,實際造成延遲的原因是,渲染速度跟不上解碼速度
查了下ff_fpaly.c中的視訊渲染線程
static int video_refresh_thread(void *arg)
{
FFPlayer *ffp = arg;
VideoState *is = ffp->is;
double remaining_time = 0.0;
while (!is->abort_request) {
if (remaining_time > 0.0)
av_usleep((int)(int64_t)(remaining_time * 1000000.0));
remaining_time = REFRESH_RATE;//這裡有重新整理速率限制
if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh))
video_refresh(ffp, &remaining_time);
}
return 0;
}
以上代碼中,REFRESH_RATE速率限制會造成渲染線程有一定的睡眠時間
這裡預設配置REFRESH_RATE為0.01,我們可以嘗試調小這個值,在一定情況下可以解決延遲問題,但是這樣修改也不徹底,我們繼續檢視渲染中的延遲計算
在static void video_refresh(FFPlayer *opaque, double *remaining_time)方法中
static void video_refresh(FFPlayer *opaque, double *remaining_time)
{
.......
/* compute nominal last_duration */
last_duration = vp_duration(is, lastvp, vp);
delay = 0;//compute_target_delay(ffp, last_duration, is);//計算渲染延時
.......
}
實時流不需要做延時計算,因為碼流是實時的,實際解碼不會解得過多的frame,那麼我們直接将上面的delay變量置0即可,通過以上修改即可解決播放rtsp碼流的延遲問題