相关文章推荐

AV Foundation 照片和视频捕捉功能是从框架搭建之初就是它的强项。 从iOS 4.0 我们就可以直接访问iOS的摄像头和摄像头生成的数据(照片、视频)。目前捕捉功能仍然是苹果公司媒体工程师最关注的领域。

1.1 捕捉会话

AV Foundation  捕捉栈核心类是AVCaptureSession。一个捕捉会话相当于一个虚拟的“插线板”。用于连接输入和输出的资源。

1.2 捕捉设备

AVCaptureDevice为摄像头、麦克风等物理设备提供接口。大部分我们使用的设备都是内置于MAC或者iPhone、iPad上的。当然也可能出现外部设备。但是AVCaptureDevice 针对物理设备提供了大量的控制方法。比如控制摄像头聚焦、曝光、白平衡、闪光灯等。

1.3 捕捉设备的输入

注意:为捕捉设备添加输入,不能添加到AVCaptureSession 中,必须通过将它封装到一个AVCaptureDeviceInputs实例中。这个对象在设备输出数据和捕捉会话间扮演接线板的作用。

1.4 捕捉的输出

AVCaptureOutput 是一个抽象类。用于为捕捉会话得到的数据寻找输出的目的地。框架定义了一些抽象类的高级扩展类。例如 AVCaptureStillImageOutput 和 AVCaptureMovieFileOutput类。使用它们来捕捉静态照片、视频。例如 AVCaptureAudioDataOutput 和 AVCaptureVideoDataOutput ,使用它们来直接访问硬件捕捉到的数字样本。

1.5 捕捉连接

AVCaptureConnection类.捕捉会话先确定由给定捕捉设备输入渲染的媒体类型,并自动建立其到能够接收该媒体类型的捕捉输出端的连接。

1.6 捕捉预览

如果不能在影像捕捉中看到正在捕捉的场景,那么应用程序用户体验就会很差。幸运的是框架定义了AVCaptureVideoPreviewLayer 类来满足该需求。这样就可以对捕捉的数据进行实时预览。

二. 创建预览视图

2.1 创建预览视图

图2-1是项目的用户界面的组成图示。我们把重点放在中间层THPreview View的实现上。因为它直接包含了AV Foundation 的用户界面。

图2-1所示的THPreview View 类提供给用户用i 个摄像头当前拍摄内容的实时预览图。我们将使用AVCaptureVideoPreviewLayer方法实现这个行为。首先我们通过认识THPreview View 的接口开始了解如何实现。

THPreviewView 接口
THPreviewView 实现

2.2 坐标空间转换

当使用AV Foundation 的捕捉API时,一定要理解屏幕坐标系和捕捉设备坐标系不同。iOS6.0之前的版本,要在这2个坐标空间进行转换非常困难。要精确的将屏幕坐标点转换为摄像头坐标点。开发者必须考虑诸如视频重力、镜像、图层变换和方向等因素进行综合计算。幸运的是,AVCaptureVideoPreviewLayer现在定义了一个转换方法让这一过程变得简单多了。

AVCaptureVideoPreviewLayer定义了2个方法用于坐标系间进行转换:

captureDevicePointOfInterestForPoint:获取屏幕坐标系的CGPoint 数据,返回转换得到的设备坐标系CGPoint数据。

pointForCaptureDevicePointOfInterest:获取摄像头坐标系的CGPoint数据,返回转换得到的屏幕坐标系CGPoint 数据。

THPreview  View 使用captureDevicePointOfInterestForPoint:方法将用户触点信息转换为摄像头设备坐标系的中的点。在项目中点击对焦和点击曝光功能实现会用到这个转换坐标点。

三.创建捕捉控制器

3.1 在THCameraController 类中实现

用于配置不同的捕捉设备,同时对捕捉的输出进行控制和交互。

3.2 在设置捕捉会话 在 THCameraController.m

需要导入系统框架<AVFoundation/AVFoundation.h><AssetsLibrary/AssetsLibrary.h>

3.3 设置捕捉会话 setupSession:方法实现

3.5 处理隐私需求

在这个项目会涉及到摄像头、相册、麦克风。需要给出用户提醒,处理隐私需求

注意:iOS7版本只有特定地区有法律规定才会询问用户是否可以访问设备的相机。而从iOS8.0之后,所有的地区和用户都要在应用程序中取得授权才可以访问相机。

常用的隐私设置 plist 修改

四.切换摄像头

4.1 摄像头的支撑方法

4.2 切换摄像头

五.配置捕捉设备

每当修改摄像头设备时,一定要先测试修改动作是否能被设备支持。并不是所有的摄像头都支持所有功能,例如前置摄像头就不支持对焦操作,因为它和目标距离一般在一臂之长的距离。但大部分后置摄像头是可以支持全尺寸对焦。尝试应用一个不被支持的动作,会导致异常崩溃。所以修改摄像头设备前,需要判断是否支持。比如,将对焦模式设置为自动之前,首先要检查此模式是否被支持。

当验证这一个配置的修改可以支持时,就可以执行实际的设置配置了。修改捕捉设备的基本技巧包括先锁定设备准备配置,执行所需的修改,最后解锁设备。

Mac、iPhone、iPad上的设备都是系统通用的,所以在进行修改前,AVCaptureDevice要求开发者获得设备上的一个排它锁🔒,不这样做会导致应用程序抛出异常。虽然不要求配置完立即释放排它锁🔒,不过如果不释放则会对其他使用同一个资源的应用程序产生副作用,所以大多数时候我们每当配置完成后就释放这个排它锁🔒。

cameraSupportsTapToFocus:方法实现

focusAtPoint:方法实现

cameraSupportsTapToExpose:方法实现

exposeAtPoint: 方法实现

observeValueForKeyPath:...方法实现

resetFoucsAndExposureModes方法实现

六.调整闪光灯&手电筒模式

设备后面的LED灯当拍摄静态图片时作为闪光灯,而当拍摄视频时用作连续灯光(手电筒)。捕捉设备的flashMode和 touchMode 属性可以被设置为以下3个值中的一个:

AVCapture(Torch|Flash)ModeOn: 闪关灯|手电筒总是开启

AVCapture(Torch|Flash)ModeOff:闪关灯|手电筒总是关闭

AVCapture(Torch|Flash)ModeAuto:系统会基于周围关照环境情况自动关闭或打开LED

点击对焦方法实现

七.拍摄静态图片

在setupSession:方法中,将一个AVCaptureStillImageOutput实例添加到捕捉会话。这个类是AVCaptureOutput 的子类,用于捕捉静态图片。

AVCaptureConnection *connection = // Active video capture connection

id completionHandler = ^(CMSampleBufferRef buffer,NSError *error)

//Handle image capture

[imageOutput captureStillImageAsynchronouslyFromConnection:connection completionHandler:completionHandler];

创建一个会话并添加捕捉设备输入&捕捉输出时,会话自动建立输入和输出的连接,按需选择信号流线路。访问这些连接在一些情况下是非常实用的功能,因为可以让开发者更好地对发送到输出端的数据进行控制。

7.1 捕捉静态图片

7.2 使用 ASSets Library 框架

ASSets Library 框架可以让开发者通过编程方式访问iOS Photos 应用程序所管理的用户相册&视频库。这个框架的核心类是:ALAssetsLibrary.ALAssetsLibrary类定义了于用户库进行交互的接口。该对象具有多个“写入”方法,可以让开发者将照片&视频写入到自己的库中。

当然涉及到用户隐私,同样需要在plist中修改,还需要在用户的允许才能访问相册。

八.输出 AVCaptureMovieFileOutput

当设置捕捉会话时,添加一个名为AVCaptureMovieFileOutput的输出。这个了定义了方法将QuickTime 影片捕捉到磁盘。这个类大多数核心功能继承于超类AVCaptureFileOutput.这个超类定义了许多实用功能。比如录制到最长时限或录制到特定文件大小时为止。还可以配置成保留最小可用的磁盘空间。这一点在存储空间有限的移动设备上录制视频时非常重要。

通常当QuickTime影片准备发布时,影片头的元数据处于文件的开始位置。这样可以让视频播放器快速读取头包含信息,来确定文件的内容、结构和其包含的多个样本的位置。不过,当录制一个QuickTime影片时,直到所有的样片都完成捕捉后才能创建信息头。当录制结束时,创建头数据并将它附在文件结尾处。

将创建头的过程放在所有影片样本完成捕捉之后存在一个问题,尤其是在移动设备的情况下。如果遇到崩溃或其他中断,比如有电话拨入,则影片头就不会被正确写入,会在磁盘生成一个不可读的影片文件。 AVCaptureMovieFileOutput 提供一个核心功能就是分段捕捉QuickTime影片。

当录制开始时,在文件最前面写入一个最小化的头信息,随着录制的进行,片段按照一定的周期写入,创建完整的头信息。默认状态下,每10秒写入一个片段,不过这个时间的间隔可以通过修改捕捉设备输出的movieFragentInterval属性来改变。写入片段的方式可以逐步创建完整的QuickTime影片头。这样确保了当遇到应用程序崩溃或中断时,影片仍然会以最好的一个写入片段为终点进行保存。我们用默认的间隔来做这demo,但是如果你可以在你的的APP修改这个值。

八.输出 AVCaptureMovieFileOutput
 
推荐文章