问题1 相机预览画面变形
造成原因:
画面显示空间的长宽比例与相机预览的分辨率比例不一致
解决方案:
根据SurfaceView的长宽比例选择合适的相机分辨率,并调整SurfaceView的显示比例(因为相机预览的分辨率是固定的那几组,而你无法百分百确定选择相机的分辨率会和你SurfaceView的比例一致,所以,选择完相机预览分辨率后,你还得调整显示画面的比例)
/**
* 选择合适的预览尺寸
*
* @param choices
* @param textureViewWidth
* @param textureViewHeight
* @return
*/
private Size chooseOptimalSize(Size[] choices, int textureViewWidth, int textureViewHeight) {
//先查找preview中是否存在与surfaceview相同宽高的尺寸
for (Size option : choices) {
if ((option.getWidth() == textureViewWidth) && (option.getHeight() == textureViewHeight)) {
return option;
}
}
// 得到与传入的宽高比最接近的size
float reqRatio = ((float) textureViewWidth) / textureViewHeight;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
Size retSize = null;
for (Size size : choices) {
curRatio = ((float) size.getWidth()) / size.getHeight();
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
return retSize;
}
问题2 Camera2手动点击聚焦失效
问题详情:参考Camera2-master项目手动点击聚焦,设置完CaptureRequest.Builde所需要手动聚焦的参数后,使用CameraCaptureSession.setRepeatingRequest()请求相机聚焦于某一区域,小米手机上面测试失效。然后并不是所有的设备都会失效,我所使用的另一台华为mate9设备能够正常聚焦。
代码如下:
//List of metering areas to use for auto-exposure adjustment. 自动曝光
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, mAERegions);
//传感器所需要捕获的区域
mCaptureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, mCropRegion);
// float minimumLens = mCameraCharacteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
// float num = (((float) 1) * minimumLens / 100);
// mCaptureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0.0f);
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);
updatePreview(mCameraCaptureSession);
/**
* 更新相机预览
*
* @param session
*/
private void updatePreview(CameraCaptureSession session) {
try {
session.setRepeatingRequest(mCaptureRequestBuilder.build(), null, mChildHander);
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
//CameraDevice was already closed
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
造成原因
具体的原因还没有找到,查看谷歌官方文档,比较了一下setRepeatingRequest 和capture方法的区别,一个是他们的优先级不一样,后者要高于前者,后来再仔细想想,请求聚焦应该只是某一刻的时候发生的事情,也不应该是连续的事情,所以使用capture还是挺合理的。
解决方案:
在谷歌上找到关于AF的一些问题的方法,尝试使用CameraCaptureSession.capture()方法去请求需要手动聚焦的区域,在小米手机上面测试,效果显著,问题解决。
//List of metering areas to use for auto-focus 用来自动对焦的测量面积列表
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, mAFRegions);
//List of metering areas to use for auto-exposure adjustment. 自动曝光
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, mAERegions);
//传感器所需要捕获的区域
mCaptureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, mCropRegion);
// float minimumLens = mCameraCharacteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
// float num = (((float) 1) * minimumLens / 100);
// mCaptureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0.0f);
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);
try {
mCameraCaptureSession.capture(mCaptureRequestBuilder.build(),null,mChildHander);
} catch (CameraAccessException e) {
e.printStackTrace();
}