Android原生Camera2预览尺寸的代码流程分析

不管现实多么惨不忍睹,都要持之以恒地相信,这只是黎明前短暂的黑暗而已。不要惶恐眼前的难关迈不过去,不要担心此刻的付出没有回报,别再花时间等待天降好运。真诚做人,努力做事!你想要的,岁月都会给你。Android原生Camera2预览尺寸的代码流程分析,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

1,先看看Hal3支持哪些分辨率的尺寸:

const std::vector<int32_t> availableStreamConfigurationsProc = {
        HAL_PIXEL_FORMAT_BLOB, 1920, 1080, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
 。。。。。。       
        HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 1920, 1080, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
 。。。。。。       
        HAL_PIXEL_FORMAT_YCbCr_420_888, 1920, 1080, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,        
    };

可以看到HAL_PIXEL_FORMAT_BLOB格式就是照片支持的分辨率,HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED和HAL_PIXEL_FORMAT_YCbCr_420_888格式就是预览支持的分辨率尺寸。

2,回到上层,看Camera2原生代码。在camera open的时候会回调如下代码

 public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            ........
            updatePreviewTransform(width, height, true);
			.......
        }

这里的width和height就是surface的大小,一般就是屏幕的分辨率。

3,接着进入调用的接口看

private void updatePreviewTransform(int incomingWidth, int incomingHeight,
            boolean forceUpdate) {
       ..........
            mScreenWidth = incomingWidth;
            mScreenHeight = incomingHeight;
            updatePreviewBufferDimension();

        ..........
           
                Matrix transformMatrix = mPreviewTransformCalculator.toTransformMatrix(
                        new Size(mScreenWidth, mScreenHeight),
                        new Size(mPreviewBufferWidth, mPreviewBufferHeight));
                mAppController.updatePreviewTransform(transformMatrix);
       ..........     
        }
    }

4,这个函数也简单,接着看里面的接口调用

private void updatePreviewBufferDimension() {
		..........
        Size previewBufferSize = mCamera.pickPreviewSize(mPictureSize, mUI.getActivity());
        mPreviewBufferWidth = previewBufferSize.getWidth();
        mPreviewBufferHeight = previewBufferSize.getHeight();

        ..........
        updatePreviewBufferSize();
    }

4.1,这里的mCamera 实际就是GenericOneCameraImpl对象,而mCamera.pickPreviewSize接口实际作用是调用mPreviewSizeSelector.pickPreviewSize(pictureSize);
4.2,而mPreviewSizeSelector也就是Camera2PreviewSizeSelector对象,该对象在创建的时候会传入supportedPreviewSizes。
4.3,那这个supportedPreviewSizes就是通过metadata获取到Hal3层里面支持的尺寸了,就是我们上面看到的支持分辨率的列表。

List<Size> supportedPreviewSizes = characteristics.getSupportedPreviewSizes();

5,接着看重点mPreviewSizeSelector.pickPreviewSize(pictureSize);

public Size pickPreviewSize(Size pictureSize) {
        if (pictureSize == null) {
            // TODO The default should be selected by the caller, and
            // pictureSize should never be null.
            pictureSize = getLargestPictureSize();
        }
        float pictureAspectRatio = pictureSize.getWidth() / (float) pictureSize.getHeight();

        Size size = CaptureModuleUtil.getOptimalPreviewSize(
                (Size[]) mSupportedPreviewSizes.toArray(new Size[mSupportedPreviewSizes.size()]),
                pictureAspectRatio, null);
        return size;
    }

5.1,这个的pictureSize 就是前面创建对象时传进来的列表,从中找到最大的分辨率。
5.2,pictureAspectRatio 这个就是分辨率的宽高比,例如16:9或者4:3的比例了。
5.3,CaptureModuleUtil.getOptimalPreviewSize这个接口的逻辑就是先计算预览列表里面支持的分辨率的宽高比,再计算preview_rate – pictureAspectRatio < 0.02也就是找到宽高比最接近的比例,那么就找到了预览的分辨率了。

public static Size getOptimalPreviewSize(Size[] sizes,
            double targetRatio, Double aspectRatioTolerance, Activity context) {
        // TODO(andyhuibers): Don't hardcode this but use device's measurements.
        final int MAX_ASPECT_HEIGHT = 1080;

        // Count sizes with height <= 1080p to mimic camera1 api behavior.
        int count = 0;
        for (Size s : sizes) {
            if (s.getHeight() <= MAX_ASPECT_HEIGHT) {
                count++;
            }
        }
        ArrayList<Size> camera1Sizes = new ArrayList<Size>(count);

        // Set array of all sizes with height <= 1080p
        for (Size s : sizes) {
            if (s.getHeight() <= MAX_ASPECT_HEIGHT) {
                camera1Sizes.add(new Size(s.getWidth(), s.getHeight()));
            }
        }

        int optimalIndex = CameraUtil
                .getOptimalPreviewSizeIndex(camera1Sizes, targetRatio,
                        aspectRatioTolerance, context);

        if (optimalIndex == -1) {
            return null;
        }

        Size optimal = camera1Sizes.get(optimalIndex);
        for (Size s : sizes) {
            if (s.getWidth() == optimal.getWidth() && s.getHeight() == optimal.getHeight()) {
                return s;
            }
        }
        return null;
    }

6,总结一下,将找到的preview size设置成surfacetextview的size。就是显示窗口的大小了。其中还有个变换矩阵Matrix,这个Matrix的作用就是调整显示窗口的比例大小。首先会根据display的旋转角度设置到Matrix中做旋转,在将display的宽高通过scale操作变换成preview size。这样surface既可以设置成不同比例的显示画面。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/182001.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!