第12讲 StreamConfigurationMap实战二 - Android Camera2 API

2024年10月24日 第12讲 StreamConfigurationMap实战二 极客笔记

本讲是Android Camera专题系列的第12讲,我们介绍Android Camera2 API专题的StreamConfigurationMap实战之如何获取录像Size。

更多资源:

资源 描述
在线课程 极客笔记在线课程
知识星球 星球名称:深入浅出Android Camera
星球ID: 17296815
Wechat 极客笔记圈

获取录像Size

录像组件

  • MediaRecorder / MediaCodec

需要考虑的点

  • 录像Size:Camera支持列表 与 Encoder支持列表 交集
    • 正常帧率

    • 高帧率

判断Video Encoder是否支持某种Size和FPS

/**
 * Check if encoder can support this size and frame rate combination by querying
 * MediaCodec capability. Check is based on size and frame rate. Ignore the bit rate
 * as the bit rates targeted in this test are well below the bit rate max value specified
 * by AVC specification for certain level.
 */
private static boolean isSupportedByAVCEncoder(android.util.Size sz, int frameRate) {
    MediaFormat format = MediaFormat.createVideoFormat(
            MediaFormat.MIMETYPE_VIDEO_AVC, sz.getWidth(), sz.getHeight());
    format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
    MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
    return mcl.findEncoderForFormat(format) != null;
}

获取Camera支持的录像正常帧率Size列表

private void doInitSupportedVideoSizes(CameraFeatures camera_features,
                                           StreamConfigurationMap configs) throws CameraControllerException {
        android.util.Size[] camera_video_sizes = configs.getOutputSizes(MediaRecorder.class);
        camera_features.mSupportedVideoSizes = new ArrayList<>();
        int min_fps = 9999;
        for(int[] r : this.mAeFpsRanges) {
            min_fps = Math.min(min_fps, r[0]);
        }
        if( camera_video_sizes == null ) {
            // camera_video_sizes is null on Samsung Galaxy Note 10+ and S20 for camera ID 4!
            Log.e(TAG, "no video sizes returned by getOutputSizes");
            throw new CameraControllerException();
        }
        else {
            for(android.util.Size camera_size : camera_video_sizes) {
                long mfd = configs.getOutputMinFrameDuration(MediaRecorder.class, camera_size);
                int  max_fps = (int)((1.0 / mfd) * 1000000000L);
                if (isSupportedByAVCEncoder(camera_size, max_fps)) {
                    ArrayList<int[]> fr = new ArrayList<>();
                    fr.add(new int[] {max_fps, max_fps});
                    CameraController.Size normal_video_size = new CameraController.Size(
                            camera_size.getWidth(),
                            camera_size.getHeight(),
                            fr,
                            false);
                    camera_features.mSupportedVideoSizes.add(normal_video_size);
                    if( MyDebug.LOG ) {
                        Log.i(TAG, "doInitSupportedVideoSizes normal video size: " + normal_video_size +
                                    ",max fps:" + max_fps);
                    }
                } else {
                    Log.e(TAG, "doInitSupportedVideoSizes not support!" +
                            "camera_size:" + camera_size.toString() +
                            ",max_fps:" + max_fps);
                }
            }
        }
        Collections.sort(camera_features.mSupportedVideoSizes, new CameraController.SizeSorter());
    }

获取Camera支持的录像高帧率Size列表

private void doInitSupportedHighSpeedVideoSizes(CameraFeatures camera_features,
                                                StreamConfigurationMap configs) {

    hs_fps_ranges = new ArrayList<>();
    camera_features.mSupportedVideoSizesHighSpeed = new ArrayList<>();

    for (Range<Integer> r : configs.getHighSpeedVideoFpsRanges()) {
        hs_fps_ranges.add(new int[] {r.getLower(), r.getUpper()});
    }
    Collections.sort(hs_fps_ranges, new CameraController.RangeSorter());
    if( MyDebug.LOG ) {
        Log.i(TAG, "Supported high speed video fps ranges: ");
        for (int[] f : hs_fps_ranges) {
            Log.i(TAG, "   hs range: [" + f[0] + "-" + f[1] + "]");
        }
    }


    android.util.Size[] camera_video_sizes_high_speed = configs.getHighSpeedVideoSizes();
    for(android.util.Size camera_size : camera_video_sizes_high_speed) {
        for (Range<Integer> r : configs.getHighSpeedVideoFpsRangesFor(camera_size)) {
            int profile_fps = getFpsFromHighSpeedProfileForSize(camera_size);
            if (r.getUpper() > r.getLower()) {
                Log.e(TAG, "doInitSupportedHighSpeedVideoSizes fps range:" + r.toString());
                continue;
            }
            if (!isSupportedByAVCEncoder(camera_size, r.getUpper())) {
                Log.e(TAG, "doInitSupportedHighSpeedVideoSizes high speed recording " +
                        camera_size + "@" + r.getLower() + "fps"
                        + " is not supported by CamcorderProfile, fps:" + profile_fps);
                continue;
            }
            ArrayList<int[]> fr = new ArrayList<>();
            fr.add(new int[] { r.getLower(), r.getUpper()});

            CameraController.Size hs_video_size = new CameraController.Size(
                    camera_size.getWidth(),
                    camera_size.getHeight(),
                    fr,
                    true);
            if (MyDebug.LOG) {
                Log.i(TAG, "doInitSupportedHighSpeedVideoSizes high speed video size: " +
                        hs_video_size +
                        ", fps range:" + r.toString());
            }
            camera_features.mSupportedVideoSizesHighSpeed.add(hs_video_size);
        }
    }
    Collections.sort(camera_features.mSupportedVideoSizesHighSpeed, new CameraController.SizeSorter());
}

本文链接:http://so.lmcjl.com/news/16109/

展开阅读全文