通过输入(inputs)和输出(outputs)对象来对采集设备(比如摄像头或麦克风)进行管理. 使用 AVCaptureSession 对象协调inputs和outputs之间的数据.
使用CALayer的子类 AVCaptureVideoPreviewLayer , 可以展示摄像头采集的画面预览. 对于一个session, 可以配置多个inputs和outputs, 如图所示:
对于大部分的应用而言, 这已经足够了. 但是有些情况下, 会涉及到如何表示一个inputs的多个端口(ports), 以及这些ports如何连接到outputs. Capture session中使用 AVCaptureConnection 表示inputs和outputs之间的连接. 一个Inputs包含一个或多个input ports( AVCaptureInputPort ). Outputs可以从一个或多个来源接收数据, 比如 AVCaptureMovieFileOutput 可以同时接收视频和音频数据. 如下图所示, 当在session中添加一个input或output时, session会为所有可匹配的inputs和outputs之前生成connections( AVCaptureConnection ).
可以使用一个connection来开启或关闭一个input或output数据流. 也可以使用connection监控一个audio频道的码率平均值和峰值. 注意: 媒体捕捉不支持模拟器,也不能同时使用iOS设备上的前置摄像头和后置摄像头进行捕捉 使用Capture Session协调数据流数据采集管理的核心是 AVCaptureSession . 在session中添加采集设备并对output进行配置之后, 可以向session发送 startRunning 消息开始采集, 发送 stopRunning消息停止采集. AVCaptureSession *session = [[AVCaptureSession alloc] init]; // Add inputs and outputs. [session startRunning]; 配置Capture Session使用session的
在设置一个preset之前, 需要判断设备是否支持该preset值: if ([session canSetSessionPreset:AVCaptureSessionPreset1280x720]) { session.sessionPreset = AVCaptureSessionPreset1280x720; } else { // Handle the failure. } 如果需要设置一个更高分辨率的preset, 或者在session运行时修改一些配置, 需要在beginConfiguration 和 commitConfiguration 之间完成修改. beginConfiguration和 commitConfiguration 方法确保所有的修改被整体应用, 减少对预览状态的影响. 在调用 beginConfiguration 之后, 可以添加或移除一个output, 修改 [session beginConfiguration]; // Remove an existing capture device. // Add a new capture device. // Reset the preset. [session commitConfiguration]; 监测Capture Session的状态可以使用通知(NSNotification)监测session的状态, 并且所有的通知都在主线程中发送. 注册监听 AVCaptureSessionRuntimeError 通知可以捕捉运行时发生的错误. 也可以使用session的 使用AVCaptureDevice表示输入设备AVCaptureDevice 是对实际的物理捕捉设备的抽象, 物体捕捉设备向 使用 设备特性可以获取一个设备的设备特性. 也可以通过 hasMediaType: 方法判断设备是否支持特定媒体类型的捕捉, 通过 supportsAVCaptureSessionPreset: 判断设备是否支持特定的分辨率. 当要提供一个可用的捕捉设备列表给用户进行选择时, 获取展示出设备的位置以及名称(比如前摄像头或后摄像头)拥有更好的用户体验. 下图展示了前摄像头(
下面的代码遍历了所有的可用设备并打印其名称, 如果是视频设备, 则打印其位置: NSArray *devices = [AVCaptureDevice devices]; for (AVCaptureDevice *device in devices) { NSLog(@"Device name: %@", [device localizedName]); if ([device hasMediaType:AVMediaTypeVideo]) { if ([device position] == AVCaptureDevicePositionBack) { NSLog(@"Device position : back"); } else { NSLog(@"Device position : front"); } } } 此外, 还可以获取设备的model ID以及unique ID. 捕捉设置不同的设备之间存在性能差异, 比如一些设备支持特殊的对焦或闪光灯模式, 某些设备还支持兴趣点对焦. 下面的代码示例了如何找出一个支持手电筒模式和特定preset的设备: NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; NSMutableArray *torchDevices = [[NSMutableArray alloc] init]; for (AVCaptureDevice *device in devices) { [if ([device hasTorch] && [device supportsAVCaptureSessionPreset:AVCaptureSessionPreset640x480]) { [torchDevices addObject:device]; } } 如果找到了多个符合要求的设备, 你可能需要让用户选择其中的某一个设备, 这时可以使用 localizedName 属性获取设备的描述信息. 可以用类似的方式实现各种不同的捕捉设置. 框架预定义了一些常量用来代表特定的捕捉模式, 你可以使用这些常量以便于判断设备是否支持特定的模式. 在大部分情况下, 可以通过属性监听获取设备特性的变化状态. 任何情况下, 在改变设备的捕捉设置之前, 都应该先锁定设备, 详见下节 兴趣点对焦模式和兴趣点曝光模式是互斥的, 正如对焦模式和曝光模式也是互斥的一样 对焦模式有三种对焦模式:
使用 isFocusModeSupported: 方法判断设备是否支持给定的对焦模式, 然后设置属性 focusMode 改变对焦模式. 此外, 一些设备还支持兴趣点对焦模式. 通过方法 focusPointOfInterestSupported判断是否支持该模式, 然后使用属性 focusPointOfInterest 设置焦点. 无论设备是横屏(Home键靠右)或竖屏模式, CGPoint{0,0}代表设备左上角, CGPoint{1,1}代表设备右下角. 属性 adjustingFocus 可以用来判断当前设备是否正在对焦中. 可以使用KVO监听该属性获取对焦开始与结束的通知. 设置对焦模式的示例代码如下: if ([currentDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) { CGPoint autofocusPoint = CGPointMake(0.5f, 0.5f); [currentDevice setFocusPointOfInterest:autofocusPoint]; [currentDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; } 曝光模式有两种曝光模式:
使用 isExposureModeSupported: 方法判断设备是否支持给定的曝光模式, 然后设置属性 exposureMode 改变曝光模式. 此外, 一些设备还支持兴趣点曝光模式. 通过方法 exposurePointOfInterestSupported 判断是否支持该模式, 然后使用属性 exposurePointOfInterest 设置曝光点. 无论设备是横屏(Home键靠右)或竖屏模式, CGPoint{0,0}代表设备左上角, CGPoint{1,1}代表设备右下角. 属性 adjustingExposure 可以用来判断当前设备是否正在改变曝光设置中. 可以使用KVO监听该属性获取开始设置曝光模式与结束设置曝光模式的通知. 设置曝光模式的示例代码如下: if ([currentDevice isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) { CGPoint exposurePoint = CGPointMake(0.5f, 0.5f); [currentDevice setExposurePointOfInterest:exposurePoint]; [currentDevice setExposureMode:AVCaptureExposureModeContinuousAutoExposure]; } 闪光模式有三种闪光模式:
使用方法 hasFlash 判断一个设备是否有闪光灯. 使用方法 isFlashModeSupported: 判断是否支持某个闪光模式, 使用属性 flashMode 设置闪光灯模式. 手电筒模式手电筒模式下, 闪光灯会一直处于开启状态, 用于视频捕捉. 有三种手电筒模式:
使用方法 hasTorch 判断一个设备是否有闪光灯. 使用方法 isTorchModeSupported: 判断是否支持某个手电筒模式, 使用属性 torchMode 设置手电筒模式. 对于一个有手电筒的设备, 手电筒只有在设备与一个运行中的 capture session进行了关联后才可以设置为开启. 视频稳定性依赖于某些特殊的硬件设备, 视频会有更好设置达到电影级别的稳定性. 但并不支持所有的视频格式和分辨率. 开启电影级别的视频稳定性特性在捕捉视频时可能会增加延迟. 使用属性 videoStabilizationEnabled 可以判断当前是否使用了视频稳定性特性. 属性 enablesVideoStabilizationWhenAvailable 可以在设备支持的情况下自动开启视频稳定性特性, 该属性默认为关闭状态. 白平衡有两种白平衡模式:
使用方法 isWhiteBalanceModeSupported: 判断设备是否支持给定的白平衡模式, 然后通过属性 whiteBalanceMode 设置白平衡模式. 使用属性 adjustingWhiteBalance 判断当前是否正在修改白平衡模式. 可以使用KVO监听该属性获取开始设置白平衡模式与结束设置白平衡模式的通知. 设置设备方向可以在 使用属性 AVCaptureConnection *captureConnection = <#A capture connection#>; if ([captureConnection isVideoOrientationSupported]) { AVCaptureVideoOrientation orientation = AVCaptureVideoOrientationLandscapeLeft; [captureConnection setVideoOrientation:orientation]; } 设备配置要修改设备的捕捉属性, 首先需要使用方法 lockForConfiguration: 锁定设备, 这样可以避免与其他应用的设置产生冲突. if ([device isFocusModeSupported:AVCaptureFocusModeLocked]) { NSError *error = nil; if ([device lockForConfiguration:&error]) { device.focusMode = AVCaptureFocusModeLocked; [device unlockForConfiguration]; } else { // Respond to the failure as appropriate. } 切换设备某些场景下可能需要允许用户切换输入设备, 比如前后摄像头. 为了避免卡顿, 可以重新配置正在运行的session, 但是嵌套使用 声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除 |