前两天给大家介绍了如何在iOS下进行音频采集,今天介绍一下在iOS下进行视频采集。要了解iOS是怎样进行视频采集的,首先我们要了解 AVCaptureSession, AVCaptureDevice等几个基本概念及iOS上视频采集的工作原理。
iPhone包括了摄像头,麦克风等设备,我们用 AVCaptureDevice 代表它们。同时,摄像头又是一个输入设备,我们还可以用AVCaptureDeviceInput 表式它;同样,麦克风则是另一个输入设备(AVCaptureDeviceInput)。
为了方便,iOS定义了AVCaptureSession类来管理这些输入设备,可以通过 AVCaptureSession 打开某个输入设备进行数据采集,或关闭某个输入设备。
当数据被采集回来后,需要把这些数据进行保存,处理,于是iOS又定义了AVCatpureOutput来做这件事。
下面我们分别介绍每个类。
AVCaptureSession对象用于管理采集活动,协调数据的流入流出。
AVCaptureSession对象的 startRunning() 方法是一个阻塞调用,可能需要一些时间,因此您应该在串行队列上执行会话设置,以使主队列不被阻止(这将保持UI响应)
AVCaptureDevice对象代表了一个物理设备及与设备相关的属性。你可以使用它设置底层硬件的属性。一个采集设备还可以为 AVCaptureSession 对象提供数据。
可以使有 AVCaptureDevice 的类方法枚举所有有效的设备,并查询它们的能力。当设备有效或无效时,AVCaptureDevice会得到系统的通知。
设置设备属性时,必须首先使用lockForConfiguration()方法将设备锁住。为设备设置完属性后,你应该查询是否已经设置成功,并在设置完成后调用 unlockForConfiguration() 释放锁。
对于大部分属性配置都可以通过 AVCaptureSession 对象来设置,但一些特殊的选项如高帧率,则需要直接在 AVCaptureDevice 上进行设置。
AVCaptureDeviceInput 是采集设备中的输入端,它继承自 AVCaptureInput,AVCaptureInput是一个抽象类。
AVCaptureConnection 代表的是 AVCaptureSession 里 AVCaptureInput 与 AVCaptureOutput 对象之间建立的连接。
AVCaptureOutput 是一个抽象类,有很多具体的实现类,如AVCaptureVideoDataOutput、AVCaptureMovieFileOutput等。如下图所示。但今天我们主要介绍的是 AVCaptureVideoDataOutput。
AVCaptureVideoDataOutput是录制视频和访问视频帧的输出。它继承自 AVCaptureOutput。
下图是AVCaptureDeviceInput、AVCaptureConnection及AVCaptureOutput关系图:
在 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 步)。