AVFoundation框架可以用来自定义相机,看了别人的代码,有很多的不明白,看了文档,就大致翻译下吧,怕以后忘记!
Media Capture
从相机or麦克风获取信息,至少需要以下几个类:
1.一个 AVCaptureDevice 的实例,来代表输入的设备,例如:相机or麦克风
2.一个 AVCaptureInput 具体子类的实例,来配置输入设备的端口。
3.一个 AVCaptureOutput 具体子类的实例,来管理到movie 文件or静态图片的输出。
4.一个 AVCaptureSession 的实例,来协调从输入到输出的数据流。
为了向用户展示相机正在录取的图形图像,可能会用到AVCaptureVideoPreviewLayer(CALayer的子类)
通过一个单独的session,可以来配置多个输入输出,如下展示:
然而,对于某些操作,还有考虑输入设备的各种端口是怎样表示的 和 这些端口是怎样连接到输出的。
在capture session中,capture input 和 capture output 之间的联系,是用 AVCaptureConnection 对象表示的。Capture inputs(AVCaptureInput的实例)拥有一个或者多个输入端口(AVCaptureInputPort的实例)。Capture outputs(AVCaptureOutput的实例)能接收一个或多个来源的数据(例如,AVCaptureMovieFileOutput 对象既能接收视频也能接收音频)。
当把一个input 或者 一个output 加入到一个session中时,session就在所有相符的 inputs 端口 和 output之间,建立连接。
可以是用capture connection 来建立或者取消 一个input or output 的数据流。
注意:在iOS设备中,Media capture 不支持同时捕捉前置摄像头和后置摄像头。
使用Capture Session 来协调数据流
AVCaptureSession 是用来管理数据流的中心协调对象。使用此对象的实例来协调AV inputs 到 outputs的输出。把你想要的capture设备和输出加入到session中,用 startRunning 来开始数据流,用 stopRunning 来停止数据流。
AVCaptureSession *session = [[AVCaptureSession alloc] init];
// Add inputs and outputs.
[session startRunning];
配置Session
你可以使用session的preset来指定图像的质量和分辨率。preset是一个常量,指定可能配置中某一个,在某些情况下,特定于设备的实际配置:
如果你想设置媒体的frame size,你应该检查它是否支持此种设置,如下:
if ([session canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
session.sessionPreset = AVCaptureSessionPreset1280x720;
}
else {
// Handle the failure.
}
如果你需要更精确的调整session参数 or 在session运行时做出调整,那么你就需要在 beginConfiguration 和 commitConfiguration 方法之间来调整。beginConfiguration 和 commitConfiguration方法确保设备作为一个群体 变化, 减少可见性或不一致的状态。在调用 beginConfiguration 之后,你可以增加 or 移除 outputs,改变 sessionPreset 属性的值 ,或者配置个人capture输入或输出属性。只有在你调用了commitConfiguration方法后,这些改变才真正的起作用:
[session beginConfiguration];
// Remove an existing capture device.
// Add a new capture device.
// Reset the preset.
[session commitConfiguration];
监视Capture Session的状态
当Capture Session 开始或者停止,或者中断,capture session会发送通知。如果一个运行时错误发生,你将会收到AVCaptureSessionRuntimeErrorNotification 的通知。你可以通过查询session的running 属性来判断它是否在运行,通过 interrupted 属性来判断是否被中断。此外,running 和 interrupted 属性都是符号KVO的,并且通知都是在主线程中发送的。
AVCaptureDevice 代表Input设备
AVCaptureDevice 抽象表示一个可以提供input 数据(例如视频和音频)给AVCaptureSession对象的物理capture设备。例如,两个视频:一个前置摄像头,一个后置摄像头,一个音频:麦克风。
可以使用 AVCaptureDevice 的类方法 devices 和 devicesWithMediaType: 来找出当前可以使用的 capture设备。可使用的设备也可能会改变,你应该注册来接收 AVCaptureDeviceWasConnectedNotification 和 AVCaptureDeviceWasDisconnectedNotification 的通知。
设备的特性
使用hasMediaType: 来测试设备是否提供了特定的媒体类型,使用supportsAVCaptureSessionPreset: 来测试设备是否支持给定的capture session的预设值。为了给使用者提供信息,你可以得到capture 设备的位置(前面or后面),以及它们的名称。这在你提供一个capture列表给用户选择的时候,可能会有用。
下图显示了前置(AVCaptureDevicePositionFront)和后置(AVCaptureDevicePositionBack)摄像头的位置。
下面的代码示例,遍历所有可用的设备,输出它们的名字,对于视频设备还输出它们的位置:
NSArray *devices = [AVCaptureDevice devices];
for (AVCaptureDevice *device in devices) {
NSLog(@"Device name: %@", [device localizedName]);
if ([device hasMediaType:AVMediaTypeVideo]) {
if ([device position] == AVCaptureDevicePositionBack) {
NSLog(@"Device position : back");
}
else {
NSLog(@"Device position : front");
}
}
}
另外,你还可以得到设备的 model ID 和 unique ID。
Capture设备设置
不同的设备有不同的功能,例如,有些支持不同的 focus or flash 模式......
下面的代码片段,展示了怎样去发现一个视频输入设备有手电筒模式,并且支持给定的capture session 预设值:
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
NSMutableArray *torchDevices = [[NSMutableArray alloc] init];
for (AVCaptureDevice *device in devices) {
[if ([device hasTorch] &&
[device supportsAVCaptureSessionPreset:AVCaptureSessionPreset640x480]) {
[torchDevices addObject:device];
}
}
使用Capture Inputs 加入Capture Device 到Session
为了把一个capture设备加入到capture session中,可以使用 AVCaptureDeviceInput 的一个实例(抽象类AVCaptureInput的具体类)。capture input 设备管理设备的端口:
NSError *error;
AVCaptureDeviceInput *input =
[AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
// Handle the error appropriately.
}
使用addInput: 把inputs 加入到session中。如果合适,你可以使用 canAddInput: 检查是否兼容现有的session。
AVCaptureSession *captureSession = <#Get a capture session#>;
AVCaptureDeviceInput *captureDeviceInput = <#Get a capture device input#>;
if ([captureSession canAddInput:captureDeviceInput]) {
[captureSession addInput:captureDeviceInput];
}
else {
// Handle the failure.
}
一个AVCaptureInput 提供一个或者多个流媒体数据。例如,input设备既能提供音频数据也能提供视频数据。input提供的每一个媒体流用AVCaptureInputPort 对象表示。一个capture session使用AVCaptureConnection对象来决定一系列
AVCaptureInputPort 和 当个AVCaptureOutput 之间的映射。使用Capture Outputs 从 Session 处得到Output
要想从capture session处获得output,需添加一个或多个outputs。output是AVCaptureOutput具体子类。如下:
- AVCaptureMovieFileOutput to output to a movie file
- AVCaptureVideoDataOutput
- AVCaptureAudioDataOutput
- AVCaptureStillImageOutput
用addOutput:方法把output加入到capture session中,使用canAddOutput:方法来检查capture output是否与存在的session兼容。可以在session正在运行的时候,来增加或者移除outputs:
AVCaptureSession *captureSession = <#Get a capture session#>;
AVCaptureMovieFileOutput *movieOutput = <#Create and configure a movie output#>;
if ([captureSession canAddOutput:movieOutput]) {
[captureSession addOutput:movieOutput];
}
else {
// Handle the failure.
}