iOS WebRTC 杂谈之 视频采集添加美颜特效

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS WebRTC 杂谈之 视频采集添加美颜特效相关的知识,希望对你有一定的参考价值。

参考技术A

使用WebRTC进行互动直播时,我们希望采集的画面可以添加美颜特效,现有两套解决方案:

方案一的思路是替换WebRTC的原生采集,使用GPUImageVideoCamera替换WebRTC中的视频采集,得到经过GPUImage添加美颜处理后的图像,发送给WebRTC的OnFrame方法。
方案二的思路是拿到WebRTC采集的原始视频帧数据,然后传给GPUImage库进行处理,最后把经过处理的视频帧传回WebRTC。

通过查阅WebRTC源码发现,WebRTC原生采集和后续处理的图像格式是NV12(YUV的一种),而GPUImage处理后的Pixel格式为BGRA,因此无论使用方案一还是方案二都需要进行像素格式转换。下面来介绍方案一的实现方法(方案二和方案一并无本质区别,可参考方案一的实现思路)。

在实现该方案前,我们先介绍几个必须掌握的知识:

ios视频采集支持三种数据格式输出:420v,420f,BGRA。

420f 和 420v 都是YUV格式的。 YUV是一种颜色编码方法,分为三个分量,Y表示亮度(Luma),也称为灰度。U和V表示色度(chroma)描述色彩与饱和度。YUV的存储格式分为两大类:planar和packed。planar(平面)先连续存储所有像素点的Y,然后存储所有像素点的U,随后是所有像素点的V。packed是将每个像素点的Y,U,V交叉存储的。 我们最终需要的,用于WebRTC编解码的像素格式是kCVPixelFormatType_420YpCbCr8BiPlanarFullRange的,即双平面的YUV420,Y和UV分开存储,这对后面我们的格式转换非常重要。

420f和420v的区别在于Color Space。f指Full Range,v指Video Range。
Full Range的Y分量取值范围是[0,255]
Video Range的Y分量取值范围是[16,235]
从采集编码到解码渲染,整个过程中,颜色空间的设置都必须保持一致,如果采集用了Full Range 而播放端用Video Range,那么就有可能看到曝光过度的效果。

BRGA是RGB三个通道加上alpha通道,颜色空间对应的就是它在内存中的顺序。比如kCVPixelFormatType_32BGRA,内存中的顺序是 B G R A B G R A...。

大端模式(Big-endian),是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
小端模式(Little-endian),是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。
iOS采用的是小端存储。

LibYUV是Google开源的实现各种YUV与RGB之间相互转换、旋转、缩放的库。
上面提到WebRTC使用的图像格式为NV12,而通过GPUImage采集到的图像格式为BGRA,因此,就需要做BGRA→NV12的转换。

iOS中采用的是小端模式, libyuv中的格式都是大端模式。小端为BGRA,那么大端就是ARGB,所以我们使用libyuv::ARGBToNV12。

下面介绍方案一的具体实现:

修改 avfoundationvideocapturer.mm 中的 - (BOOL)setupCaptureSession 方法,启动GPUImage采集,在回调中拿到BGRA格式的CMSampleBuffer。并修改 - (void)start 和 - (void)stop ,确保采集的启停功能正常。
这里便得到了添加美颜等特效的BGRA源视频帧数据。

先获取BGRA格式的pixelBuffer首地址,并创建转换后NV12格式的内存地址*dstBuff,使用libyuv::ARGBToNV12进行转换,最终我们得到了存储NV12数据的内存地址dstBuff。

pixelBufferAttributes 这个参数是optional的,但是却非常重要。它指定创建时是否使用IOSurface框架,有无这个参数最后创建的Pixelbuffer略有不同,经测试,如不写这个参数,在iOS13中将无法创建正常可用的pixelBufferRef。

上面提到,NV12是双平面的YUV420格式,即在dstBuff中Y和UV分开存储,因此我们需要分别逐行拷贝Y和UV。
注意: 在操作CVPixelBuffer之前,一定要记得先进行加锁,防止读写操作同时进行。

以UV拷贝为例:

这里便得到了NV12格式CVPixelBuffer。

最终交付给WebRTC处理的是CMSampleBuffer,因此我们需要做CVPixelBuffer→CMSampleBuffer的转换:

这里就得到了可用于WebRTC的经过GPUImage处理的CMSampleBuffer,然后将CMSampleBuffer传给WebRTC的OnFrame方法即可。
到这里就完成了为WebRTC的视频添加美颜等特效。其中的坑还是要自己踩过才印象深刻。其中要着重注意iOS13的崩溃问题。

以上是关于iOS WebRTC 杂谈之 视频采集添加美颜特效的主要内容,如果未能解决你的问题,请参考以下文章

IOS技术分享| 在iOS WebRTC 中添加美颜滤镜

WebRTC音视频之美颜开启后小流闪烁问题

WebRTC音视频之美颜开启后小流闪烁问题

Android技术分享| 超简单!给 Android WebRTC增加美颜滤镜功能

reSipWebRTC

WebRTC手记之本地音频采集