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内部支持的也不太好,关闭资源时会崩溃,所以在这份代码里作者也没有好好清理资源,留下一堆垃圾。

猜你喜欢

转载自blog.csdn.net/sonysuqin/article/details/79860179
今日推荐