音视频直播技术--Android视频采集(Camera2)

来源:互联网 发布:济南seo外包公司 编辑:程序博客网 时间:2024/04/30 03:55
![Camera2](http://upload-images.jianshu.io/upload_images/5956443-ee30858abc539948.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/400)




## 介绍
今天为大家介绍一下如何在 Android 上进行视频采集。在 Android 系统下有两套 API 可以进行视频采集,它们是 Camera 和 Camera2 。Camera是以前老的 API ,从 Android 5.0(21)之后就已经放弃了。我今天主要给大家介绍一下如何使用 Camera2 进行视频的采集。[原码可以在这里获取](https://github.com/garrylea/Android-Camera2Video.git)


## Camera2 整体工作结构
![Camera2结构图](http://upload-images.jianshu.io/upload_images/5956443-89faff2955ebbdb6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
- Camera Device:代表一个摄像头,在一部手机上有可能有多个摄像头,如前置摄像头,后置摄像头等。
- CameraCaptureSession:表式Android Device(APP)与CameraDevice之间的会话层,类似于 http中的 session。
- CaptureRequest:APP要想拍照,摄像都是向 CameraDevice 发送CaptureRequest请求。这个请求是通过上面的 Session发送出去的。
- CameraMetadata:CameraDevice将捕获到的数据封装成CameraMetadata通过Session传给 APP。其实这一步基本是隐藏起来的,在API中我们很少直接用它。
- Android Device:可以把它想象成我们自己的APP应用。
- Surface:存放数据的类,在实际的操作中,我们只要把 surface告诉CaptureRequest.Builder,当有数据到来之后,系统底层就会将数据存放到 surface中。


## Camera2 主要类介绍
- **CameraManager**:摄像头管理器。用于摄像头的管理,如检测系统摄像头、打开系统摄像头,获取摄像头参数。
- **CameraCharacteristics**:用于管理摄像头特性。该对象通过CameraManager来获取,用于描述特定摄像头所支持的各种特性。
- **CameraDevice**:代表系统摄像头设备。
- **CameraDevice.StateCallback**:该类是CameraDevice的内部类,其中定义了 onOpened, onDisconnected, onError三个方法,这三个方法需要用户来实现。系统会根据打开 Camera 设备的状态结果,回调三个不同的方法。



> 1. onOpened:表式成功打开了 Camera 。
> 2. onDisconnected:表式关闭了与 Camera 的连接。
> 3. onError:表式打开 Camera 失败。



- **CameraCaptureSession**:该类代表 APP 与 Camera 设备之间的**连接**。就好像 APP 与某个 Camera 设备之间建了一个通道,你的APP无论是拍照,摄像等都可以通过这个通道向 Camera 设备发命令请求,Camera接收请求后做相应的工作。这是典型的异步工作方式。
- **CameraCaptureSession.StateCallback**:该类是CameraCaptureSession的内部类,其中定义了 onConfigured 和 onConfigureFailed 两个方法,这两个方法需要用户自己来实现,系统会根据 Session 的创建状态结果回调不同的方法:


> 1. onConfigured:表式 Session 创建成功。
> 2. onConfigureFailed:表式 Session 创建失败。

- **CameraCaptureSession.CaptureCallback**:该类是CameraCaptureSession的另一个内部类,其中定义了 onCaptureCompleted 和 onCaptureProgressed 两个方法,这两个方法也需要用户自己来实现,系统会根据 Session 捕获图片的不同阶段来回调这两个不同的方法:


> 1. onCaptureCompleted:图片捕获完成。
> 2. onCaptureProgressed:图片正在处理中。

- **CameraRequest**:代表了一次捕获请求,用于描述捕获图片的各种参数设置,比如对焦模式、曝光模式等等,APP需要对捕获的所做的各种控制,都通过CameraRequest参数进行设置。
- **CameraRequest.Builder**:负责生成CameraRequest对象。



## 使用 Camera2 基本流程


- 创建一个专门的线程用于Camera的具体操作。Android系统已经为我们提供了 HandlerThread类,以方便我们创建 Hander 类型的线程。对于 HanderThread我们专门再写一篇与之相关的文章。
- 创建一个预览view,它可以是GLSurfaceView或TextureView(这两个View的区别我也会再写一篇文章来介绍),用于视频采集时观看采集到的结果。当APP接收到preview创建成功后,就可以开始Camera设备相关的操作了。
- 在CameraManager中找到一个合适的 Camera 设备,得到其设备号。通过 CameraID 得到该设备的各种参数,我们可以再根据这些参数调整preview。
- 调用CameraManager的openCamera(String cameraId, **CameraDevice.StateCallback callback**, Handler handler)方法打开指定摄像头。

> 1. 该方法的第一个参数代表要打开的摄像头ID;
> 2. 第二个参数 **callback** 用于监听摄像头的状态;
> 3. 第三个参数代表执行callback的Handler,如果程序希望直接在当前线程中执行callback,则可将handler参数设为null。
    
- 当摄像头被打开之后,系统就会回调 **CameraDevice.StateCallback** 类中的 **onOpened** 方法,在该方法中 APP 可获取 CameraDevice 对象。
- 拿到CameraDevice设备后,调用它的createCaptureRequest(int templateType)方法创建CaptureRequest.Builder对象。CaptureRequest.Builder是一个非常重要的对象,它主要包括两方面的作用,一是可以把预览或录制的Surface给它,这样每个Surface就可以从Camera拿到采集到的图片原始数据,这是一个典型的观察者模式,二是可以给Camera设备设置自动对焦,光圈大小等Camera设备参数。另外**templateType** 参数也要强调一下,包括下面三种类型:


> 1. TEMPLATE_PREVIEW(预览)
> 2. TEMPLATE_RECORD(拍摄视频)
> 3. TEMPLATE_STILL\_CAPTURE(拍照)等参数。

- 然后调用CameraDevice的createCaptureSession(List<Surface> outputs, **CameraCaptureSession.StateCallback callback**,Handler handler)方法来创建CameraCaptureSession。


> 1. 该方法的第一个参数是一个List集合,封装了所有需要从该摄像头获取图片的Surface;
> 2. 第二个参数 **StateCallback** 用于监听CameraCaptureSession的创建过程;
> 3. 第三个参数代表执行callback的Handler,如果程序希望直接在当前线程中执行callback,则可将handler参数设为null。


- 如果 CameraCaptureSession 创建成功,系统会回调 **StateCallback** 的 **onConfigured** 方法。在该方法中我们可以拿到创建好的 **CameraCaptureSession**对象。
- 再调用**CameraCaptureSession**对象的setRepeatingRequest(CaptureRequest request, CaptureCallback callback, Handler handler)方法,向Camera发送命令请求。


> 1. 第一个参数是由前面讲的 createCaptureRequest 创建的 CaptureRequest.Builder对象生成的。
> 2. 第二个参数callback是Camera捕获时的回调对象。
> 3. 第三个参数代表执行callback的Handler,如果程序希望直接在当前线程中执行callback,则可将handler参数设为null。


通过以上的步骤,就可以从Camera设备中获取到视频了。我们还可以通过Android的MediaRecorder类将获取到的视频录制下来进行回看。对于MediaRecorder我会在另一篇文章中再做介绍。


## 小结
通过上面对 Camera2 API 使用的分析,我们们可以看到 Camera2 完全采用了异步的架构模式,在完成 Camera 每一步操作后系统都会通知用户,用户可以在回调时做下一步的操作,而不用一直等待。采用这种模式的优点是可以大大提高APP的工作效率,缺点是不那么直观,增加了一些学习和开发成本。


## 参考资料
1. google sample android-Camera2video
2. http://blog.csdn.net/lushuo9156/article/details/58059516
---
![微信公众号](http://upload-images.jianshu.io/upload_images/5956443-a207e82a3b27edf4.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
原创粉丝点击