Android camea startPreview()在拍摄多张照片时失败

时间:2015-11-10 11:24:51

标签: android camera android-camera

我正在编写一个用于通过相机拍摄多张照片的APP。 (就像Camera2中的连拍模式一样,但是我正在使用旧版本。) 它由takePicture()/ onPictureTaken()回调实现,并且在一些设备上正常工作,除了一些性能问题。但是当我尝试开始第二张图片的预览时,我在HTC Sensation设备上遇到了startPreview的RuntimeException失败。

以下是关于多重镜头的功能:

points .- mean(points, 2)

在拍摄第一张照片后,startPreview()函数可能会在指定设备上以10-20%的速率失败。我的APP总是在前台运行,并有一个可见的视图来显示预览帧。我也尝试绕过JPEG数据而不进行处理,但错误仍然存​​在。

我发现了类似的报告at here。似乎拍摄照片的底层线程没有完成其工作,但我们无法检查它。所以我尝试从startPreview()中捕获异常并暂停一段时间:

final int multishot_count = 3;

....

public void TakePicture()
{
    // Invoke multishot from UI when the camera preview is already started.

    // startup of multishot task
    ...

    m_take_picture_count = 0;

    TakeOnePicture();
}

private void TakeOnePicture()
{
    m_camera.takePicture(null, null, new Camera.PictureCallback()
    {
        @Override
        public void onPictureTaken(byte[] data, final Camera camera) 
        {
            m_take_picture_count++;

            // feed the JPEG data to a queue and handle it in another thread
            synchronized(m_jpeg_data_lock)
            {
                int data_size = data.length;
                ByteBuffer buffer = ByteBuffer.allocateDirect(data_size);
                buffer.put(data, 0, data_size);

                m_jpeg_data_queue.offer(buffer);

                if (m_take_picture_count == multishot_count)
                    m_is_all_pictures_taken = true;
            }

            if (m_take_picture_count < multishot_count)
            {
                m_camera.startPreview();
                TakeOnePicture();
            }
            else
            {
                // Finalize the multishot task and process the image data
                EndTakePictureTask end_take_picture_task = new EndTakePictureTask();
                end_take_picture_task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
            }
        }
    });
}

但是一旦startPreview失败,无论我睡多少次都会永远失败。

我还发现你需要为较旧的Android版本中的表面持有者调用setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS),以使startPreview()正常工作。但该设备具有Android 4.0.3版本,不应该要求此调用。我仍然尝试添加它,但问题仍然存在。此外,startPreview()的第一次调用正常工作,而onPictureTaken()之后的第二次调用获得错误。这与旧版本中缺少setType()的问题不同。

最后,我使用了可能会严重影响性能的解决方法:

            if (m_take_picture_count < multishot_count)
            {
                boolean is_try_start_preview = true;
                while (is_try_start_preview)
                {
                    try
                    {
                        m_camera.startPreview();
                        is_try_start_preview = false;
                    }
                    catch (RuntimeException e)
                    {
                        try
                        {
                            Thread.sleep(50);
                        }
                        catch (InterruptedException e2)
                        {
                            e2.printStackTrace();
                        }
                    }
                }

                TakeOnePicture();
            }

也就是说,当startPreview()失败时,我只是关闭相机,用相同的设置重新打开它,然后开始预览以拍摄另一张照片。

我想知道我是否遗漏了拍照API的问题,并且有一种比这种强力解决方案更好的解决方案。

1 个答案:

答案 0 :(得分:1)

感谢Alex Cohn的建议,我找到了解决方案。此解决方案仅在HTC Sensation设备上进行测试,但它对此设备有显着影响。

我只是在startPreview()之前放入一个睡眠指令,它将在onPictureTaken()中调用:

try
{
    Thread.sleep(20);
}
catch (Exception e)
{
    e.printStackTrace();
}

然后我进行了100次测试,每次运行连续拍摄3张照片。在睡眠中,我在100次运行中没有从startPreview()获得任何错误。如果没有睡眠,我需要重新打开相机78次,并在100次运行中重启设备8次。