Camera2 API允许我们指定接收包含CameraDevice、CameraCaptureSession、CaptureResult等回调的线程(传递Handler实例)。我们使用这些回调中的信息配置捕获会话,创建捕获请求并获得捕获结果。然而,当用户通过UI控制相机配置(例如调焦、计量器)时,他从主线程进行控制。在这里,我们开发人员有两个选择:
CameraCaptureSession.capture)“直接”(包括main thread)。在这里,我们需要管理会话状态并同步对Camera2 API的访问。Handler将消息发送到“Camera2”。因此,我们实际上将只从单个线程("CameraThread")使用它。请让我澄清我的意思。假设我们为HandlerThread API回调创建了Camera2。
mCameraThread = new HandlerThread("CameraThread");
mCameraThread.start();
mHandler = new Handler(mCameraThread.getLooper());第一种方法:
CameraCaptureSession.StateCallback运行在"CameraThread“上。
public void onConfigured(@NonNull CameraCaptureSession session) {
synchronized (STATE_MONITOR){
mState = State.Configured;
mSession = session;
}
}用户可以在任何线程(包括"MainThread“)上调用以下方法,因此我们需要同步对mSession的访问。
public void takePicture() {
synchronized (STATE_MONITOR){
if(mState == State.Configured){
CaptureRequest request = ...;
mSession.capture(request, callback, mHandler)
}
}
}在Camera2Basic示例中使用了这种方法。到目前为止,我还在使用第一种方法。
第二种方法:
CameraCaptureSession.StateCallback在"CameraThread“上运行,就像在前面的例子中一样。
public void onConfigured(@NonNull CameraCaptureSession session) {
mState = State.Configured;
mSession = session;
}但是,我们不是“直接”访问mSession,而是将消息发布到"CameraThread“。因此,这里不需要同步,因为mSession只能从单个线程访问。
public void takePicture() {
assertThatThreadIsRunning();
mHandler.post(() -> {
if(mState == State.Configured){
CaptureRequest request = ...;
mSession.capture(request, callback, mHandler)
}
});
}第二种方法的好处是我们可以避免任何多线程问题。例如,我们可以考虑预览捕获请求的CameraCaptureSession.CaptureCallback。来自这种重复请求的回调非常频繁地触发,应该对AF和AE控件进行处理。第二种方法允许我们在这种情况下避免同步成本,我认为这可能会稍微提高性能和降低能耗。
据我从资料来源获得的信息,CameraDeviceImpl和CameraCaptureSessionImpl都是线程安全的,因此这两种方法都是可以接受的。
然而,我想知道第二种方法是否可行,哪一种更好?
发布于 2020-09-22 22:35:45
它们都是可行的。“更好”取决于一系列因素,比如代码库的大小,以及代码中希望使用会话和设备的不同位置。
将回调发送到相机处理程序线程,再加上更多的样板需要编写,因此对于较小的应用程序,只需从任何线程调用并适当地同步就可以了。
然而,随着应用程序复杂性的增加,将与camera的所有交互都保持在一个线程上会变得越来越有吸引力;这不仅仅是因为您不必显式同步,还因为如果每次与相机对象的交互都发生在同一个线程上,则更容易推理所有权、系统状态等等。另外,由于一些camera方法可以阻塞很长的时间,所以您确实不希望将UI冻结那么长时间。因此,将调用发送到另一个线程是很有价值的。
因此,这是一个额外的样板+小开销与不能集中在一个地方的相机代码的简单和平滑的权衡。
https://stackoverflow.com/questions/64012443
复制相似问题