OC

OC之AVCaptureSession

2018-08-22  本文已影响0人  苏沫离

AVCaptureSession 继承自NSObject,是AVFoundation的核心类;用于管理捕获对象AVCaptureInput的视频和音频的输入,协调捕获的输出AVCaptureOutput

AVCaptureSession内部流程.png

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(默认值)时,会话配置适合于广域捕获:

注意:当此属性为YES,且会话配置不适合于广域捕获时,除AVCaptureSessionPresetInputPriority之外的会话预置可以选择不支持广域捕获的捕获格式。

如果要直接更改捕获设备AVCaptureDeviceactiveColorSpace属性的值,请将此属性设置为NO(不管您是使用会话预设配置设备,还是直接设置捕获格式)。

上一篇下一篇

猜你喜欢

热点阅读