我正在尝试使用ImageReader处理帧,同时还在SurfaceView上显示摄像机预览。如果我添加的唯一目标曲面是SurfaceView,则预览是平滑的,但如果我将ImageReader添加为第二个目标,则预览会开始严重滞后。为什么会这样?我试图创建一个HandlerThread和一个Handler并使用它们,但它并没有改变一件事。我现在唯一想到的就是获取并关闭下一张图像。
public void startBackgroundThread() {
handlerThread = new HandlerThread("Image Processing Thread");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
}
在此配置相机:
public void configureCamera() {
try {
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
StreamConfigurationMap configs = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] sizes = configs.getOutputSizes(ImageFormat.YUV_420_888);
imageReader = ImageReader.newInstance(sizes[0].getWidth(), sizes[0].getHeight(), ImageFormat.YUV_420_888, 1);
Range<Integer>[] ranges = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
fpsRange = ranges[ranges.length - 1];
imageReader.setOnImageAvailableListener(this, handler);
cameraSurfaceView.getHolder().setFixedSize(sizes[0].getWidth(), sizes[0].getHeight());
} catch (CameraAccessException | NullPointerException e) {
e.printStackTrace();
}
}
启动相机预览:
private void startCamera() {
try {
cameraManager.openCamera("0", new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
cameraDevice = camera;
try {
cameraDevice.createCaptureSession(Arrays.asList(cameraSurfaceView.getHolder().getSurface(), imageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
captureSession = session;
try {
requestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
requestBuilder.addTarget(cameraSurfaceView.getHolder().getSurface());
requestBuilder.addTarget(imageReader.getSurface());
requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
requestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
captureRequest = requestBuilder.build();
cameraReady = true;
captureSession.setRepeatingRequest(captureRequest, null, handler);
onStartButtonClick(startButton);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
这里有ImageReader的OnImageAvailableListener(这是我目前的主要活动):
@Override
public void onImageAvailable(ImageReader reader) {
reader.acquireNextImage().close();
}
这些代码段目前都存在于我的主要活动中。我正在使用的手机是用于测试目的的摩托罗拉Moto X Play。 cameraSurfaceView只是一个简单的SurfaceView,无需任何自定义。
答案 0 :(得分:0)
有点难以看到缩进形式,但看起来你正在从代码片段中运行当前线程上的相机处理程序。
cameraManager.openCamera中的最后一个参数告诉它使用什么线程 - 如果它为null,它只使用当前线程。来自Android文档:
参数 cameraId String:要打开的摄像机设备的唯一标识符
callback CameraDevice.StateCallback:打开相机后调用的回调
handler Handler:应该在其上调用回调的处理程序,或者为null以使用当前线程的looper。
如果您在GitHub上查看Camera2Basic()的示例,您可以看到它们指定了一个单独的处理程序:
manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
这是在一个单独的线程上开始的:
/**
* Starts a background thread and its {@link Handler}.
*/
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("CameraBackground");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}