下面是在deepstream使用過程中碰到的一些坑:
(1)Pipeline中的Sink如果需要編碼存文件或者推rtmp的流,注意控制編碼的參數,編碼質量不要太高。否則可能Sink帶不動,整個Pipeline有數據積累,延時越來越高,程序占用的內存越來越大,最終crash。開發中碰到一個問題:剛開始延時2秒,后來延時慢慢增大,觀察發現內存一點點增高。排除了推理性能不夠的因素,最后定位編碼推rtmp流的時候,分辨率太大(deepstream3.0沒有硬編碼的插件),導致編碼性能不夠,后來調整編碼分辨率,延時沒有積累。這個就像高速出口擁堵,擁堵長度慢慢增加,從匝道一直堵到了主干路。
(2)分析Pipeline的Src有很多種,file、rtsp、rtp等等。個人經驗判斷,使用rtp的方式最好(udpsrc插件)。如果需要分析N路視頻,需要創建N個udpsrc,N個decoder,每路一個decoder,各自連接在一起,最終通過nvstreammux插件將這N條分支合並起來,再與推理插件連接。使用rtp的好處是:即插即用,與其他模塊的耦合性低。一個系統中用於視頻分析pipeline不可能獨立存在,前面還需要給他推流的模塊,而使用udp的方式接收rtp報文無疑是最方便的,哪路有數據哪路就開始工作,沒數據的分支不影響有數據的分支。注意,如果有N路視頻流,在用nvstreammux合並的時候,nvstreammux的 batched-push-timeout屬性一定不能設置為-1,-1表示無限等待,必須等到每個分支都收到數據,如果這時候有一路沒有視頻流了(只有N-1路有數據),那么會無限等待,其他分支不能正常工作。可以設置一個合理的值,比如40000(40ms),過了這個時間如果某個分支沒有數據,等待40ms之后就不會再等了。
(3)動態刪除/添加/替換Pipeline中的插件非常麻煩,實際應用中,比如需要給某路視頻錄像,由於錄像是有時間限制的,因此不可能一直使用filesink,當時間到了,我們需要將錄像用到的filesink替換成fakesink,這個替換過程很復雜:先需要在filesink的上一個插件的src-pad上添加一個block 的probe,然后在這個probe中編寫代碼將filesink remove掉,創建新的fakesink,然后將fakesink連在原來filesink的位置,最后返回GST_PAD_PROBE_REMOVE,表示將block probe移除,整個流程結束。反過來,當需要錄像時,一樣需要添加一個block probe,然后在這個probe中將filesink加上去,開始錄像。
(4)目標跟蹤優先使用KLT算法,但是這個算法特別吃CPU,所以如果影響到整個pipeline的性能了,比如FPS變小了,可以切換到IOU,IOU的跟蹤效果不如KLT,但是還湊合,關鍵還是檢測模型要准,這樣可以彌補一下IOU的缺陷。IOU相對而言對CPU依賴更小。
(5)在使用udpsrc接收其他模塊發來的rtp數據時,由於其他模塊可能出現故障會重啟,重啟后接着發送rtp數據,這時候pipeline中的rtph264depay可能會拋出NAL unit type 26 not supported的異常,這是因為之前piepline中可能有殘留數據,導致depay失敗。對於這個error,我們在bus_callback中捕獲之后,不需要做任何處理,千萬不要delete整個pipeline再recreate,這樣會導致內存泄漏(至今沒找到什么原因),最后越來越卡,FPS越來越小。
未完待續