当前位置:网站首页>webrtc中视频采集实现分析(一) 采集及图像处理接口封装
webrtc中视频采集实现分析(一) 采集及图像处理接口封装
2022-08-04 05:25:00 【mo4776】
文章目录
视频采集是媒体库最基础功能。但是它的实现与操作系统有强相关性,因为不同的操作系统提供的视频采集接口不一样。视频采集模块也具有通用性,不同媒体库的视频采集模块实现的功能是相同的,主要包括如下几个功能:
- 检索视频采集设备
- 指定视频采集设备进行采集
- 根据指定的采集参数(包括分辨率,帧率,图像格式)来初始化设备
- 视频帧数据分发
所以如果要实现自己的媒体库,完全可以把webrtc中视频采集模块移植过来。尽管是复用代码,但也需要弄清楚代码的结构,了解它特点和局限性。
我将从来这三个方面:视频采集类,视频数据帧处理类,视频分发框架来分析webrtc视频采集的实现,这篇文章主要介绍前两个方面。
webrtc中视频采集类
webrtc中视频采集模块的代码位于video_capture目录下。建立了两个类体系来定义了视频采集的接口,分别是DeviceInfo和VideoCaptureModule。还有一个辅助类VideoCaptureFactory,是个工厂类,用来创建DeviceInfo和VideoCaptureModule具体的实现对象。
DeviceInfo
如下为对应的类图

DeviceInfo可以从接口的名字上看出,这个类提供就是检索视频采集设备及采集能力的接口
DeviceInfo为抽象类,定义的都是接口DeviceInofImpl也为抽象类,实现了可以提炼出来的平台通用的接口DeviceInfoDs和DeviceInfoLinux分别对应的是windows和linux的视频采集实现了采集设备有唯一标示,接口中对应为
deviceUniqueIdUTF8
GetBestMatchedCapability
它有个GetBestMatchedCapability接口要着重的讲一下,它实现了如何决策视频采集参数,所谓的视频采集参数包括:分辨率,帧率,图像格式 ,分别决定了视频的清晰度,流畅度和保真度。
GetBestMatchedCapability中有个requested参数就表示上层业务指定的参数,但是指定的参数与设备的实际支持的参数可能匹配不了,最坏的情况是所有的都匹配不上。所以往往是找一个最接近而不是完全匹配的,比如:设置的参数是 640480 30fps,但是设备支持的有1080P(19201080 30fps),720P(1080*720 30fps),那么720P是比1080P更加适合。
GetBestMatchedCapability它选取最佳匹配的策略是:先保证分辨率,再保证帧率,再保图像格式。也就是说分辨率的优先级是最高的,如果采集设备有640*480的图像,但是只有15fps,则还是会选择该采集参数。
采集参数的选取至关重要,如果选择的帧率比较低,则图像看的就不流畅。图像格式YUV422比YUV420就更加保真。所以这种视频参数的匹配策略是根据场景需要来确定,可以优先匹配帧率,或优先匹配图像格式。
VideoCaptureModule
VideoCaptureModule类提供了视频采集的接口,如下类图
VideoCaptureModule为抽象类,定义的都是接口VideoCaptureImpl也为抽象类,实现了可以提炼出来的平台通用的接口VideoCaptureDs是windows平台的实现,通过directshow实现。VideoCaptureModuleV4L2是linux平台的实现,通过V4L2实现。抛出视频帧的方式都是通过回调。
VideoCaptureModule中接口接口都定义的比较清晰易懂,可以直接看代码看看它们的具体实现。
VideoCaptureFactory

VideoCaptureFactory比较简单,提供 创建VideoCaptureModule和DeviceInfo接口
示例
通过 VideoCaptureModule,DeviceInfo,VideoCaptureFactory提供的接口可以很方便的实现视频采集,如下是个简单示例代码
webrtc::VideoCaptureModule::DeviceInfo* pDevideInfo = webrtc::VideoCaptureFactory::CreateDeviceInfo(); // 1
uint32_t number = pDevideInfo->NumberOfDevices();// 2
std::cout <<"video caputre number "<<number << std::endl;
char deviceName[128] = { 0 };
char deviceUniqueId[128] = { 0 };
pDevideInfo->GetDeviceName(0, deviceName, 128, deviceUniqueId, 128); // 3
std::cout << "device name: " << deviceName << ",device unique id: " << deviceUniqueId << std::endl;
webrtc::VideoCaptureCapability cap;
int32_t capNum = pDevideInfo->NumberOfCapabilities(deviceUniqueId); // 4
std::cout << "cap num " << capNum<<std::endl;
webrtc::VideoCaptureCapability requestCap; // 5
requestCap.width = 352;
requestCap.height = 288;
requestCap.maxFPS = 30;
requestCap.videoType = mediaengine::VideoType::kI420;
webrtc::VideoCaptureCapability bestCap; // 6
int32_t num = pDevideInfo->GetBestMatchedCapability(deviceUniqueId, requestCap, bestCap); // 7
std::cout << "best match num " << num<<std::endl;
//rtc::scoped_refptr<VideoCaptureModule> pVCM = webrtc::VideoCaptureFactory::Create(deviceUniqueId); // 8
//pVCM->StartCapture(bestCap);// 9
- 在代码1处创建了一个
DeviceInfo对象,可以检索系统中所有可用的采集设备 - 在代码3处通过
GetDeviceName()方法,获取第一个采集设备的deviceUniqueId,这是这个采集设备的唯一标识 - 在代码4处通过
NumberOfCapabilities()方法,获取采集设备支持的能力(视频采集参数) - 在代码5处定义了一个
VideoCaptureCapability对象,表示业务需要的能力(视频采集参数) - 在代码7处调用
GetBestMatchedCapability()方法,获取最匹配的能力(视频采集参数) - 在代码8和9,创建了一个
VideoCaptureModule对象,然后调用StartCapture()方法,启动采集。这里的代码注释了,因为在启动采集之前,需要通过RegisterCaptureDataCallback方法往VideoCaptureModule对象中注册一个回调,用于处理视频帧数据
视频帧处理
采集到视频帧后,会将视频帧数据通过回调抛到业务层。业务层根据需要会对图像进行处理,包括:格式转换,分辨率缩放,图像旋转。
- 格式转换
在前面提到过视频采集参数,其中就包括图像格式。在决策最适合的视频采集参数时,采集的图像格式可能并不是需要的格式。典型地,编码器需要的图像格式是YUV420,如果采集的视频格式并不是YUV420,就涉及到图像格式的转换
- 分辨率缩放
在视频帧分发时,会涉及对分辨率的缩放。所谓的视频分发就是,采集的视频帧会有不同的用途,比如会用于编码,会用于回显等。
- 图像旋转
在移动端中,涉及到旋转图像,比如从竖屏变为横屏
在webrtc中这些图像处理都封装在图像格式代表的类中,它们都属于VideoFrameBuffer体系。表示一个视频帧数据(图像),可以代表对应格式的视频帧。整个类体系如下
VideoFrameBuffer是个抽象类,在最末端的I420Buffer为具体实现类,还有NV12Buffer和I010Buffer也是VideoFrameBuffer的实例类。通过GetI420,Get010,GetNV12等接口可以获取代表具体图像格式的类。这里主要介绍I420Buffer类,因为它的使用范围最广。
I420Buffer
上面的类图只是罗列出了图像处理的几个接口,它还有几个用于构造的I420Buffer的静态方法,如下:
static rtc::scoped_refptr<I420Buffer> Create(int width, int height);
static rtc::scoped_refptr<I420Buffer> Create(int width,
int height,
int stride_y,
int stride_u,
int stride_v);
stride_y,stride_u,stride_v分别代表Y分量,U分量,V分量的步长。这两个方法的意义是相同的,因为通过width,height可以算出Y,U,V分量的步长。
下面几个方法是用于图像处理的方法
- CropAndScaleFrom
void CropAndScaleFrom(const I420BufferInterface& src,
int offset_x,
int offset_y,
int crop_width,
int crop_height);
从src上裁剪一部分区域,缩放至this的大小(width,height) ,I420BufferInterface代表的就是一个I420帧
- ScaleFrom
void ScaleFrom(const I420BufferInterface& src);
将src缩放至this的大小(width,height)
- PasteFrom
void PasteFrom(const I420BufferInterface& picture,
int offset_col,
int offset_row);
以this为画布,将picture贴在offset_col,offset_row处
- Rotate
static rtc::scoped_refptr<I420Buffer> Rotate(const I420BufferInterface& src,
VideoRotation rotation);
将 src 旋转,产生一个新的I420Buffer
在媒体库中,最主要处理YUV420的图像,所以媒体库中复用I420Buffer就足够,没必要引入VideoFrameBuffer整个体系。
边栏推荐
- Handling List
- 自动化测试的成本高效果差,那么自动化测试的意义在哪呢?
- 实现登录密码混合动态因子,且动态因子隐式
- Resolved error: npm WARN config global `--global`, `--local` are deprecated
- sql server如何得到本条记录与上一条记录的差异,即变动值
- 一个对象引用的思考
- Unity行为树AI分享
- 8、自定义映射resultMap
- 解决安装nbextensions后使用Jupyter Notebook时出现template_paths相关错误的问题
- npm报错Beginning October 4, 2021, all connections to the npm registry - including for package installa
猜你喜欢
随机推荐
7.13 Day20----MYSQL
嵌入式系统驱动初级【4】——字符设备驱动基础下_并发控制
败给“MySQL”的第60天,我重振旗鼓,四面拿下蚂蚁金服offer
9、动态SQL
Wwise入门和实战
CentOS7 —— yum安装mysql
强制结束进程
Performance testing with Loadrunner
利用Jenkins实现Unity自动化构建
文献管理工具 | Zotero
4.3 基于注解的声明式事务和基于XML的声明式事务
The idea setting recognizes the .sql file type and other file types
乱码解决方案
Unity开发类似Profile那样的数据分析工具
如何将 DevSecOps 引入企业?
Landing, the IFC, GFC, FFC concept, layout rules, forming method, use is analysed
动态规划总括
TSF微服务治理实战系列(一)——治理蓝图
ORACLE LINUX 6.5 安装重启后Kernel panic - not syncing : Fatal exception
[Cocos] cc.sys.browserType可能的属性









