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

2019-04-14  本文已影响0人  Seacen_Liu

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];
    }
}

配置整合

在对会话进行配置的时候,需要通过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

上一篇 下一篇

猜你喜欢

热点阅读