如何在Android中线程相机回调?

时间:2015-10-31 19:59:52

标签: android multithreading optimization camera android-handler

我正在编写一个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线程中收到这些更新?

2 个答案:

答案 0 :(得分:3)

是的,将在主(UI)线程上调用回调。根据{{​​3}},来自其他方法的所有Camera Callback都被传递到调用open()的线程的事件循环。
这意味着如果没有线程的任何事件循环,则回调将传递到主应用程序事件循环。如果没有主应用程序事件循环,则根本不会传递回调。

在这种情况下,由于onPreviewFrame在主线程上被调用,因此处理大像素矩阵的任务可能会在执行UI操作时卡住,例如显示动画,打开菜单,甚至消息印在屏幕上。

解决方案是创建一个新的Documentation。 HandlerThread可以用来启动一个内置looper机制的新线程。

此外,尝试使用HandlerThread而不是setPreviewCallback(),因为它重用一个缓冲区而不必在每个帧上分配新的缓冲区。它允许预览帧存储器重用,从而提高了预览效率和帧速率。

请参阅此处查看setPreviewCallbackWithBuffer()

答案 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();
            }
        }
    });