PipleLine
Camera1 功能区别
-
一次拍摄一张图片,Camera2支持一次拍摄多张图片,甚至是多张格式和尺寸不同的图片,例如你可以同时拍摄一张 1440x1080 的 JPEG 图片和一张全尺寸的 RAW 图片。
-
出于某些原因,你可能需要先检查相机信息再决定是否开启相机,例如检查闪光灯是否可用。在 Caemra1 上,你无法在开机相机之前检查详细的相机信息,因为这些信息都是通过一个已经开启的相机实例提供的。在 Camera2 上,我们有了和相机实例完全剥离的 CameraCharacteristics 实例专门提供相机信息,所以我们可以在不开启相机的前提下检查几乎所有的相机信息。
-
在不开启预览的情况下拍照
-
在 Camera2 上,你可以在规定的曝光时长范围内配置拍照的曝光时间,从而实现拍摄长曝光图片,你甚至可以延长每一帧预览画面的曝光时间让整个预览画面在暗环境下也能保证一定的亮度
Capture
单次模式----多次模式(指的是连续多次执行指定的 Capture 操作,该模式和多次执行单次模式的最大区别是连续多次 Capture 期间不允许插入其他任何 Capture 操作,多组多次模式的 Capture 会进入队列按顺序执行)-重复模式(该模式的 Capture 是全局唯一的,也就是新提交的重复模式 Capture 会覆盖旧的重复模式 Capture)
CameraManager
是一个负责查询和建立相机连接的系统服务,它的功能不多
将相机信息封装到 CameraCharacteristics 中,并提获取 CameraCharacteristics 实例的方式。
根据指定的相机 ID 连接相机设备。
提供将闪光灯设置成手电筒模式的快捷方式。
CameraDevice
区别于Camera1, 其中Camera类负责了所有相机的操作,而CameraDevice功能则十分单一,只负责建立相机连接的事物,具体操作t
其他
3A算法
自动对焦(AF)、自动曝光(AE)、自动白平衡(AWB)
示例使用中
通过CameraManager 可以获取到支持的摄像头id列表manager.getCameraIdList()
根据cameraId可以获取到CameraCharacteristics characteristics
= manager.getCameraCharacteristics(cameraId);
通过characteristics可以获取到支持的格式以及分辨率之类的,通过comparator获取到最大的分辨率
选择到想要使用的cameraId
可以新建ImageReader用RefCountedAutoCloseable进行封装当没有人使用的时候再进行close
如:
new RefCountedAutoCloseable<>(
ImageReader.newInstance(largestRaw.getWidth(),
largestRaw.getHeight(), ImageFormat.RAW_SENSOR, /maxImages/ 5));
mRawImageReader.get().setOnImageAvailableListener(
mOnRawImageAvailableListener, mBackgroundHandler);
当从IMageReader中获取到的图像数据到达时,端上可能来不及处理,需要缓存加入队列中。
在之前的模式切换需求中用到AtomicInteger,并且:
captureBuilder.setTag(mRequestCounter.getAndIncrement());
这个也是一样的在返回中,可以获取到request,并且获取到tag---->请求顺序。
获取CameraDevice
异步操作,通过CameraManager获取:
manager.openCamera(cameraId, mStateCallback, backgroundHandler);
其中CameraDevice.StateCallback mStateCallback
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice cameraDevice) {
// This method is called when the camera is opened. We start camera preview here if
// the TextureView displaying this has been set up.
synchronized (mCameraStateLock) {
mState = STATE_OPENED;
mCameraOpenCloseLock.release();
mCameraDevice = cameraDevice;
// Start the preview session if the TextureView has been set up already.
if (mPreviewSize != null && mTextureView.isAvailable()) {
createCameraPreviewSessionLocked();
}
}
}
@Override
public void onDisconnected(CameraDevice cameraDevice) {
synchronized (mCameraStateLock) {
mState = STATE_CLOSED;
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
}
@Override
public void onError(CameraDevice cameraDevice, int error) {
Log.e(TAG, "Received camera device error: " + error);
synchronized (mCameraStateLock) {
mState = STATE_CLOSED;
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
}
};
获取captureSession 也是异步的方式获取:
mCameraDevice.createCaptureSession(Arrays.asList(mPreviewSurface, mJpegImageReader.get().getSurface(),
mRawImageReader.get().getSurface()
), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
// 生命周期可能存在不同步的情况,因此需要进行加锁操作
synchronized (mCameraStateLock) {
if (null == mCameraDevice) {
return;
}
try {
setup3AControlsLocked(mPreviewRequestBuilder);
// Finally, we start displaying the camera preview.
cameraCaptureSession.setRepeatingRequest(
mPreviewRequestBuilder.build(),
mPreCaptureCallback, mBackgroundHandler);
mState = STATE_PREVIEW;
} catch (CameraAccessException | IllegalStateException e) {
e.printStackTrace();
return;
}
// When the session is ready, we start displaying the preview.
mCaptureSession = cameraCaptureSession;
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
}
}, mBackgroundHandler);
并且都要传入一个异步的handler,加入要捕获的surface,设置repeatingrequest等参数,真正发起的时候调用:
mCaptureSession.capture(request, mCaptureCallback, mBackgroundHandler);
在mCaptureCallback中可以实现很多逻辑,比如判断当前的3A状态,开始执行截图,在截图的回调中,又开始设置要保存数据的一些东西。获取各种状态,真正的数据传递给了构造CaptureSession的Surface。
请求:
mCaptureSession.capture(request, mCaptureCallback, mBackgroundHandler);
网友评论