我正在编写一个Android应用程序,可以从相机获取连续更新,并在调用onPreviewFrame(byte []数据,相机相机)时对其进行处理。
问题是onPreviewFrame每秒调用大约8-10次,而不是30次(我预计30 FPS摄像头)。我认为这是因为我的UI正在接收所有相机回调,而不是单独的线程。
这是我的SurfaceView,用于保存相机并接收相机回调:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback, Callback {
private Camera mCamera;
...
mCamera.setPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
//Frame received (about 8 per second)
以下是打开相机的代码(在我的主要活动中):
final Camera camera = getCameraInstance(); //calls camera.open()
mPreview = new CameraPreview(this, camera);
我应该如何使用线程,Asynctask或Handler来使相机回调发生在一边?我将如何在UI线程中收到这些更新?
答案 0 :(得分:3)
是的,将在主(UI)线程上调用回调。根据{{3}},来自其他方法的所有Camera Callback都被传递到调用open()的线程的事件循环。
这意味着如果没有线程的任何事件循环,则回调将传递到主应用程序事件循环。如果没有主应用程序事件循环,则根本不会传递回调。
在这种情况下,由于onPreviewFrame
在主线程上被调用,因此处理大像素矩阵的任务可能会在执行UI操作时卡住,例如显示动画,打开菜单,甚至消息印在屏幕上。
解决方案是创建一个新的Documentation。 HandlerThread可以用来启动一个内置looper机制的新线程。
此外,尝试使用HandlerThread而不是setPreviewCallback()
,因为它重用一个缓冲区而不必在每个帧上分配新的缓冲区。它允许预览帧存储器重用,从而提高了预览效率和帧速率。
答案 1 :(得分:0)
以下是我的回答,这个问题阻碍了我好几个星期。
在我的情况下,我的相机是从低级C代码创建的线程启动的。
但是当@Pavitra Kansara回答时,线程需要一个事件循环,如果没有,则可能会调用onPreviewFrame。所以你需要将相机打开的funcalls放回主(UI)线程,如下所示:
((SomeActivity)context).runOnUiThread(new Runnable() {
@Override
public void run() {
try {
open camera funcalls ...
}
catch (Exception e) {
e.printStackTrace();
}
}
});