Android 音视频基础3——Android Camera API及Camera2 API的使用

背景

音视频学习的视频学习部分,必须熟练掌握Camera API的原理即使用,而Android在5.0(API>=21)就提供了Camera2 API,并且建议应用使用Comera2 API,在androidX支持库中还提供了CameraX包,本文主要就是介绍Camera API、Camera2 API 以及androidX中CameraX的使用

Camera API使用

简介

在Google提出Camera2 API之前,所有的相机操作,都是通过Camera这个类完成的,Camera类独自承接了以下以下工作:

  • Camera的直接操作,如获取实例open,释放实例release,开始预览startPreview,停止预览stopPreview,拍照takePicture等等。
  • Camera的参数配置,则在Camera的内部类Parameters来实现,如图片格式设置、图片尺寸设置、闪光灯设置等配置信息,大都可以通过该类找到。
  • 功能回调都有相应的内部类实现,如:
    • PreviewCallback,向调用者提供预览的一组帧数据;
    • AutoFocusCallback,向调用者提供自动对焦的结果信息(是否对焦成功)
    • PictureCallback,向调用者提供拍照回调(包括拍照的byte[] 数据)
    • OnZoomChangeListener和FaceDetectionListener,缩放和人脸识别监听

代码虽然多,但是看起来简单,用起来更简单。

常用操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Camera camera = Camer.open(CAMERA_ID);// CAMERA_ID通常为Camera.CameraInfo.CAMERA_FACING_BACK或CAMERA_FACING_FRONT
Camera.Parameters parameters = camera.getParameters(); // 获取
// 设置预览照片大小
parameters.setPreviewSize(mSurfaceWidth, mSurfaceHeight);
// 设置预览照片帧数
parameters.setPreviewFpsRange(4, 10);
// 设置图片格式
parameters.setPictureFormat(ImageFormat.JPEG);
// 设置图片质量
parameters.setJpegQuality(90);
// parameters.set("jpeg-quality", 90)
// 设置照片大小
parameters.setPictureSize(mSurfaceWidth, mSurfaceHeight);
// 闪光灯设置,调用之前最好动过Camera.Parameters#getSupportedFlashModes来判断一下当前设备是否支持闪光灯
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
// 设置目标
camera.setPreviewDisplay(mSurfaceHolder);
// 开始预览
camera.startPreview();
// ...

// 停止预览
camera.stopPreview();

// 释放相机资源
camera.release();

注意事项

  1. 切换相机是记得先调用释放掉之前的相机,再开启新的相机;
  2. 配合SurfaceView抓取视频数据时,需要再SurfaceView创建后再初始化相机,并在SurfaceView销毁时释放相机资源;
  3. 开始录屏的时候,需要停止预览,然后在停止录屏的时候恢复预览。录屏的时候还要注意lock()/unlock()的调用,具体可以看看两个函数的说明;

Camera2 API使用

简介

Camera2 虽然功能比Camera强大,但类结构也复杂了不少,不过好在各个类的职责还是比较明确的。CameraMamager负责获取CameraDevice,CameraDevice负责获取可以创建CaptureRequest的CaptureRequest.Builder,而且可以建立数据接收者Surface和数据收集者CameraDevice之间的会话,并在会话成功建立后,通过CaptureRequest来对相机进行配置。至于使用者是想进行拍照还是进行录屏,只要在创建CaptureRequest指定不同的模板,并在建立会话是传递不同的数据接收者就可以了。分工明确,流程清楚。

主要对核心类进行说明:

  • CameraManager,系统服务(需要通过ContextgetSystemService方法来获取,用来对CameraDevice进行检测(是否有新的Camera)、控制(如何打开等)、连接、闪光灯控制等,是Camera2的核心类。
    • getCameraIdList,查询可用的Camera列表,如前置后置;
    • AvailabilityCallback,Camera可用性回调通知;
    • TorchCallback,闪光灯状态回调;
    • openCamera(),打开Camera;
    • getCameraCharacteristics,查询到这个连接的相机支持哪些功能;
  • CameraDevice,代表的就是一个链接到Android设备的Camera,通过Camera Device你可以创建CameraCaptureSession,创建CaptureRequest;
  • CameraCharacteristicsCameraDevice的属性描述文件,类似于Camera.Parameters,但包含更多的属性配置。

注意事项

  1. 切换相机是记得先调用释放掉之前的相机,再开启新的相机;
  2. 配合SurfaceView抓取视频数据时,需要再SurfaceView创建后在获取CameraDevice,并在SurfaceView销毁时释放CameraDevice;
  3. 在获取CameraDevice时,为防止一直打不开的情形,最好设置一把超时锁。
  4. 创建会话时需要传递一个Handler,这个Handler最好是子线程的looper创建而来。
  5. 重新创建会话前,记得先关闭之前的会话,释放之前申请的资源;

错误集锦

  1. E/MediaRecorder: stop called in an invalid state: 0
  2. MediaRecorder: stop failed :-1007
  3. MediaRecorder: start failed: -38,说明Camera正在被使用,有可能是别的MediaRecorder没有释放,有可能是用来预览的CaptureSession没有关闭,我的原因是后者,开始录屏时一定要关闭预览的CameraCaptureSession
  4. java.lang.IllegalArgumentException: CaptureRequest contains unconfigured Input/Output Surface!

参考文章: