OC之AVCaptureSession
AVCaptureSession 继承自NSObject
,是AVFoundation
的核心类;用于管理捕获对象AVCaptureInput
的视频和音频的输入,协调捕获的输出AVCaptureOutput
。
1、管理输入和输出
属性或方法 | 描述 |
---|---|
@property(nonatomic, readonly) NSArray<__kindof AVCaptureInput *> *inputs |
数据流的输入管理AVCaptureInput 对象集; |
- (BOOL)canAddInput:(AVCaptureInput *)input |
返回一个布尔值,该值指示给定的输入是否可以添加到会话中。 |
- (void)addInput:(AVCaptureInput *)input |
向会话添加给定的输入。如果canAddInput: 返回true ,则使用此方法向会话添加输入;canAddInput: 返回false ,则该方法在调用时抛出异常。 |
- (void)removeInput:(AVCaptureInput *)input |
删除一个给定的输入;可以在会话运行时调用此方法。 |
@property(nonatomic, readonly) NSArray<__kindof AVCaptureOutput *> *outputs |
数据流的输出管理AVCaptureOutput 对象 |
- (BOOL)canAddOutput:(AVCaptureOutput *)output |
返回一个布尔值,该值指示给定的输出是否可以添加到会话中。 |
- (void)addOutput:(AVCaptureOutput *)output |
向会话添加给定的输出;如果canAddOutput: 返回true ,则使用此方法向会话添加输出;canAddOutput: 返回false ,则该方法在调用时抛出异常。 |
- (void)removeOutput:(AVCaptureOutput *)output |
删除一个给定的输出;可以在会话运行时调用此方法。 |
要执行实时或脱机捕获,需要实例化AVCaptureSession
对象并添加适当的输入(如AVCaptureDeviceInput
)和输出(如AVCaptureMovieFileOutput)
。下面的代码片段说明了如何配置捕获设备来记录视频:
dispatch_queue_t serialQueue = dispatch_queue_create("com.demo.gcdqueue.recordVideo", DISPATCH_QUEUE_SERIAL);
AVCaptureSession *captureSession = [[AVCaptureSession alloc] init];
AVCaptureDevice *videoCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoCaptureDevice error:&error];
AVCaptureMovieFileOutput *videoOutput = [[AVCaptureMovieFileOutput alloc] init];
if ([captureSession canAddInput:videoInput]) {
[captureSession addInput:videoInput];
}
else {
//处理失败
}
if ([captureSession canAddOutput:videoOutput]){
[captureSession addOutput:videoOutput];
}
else {
//处理失败
}
2、管理运行状态
属性、方法或通知 | 描述 |
---|---|
- (void)startRunning |
告诉AVCaptureSession 实例开始运行。此方法用于启动从输入到连接到AVCaptureSession 实例(即接收者)的输出的数据流。此方法是同步的,会阻塞,直到接收器完全开始运行或无法开始运行为止。如果在此过程中发生错误,且AVCaptureSession 未能开始运行,将收到AVCaptureSessionRuntimeErrorNotification 通知。 |
- (void)stopRunning |
告诉AVCaptureSession 实例停止运行。此方法用于停止从输入到连接到AVCaptureSession 实例(即接收方)的输出的数据流。这个方法是同步的,会阻塞直到接收器完全停止运行。 |
@property(nonatomic, readonly, getter=isRunning) BOOL running |
指示接收器是否正在运行;可以使用KVO来观察这个属性的值。 |
@property(nonatomic, readonly, getter=isInterrupted) BOOL interrupted |
指示接收器是否被中断。可以使用KVO来观察这个属性的值。 |
AVCaptureSessionRuntimeErrorNotification |
在捕获会话中发生错误时发送;使用键AVCaptureSessionErrorKey 从通知的用户信息字典中检索底层错误。 |
AVCaptureSessionDidStartRunningNotification |
AVCaptureSession 实例开始运行时发送通知 |
AVCaptureSessionDidStopRunningNotification |
AVCaptureSession 实例停止时发送通知 |
AVCaptureSessionWasInterruptedNotification |
AVCaptureSession 实例被中断时发送通知。可以使用AVCaptureSessionInterruptionReasonKey 键检索关于中断原因的信息,这个键的值是一个包含AVCaptureSessionInterruptionReason 值的NSNumber对象。还可以使用AVCaptureSessionInterruptionSystemPressureStateKey 键检索导致捕获会话中断的系统压力因素信息,如果AVCaptureSession 实例由于系统压力而中断,则该通知的userInfo 字典包含这个键,它的相应值是AVCaptureSystemPressureState 对象,提供关于系统压力级别的详细信息以及导致中断的因素。 |
AVCaptureSessionInterruptionEndedNotification |
AVCaptureSession 实例的中断结束时发送通知 |
可以调用startRunning
来启动从输入到输出的数据流,调用stopRunning
来停止流。
dispatch_queue_t serialQueue = dispatch_queue_create("com.demo.gcdqueue.recordVideo", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
//开始运行session
if (captureSession.running == NO){
[captureSession startRunning];
}
//停止session
if (captureSession.running){
[captureSession stopRunning];
}
});
注意:
startRunning
方法是一个耗时操作,它会阻塞当前线程直到启动会话完毕;因此应该在串行队列上执行会话设置,这样主队列就不会阻塞(这会使UI保持响应)。可以参见Apple Demo 示例。
3、更改配置
方法 | 描述 |
---|---|
- (void)beginConfiguration |
指示要原子化地进行的一组配置更改的开始 |
- (void)commitConfiguration |
提交一组配置更改 |
可以使用-beginConfiguration
和-commitConfiguration
将正在运行的会话上的多个配置操作批处理为原子更新。在调用-beginConfiguration
之后,例如,可以添加或删除输出,更改sessionPreset
,或配置单个捕获输入或输出属性。在调用-commitConfiguration
之前,实际上不会进行任何更改,在此阶段,它们将一起应用。
dispatch_async(serialQueue, ^{
[captureSession beginConfiguration];
NSError *error = nil;
AVCaptureDevice *audioCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioCaptureDevice error:&error];
if ([captureSession canAddInput:audioInput]) {
[captureSession addInput:audioInput];
}
else{
//处理失败
}
[captureSession commitConfiguration];
});
4、预设管理会话
属性或方法 | 描述 |
---|---|
@property(nonatomic, copy) AVCaptureSessionPreset sessionPreset |
一个常数值,指示输出的质量级别或比特率;默认值是 AVCaptureSessionPresetHigh 。可以在会话运行时设置此值;如果-canSetSessionPreset: 返回YES,则能设置此值。 |
- (BOOL)canSetSessionPreset:(AVCaptureSessionPreset)preset |
返回一个布尔值,该值指示AVCaptureSession 实例是否可以使用给定的预设值。 |
使用AVCaptureSessionPreset属性定义捕获设置预置的常量。
typedef NSString * AVCaptureSessionPreset
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPresetPhoto NS_AVAILABLE(10_7, 4_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPresetHigh NS_AVAILABLE(10_7, 4_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPresetMedium NS_AVAILABLE(10_7, 4_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPresetLow NS_AVAILABLE(10_7, 4_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPreset320x240 NS_AVAILABLE_MAC(10_7) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPreset352x288 NS_AVAILABLE(10_7, 5_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPreset640x480 NS_AVAILABLE(10_7, 4_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPreset960x540 NS_AVAILABLE_MAC(10_7) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPreset1280x720 NS_AVAILABLE(10_7, 4_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPreset1920x1080 NS_AVAILABLE_IOS(5_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPreset3840x2160 NS_AVAILABLE_IOS(9_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPresetiFrame960x540 NS_AVAILABLE(10_9, 5_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPresetiFrame1280x720 NS_AVAILABLE(10_9, 5_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
AVF_EXPORT AVCaptureSessionPreset const AVCaptureSessionPresetInputPriority NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
可以使用sessionPreset
属性为输出AVCaptureOutput
自定义质量级别、比特率或其他设置。大多数常见的捕获配置都可以通过会话预置获得;然而,一些特殊的选项(比如高帧率)需要直接在AVCaptureDevice
实例上设置捕获格式。
dispatch_async(serialQueue, ^{
[captureSession beginConfiguration];
if ([captureSession canSetSessionPreset:AVCaptureSessionPreset1920x1080]){
captureSession.sessionPreset = AVCaptureSessionPreset1920x1080;
}
else if ([self.session canSetSessionPreset:AVCaptureSessionPreset1280x720]){
captureSession.sessionPreset = AVCaptureSessionPreset1280x720;
}
else if ([self.session canSetSessionPreset:AVCaptureSessionPreset640x480]){
captureSession.sessionPreset = AVCaptureSessionPreset640x480;
}
else{
captureSession.sessionPreset = AVCaptureSessionPresetLow;
}
[captureSession commitConfiguration];
});
5、管理连接
方法 | 描述 |
---|---|
- (void)addConnection:(AVCaptureConnection *)connection |
向会话添加给定的捕获连接。如果-canAddConnection: 返回YES,则可以使用此方法向会话添加AVCaptureConnection 实例。当使用addInput: 或addOutput: 时,所有兼容的输入和输出之间会自动形成连接。手动添加连接仅在添加没有连接的输入或输出时才需要。 |
- (BOOL)canAddConnection:(AVCaptureConnection *)connection |
返回一个布尔值,该值指示给定连接是否可以添加到AVCaptureSession 实例。 |
- (void)addInputWithNoConnections:(AVCaptureInput *)input |
在没有形成任何连接的情况下向会话添加捕获输入。可以在会话运行时调用此方法。通常应该使用addInput: 向会话添加输入。如果需要细粒度控制哪些输入连接到哪些输出,可以使用此方法。 |
- (void)addOutputWithNoConnections:(AVCaptureOutput *)output |
在没有形成任何连接的情况下向会话添加捕获输出。可以在会话运行时调用此方法。通常,您应该使用addOutput: 向会话添加输出。如果需要细粒度控制哪些输入连接到哪些输出,可以使用此方法。 |
- (void)removeConnection:(AVCaptureConnection *)connection |
从会话中删除捕获连接。 |
6、共享应用程序的音频会话
属性 | 属性类型 | 描述 |
---|---|---|
usesApplicationAudioSession |
BOOL |
指示捕获会话是否使用应用程序的共享音频会话。如果此属性的值为NO,则AVCaptureSession 会话使用私有的AVAudioSession 实例进行音频录制,如果应用程序使用其自己的音频会话进行回放,可能会导致中断。对于iOS 7.0或更新版本的应用程序,这个属性默认为YES,允许同时播放和录制。 |
automaticallyConfiguresApplicationAudioSession |
BOOL |
指示捕获会话是否自动更改应用程序的共享音频会话的设置。只有当usesApplicationAudioSession 属性的值为YES时,此属性才生效,该属性的值默认为YES。导致捕获会话自动配置应用程序的共享AVAudioSession 实例以获得最佳记录。例如,如果捕捉会话使用设备的后置摄像头,音频会话的麦克风和极性模式将被设置为从该方向最佳记录声音。注意,在捕获完成后,音频会话的原始状态不会恢复。如果将此属性的值设置为NO,应用程序将负责选择适当的音频会话设置。如果音频会话的设置与捕获会话不兼容,录制可能会失败。 |
7、同步多个输入和输出
//用于输出同步的时钟对象。
@property(nonatomic, readonly) CMClockRef masterClock;
返回的CMClockRef对象是只读的,并为捕获输出中的所有示例缓冲区提供了一个时间基础。这可以与AVCaptureInputPort
对象中的时钟一起使用,以同步捕获输出和外部数据源(如运动示例)。
例如,要将输出时间戳同步到输入设备提供的原始时间戳,可以在captureOutput
中执行以下操作:
AVCaptureInputPort *port = [[connection inputPorts] objectAtIndex:0];
CMClockRef originalClock = [port clock];
CMTime syncedPTS = CMSampleBufferGetPresentationTime( sampleBuffer );
CMTime originalPTS = CMSyncConvertTime( syncedPTS, [captureSession masterClock], originalClock );
8、管理颜色空间
@property(nonatomic) BOOL automaticallyConfiguresCaptureDeviceForWideColor;
一个布尔值,指定会话是否应该在可用的地方自动使用宽域颜色。所有设备和格式都支持sRGB颜色空间中的捕获。一些设备和格式也可以捕获P3颜色空间,其中包含更广泛的颜色范围。宽域捕获仅适用于某些捕获工作流,因此该属性控制这些工作流的自动配置。
当此属性为YES(默认值)时,会话配置适合于广域捕获:
- 如果使用
AVCaptureSessionPresetInputPriority
之外的会话预置,会话会自动将设备AVCaptureDevice的activeFormat
属性设置为支持广域捕获的,并将设备AVCaptureDevice
的activeColorSpace
属性设置为广域颜色空间。 - 如果手动选择捕获格式(从而将会话设置为输入优先级),则会话仅当选择的格式支持广域捕获时,才会自动将设备
AVCaptureDevice
的activeColorSpace
属性设置为宽域颜色空间。
注意:当此属性为YES,且会话配置不适合于广域捕获时,除
AVCaptureSessionPresetInputPriority
之外的会话预置可以选择不支持广域捕获的捕获格式。
如果要直接更改捕获设备AVCaptureDevice的activeColorSpace
属性的值,请将此属性设置为NO(不管您是使用会话预设配置设备,还是直接设置捕获格式)。