「音视频直播技术」iOS视频采集
![](https://img.haomeiwen.com/i5956443/f1cad96df6710df4.png)
前言
前两天给大家介绍了如何在iOS下进行音频采集,今天介绍一下在iOS下进行视频采集。要了解iOS是怎样进行视频采集的,首先我们要了解 AVCaptureSession, AVCaptureDevice等几个基本概念及iOS上视频采集的工作原理。
![](https://img.haomeiwen.com/i5956443/619603de56bc8be0.png)
基本概念
iPhone包括了摄像头,麦克风等设备,我们用 AVCaptureDevice 代表它们。同时,摄像头又是一个输入设备,我们还可以用AVCaptureDeviceInput 表式它;同样,麦克风则是另一个输入设备(AVCaptureDeviceInput)。
为了方便,iOS定义了AVCaptureSession类来管理这些输入设备,可以通过 AVCaptureSession 打开某个输入设备进行数据采集,或关闭某个输入设备。
当数据被采集回来后,需要把这些数据进行保存,处理,于是iOS又定义了AVCatpureOutput来做这件事。
下面我们分别介绍每个类。
AVCaptureSession
AVCaptureSession对象用于管理采集活动,协调数据的流入流出。
AVCaptureSession对象的 startRunning() 方法是一个阻塞调用,可能需要一些时间,因此您应该在串行队列上执行会话设置,以使主队列不被阻止(这将保持UI响应)
AVCaptureDevice
AVCaptureDevice对象代表了一个物理设备及与设备相关的属性。你可以使用它设置底层硬件的属性。一个采集设备还可以为 AVCaptureSession 对象提供数据。
可以使有 AVCaptureDevice 的类方法枚举所有有效的设备,并查询它们的能力。当设备有效或无效时,AVCaptureDevice会得到系统的通知。
设置设备属性时,必须首先使用lockForConfiguration()方法将设备锁住。为设备设置完属性后,你应该查询是否已经设置成功,并在设置完成后调用 unlockForConfiguration() 释放锁。
对于大部分属性配置都可以通过 AVCaptureSession 对象来设置,但一些特殊的选项如高帧率,则需要直接在 AVCaptureDevice 上进行设置。
AVCaptureDeviceInput
AVCaptureDeviceInput 是采集设备中的输入端,它继承自 AVCaptureInput,AVCaptureInput是一个抽象类。
AVCaptureConnection
AVCaptureConnection 代表的是 AVCaptureSession 里 AVCaptureInput 与 AVCaptureOutput 对象之间建立的连接。
AVCaptureOutput
AVCaptureOutput 是一个抽象类,有很多具体的实现类,如AVCaptureVideoDataOutput、AVCaptureMovieFileOutput等。如下图所示。但今天我们主要介绍的是 AVCaptureVideoDataOutput。
![](https://img.haomeiwen.com/i5956443/4031a4221cbe651f.png)
AVCaptureVideoDataOutput
AVCaptureVideoDataOutput是录制视频和访问视频帧的输出。它继承自 AVCaptureOutput。
下图是AVCaptureDeviceInput、AVCaptureConnection及AVCaptureOutput关系图:
![](https://img.haomeiwen.com/i5956443/238f939a5f90b053.png)
采集视频的步骤
- 创建并初始化 AVCaptureSession。
- 创建并初始化 AVCaptureVideoDataOutput。
- 设置 AVCaptureVideoDataOutput的videoSettings,videoSettings 中的 Key and value 包含了输出图像与视频格式定义。
- 调用 AVCaptureVideoDataOutput 对象的 setSampleBufferDelegate 方法,设置采样数据缓冲区的代理。这样当从输入设备采集到数据后,系统就会自动调用AVCaptureVideoDataOutputSampleBufferDelegate 协议中的 captureOutput 方法,从而获取到视频数据。
- 将 AVCaptureVideoDataOutput 对象添加到 AVCaptureSession对象中。
- 根据视频类型 AVMediaTypeVideo,创建 AVCaptureDevice 对象。(可以创建视频设备也可以创建音频设备)。
- 以 AVCaptureDevice 为参数,创建 AVCaptureDeviceInput 对象。
- 将 AVCaptureDeviceInput 对像添加到 AVCaptureSession 对象中。
- 调用 AVCaptureSession 对象的 setSessionPreset 方法进行属性设置。如 设置 quality level, bitrate, 或其它 output 的 settings。
- 调用 Output 对象的 connectionWithMediaType 方法,建立 Input与Output之前的连接。
- 调用 AVCaptureSession 对象的 startRunning() 方法,开始视频采集。
- 调用 AVCaptureSession 对像的 stopRunning() 方法,停止视频采集。
看看WebRTC是如何做的
在 WebRTC 的 modules/video_capture/objc/rtc_video_capture_objc.mm 文件中实现了iOS视频采集相关的工作:
- 初始化
......
_captureSession = [[AVCaptureSession alloc] init];
......
// create and configure a new output (using callbacks)
AVCaptureVideoDataOutput* captureOutput =
[[AVCaptureVideoDataOutput alloc] init];
......
NSDictionary* videoSettings =
[NSDictionary dictionaryWithObject:val forKey:key];
captureOutput.videoSettings = videoSettings;
// 向 Session 添加输出
if ([_captureSession canAddOutput:captureOutput]) {
[_captureSession addOutput:captureOutput];
} else {
......
}
......
- 设置捕获设备
......
//获得设备
AVCaptureDevice* captureDevice =
[DeviceInfoIosObjC captureDeviceForUniqueId:uniqueId];
......
//获得输入设置
AVCaptureDeviceInput* newCaptureInput =
[AVCaptureDeviceInput deviceInputWithDevice:captureDevice
error:&deviceError];
......
// 偿试向 Session 添加新设备
[_captureSession beginConfiguration];
if ([_captureSession canAddInput:newCaptureInput]) {
[_captureSession addInput:newCaptureInput];
addedCaptureInput = YES;
} else {
addedCaptureInput = NO;
}
[_captureSession commitConfiguration];
......
- 开始采集数据
......
NSString* captureQuality =
[NSString stringWithString:AVCaptureSessionPresetLow];
if (_capability.width >= 1280 || _capability.height >= 720) {
captureQuality = [NSString stringWithString:
AVCaptureSessionPreset1280x720];
} else if (_capability.width >= 640 || _capability.height >= 480) {
captureQuality = [NSString stringWithString:
AVCaptureSessionPreset640x480];
} else if (_capability.width >= 352 || _capability.height >= 288) {
captureQuality = [NSString stringWithString:
AVCaptureSessionPreset352x288];
}
[_captureSession beginConfiguration];
// picture resolution
[_captureSession setSessionPreset:captureQuality];
_connection = [currentOutput connectionWithMediaType:AVMediaTypeVideo];
[self setRelativeVideoOrientation];
[_captureSession commitConfiguration];
[_captureSession startRunning];
......
小结
我们首先介绍了在iOS进行视频采集的一些基础概念,然后又通过分析 WebRTC 代码了解了视频采集的基本步骤(共 12 步)。
下一篇文章我将向大家介绍采集后的视频数据如何进行编解码。
希望大家多多观注,谢谢!