首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Camera2 API访问同步

Camera2 API访问同步
EN

Stack Overflow用户
提问于 2020-09-22 14:59:33
回答 1查看 133关注 0票数 0

Camera2 API允许我们指定接收包含CameraDeviceCameraCaptureSessionCaptureResult等回调的线程(传递Handler实例)。我们使用这些回调中的信息配置捕获会话,创建捕获请求并获得捕获结果。然而,当用户通过UI控制相机配置(例如调焦、计量器)时,他从主线程进行控制。在这里,我们开发人员有两个选择:

  1. 使用来自任何线程的Camera2 API调用(例如,CameraCaptureSession.capture)“直接”(包括main thread)。在这里,我们需要管理会话状态并同步对Camera2 API的访问。
  2. 将所有Camera2 API调用移动到"CameraThread“。当我们需要访问CameraThread API时,使用Handler将消息发送到“Camera2”。因此,我们实际上将只从单个线程("CameraThread")使用它。

请让我澄清我的意思。假设我们为HandlerThread API回调创建了Camera2。

代码语言:javascript
复制
mCameraThread = new HandlerThread("CameraThread");
mCameraThread.start();
mHandler = new Handler(mCameraThread.getLooper());

第一种方法:

CameraCaptureSession.StateCallback运行在"CameraThread“上。

代码语言:javascript
复制
public void onConfigured(@NonNull CameraCaptureSession session) {
    synchronized (STATE_MONITOR){
        mState = State.Configured;
        mSession = session;
    }
}

用户可以在任何线程(包括"MainThread“)上调用以下方法,因此我们需要同步对mSession的访问。

代码语言:javascript
复制
public void takePicture() {
    synchronized (STATE_MONITOR){
        if(mState == State.Configured){
            CaptureRequest request = ...;
            mSession.capture(request, callback, mHandler)
        }
    }
}

Camera2Basic示例中使用了这种方法。到目前为止,我还在使用第一种方法。

第二种方法:

CameraCaptureSession.StateCallback在"CameraThread“上运行,就像在前面的例子中一样。

代码语言:javascript
复制
public void onConfigured(@NonNull CameraCaptureSession session) {
    mState = State.Configured;
    mSession = session;
}

但是,我们不是“直接”访问mSession,而是将消息发布到"CameraThread“。因此,这里不需要同步,因为mSession只能从单个线程访问。

代码语言:javascript
复制
public void takePicture() {
    assertThatThreadIsRunning();
    mHandler.post(() -> {
        if(mState == State.Configured){
            CaptureRequest request = ...;
            mSession.capture(request, callback, mHandler)
        }
    });
}

第二种方法的好处是我们可以避免任何多线程问题。例如,我们可以考虑预览捕获请求的CameraCaptureSession.CaptureCallback。来自这种重复请求的回调非常频繁地触发,应该对AF和AE控件进行处理。第二种方法允许我们在这种情况下避免同步成本,我认为这可能会稍微提高性能和降低能耗。

据我从资料来源获得的信息,CameraDeviceImplCameraCaptureSessionImpl都是线程安全的,因此这两种方法都是可以接受的。

然而,我想知道第二种方法是否可行,哪一种更好?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-22 22:35:45

它们都是可行的。“更好”取决于一系列因素,比如代码库的大小,以及代码中希望使用会话和设备的不同位置。

将回调发送到相机处理程序线程,再加上更多的样板需要编写,因此对于较小的应用程序,只需从任何线程调用并适当地同步就可以了。

然而,随着应用程序复杂性的增加,将与camera的所有交互都保持在一个线程上会变得越来越有吸引力;这不仅仅是因为您不必显式同步,还因为如果每次与相机对象的交互都发生在同一个线程上,则更容易推理所有权、系统状态等等。另外,由于一些camera方法可以阻塞很长的时间,所以您确实不希望将UI冻结那么长时间。因此,将调用发送到另一个线程是很有价值的。

因此,这是一个额外的样板+小开销与不能集中在一个地方的相机代码的简单和平滑的权衡。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64012443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档