美文网首页
【iOS】自定义相机(四)会话配置

【iOS】自定义相机(四)会话配置

作者: Seacen_Liu | 来源:发表于2019-04-14 13:15 被阅读0次

    AVCaptureSession是媒体捕捉中核心类,因此会话的创建与配置是做好自定义相机的第一步。这篇文章将会介绍下图会话配置的过程以及注意事项。

    官方文档

    具体的会话配置代码可以参考SCCamera中的SCCameraController.m代码

    会话创建

    1. 会话的创建十分简单,只要单纯的调用[[AVCaptureSession alloc] init]即可
    2. 设置sessionPreset,即设置会话输出的分辨率

    配置输入

    1. 获取硬件设备
    2. 创建捕捉输入
    3. 添加到会话中
    - (void)setupSessionInput:(NSError**)error {
        // 视频输入(默认是后置摄像头)
        AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        AVCaptureDeviceInput *videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:videoDevice error:error];
        if ([_session canAddInput:videoInput]) {
            [_session addInput:videoInput];
        }
        
        // 音频输入
        AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
        AVCaptureDeviceInput *audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:audioDevice error:error];
        if ([_session canAddInput:audioInput]){
            [_session addInput:audioInput];
        }
    }
    

    PS: 每次添加输入或者输出,都需要调用addInput判断是否可添加该输入或输出

    配置预览视图

    重要的操作是设置AVCaptureVideoPreviewLayersession属性,将预览视图与使用的捕捉会话绑定在一起。剩下的预览显示工作就可以交给 AVFoundation 去完成了。

    dispatch_async(dispatch_get_main_queue(), ^{
        self.cameraView.previewView.captureSession = self.session;
    });
    

    PS:很多时候我们会话配置都会选择在子线程中执行,然而CALayer的操作(即UI操作)必须放在主线程中。因此,我们需要回到主线程去执行预览视图的配置。

    配置输出

    - (void)setupSessionOutput:(NSError**)error {
        // 照片输出
        AVCapturePhotoOutput *photoOutput = [AVCapturePhotoOutput new];
        if ([_session canAddOutput:photoOutput]) {
            [_session addOutput:photoOutput];
        }
        
        // 视频文件输出
        AVCaptureMovieFileOutput *movieFileOutput = [AVCaptureMovieFileOutput new];
        if ([_session canAddOutput:movieFileOutput]) {
            [_session addOutput:movieFileOutput];
        }
    }
    
    • 配置输出和输入的步骤十分相似,并且都需要判断会话是否可添加。这一步虽然看上去比较多余,但是还是需要有这个判断的习惯
    • AVCapturePhotoOutput是iOS 10新增的用于拍照的输出类。他有和AVCaptureStillImageOutput一样的静态图片获取能力,也有拍摄 Live 照片的能力。(AVCaptureStillImageOutput已被标记为弃用)
    • ※ 如果使用了AVCaptureMovieFileOutput,那么AVCaptureVideoDataOutputAVCaptureAudioDataOutput将不会工作

    配置整合

    在对会话进行配置的时候,需要通过beginConfigurationcommitConfiguration方法进行单独的、原子性的操作。

    - (void)configureSession:(NSError**)error {
        [self.session beginConfiguration];
        self.session.sessionPreset = AVCaptureSessionPresetPhoto;
        [self setupSessionInput:error];
        dispatch_async(dispatch_get_main_queue(), ^{
            // 在添加视频输入后就可以设置
            self.cameraView.previewView.captureSession = self.session;
        });
        [self setupSessionOutput:error];
        [self.session commitConfiguration];
    }
    

    在进行会话配置的时候,一般我们还需要做权限的判断,在有所有必须的权限后才进行会话的配置。

    if (!self.hasAllPermissions) { 
        // TODO: - 没有权限的操作
    } else {
        dispatch_async(self.sessionQueue, ^{
            NSError *error;
            [self configureSession:&error];
            // TODO: - 处理配置会话错误情况
        });
    }
    

    由于会话配置的过程不是UI操作,也算是一个耗时操作,因此我们可以将会话配置的操作放在子线程中执行。常用的方式就是创建一个同步队列(self.sessionQueue),并进行异步执行,达到将会话操作都放在子线程中顺序同步执行的效果。

    会话运行与停止

    在会话配置后我们需要调用startRunningstopRunning进行会话的运行与停止。当然,这个操作也需要放在self.sessionQueue中,我们也需要保证startRunning在会话配置操作后执行。

    // 会话运行
    dispatch_async(self.sessionQueue, ^{
        if (self.hasAllPermissions && !self.session.isRunning) {
        [self.session startRunning];
        }
    });
    
    // 会话停止
    dispatch_async(self.sessionQueue, ^{
        if (self.session.isRunning) {
            [self.session stopRunning];
        }
    });
    

    会话的运行与停止,就代表了AVFoundation的工作与否。在不需要用到当前AVFoundation工作的时候,停止会话可以节省系统开支。

    官方文档

    Setting Up a Capture Session

    相关文章

      网友评论

          本文标题:【iOS】自定义相机(四)会话配置

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