使用 VideoToolbox 探索低延遲視訊編碼 | WWDC 演講實錄
本文根據 Peikang 在 WWDC 2021 分享翻譯,演講者 Peikang,來自 Video Coding 和 Processing 團隊。譯者陶金亮,網易雲信資深音視訊開發工程師,擁有多年端側音視訊工作經驗。
支援低延遲編碼已成為視訊應用程式開發過程的一個重要方面,在低延遲直播和 RTC 領域有著廣泛的應用。本分享主要分享了 VideoToolbox(一個低階框架,提供對硬體編碼器和解碼器的直接訪問, 它提供視訊壓縮和解壓縮服務,以及儲存在 CoreVideo 畫素緩衝區中的光柵影象格式之間的轉換)是如何支援低延遲 H.264 硬體編碼,以最大限度地減少端到端延遲並實現新的效能水平,最終實現最佳實時通訊和高質量視訊播放。
分享實錄視訊:https://developer.apple.com/videos/play/wwdc2021/10158
低延遲編碼對於許多視訊應用非常重要,尤其是實時視訊通訊應用。在本次演講中,我將在 VideoToolbox 中介紹一種新的編碼模式,以實現低延遲編碼。這種新模式的目標是針對是實時視訊通訊應用優化現有的編碼器流水線。那麼實時視訊通訊應用需要什麼?我們需要最大限度地減少通訊中的端到端延遲。
我們期望通過讓視訊應用程式與更多裝置進行通訊來增強互操作性。例如:當呼叫中有多個接收者時,編碼器管道也應該是高效的,並且,該應用程式需要以最佳視覺質量來呈現視訊。那麼,我們需要一種可靠的機制來從網路丟失引入的錯誤中恢復通訊。
我今天要講的低延遲視訊編碼將在這些方面進行優化。使用低延遲編碼模式,我們的實時應用程式可以達到新的效能水平。在本次演講中,我將首先概述低延遲視訊編碼。我們可以對如何在管道中實現低延遲有基本的瞭解。然後我將展示如何使用 VTCompressionSession API 來構建管道並使用低延遲模式進行編碼。最後,我將討論我們在低延遲模式下引入的多個功能。
低延遲視訊編碼
首先讓我概述一下低延遲視訊編碼。這是 Apple 平臺上視訊編碼器管道的簡圖。 VideoToolbox 將 CVImagebuffer 作為輸入影象,它要求視訊編碼器執行 H.264 等壓縮演算法以減少原始資料的大小。輸出的壓縮資料封裝在 CMSampleBuffer 中,可以通過網路傳輸進行視訊通訊。從上圖中我們可以注意到,端到端延遲可能受兩個因素影響:處理時間和網路傳輸時間。
為了最大限度地減少處理時間,**低延遲模式消除了幀重新排序,遵循一進一出的編碼模式。**此外,該低延遲編碼模式下的速率控制器對網路變化的適應速度也更快,因此也可以最大限度減少網路擁塞造成的延遲。通過這兩個優化,我們已經可以看到與預設模式相比,已經有了明顯的效能提升。**對於 720p 30fps 的視訊,低延遲編碼可以減少高達 100 毫秒的延遲。**這種節省對於視訊會議至關重要。
通過這樣的操作實現了減少延遲,我們可以為視訊會議和直播等實時通訊實現更高效的編碼管道。
此外,低延遲模式始終使用硬體加速視訊編碼器以節省電量。請注意,此模式支援的視訊編解碼器型別為 H.264,我們將在 iOS 和 macOS 上引入此功能。
在 VideoToolbox 中使用低延遲模式
接下來,我想談談如何在 VideoToolbox 中使用低延遲模式。我將首先回顧 VTCompressionSession 的使用,然後向您展示啟用低延遲編碼所需的步驟。
VTCompressionSession 的使用
當我們使用 VTCompressionSession 時,首先要使用 VTCompressionSessionCreate API 建立會話。並通過 VTSessionSetProperty API 配置會話,例如目標位元率。如果未提供配置,編碼器將以預設行為執行。
建立會話並正確配置後,我們可以通過呼叫 VTCompressionSessionEncodeFrame 將 CVImageBuffer 傳遞給會話,同時可以從會話建立期間提供的輸出處理程式中檢索編碼結果。
在壓縮會話中啟用低延遲編碼很容易,我們唯一需要做的就是在會話建立過程中進行修改,如下文的程式碼:
- 首先,我們需要一個用於編碼器規範的 CFMutableDictionary,編碼器規範用於指定會話必須使用的特定視訊編碼器。
- 然後我們需要在 encoderSpecification 中設定 EnableLowLatencyRateControl 標誌。
- 最後,我們將此 encoderSpecification 賦予 VTCompressionSessionCreate,壓縮會話就將在低延遲模式下執行。
配置步驟和往常一樣。例如,我們可以使用 AverageBitRate 屬性設定目標位元率。
好的,我們已經介紹了 Video Toolbox 低延遲模式的基礎知識。下面,我想繼續介紹此模式中的新功能,它們可以進一步幫助我們開發實時視訊應用程式。
VideoToolbox 低延遲模式新功能
到目前為止,我們已經討論了使用低延遲模式的延遲優勢,其餘的好處可以通過我將要介紹的功能來實現。
第一個功能是新的 Profiles,我們通過向管道新增兩個新 Profiles來增強互操作性。也會聊聊**時域分層SVC,此功能在視訊會議中非常有用。也可以使用最大幀量化引數(Max QP)對影象質量進行細粒度控制。最後,我們希望通過新增長期參考(LTR)**的支援來提高錯誤恢復能力。
新的 Profiles 支援
讓我們談談新的 Profiles 支援。 Profile 定義了一組解碼器能夠支援的編碼演算法,Profile 用於確定視訊編碼過程中幀間壓縮使用的演算法(例如是否包含 B 幀、CABAC 支援、顏色空間支援等),Profile 越高,就說明採用了越高階的壓縮特性,對應的對編解碼硬體的要求也越高。為了與接收方通訊,編碼位元流應符合解碼器支援的特定配置檔案。
在 VideoToolbox 中,我們支援一系列profiles,例如Baseline Profile、Main Profile和High Profile。今天,我們為該系列添加了兩個新profiles:Constrained Baseline Profile (CBP) 和 Constrained High Profile (CHP) 。
CBP 主要用於低成本應用,而 CHP 則具有更先進的演算法以獲得更好的壓縮比。我們可以先檢查解碼器功能以判斷應該使用哪個 Profile。
想要使用 CBP,只需將 ProfileLevel 會話屬性設定為 ContrainedBaseLine_AutoLevel。同樣,我們可以將Profile級別設定為 ContrainedHigh_AutoLevel 以使用 CHP。
時域分層 SVC
現在讓我們談談時域分層 SVC。我們可以使用時域分層來提高多方視訊通話的效率。
例如:一個簡單的三方視訊會議場景。在此模型中,接收器 A 的頻寬較低,為 600kbps,而接收器 B 的頻寬較高,為 1,000kbps。通常,傳送端需要對兩組碼流進行編碼,以滿足每個接收端的下行頻寬。這種做法可能不是最佳的。
該模型可以通過時域分層 SVC 來更加高效的實現,其中傳送方只需要編碼一個位元流,但最後可以位元流輸出可以分為兩層。
我們來看看這個過程是如何工作的。這是一個編碼視訊幀序列,其中每一幀都使用前一幀作為預測參考。
我們可以將一半的幀拉入另一層,我們可以更改參考,以便只有原始層中的幀用於預測。原始層稱為基礎層,新構建的層稱為增強層。增強層可以作為基礎層的補充,以提高幀率。
對於接收器 A,我們可以傳送基礎層幀,因為基礎層本身已經是可解碼的。更重要的是,由於基礎層只包含一半的幀,所以傳輸的資料速率會很低。
另一方面,接收器 B 可以享受更流暢的視訊,因為它有足夠的頻寬來接收基本層幀和增強層幀。
我們來看看使用時域分層 SVC 編碼的視訊。我將播放兩個視訊,一個來自基礎層,另一個來自基礎層和增強層。基礎層本身可以正常播放,但同時我們可能會注意到視訊不太流暢。如果我們播放第二個視訊,我們可以立即看到差異。與左側視訊相比,右側視訊具有更高的幀速率,因為它同時包含基礎層和增強層。
左側視訊具有 50% 的輸入幀率,並使用 60% 的目標位元率。這兩個視訊只需要編碼器一次編碼一個位元流。當我們進行多方視訊會議時,這將更加節能。
時域分層的另一個好處是錯誤恢復能力。我們可以看到,增強層中的幀不用於預測,因此對這些幀沒有依賴性。這意味著如果在網路傳輸過程中丟失了一個或多個增強層幀,其他幀不會受到影響。這使得整個會話更加健壯。
啟用時域分層的方法非常簡單。我們在低延遲模式下建立了一個名為 BaseLayerFrameRateFraction 的新會話屬性,只需將此屬性設定為 0.5,這意味著一半的輸入幀分配給基礎層,其餘分配給增強層。
我們可以從示例緩衝區附件中檢查圖層資訊。對於基礎層幀,CMSampleAttachmentKey_ IsDependedOnByOthers 將為真,否則為假。
我們還可以選擇為每一層設定目標位元率。請記住,我們使用會話屬性 AverageBitRate 來配置目標位元率。目標位元率配置完成後,我們可以設定新的 BaseLayerBitRateFraction 屬性來控制基礎層所需的目標位元率百分比。如果未設定此屬性,則將使用預設值 0.6。我們建議基礎層位元率分數應在 0.6 到 0.8 的範圍內。
最大幀 QP
現在,讓我們看看最大幀量化引數或者說是最大幀 QP。幀 QP 用於調節影象質量和資料速率。
我們可以使用低幀 QP 來生成高質量的影象。但在這種情況下,影象尺寸會很大。
另一方面,我們可以使用高幀 QP 來生成低質量但尺寸較小的影象。
在低延遲模式下,編碼器使用影象複雜度、輸入幀速率、視訊運動等因素調整幀 QP,以在當前目標位元率約束下產生最佳視覺質量。所以我們鼓勵依靠編碼器的預設行為來調整幀 QP。
但是在某些客戶端對視訊質量有特定要求的情況下,我們可以控制編碼器使用最大幀 QP。使用最大幀 QP 時,編碼器將始終選擇小於此限制的幀 QP,因此客戶端可以對影象質量進行細粒度的控制。
值得一提的是,即使指定了最大幀 QP,常規速率控制仍然有效。如果編碼器達到最大幀 QP 上限但位元率預算用完,它將開始丟棄幀以保持目標位元率。
使用此功能的一個示例是通過較差的網路傳輸螢幕內容視訊。我們可以通過犧牲幀速率來進行權衡,以傳送清晰的螢幕內容影象,通過設定最大幀 QP 可以滿足此要求。
我們可以使用新的會話屬性 MaxAllowedFrameQP 傳遞最大幀 QP。根據標準最大幀 QP 的值必須介於 1 到 51 之間。
長期參考幀 (LTR)
說一下我們在低延遲模式下開發的最後一個功能,長期參考幀。長期參考幀即 LTR 可用於錯誤恢復。讓我們看一下這張圖,其中顯示了管道中的編碼器、傳送方客戶端和接收方客戶端。
假設視訊通訊通過一個連線不良的網路,由於傳輸錯誤,可能會發生幀丟失。當接收方客戶端檢測到幀丟失時,它可以請求重新整理幀以重置會話。如果編碼器收到請求,通常它會編碼一個關鍵幀以用於重新整理目的,但關鍵幀通常相當大。大的關鍵幀需要更長的時間才能到達接收器。由於網路條件已經很差,大幀可能會加劇網路擁塞問題。那麼,我們可以使用預測幀而不是關鍵幀進行重新整理嗎?答案是肯定的,如果我們有幀確認。讓我們來看看它是如何工作的。
首先,我們需要決定確認的幀。我們稱這些幀為長期參考幀或 LTR,這是編碼器的決定。當傳送方客戶端傳輸 LTR 幀時,還需要向接收方客戶端請求確認。如果成功接收到 LTR 幀,則需要返回確認。一旦傳送方客戶端獲得確認並將該資訊傳遞給編碼器,編碼器就知道對方收到了哪些 LTR 幀。
再來看看網路不好的情況:當編碼器收到重新整理請求時,因為這次,編碼器有一堆已確認的 LTR,它能夠對從這些已確認的 LTR 中的一個預測的幀進行編碼,以這種方式編碼的幀稱為 LTR-P。與關鍵幀相比,LTR-P 的編碼幀大小通常要小得多,因此更容易傳輸。
現在,讓我們談談 LTR 的 API。請注意,幀確認需要由應用層處理,它可以通過 RTP 控制協議中的 RPSI 訊息等機制來完成。這裡我們只關注編碼器和傳送方客戶端在這個過程中是如何通訊的。啟用低延遲編碼後,我們可以通過設定 EnableLTR 會話屬性來啟用此功能。
當 LTR 幀被編碼時,編碼器將在示例附件 RequireLTRAcknowledgementToken 中用訊號傳送一個唯一的幀令牌。
傳送方客戶端負責通過 AcknowledgedLTRTokens 幀屬性將確認的 LTR 幀報告給編碼器。由於一次可以收到多個確認,我們需要使用一個數組來儲存這些幀標記。
我們可以隨時通過 ForceLTRRefresh 框架屬性請求重新整理框架。一旦編碼器收到這個請求,一個 LTR-P 將被編碼。如果沒有已確認的 LTR 可用,在這種情況下,編碼器將生成一個關鍵幀。
總結
以上就是本次 Peikang 在 WWDC 2021 大會上分享的全部內容譯文,若有翻譯不合理處,歡迎指正交流。
目前網易雲信在客戶端層面實現了軟體編碼的 SVC 和長期參考幀方案,同時伺服器在轉發上面也實現了 SVC 方案。SVC 提供了伺服器一個額外的手段控制視訊流的轉發位元速率,再結合大小流和位元速率壓制, 以及客戶端下行的網路頻寬探測和擁塞控制等手段,網易雲信為了追求極致的觀看體驗,不斷的打磨產品,本次分享的內容,我相信不久就可以在雲信的產品中得到很好的運用。
- 資訊|WebRTC M93 更新
- 技術實踐|網易雲信 IM SDK 服務高可用技術方案
- 久等了!【Innovation 2021】網易應用創新開發者大賽正式開賽!
- 用程式碼,打造創意新世界!【Innovation 2021】網易應用創新開發者大賽正式開賽!
- Web端實現RTC視訊特效的解決方案
- 從0搭建線上聊天室,只需4步!
- JavaScript 之事件迴圈(Event Loop)
- C 20 四大特性之一:Module 特性詳解
- Android Flutter 多例項實踐
- 技術實踐 | 網易雲信視訊轉碼提速之分片轉碼
- 網易雲信線上萬人連麥技術大揭祕
- 視訊 QoE 的平衡之道—揭祕網易雲信 NERTC 視訊質量控制系統
- 使用 VideoToolbox 探索低延遲視訊編碼 | WWDC 演講實錄
- 技術實踐 | 如何基於 Flink 實現通用的聚合指標計算框架
- 網易雲信大規模聊天室系統架構解析
- 探尋使用者自定義定時任務的實踐方案
- 如何在 Electron 上實現 IM SDK 聊天訊息全文檢索
- 架構解析|網易自研新一代大規模分散式傳輸網
- 直播點播窄帶高清之 JND 感知編碼技術
- Flutter 混合開發基礎