Android Camera2 拉伸问题

1. 前言

Camera2在一些低端机器上出现拉伸问题,当然首先排除不是笔者低级错误设置的分辨率有问题。

2. 拉伸问题详细描述

Camera2在某些机型上画面拉伸,表象是我们设置16:9的输出(当然是查询到支持的分辨率),但是Camera实际输出的是4:3。
整个过程如下:

  1. 获取Camera支持的输出分辨率

                StreamConfigurationMap streamConfigurationMap = cameraInfo.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            outputSizes = streamConfigurationMap.getOutputSizes(SurfaceTexture.class);
            getBestMatchCameraPreviewSize(outputSizes);

    笔者选取oppo a37f为例,其支持的分辨率如下:
    《Android Camera2 拉伸问题》

  2. 选择适合的分辨率

      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);
      }
    });
    }

    笔者选取1280×720分辨率,这个在上面列表中是支持的。

  3. 开始预览
    这个时候就坑了,画面被拉伸了。通过Log发现,Camera实际输出的是1280×960的图像。更加坑爹的是,没有接口获取Camera真正输出的分辨率。日志如下:

    242 06-06 12:59:50.875  7451  8170 E Camera  : setPreviewSize(), mPackageName = xxxxxxx , width = 1280 , height = 960

看看吧,这个坑货,说是支持720P,设置也成功了,但是输出是1280×960!!

3. 不完美的解决方案

Google后发现这个问题还是相当普遍的,笔者就在Stack Overflow上找到相同的提问,但是并没有解决这个问题:
Camera2 Preview Stretching

3.1 WebRTC解决方案

后来笔者在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;
    }
  }

3.2 CameraView解决方案

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;
            }

4. 参考文献

[1] WebRTC
[2] CameraView

    原文作者:拉丁方阵问题
    原文地址: https://blog.csdn.net/matrix_laboratory/article/details/80694158
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞