ffmpeg接收rtsp流問題
項目使用mingw環境g++5.3,C++調用ffmpeg接收rtsp流,再通過C#顯示。結構上是C#調用C++的so文件,讀取得到的視頻幀(RGB888格式),通過圖片控件顯示。
一開始是使用opencv打開視頻源,本地文件和rtsp的源使用一樣的接口,方便使用。但是通過opencv打開rtsp源的時候,發現720p2Mbit的視頻能夠正常打開,但1080p的視頻打開後出馬賽克,卡頓比較多。
而同樣的視頻源,使用VLC就能流暢的打開,不過延時很高,大約1s。
後來又發現,使用i3低電壓版CPU的筆記本上,連720p也有卡頓和馬賽克。使用3代i5處理器的筆記本能夠流暢播放720p,1080p的會出馬賽克。一開始認為是opencv的問題,所以換成了用ffmpeg打開rtsp流。但是效果與opencv的完全一致。
由於解碼的CPU占用率很高,而且性能高的筆記本問題就少,所以懷疑是解碼時間長,導致丟數據。所以在ffmpeg打開rtsp流之前加了強制使用tcp的選項:
AVDictionary* options = NULL; av_dict_set(&options, "rtsp_transport", "tcp", 0); //強制使用tcp,udp在1080p下會丟包導致花屏 result = avformat_open_input(&fmt_ctx, video_url.c_str(), NULL, &options); //打開文件
這樣就解決了丟包問題,本以為就完美了,後來視頻源經過圖傳傳輸到筆記本上,使用1080p 2Mbit,這一版程序的就出現了大量的馬賽克,卡頓嚴重。
分析認為是網絡圖傳限制了最大傳輸帶寬為6Mbit,且延時大約30ms,可能對rtsp傳輸有影響。所以又恢復了之前udp的方式,結果效果就好多了,但是和之前一樣,還是會出馬賽克。
使用tcp的方式無法通過圖傳,也就否定了這種解決方案。所以還是需要解決udp方式丟包的問題。
對於udp丟包的問題,可以使用增加緩存的方式解決,而我在網上沒有查到有關ffmpeg打開rtsp流增加udp緩存的方法,所以還是到ffmpeg源碼中搜索avformat_open_input函數的源碼,和rtsp_transport等關鍵字,最後搜到了這個函數的所有配置,發現buffer_size這個選項最終在socket中修改了udp的接收緩存。默認64K,修改為1MB以後,視頻流暢播放了:
AVDictionary* options = NULL; av_dict_set(&options, "buffer_size", "1024000", 0); //設置udp的接收緩沖 result = avformat_open_input(&fmt_ctx, video_url.c_str(), NULL, &options); //打開文件
ffmpeg接收rtsp流問題