網易雲信 NERTC 高清畫質體驗之 H.265的工程實踐 | 體驗共享技術專題

網易雲信發表於2021-10-13

導讀:H.265是 ITU-T VCEG 繼 H.264之後制定的新一代視訊編碼標準,相比於 H.264,H.265能夠進一步提高壓縮效率,提升畫質,在當前的很多音視訊場景中,得到了越來越廣泛的應用,我們在網易雲信 NERTC 中對 H.265做了大量的工程實踐,本文為體驗共享系列第三篇—視訊篇,文章將從四個方面做具體介紹。

能力協商

一個客戶端能否傳送指定的特徵的碼流,不僅由本端是否支援編碼決定,也由房間裡其他接收端能否解碼決定。即傳送端和接收端共同決定了本端能傳送什麼樣的碼流。對於 H.265,可能會出現下面的情況:

那麼他們之間將如何通訊?客戶端 B 如果發 H.265的流,客戶端 A 和客戶端 D 由於只支援 H.264解碼,它們接收到客戶端 B 傳送的 H.265的碼流,是無法解碼的,所以我們需要設計一套能力協商機制,來保證支援不同編解碼能力的客戶端之間可以正常的通訊。

下圖為能力協商的整體設計圖:

下面詳細介紹一下我們能力協商的設計方案。

能力集設計

能力集定義為 { uint32 key : [ uint8 value1, uint8 value2 ... ] },使用1位掩碼

sdk 的 key 範圍是 [ 0, 2^8  ) 

video 的 key 範圍是 [ 2^8, 2^16 )

audio 的 key 的範圍是 [ 2^16, 2^24 )

位元組示意如下:

舉例說明如下:

能力協商流程(客戶端)

  1. 客戶端本地定義能力集
  2. 客戶端本地實現能力集上報,能力集下發配置的機制
  3. 服務端提供頻道內能力集的生成、綜合以及下發功能

舉例說明:

定義:能力欄位 VideoCodec : 256 (2^8),能力值 H.264 : 0,H.265 : 1

 客戶端 A 和客戶端 B 進入同一個頻道時,客戶端 A 上報能力集{ 256 : [0, 1]},客戶端 B 上報能力{ 256 : [0]}

服務端收到客戶端 A 和客戶端 B 的能力集上報之後,知道 A 支援 H.264和 H.265,B 支援 H.264,綜合 A 和 B 的能力集,得到頻道內支援 H.264的結論,下發能力集 {256: [0]}

客戶端 A 收到能力集後,主動關閉自己的 H.265能力;客戶端 B 收到能力集後,和自己的能力集一致,不做改變。

能力協商流程(伺服器)

  1. 房間建立時,生成預設能力集,**預設能力集由引擎提供,伺服器用作一個全域性配置
    **
  2. 第一個 edge_login 請求如果有能力集欄位,則使用這個能力集覆蓋預設能力集,作為房間的能力集;如果沒有能力集欄位,則使用預設能力集作為房間的能力集。由於是第一個,不需要廣播。
  3. 後續每個使用者進來,如果能力集大於房間的能力集,則返回房間的能力集給這個使用者,房間的能力集不變。舉例說明如下圖:

  1. 後續每個使用者進來,如果能力集小於房間的能力集,則取交集,縮小房間的能力集,並把結果廣播給所有的使用者。舉例說明如下圖:

H.265編解碼器實踐

各個平臺有自己特有的硬體265編解碼器,同時還有各種開源的軟體265編解碼器,那麼我們將如何選擇,才能實現最佳的使用效果?

下面我們將分 Android,iOS,Mac 和 Windows 四個平臺分別介紹各平臺265編解碼器的實踐情況。其中軟體編碼器選用 x265做測評,軟解選用 ffmpeg,libhevc 做測評。

Android 端

首先我們看一下 android 端硬體編解碼器的功耗和位元速率情況(測試機型 Mi 10 : Qualcomm Technologies, Inc SM8250,測試 Profile:720P 30fps 1.7M)

再看一下 android 端各軟體編解碼器的效能情況(測試機型 Mi 10 : Qualcomm Technologies, Inc SM8250,測試 Profile:720P 30fps 1.7M)

最後看一下畫質對比(測試機型 Mi 10 : Qualcomm Technologies, Inc SM8250,測試 Profile:720P 30fps 858k),左為 H.264,右為 H.265

總結:

  1. android 硬編265在功耗方面基本跟硬編264持平,同時 android 硬編265位元速率比硬編264更穩一些
  2. android 端軟編265的效能還是比較差的,不能滿足需求
  3. android 端 ffmpeg 軟解265在 arm64上面效能比較差,CPU 佔用達15%,同樣條件下,使用 libhevc,CPU 佔用只有4.5%,效能上有很大提升空間
    4. android 硬編265的畫質明顯要比硬編264的畫質更清晰,畫質收益很明顯

所以 android 端我們265編解碼器的使用策略如下:

  1.  優先使用265硬解。一些裝置存在265硬解相容問題的,高階機型選擇265軟解碼器,低端裝置直接認為不支援265解碼
  2.  優先使用265硬編。一些裝置存在265硬編相容問題的,則認為不支援265編碼,降級到264編碼
  3. 由於 libhevc 軟解的效能明顯優於 ffmpeg 軟解265,所以265軟解碼器我們會優先選擇 libhevc

iOS 端

首先我們看一下 iOS 端硬體編解碼器的功耗情況(測試機型 iPhone11,測試 Profile:720P 30fps 1.7M)

另外我們發現在某些機型上或者某些場景下,iOS 硬編265會出現明顯的位元速率不足的問題(測試機型 iPhoneXR,測試 Profile:720P 30fps 1.7M)

H.264:

H.265:

像這種出現位元速率嚴重不足的情況,我們基於 iOS 硬編碼控,設計了一套位元速率監控方法,如果監控到位元速率出現嚴重不足,會從 H.265回退到 H.264

最後看一下在硬編位元速率穩定的情況下的畫質對比(測試機型 iPhone11,測試 Profile:720P 30fps 858k)

左 H.264,右 H.265

總結:

  1. 使用 iOS 硬編265功耗明顯比硬編264要大,同樣的使用 iOS 硬解265功耗也明顯比硬解264要大一些
  2. iOS 硬編265偶現一些位元速率不足的情況,導致畫質反而不如264

3. iOS 硬編265的畫質要比硬編264的畫質更清晰一些,有一些畫質收益

所以最後 iOS 端我們265編解碼器的使用策略如下:

1. 優先使用硬編265,不支援軟編265

2. 優先使用硬解265,只有在硬解265多次解碼失敗無法恢復後才會回退到 ffmpeg 265軟解

  1. 由於 iOS 265硬體編碼功耗比硬體264要大,監測 iOS 裝置整體電量,在低電量情況下(比如到20%臨界點),我們把硬體265切回到了264硬體編碼器
  2. 使用 iOS 硬編碼控模組,監測實際編碼位元速率情況,若出現明顯的位元速率不足或者位元速率超發,我們把硬編265切回到了硬編264

iOS 硬編碼控

下圖為硬編碼控模組設計圖:

碼控流程:

首先硬編碼器將目標位元速率 Target Bitrate 傳遞給碼控模組 HWBitrateController

每編碼完成一幀,將編碼後的幀大小更新給 HWBitrateController 估算出每秒的實際編碼位元速率 Estimated Bitrate

計算目標位元速率與實際位元速率直接的差值 Diff

通過二分法,取0.5倍的 Diff 加 Target Bitrate,作為需要調整的位元速率 Adjusted Bitrate

將需要調整的位元速率 Adjusted Bitrate 設定回硬編碼器 HWEncoder,作為 HWEncoder 的目標位元速率 Target Bitrate

回到第一步,硬編碼器將當前目標位元速率 Target Bitrate 傳遞給碼控模組 HWBitrateController

計算 Diff/Target Bitrate,如果持續大於30%,則認為位元速率出現明顯不足,需要觸發降級編碼器

Mac 端 

首先我們看一下 Mac 端265軟硬體編解碼器的 CPU 和位元速率情況(測試機型 MacBook Pro (15-inch, 2016): Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz,測試 Profile:720P 30fps 1.7M)

硬編265位元速率情況:

軟編265位元速率情況:

同時,我們通過 dump Mac 硬編265的碼流,發現使用前向 B 幀取代了 P 幀

最後,我們看一下畫質對比(測試機型 MacBook Pro (15-inch, 2016): Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz,測試 Profile:720P 30fps 1M)

總結:

  1. Mac 上面硬體265相對於軟體265,CPU 佔用更低,效能收益比較明顯

2. 硬編265位元速率穩定性不如軟編265,波動比較大,但都是圍繞目標位元速率上下波動,經過長時間測試,發現整體位元速率平均下來沒有明顯的超發或者不足情況出現

3. 硬編編碼碼流前向 B 幀取代了 P 幀,整體壓縮率會更高,同等位元速率畫質更優

4. 硬編265畫質明顯優於264,而軟編265與硬編265畫質差異不大

所以 Mac 端我們265編解碼器的使用策略如下:

  1. 優先使用265硬解。一些裝置存在265硬解相容問題或者不支援265硬解的,在 CPU 效能比較強的裝置上面使用軟解265(ffmpeg),如果是 CPU 比較弱的裝置,則認為不支援265解碼
  2. 優先使用265硬編。一些裝置存在265硬編相容問題或者不支援265硬編的,在 CPU 效能比較強的裝置上面使用軟編265,如果是 CPU 比較弱的裝置,則認為不支援265編碼

Windows 端 

windows 上面由於硬編硬解碎片化比較嚴重,我們暫時沒有考慮使用硬編硬解,目前以使用軟編軟解為主。

下圖為 win 上面軟編軟解265的情況(測試機型 Dell Latitude 5290: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz,測試 Profile:720P 30fps 1.7M)

可以看到:

1. 軟編265和軟解265在 x86上面的效能表現不如 x86_64

2. 軟編265在 x86_64上面的 CPU 消耗也是遠遠高於軟編264的

所以最後 Win 端我們265編解碼器的使用策略如下:

1. 在使用 win x86的情況下,直接不支援265軟編軟解

2. 在使用 win x86_64的情況下,CPU 效能比較強的裝置上開啟265軟編軟解;同時軟編265對 CPU 效能要求比軟解265更高,所以對裝置的效能要求也會更加嚴格

工程策略

白名單策略 

前面有提到,我們在使用265硬編硬解的時候,需要考慮裝置相容性的問題;同時在使用265軟編軟解的時候,由於涉及大量的編解碼運算,也要考慮裝置的效能問題。

為了在整體工程層面提供最佳的使用者體驗,我們使用到了白名單策略。通過白名單配置下發,把是否支援265硬編硬解和軟編軟解的裝置區分出來。

以下是我們的具體做法:

  • 通過大量的裝置適配,把對265硬編硬解支援比較好的裝置,配置到線上白名單裡面
  • 通過裝置跑分,區分出裝置 CPU 效能的高低,配置高效能的裝置支援265軟編軟解,低效能裝置不支援265軟編軟解,然後將配置更新到線上白名單裡面
  • 最後通過線上白名單配置下發,客戶端獲取到當前是否支援硬編硬解和是否支援軟編軟解的配置資訊

H.265能力協商 

協商的是 H.265解碼能力,協商結果最後作用於編碼側,是否使用 H.265編碼

  • H.265解碼的配置下發,使用者設定以及當前裝置支援能力,三者綜合得出當前 H.265的解碼能力
  • 能力協商模組,根據當前 H.265的解碼能力,生成能力集,上報給能力協商伺服器
  • 能力協商伺服器綜合頻道內各客戶端的能力集,生成新的房間能力集,下發給各客戶端
  • 客戶端收到來自於伺服器下發的能力集,解析出當前頻道內 H.265的能力集
  • 根據當前頻道內 H.265的能力集,H.265編碼的配置下發、使用者設定以及當前裝置支援能力,伺服器對 H.265的支援能力,三部分綜合得出當前是否支援 H.265編碼,最後作用於編碼側是否編 H.265的流

CPU OverUse 策略 

通過跑分,區分出不同裝置 CPU 效能的高低,可能不是完全的準確。在實際場景中,有可能存在跑分資料很高,但是編碼效能不夠的情況,這時候我們需要通過實時監測統計當前視訊編碼耗時,來判斷當前是否 CPU 過載。

我們的做法是:

  • 硬編265考慮到可能存在 pipeline delay 的情況,目前我們暫不統計每幀編碼的編碼耗時
  • 在使用軟編265的時候,統計每幀編碼的編碼耗時,如果出現持續編碼耗時過長,那麼就認為當前 CPU 過載,265軟編將會立即回退到264

QP 閾值調整 

我們的 QOE 模組,會根據 QP 閾值調整幀率和解析度,以達到主觀視訊質量最優,所以設定合理的編碼器 QP 閾值就顯得非常重要,那麼在實際工程實踐中,準對硬體265編碼器,我們如何探索出合理的 QP 上下限閾值?

我們的做法是:

  • 確保 H.264和 H.265在主觀畫質基本對齊的情況下,打出 QP 值,生成 QP 曲線,基於 QP 曲線得出 QP 上下限閾值基本的範圍

我們以這款機型為例:(測試機型 Mi 10 : Qualcomm Technologies, Inc SM8250,測試 Profile:720P 30fps)

可以看到:

  1. 在720p 30fps 這個 Profile 檔位,硬編265與硬編264在畫質基本對齊的情況下,硬體265位元速率能夠節省40%,QP 波動基本相似,上下閾值也基本接近。所以如果當前 android 硬編264的 QP 上下閾值是[A, B],那麼建議 android 硬編265的 QP 上閾值範圍為[A-1, A+1],QP 下閾值範圍為[B-1,B+1]
  2. 基於步驟1得出的 QP 上下閾值範圍,逐步網損逐步放開,觀測 QOE 模組基於 QP 閾值的解析度和幀率的調整情況,從 QP 閾值範圍中摸出最合理的一個 QP 閾值,以下面的資料為例:

我們發現在 QP 閾值為[A-1,B-1]的時候,整體 QOE 表現最好,所以選定[A-1,B-1]為最後的硬編265的 QP 閾值

收益

目前第一階段的收益評測,我們是基於與 H.264解析度位元速率對齊,看畫質收益、端到端延遲、CPU 佔用、流暢度這四個指標。這裡先列舉了與硬編264對比,Android 硬編265和 iOS 硬編265的畫質收益情況,從我們評測下來的情況看,端到端延遲、CPU 佔用、流暢度這三個指標基本上差異不大,而畫質收益,可以參考以下圖表資料:

總體來看:

  1. 相比於264,265在視訊畫質上是有明顯收益的
  2. 在低位元速率、弱網或者畫面變化比較劇烈的場景下,畫質收益會更加明顯

3. android 硬編265的畫質收益要明顯優於 iOS 硬編265

總結

不管是硬編265,還是軟編265,相比於264,視訊畫質都有明顯的收益;後續網易雲信將準對畫質對齊,節省位元速率這個維度做進一步的探索。

作者介紹 

施靈凱,網易雲信音視訊引擎開發工程師,負責 NERTC 視訊引擎的開發與維護。

相關文章