WebRTC的QP、分辨率自動調整

摘要

    描述WebRTC在編碼端分辨率自動調整的原因,以及關閉分辨率自動調整策略的方法。

版本

    主要針對57版本,同時也查看了65版本的代碼,代碼結構有所改變,但是邏輯不變。

問題

    最近把SDK集成到OBS,方便客戶端合流。這樣OBS可以把合好的圖像通過WebRTC推到服務端(janus)。發現一個問題,在抓屏的場景下,拉到的流分辨率迅速下降,最後模糊到看不清。

原因

    在不抓屏的情況下,例如採集攝像頭,WebRTC會開啓QualityScaler。在編碼的時候,計算每幅圖像的量化參數(QP,Quantization Parameter,相當於圖像的複雜度),當一系列圖像的平均QP超過閾值時會調整分辨率(H264的合法範圍是24~37),超過37要降分辨率,低於24要提高分辨率。
    但是對抓屏來說這個策略並不合理,因爲屏幕圖像有很多細節,文字也會提升QP值。所以在57版的webrtcvideoengine2.cc(2084行)有註釋"Do not adapt resolution for screen content as this will likely result in blurry and unreadable text",如果在抓屏時開啓分辨率自動調整會造成模糊和不可讀的文字,因爲抓屏和攝像頭採集不一樣,圖像細節更豐富,並且基本不會切換到細節少的狀態。因此在抓屏的時候如果是使用AdaptedVideoTrackSource當作數據源,則需要重寫is_screencast方法,直接返回true,告訴WebRTC視頻源是抓屏,這樣編碼端的分辨率調整就不會生效。

    這個策略主要目的是爲了控制編碼的消耗,不過這裏閾值寫死卻不太靈活,爲了彌補這個策略在CPU與編碼性能的關係上的缺失,除了QP之外,編碼CPU佔用也在ViEEncoder中被考慮。當編碼的CPU佔用超過一定閾值的時候,分辨率也將被調整,這個策略和is_screencast是兩個並列的條件(webrtcvideoengine2.cc 1639行)。

    在默認is_screencast爲false並且根據cpu調整分辨率策略都開啓的條件下,還有一種辦法禁用分辨率scaling,就是自定義VideoEncoder,並在GetScalingSettings方法中返回false(vie_encoder.cc 441行),目前WebRTC的H264編碼器實現H264EncoderImpl的GetScalingSettings方法返回的是true。

總結

    在已經有視頻採集實現獲取到YUV數據時(NV12或者NV21),用AdaptedVideoTrackSource給WebRTC發送視頻數據最方便,WebRTC的Android和IOS端都是這種實現,注意重寫is_screencast方法,返回合適的值確保分辨率的調整策略。

題外話

    OBS集成基於WebRTC的SDK的方法主要參考以下鏈接:
    https://github.com/CoSMoSoftware/OBS-studio-webrtc
    實現了一個output插件,並對OBS原始代碼做了一點修改。
    該鏈接裏的代碼並沒有採用AdaptedVideoTrackSource,而是重載了VideoCaputreImp和WebRtcVideoCapturer,這實際上是繞了彎路,並且這種方式在WebRTC內部支持的也不太好,關閉資源時會崩潰,所以在這份代碼裏作者也沒有好好清理資源,留下一堆垃圾。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章