如何在視訊採集流水線中增加濾鏡處理節點?丨有問有答

語言: CN / TW / HK

前一時間,我在知識星球上建立了一個音視訊技術社群: 關鍵幀的音視訊開發圈 ,不少朋友加入並在裡面諮詢一些音視訊相關的技術問題,其中不乏一些開發中普遍遇到的問題,這裡我會挑一些放出來供大家參考。

如果你也有音視訊技術問題想諮詢,或者符合下面的情況:

  • 在校大學生 → 學習音視訊開發

  • iOS/Android 客戶端開發 → 轉入音視訊領域

  • 直播/短視訊業務開發 → 深入音視訊底層 SDK 開發

  • 音視訊 SDK 開發 → 提升技能,解決優化瓶頸

不妨看看 《是的,我建了一個進階百萬年薪的社群》 瞭解一下這個社群,根據自己的需要,按需加入。

今天我們要討論的問題是一位社群的朋友遇到的一個面試題,原文如下:

之前遇到一個面試題,有一個執行緒在採集攝像頭資料放到 buffer,然後在主執行緒顯示。如果這時候需要新增一個濾鏡,是否需要新開一個 buffer 和執行緒,是否會有執行緒安全問題,該怎麼解決?

以下是回答,歡迎大家留言討論補充:

從題目的意思來看,原理的流水線是: 執行緒 1:採集 → buffer → 主執行緒:渲染 ,現在想在渲染之前加一個特效節點。

1)不新開 buffer 也不新開執行緒時,對應的流水線變為: 執行緒 1:採集 → buffer → 主執行緒:濾鏡 → 主執行緒:渲染 。當濾鏡渲染不復雜,耗時不多時,這種方案是可以搞的,因為濾鏡主要涉及到 OpenGL 相關的操作,只要保證濾鏡的 OpenGL 操作與渲染的 OpenGL 操作在同一個 EAGLContext 環境內即可。可以參考下圖 OpenGL 操作緩衝區 FBO、著色器與 EAGLContext 的關係。

OpenGL

2)新開 buffer 同時新開執行緒時,對應的流水線變為: 執行緒 1:採集 → buffer 1 → 執行緒 2:濾鏡 → buffer 2 → 主執行緒:渲染 。這種方案當然是更好的方案,它使得各個模組可以並行,而且效能相容性更好。因為在實際需求中,我們採集後的影象資料處理,除了濾鏡,可能會增加人臉識別、磨皮、美白、特效等更復雜功能,這時候處理耗時就可能較長了,放在主執行緒可能卡住主執行緒,更可能會影響到渲染的幀率。此外,我們採集的影象資料除了預覽渲染,一般是需要編碼封裝後儲存本地或推流上傳網路的,編碼模組的速度與特效處理的速度不匹配時,這就需要增加 buffer 了。

這樣一來整個流程就相當於兩個生產者消費者模型了,而每個 buffer 就是對應的生產者和消費者執行緒的臨界區。保證執行緒安全其實就是確保生產者執行緒和消費者執行緒對 buffer 資料的互斥訪問,這裡使用訊號量即可。在 iOS 中可以用 dispatch_semaphore_t。