美文网首页OC
OC之AVCaptureSession

OC之AVCaptureSession

作者: 苏沫离 | 来源:发表于2018-08-22 11:41 被阅读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(默认值)时,会话配置适合于广域捕获:

    • 如果使用AVCaptureSessionPresetInputPriority之外的会话预置,会话会自动将设备AVCaptureDeviceactiveFormat属性设置为支持广域捕获的,并将设备AVCaptureDeviceactiveColorSpace属性设置为广域颜色空间。
    • 如果手动选择捕获格式(从而将会话设置为输入优先级),则会话仅当选择的格式支持广域捕获时,才会自动将设备AVCaptureDeviceactiveColorSpace属性设置为宽域颜色空间。

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

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

    相关文章

      网友评论

        本文标题:OC之AVCaptureSession

        本文链接:https://www.haomeiwen.com/subject/rtieiftx.html