Android的camea启动preVIEW()失败服用多种照片时 [英] Android camea startPreview() fails when taking multiple pictures

查看:547
本文介绍了Android的camea启动preVIEW()失败服用多种照片时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在写一个应用程序通过相机拍摄多张图片。 (如在摄像机2突发模式,但我工作的旧版本。)
它由takePicture实现()/ onPictureTaken()回调,并在除了一些性能问题,几个设备正常工作。不过,我想开始为第二个画面preVIEW时有失败的感觉HTC设备上启动preVIEW的一个RuntimeException。

I'm writing an APP for taking multiple pictures by camera. (Like the burst mode in Camera2, but I'm working on older versions.) It is implemented by takePicture() / onPictureTaken() callback, and work normally on several devices except some performance issues. However I got a RuntimeException of startPreview failed on an HTC Sensation device when trying to start preview for the 2nd picture.

下面是关于多种拍摄功能:

Here is the functions about multiple shot:

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);
            }
        }
    });
}

正在拍摄第一张图像后,开始preVIEW()函数可能无法在10-20%的指定设备上的速度。我的应用程序总是在前台运行,并有明显的视图来显示preVIEW帧。我也试图绕过JPEG数据而不处理,但仍然出现错误。

After the first picture being taken, the startPreview() function may fail in a rate of 10-20% on the specified device. My APP is always run in foreground and has a visible view to show the preview frames. I also try to bypass the JPEG data without processing it, but the error still occurs.

我发现了一个类似的报告在这里 。如此看来,对于拍照的基本线程没有完成其作品,但我们没有办法去检查一下。所以,我试图抓住从开始preVIEW(除外),并睡会儿:

I found a similar report at here. It seems that the underlying thread for taking picture does not finish its works, but we have no way to check it. So I try to catch the exception from startPreview() and sleep a while:

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

但是,一旦开始preVIEW失败,它将永远失败,无论多少次,我睡了。

But once startPreview fails, it will fail forever no matter how many times I sleep.

我还发现,你需要调用的setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS)的表面持有人较旧的Andr​​oid版本,让启动preVIEW()正常工作。但该设备具有Android版本4.0.3,应该不需要此调用。我还尝试添加它,但问题依然如故。此外,启动preVIEW()的第一次调用正常工作,而onPictureTaken后的第二个呼叫()得到错误。这是在旧版本缺少的setType()的问题不同。

I also found that you need to call setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS) for the surface holder in older Android versions to let startPreview() work correctly. But the device has Android version 4.0.3 and should not require this call. I still try to add it but the issue remains the same. Moreover, the first call of startPreview() works correctly while the second call after onPictureTaken() gets the error. This is different from the issue of missing setType() in older versions.

最后,我用一个变通方法,可以极大地伤害了性能:

Finally I use an workaround that may greatly hurt the performance:

            if (m_take_picture_count < multishot_count)
            {
                try
                {
                    m_camera.startPreview();
                }
                catch (RuntimeException e)
                {
                    // Fail to start preview. Workaround: reopen camera.
                    RestartCamera();
                }

                TakeOnePicture();
            }

也就是说,在启动时preVIEW()失败,我只是关闭相机,使用相同的设置重新打开它,然后启动preVIEW拍摄另一张照片。

That is, when startPreview() fails, I just close the camera, reopen it with the same settings, then start the preview to take another picture.

我想知道如果我错过一些关于拍摄照片的API,并且是有一个解决方案比这个蛮力解决方法更好。

I want to know if I miss something about the take picture APIs, and is there a solution better than this brute-force workaround.

推荐答案

感谢亚历克斯·科恩的建议,我找到了解决办法。该溶液仅HTC感觉装置上进行测试,但它有这样的设备上显着的效果。

Thanks for the suggestion from Alex Cohn, I found a solution. This solution is only tested on the HTC Sensation device, but it has dramatic effect on this device.

我只是把之前启动preVIEW(),将在onPictureTaken()被调用休眠指令:

I just put a sleep instruction before startPreview() that would be called in onPictureTaken():

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

然后我运行一个测试100次,其中每次运行需要连续拍摄3张照片。通过睡眠,我没有100次获得启动preVIEW()的任何错误。如果没有睡觉,我需要重新打开相机78倍,然后重新启动装置8次100次。

Then I run a test 100 times, where each run takes 3 pictures in succession. With the sleep, I didn't get any error from startPreview() in 100 runs. If There is no sleep, I need to reopen the camera 78 times, and restart the device 8 times in 100 runs.

这篇关于Android的camea启动preVIEW()失败服用多种照片时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆