我正在编写一个用于通过相机拍摄多张照片的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的问题,并且有一种比这种强力解决方案更好的解决方案。
答案 0 :(得分:1)
感谢Alex Cohn的建议,我找到了解决方案。此解决方案仅在HTC Sensation设备上进行测试,但它对此设备有显着影响。
我只是在startPreview()之前放入一个睡眠指令,它将在onPictureTaken()中调用:
try
{
Thread.sleep(20);
}
catch (Exception e)
{
e.printStackTrace();
}
然后我进行了100次测试,每次运行连续拍摄3张照片。在睡眠中,我在100次运行中没有从startPreview()获得任何错误。如果没有睡眠,我需要重新打开相机78次,并在100次运行中重启设备8次。