Camera2在一些低端机器上出现拉伸问题,当然首先排除不是笔者低级错误设置的分辨率有问题。
Camera2在某些机型上画面拉伸,表象是我们设置16:9的输出(当然是查询到支持的分辨率),但是Camera实际输出的是4:3。
整个过程如下:
获取Camera支持的输出分辨率
StreamConfigurationMap streamConfigurationMap = cameraInfo.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); outputSizes = streamConfigurationMap.getOutputSizes(SurfaceTexture.class); getBestMatchCameraPreviewSize(outputSizes);
笔者选取oppo a37f为例,其支持的分辨率如下:
选择适合的分辨率
public static TESizei getClosestSupportedSize( List<TESizei> supportedSizes, final int requestedWidth, final int requestedHeight) { return Collections.min(supportedSizes, new ClosestComparator<TESizei>() { @Override int diff(TESizei size) { return abs(requestedWidth - size.width) + abs(requestedHeight - size.height); } }); }
笔者选取1280x720分辨率,这个在上面列表中是支持的。
开始预览
这个时候就坑了,画面被拉伸了。通过Log发现,Camera实际输出的是1280x960的图像。更加坑爹的是,没有接口获取Camera真正输出的分辨率。日志如下:242 06-06 12:59:50.875 7451 8170 E Camera : setPreviewSize(), mPackageName = xxxxxxx , width = 1280 , height = 960
看看吧,这个坑货,说是支持720P,设置也成功了,但是输出是1280x960!!
Google后发现这个问题还是相当普遍的,笔者就在Stack Overflow上找到相同的提问,但是并没有解决这个问题:
Camera2 Preview Stretching
后来笔者在WebRtc中发现关于这个问题的说明:
> Video may be stretched pre LMR1 on legacy implementations. Filter out formats that have different aspect ratio than the sensor array. 也就是说在android 5.0,硬件兼容级别为legacy时,Camera2输出的宽高比和Camera Sensor保持一致。**好吧,我们算是找到原因了,但是并没有彻底解决问题,因为我的oppo a37f是5.1.1系统!!!WTF!!!!**
public static List<Size> getSupportedSizes(CameraCharacteristics cameraCharacteristics) { final StreamConfigurationMap streamMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); final int supportLevel = cameraCharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); final android.util.Size[] nativeSizes = streamMap.getOutputSizes(SurfaceTexture.class); final List<Size> sizes = convertSizes(nativeSizes); // Video may be stretched pre LMR1 on legacy implementations. // Filter out formats that have different aspect ratio than the sensor array. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1 && supportLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) { final Rect activeArraySize = cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); final ArrayList<Size> filteredSizes = new ArrayList<Size>(); for (Size size : sizes) { if (activeArraySize.width() * size.height == activeArraySize.height() * size.width) { filteredSizes.add(size); } } return filteredSizes; } else { return sizes; } }
CameraView简单粗暴,硬件兼容为LEGACY直接切到Camera1.
// Not found mCameraId = ids[0]; mCameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId); Integer level = mCameraCharacteristics.get( CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); if (level == null || level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) { return false; }
[1] WebRTC
[2] CameraView
文章来源: Android Camera2 拉伸问题