上篇文章中我们讲了CameraDevice,其中有关于CameraCaptureSession的概念,我们没有详细说明,本篇就来看下CameraCaptureSession是什么。
frameworks\base\core\java\android\hardware\camera2\CameraCaptureSession.java
我们知道在openCamera的时候,CameraApp拿到了CameraDevice的对象,但是在后续请求预览、拍照的操作中,CameraApp却并不是直接拿这个CameraDevice对象去操作,而是通过一个CameraCaptureSession的对象去操作。
CameraCaptureSession到时是什么呢?
A configured capture session for a {@link CameraDevice}, used for capturing images from the camera or reprocessing images captured from the camera in the same session previously.
这是CameraCaptureSession.java文件中的第一行类注释。
Session翻译过来是 会话 的意思,就是说CameraApp要与CameraDevice通信,需要通过这个 会话 来传递。一个CameraDevice对应一个active的CameraCaptureSession。我们可以在一个CameraDevice上去多次创建session,但是在每次创建新session之前,会先判断当前CameraDevice是否已经存在一个CameraCaptureSession对象,有的话,就先close这个session对象,在继续创建新的session对象。
下面我们来看下CameraCaptureSession中的关键方法
-
public abstract CameraDevice getDevice();
获取当前CameraCaptureSession关联的CameraDevice对象,由此也说明CameraCaptureSession与CameraDevice是一对一的关系 -
public abstract void prepare(@NonNull Surface surface)
根据方法注释,prepare方法主要是做一些Pre-allocate的动作,保证后续操作的流畅 -
public abstract void tearDown(@NonNull Surface surface)
释放参数surface对象已经分配的buffer -
public abstract int capture(@NonNull CaptureRequest request,@Nullable CaptureCallback listener, @Nullable Handler handler)
拍照方法,参数有 CaptureRequest、listener、handler -
public abstract int setRepeatingRequest(@NonNull CaptureRequest request, @Nullable CaptureCallback listener, @Nullable Handler handler)
开启预览 -
public abstract void stopRepeating()
停止预览 -
public abstract void close();
关闭当前CameraCaptureSession
与之前的CameraDevice、CameraDeviceImpl实现类似,CameraCaptureSession也是一个抽象类,其具体实现类是CameraCaptureSessionImpl
frameworks\base\core\java\android\hardware\camera2\impl\CameraCaptureSessionImpl.java
我们随便看几个上面提到的方法
@Override
public CameraDevice getDevice() {
return mDeviceImpl;
}
@Override
public void prepare(Surface surface) throws CameraAccessException {
synchronized (mDeviceImpl.mInterfaceLock) {
checkNotClosed();
mDeviceImpl.prepare(surface);
}
}
@Override
public void tearDown(Surface surface) throws CameraAccessException {
synchronized (mDeviceImpl.mInterfaceLock) {
checkNotClosed();
mDeviceImpl.tearDown(surface);
}
}
@Override
public int capture(CaptureRequest request, CaptureCallback callback,
Handler handler) throws CameraAccessException {
checkCaptureRequest(request);
synchronized (mDeviceImpl.mInterfaceLock) {
checkNotClosed();
handler = checkHandler(handler, callback);
if (DEBUG) {
Log.v(TAG, mIdString + "capture - request " + request + ", callback " + callback +
" handler " + handler);
}
return addPendingSequence(mDeviceImpl.capture(request,
createCaptureCallbackProxy(handler, callback), mDeviceExecutor));
}
}
.......
我们看到CameraCaptureSessionImpl基本什么都没干,全转给CameraDevice去实现了。
我们可以总结下Camera使用的几个关键节点:
首先,CameraApp去openCamera,得到CameraDevic对象
然后,通过CameraDevice对象去创建 CameraCaptureSession
之后,通过CameraCaptureSession与CameraDevice通信,去起预览、拍照等操作。
本篇内容较短,我们来补充说另一个常见的类:
frameworks\ex\camera2\utils\src\com\android\ex\camera2\utils\ Camera2RequestSettingsSet.java
我们看下代码:
/**
* A set of settings to be used when filing a {@link CaptureRequest}.
*/
public class Camera2RequestSettingsSet {
private final Map<Key<?>, Object> mDictionary;
private long mRevision;
类介绍说这是一个用于填充CaptureRequest的设置类,其成员变量只有两个,其中Map类型的mDictionary就是以键-值对的形式装CameraRequest的参数。
在看它的几个方法:set、remove
public <T> boolean set(Key<T> key, T value) {
if (key == null) {
throw new NullPointerException("Received a null key");
}
Object currentValue = get(key);
// Only save the value if it's different from the one we already have
if (!mDictionary.containsKey(key) || !Objects.equals(value, currentValue)) {
mDictionary.put(key, value);
++mRevision;
return true;
}
return false;
}
public boolean unset(Key<?> key) {
if (key == null) {
throw new NullPointerException("Received a null key");
}
if (mDictionary.containsKey(key)) {
mDictionary.remove(key);
++mRevision;
return true;
}
return false;
}
最重要的一个方法是提供创建CaptureRequest对象的:
- 使用CameraDevice对象,传入要创建的CaptureRequest类型,构建CaptureRequest.Builder对象
- 将键值对设置到CaptureRequest.Builder中
public CaptureRequest createRequest(CameraDevice camera, int template, Surface... targets)
throws CameraAccessException {
if (camera == null) {
throw new NullPointerException("Tried to create request using null CameraDevice");
}
Builder reqBuilder = camera.createCaptureRequest(template);//使用CameraDevice对象,传入要创建的CaptureRequest.Builder类型
for (Key<?> key : mDictionary.keySet()) {
setRequestFieldIfNonNull(reqBuilder, key);//将键值对设置到CaptureRequest.Builder中
}
for (Surface target : targets) {
if (target == null) {
throw new NullPointerException("Tried to add null Surface as request target");
}
reqBuilder.addTarget(target);
}
return reqBuilder.build();
}
private <T> void setRequestFieldIfNonNull(Builder requestBuilder, Key<T> key) {
T value = get(key);
if (value != null) {
requestBuilder.set(key, value);
}
}
Camera2RequestSettingsSet其实就是对CamraDevice中的createCaptureRequest方法的又一次封装,最大的优点是帮我们管理了需要设置给CaptureRequest的众多参数。