1. 程式人生 > >H264 in WebRTC的那些坑

H264 in WebRTC的那些坑

WebRTC 自誕生之日起, 就代表了實時通訊領域的最好的技術. 不過很長時間裡, 它所支援的視訊編碼器只有VP8, 後來隨著H265/VP9為代表的下一代視訊編碼器的誕生, WebRTC裡出現了VP9 Codec. 而當前應用最廣泛的H264 卻一直不受待見. 一直到Cisco 宣佈旗下的H264 Codec開源為OpenH264, 並且替所有OpenH264的使用者支付了H264的專利費, 以次為契機, 在IETF的WebRTC會議中, 把H264和VP8都列入了WebRTC所必需要支援的視訊編碼器。 接下來, Google終於在WebRTC中增加了對H264的支援, 在PC平臺(Windows和MAC), 編碼器是用OpenH264, 解碼器是用FFMPEG, 在iOS平臺上, 編碼器和解碼器既可以使用OpenH264和FFMPEG, 也可以用apple的VideoToolbox所支援的硬體編解碼器. 在Android平臺, 可以用 OpenH264, FFMPGE, 也可以用 MediaCodec. 這個對於廣大需要H264的公司來說是一大福音. 在下載的WebRTC程式碼中做稍許配置, 就可以使用H264了. 
WebRTC是以其出色的QoS而著稱的, 其VP8和VP9 的視訊在比較差的網路條件下都可以保持流暢, 而且其質量相對於當前的網路頻寬, 也非常不錯。 如果把Codec換成H264, 其質量是否能跟VP8/VP9相提並論呢? 
揣著這個問題, 我們對H264的質量做了下評估, 雖然在限頻寬和設定丟包的條件下, H264還比較流暢, 但是其出現卡頓的機率明顯高於VP8/VP9, 時延也大於VP8/VP9, 有時候質量也會比較差, 出現明顯的塊狀效應, 很容易判斷這類塊狀效應是由編碼質量損失造成的。 理論上, 一個好的QoS設計實現, 不應該跟Codec的型別有關, 而且公認的H264的RD效能是優於VP8的, 為什麼在WebRTC中的H264質量要差一些呢? 
帶著這個問題,我們對WebRTC做了深入分析. WebRTC的QoS策略主要是位元速率評估(類似可用頻寬評估), NACK重傳, FEC(前向糾錯), PLI 請求等, 這些控制都應該跟Codec型別無關呀。 但是真相卻並非如此, 在WebRTC的實現中,如果Codec選擇為H264的時候, FEC是被關閉的. VP8/VP9有支援時間分級, OpenH264雖然也支援時間分級, 但是在WebRTC中卻不能開啟. 
關於FEC, Google的解釋如下: 
// Payload types without picture ID cannot determine that a stream is complete 
// without retransmitting FEC, so using FEC + NACK for H.264 (for instance) is 
// a waste of bandwidth since FEC packets still have to be transmitted. Note 
// that this is not the case with FLEXFEC. 
翻譯成中文是: h264沒有picture id, 所以無法判斷流完整性, 所以使用FEC+NACK是浪費帶寬了, 因為FEC 需要被衝傳. 
這個到底是不是真相呢? 
答案是, 這個只是真相的一部分. 
真正的真相是 
1. 當H264的FEC 被啟用後, 會導致重傳包被丟棄。 接收端的JitterBuffer卻一直傻傻等待, 從而導致長時間的等待 
2. H264的FEC恢復隱藏著BUG, 容易引發流完整性判斷出錯導致解碼失敗, 引發視訊卡頓. 
3. 就是Google所說的原因, Picture ID 是VP8/VP9的概念, 用於標示視訊幀的連續性, 而H264卻只能依賴RTP序列號來判決連續。

H264不能啟用時間分級的原因是, H264的rtp 組包協議裡,無法包含視訊參考層級關係的資訊, 從而無法判決不同分層是否完整, 而VP8/VP9的rtp組包協議卻包含著豐富的資訊, 足以判斷流完整性.

所以,根本原因是VP8/VP9是Google 親生的,一切都為它們量身訂造, 而H264是抱養的, 只能硬往這個框框裡套了.

不過知道這些原因, 就容易找到對策, 實現一個質量勝過VP8的H264 方案了.

注: 本文所討論的WebRTC, 其版本號為52, 最新的程式碼可能會有所出入

本文由 Sandfox 和本人協作完成.

Reference

  1. www.webrtc.org
  2. rfc6386 - VP8 Data Format and Decoding Guide
  3. rfc6184 - RTP Payload Format for H264 Video