Android-相机

Camera

Camera2

基础概念

CameraManager

相机的系统服务,可以用来获得一些初步的信息和动作比如:

打开相机

使用一个状态回调和一个线程handler来打开相机,继而走向stateCallback回调进行下一步操作

1
manager.openCamera(cameraId, stateCallback, mBackgroundHandler);

获得相机列表

一个设备存在前后置摄像头,以及外置摄像头,CameraManager可以获得摄像头ID列表

1
manager.getCameraIdList();

获得具体摄像头的描述信息

1
manager.getCameraCharacteristics(cameraId);

CameraDevice

相机设备的抽象集合,但是和Camera的API不太相同,包含的功能并没有那么多。

  • 关闭相机
  • 创键Capture会话
  • 创键Capture请求

Camera2中,许多的操作都被抽象的定义为了Capture请求

比如预览连续重复的Capture请求,拍照则是一次Capture,甚至聚焦、闪关灯、等各种操作也都作为Capture的参数来进行请求。当然录象也是

所以大致我们流程是:

  1. 获取CameraManager
  2. 去开启指定ID的摄像头
  3. 配置图像数据载体,即摄像头的数据由谁接受
  4. 创建Capture会话
  5. 配置Capture请求
  6. 发送请求

准备工作

检查权限

首先我们使用相机肯定是要声明相机等权限和声明功能

1
2
3
4
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-feature android:name="android.hardware.camera2"/>

接着就是动态检查或请求权限了。

准备Handler

相机的诸多操作为了不给主线程麻烦,当然是需要在子线程中运行的。所以创建线程,获得到Handler

1
2
3
mBackgroundThread = new HandlerThread("CameraBackground");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());

准备预览载体Surface

这里我们通过创建TextureView来获得Surface

打开相机

这里我们首先通过获得到CameraManager,通过CameraManager去获取具体摄像头的描述信息,通过这些描述信息我们可以拿到Sensor的方向,以及Sensor支持的尺寸集,然后根据需要进行配置。继而进行打开相机。

1
2


预览

预览本质上是将实时的帧图像不断重复的显示并且覆盖在载体上。

拍照

录像

其它操作

相机sensor的自然方向和屏幕自然方向

通常描述一张图片分辨率是这样width * height,比如720 * 1080的图片。

屏幕自然自然方向,也就是人手持竖直方向的。以左上角为基准参照点展开内容。如果横屏之类的话,同样内容展开还是以左上角为内容参照点向下向右展开。

但是相机sensor方向却一直是固定的。和手机向右横屏的左上角是同一参照点。那么问题来了。竖直情况下拍摄一张图片,比如我们所看到理解的是一张720x1080的图片,但是实际上在相机sensor来说是一张1080x702。照片还是那张照片,造成了输出照片就是横着的。所以这种情况下就需要进行顺时针旋转,旋转完成后,图片才会从1080x720,变为720x1080,这是时候就可以按照正常方向显示了。

YUV进行旋转后同样,YUV里面的数据只是连续不断的字节流,需要我们给他加上分辨率,才能正确的解释为一张图片。也就是需要按照分辨率进行解析。就好比如你给了宽和高,它就能被抽象化为一个二维的字节数组,然后分别对应着像素点的。所以在我们将YUV数据进行显示或者输入到编码器时需要给与正确显示分辨率,编码器才能够正确的进行编码。