Android 拍摄多张照片时 camea startPreview() 失败
Android camea startPreview() fails when taking multiple pictures
我正在编写一个用相机拍摄多张照片的应用程序。 (就像 Camera2 中的连拍模式,但我正在研究旧版本。)
它由 takePicture() / onPictureTaken() 回调实现,并且在一些设备上正常工作,除了一些性能问题。但是,当我尝试开始第二张图片的预览时,在 HTC Sensation 设备上遇到 startPreview 的 RuntimeException 失败。
关于连拍的功能如下:
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() 函数可能会在指定设备上以 10-20% 的比率失败。我的应用程序总是 运行 在前台,并且有一个可见的视图来显示预览帧。 JPEG数据我也尝试绕过不处理,还是报错
我找到了类似的报告at here。好像拍照的底层线程没有完成它的工作,但我们没有办法检查它。所以我尝试从 startPreview() 捕获异常并睡一会儿:
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失败,不管我睡多少次都会永远失败
我还发现您需要为旧 Android 版本中的表面支架调用 setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS) 才能让 startPreview() 正常工作。但是设备有 Android 版本 4.0.3,应该不需要这个调用。我仍然尝试添加它,但问题仍然存在。此外, startPreview() 的第一次调用工作正常,而 onPictureTaken() 之后的第二次调用出现错误。这与旧版本中缺少 setType() 的问题不同。
最后我使用了一个可能会严重影响性能的解决方法:
if (m_take_picture_count < multishot_count)
{
try
{
m_camera.startPreview();
}
catch (RuntimeException e)
{
// Fail to start preview. Workaround: reopen camera.
RestartCamera();
}
TakeOnePicture();
}
也就是说,当 startPreview() 失败时,我只是关闭相机,以相同的设置重新打开它,然后开始预览以拍摄另一张照片。
我想知道我是否遗漏了一些关于拍照 API 的信息,是否有比这种蛮力解决方法更好的解决方案。
感谢 Alex Cohn 的建议,我找到了解决方案。此解决方案仅在 HTC Sensation 设备上进行了测试,但在该设备上效果显着。
我只是在将在 onPictureTaken() 中调用的 startPreview() 之前放置了一个睡眠指令:
try
{
Thread.sleep(20);
}
catch (Exception e)
{
e.printStackTrace();
}
然后我运行测试了100次,每次运行连续拍摄3张照片。随着睡眠,我在 100 运行 秒内没有从 startPreview() 收到任何错误。如果没有休眠,我需要在100运行秒内重新打开相机78次,并重启设备8次。
我正在编写一个用相机拍摄多张照片的应用程序。 (就像 Camera2 中的连拍模式,但我正在研究旧版本。) 它由 takePicture() / onPictureTaken() 回调实现,并且在一些设备上正常工作,除了一些性能问题。但是,当我尝试开始第二张图片的预览时,在 HTC Sensation 设备上遇到 startPreview 的 RuntimeException 失败。
关于连拍的功能如下:
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() 函数可能会在指定设备上以 10-20% 的比率失败。我的应用程序总是 运行 在前台,并且有一个可见的视图来显示预览帧。 JPEG数据我也尝试绕过不处理,还是报错
我找到了类似的报告at here。好像拍照的底层线程没有完成它的工作,但我们没有办法检查它。所以我尝试从 startPreview() 捕获异常并睡一会儿:
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失败,不管我睡多少次都会永远失败
我还发现您需要为旧 Android 版本中的表面支架调用 setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS) 才能让 startPreview() 正常工作。但是设备有 Android 版本 4.0.3,应该不需要这个调用。我仍然尝试添加它,但问题仍然存在。此外, startPreview() 的第一次调用工作正常,而 onPictureTaken() 之后的第二次调用出现错误。这与旧版本中缺少 setType() 的问题不同。
最后我使用了一个可能会严重影响性能的解决方法:
if (m_take_picture_count < multishot_count)
{
try
{
m_camera.startPreview();
}
catch (RuntimeException e)
{
// Fail to start preview. Workaround: reopen camera.
RestartCamera();
}
TakeOnePicture();
}
也就是说,当 startPreview() 失败时,我只是关闭相机,以相同的设置重新打开它,然后开始预览以拍摄另一张照片。
我想知道我是否遗漏了一些关于拍照 API 的信息,是否有比这种蛮力解决方法更好的解决方案。
感谢 Alex Cohn 的建议,我找到了解决方案。此解决方案仅在 HTC Sensation 设备上进行了测试,但在该设备上效果显着。
我只是在将在 onPictureTaken() 中调用的 startPreview() 之前放置了一个睡眠指令:
try
{
Thread.sleep(20);
}
catch (Exception e)
{
e.printStackTrace();
}
然后我运行测试了100次,每次运行连续拍摄3张照片。随着睡眠,我在 100 运行 秒内没有从 startPreview() 收到任何错误。如果没有休眠,我需要在100运行秒内重新打开相机78次,并重启设备8次。