正如标题所说,我在使用Camera2 API在Samsung Note5上录制视频时遇到问题。
我已经从Camera2Video示例中调整了我的代码,但不同之处在于我使用MediaRecorder
类中的配置选项设置了CamcorderProfile
,并且在开始视频录制之前进行了预览我正在捕捉ImageReader
以及将预览渲染为SurfaceTexture
(示例不使用ImageReader
)。
这是我的startVideoCapture
功能(几乎与样本相同)
private boolean startVideoCapture() {
if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
debugToast("Can't start video preview");
return false;
}
try {
closePreviewSession();
if(!setUpMediaRecorder())
{
debugToast("setUpMediaRecorder failed");
return false;
}
SurfaceTexture texture = mTextureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
final CaptureRequest.Builder previewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
List<Surface> surfaces = new ArrayList<Surface>();
Surface previewSurface = new Surface(texture);
surfaces.add(previewSurface);
previewRequestBuilder.addTarget(previewSurface);
Surface recorderSurface = mMediaRecorder.getSurface();
surfaces.add(recorderSurface);
previewRequestBuilder.addTarget(recorderSurface);
mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
debugToast("onConfigured callback received");
mCaptureSession = cameraCaptureSession;
updateVideoPreview(previewRequestBuilder);
}
@Override
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
debugToast("onConfigureFailed");
}
}, mCallbacksInterface.getBackgroundHandler());
} catch (CameraAccessException e) {
e.printStackTrace();
debugToast("CameraAccessException");
return false;
} catch (IOException e) {
e.printStackTrace();
debugToast("IOException");
return false;
}
debugToast("startVideoCapture success");
return true;
}
这是我在开始预览时设置图像阅读器的代码:
// We set up a CaptureRequest.Builder with the output Surface.
CaptureRequest.Builder previewRequestBuilder = mCameraDevice
.createCaptureRequest(templateType);
previewRequestBuilder.addTarget(mImageReader.getSurface());
previewRequestBuilder.addTarget(surface);
// Here, we create a CameraCaptureSession for camera preview.
// surface),
mCameraDevice.createCaptureSession(
Arrays.asList(mImageReader.getSurface(), surface),
new CameraCaptureSession.StateCallback() {
// etc...
这都是非常标准的东西,它在Nexus 5上工作正常:我可以在捕获曲面列表中用ImageReader
启动一个预览捕获会话,然后停止并开始在表面列表中添加MediaRecorder
的新视频并录制视频。但是,这不适用于Note5。使用createCaptureSession
中的MediaRecorder
致电startVideoCapture
时,我遇到了崩溃:
10-14 14:49:25.991: E/CameraCaptureSession(13566): Session 1: Failed to create capture session; configuration failed
10-14 14:49:26.011: W/System.err(13566): android.hardware.camera2.CameraAccessException: Operation timed out in camera service
10-14 14:49:26.011: W/System.err(13566): at android.hardware.camera2.utils.CameraBinderDecorator.throwOnError(CameraBinderDecorator.java:118)
10-14 14:49:26.021: W/System.err(13566): at android.hardware.camera2.utils.CameraBinderDecorator$CameraBinderDecoratorListener.onAfterInvocation(CameraBinderDecorator.java:73)
10-14 14:49:26.021: W/System.err(13566): at android.hardware.camera2.utils.Decorator.invoke(Decorator.java:81)
10-14 14:49:26.021: W/System.err(13566): at java.lang.reflect.Proxy.invoke(Proxy.java:393)
10-14 14:49:26.021: W/System.err(13566): at $Proxy1.waitUntilIdle(Unknown Source)
10-14 14:49:26.021: W/System.err(13566): at android.hardware.camera2.impl.CameraDeviceImpl.waitUntilIdle(CameraDeviceImpl.java:950)
10-14 14:49:26.021: W/System.err(13566): at android.hardware.camera2.impl.CameraDeviceImpl.configureStreamsChecked(CameraDeviceImpl.java:399)
10-14 14:49:26.021: W/System.err(13566): at android.hardware.camera2.impl.CameraDeviceImpl.createCaptureSessionInternal(CameraDeviceImpl.java:561)
10-14 14:49:26.021: W/System.err(13566): at android.hardware.camera2.impl.CameraDeviceImpl.createCaptureSession(CameraDeviceImpl.java:476)
10-14 14:49:26.021: W/System.err(13566): at com.example.Camera2Object.startVideoCapture(Camera2Object.java:2262)
如果我从预览捕获中删除ImageReader
,那么它可以正常工作。
我是否关闭ImageReader
中的closePreviewSession
是否有所不同(我已在预览abortCaptures
上调用了close
和CaptureSession
)。
有谁知道如何解决这个问题?
修改:可能与之相关的一点是,在此设备上使用ImageReader
时,关闭CameraDevice
中的onPause
需要花费相当长的时间(最多6秒) )。我设法通过在单独的线程中将其隐藏起来,但是如果在onResume
的6秒内调用onPause
,则会有延迟,因为我必须等待在我再次打开它之前完成关闭。开始视频录制时,显然我无法承受6秒的延迟。
问题仍然存在,即使我除了致电acquireLatestImage()
之外什么都不做,请将其关闭并立即返回onImageAvailable
的{{1}}回调。当ImageReader
的捕获分辨率非常小时,也会发生这种情况。因此,它似乎不会因为处理ImageReader
数据而过载而导致它。
系统日志,涵盖this Pastebin中从应用开始到视频录制(以及应用关闭)的时间段。
答案 0 :(得分:2)
从您的pastebin日志:
10-15 19:45:32.501:E / Camera3-Device(3151):摄像头0:waitUntilDrainedLocked:等待HAL耗尽时出错:连接超时(-110)
这通常意味着相机HAL的内容出现了问题 - 相机服务正在等待在创建新会话之前完成飞行中的捕获,但有些人永远不会返回。因此,事情会超时,并且会向应用程序返回错误。
遗憾的是,这是设备专用相机代码中的错误,因此三星需要修复它。
作为一种解决方法,您可以尝试停止重复请求,等待所有正在进行的请求完成(设备切换到“准备好”状态),然后创建新会话。然后,HAL没有正在进行的捕获错误处理。
这会增加额外的延迟,预览会冻结一段时间,但在这种情况下可能会更加强大。