Android Camera之 --- Camera API说明(一)

葛越泽
2023-12-01

Camera API 介绍系列文章:

Android Camera之 --- Camera API说明(一)

Android Camera之 --- Camera API说明(二)

Android Camera之 --- Camera API说明(三)



推荐大家浏览Android源码最便利的方法:

http://androidxref.com/


从Android5.0开始google引入新的Camera API,位于:http://androidxref.com/5.0.0_r2/xref/frameworks/base/core/java/android/hardware/camera2/

后续我会写几篇关于Camera2 API的分析文章。


Android Camera API说明:

Camera API基本上有三大功能,预览;拍照;录像,所有对Camera API的调用基本上就是围绕这三种功能来进行的。

Android Camera API 实现位于/frameworks/base/core/java/android/hardware/Camera.java


首先,在开发Camera相关APP时需要在AndroidManifest.xml中申请camera使用权限以及其他有关camera的feature,如:

uses-permission android:name="android.permission.CAMERA"
uses-feature android:name="android.hardware.camera"
uses-feature android:name="android.hardware.camera.autofocus"


预览操作:

1. 通过调用open()或者open(int cameraId)来获取Camera实例;

2. 通过调用getParameters()来获取camera默认的参数集;

3. 根据需要通过Parameters封装的函数来更改必要的参数;

4. 设置参数调用setParameters(Camera.Parameters);

5. 必须调用setPreviewDisplay(SurfaceHolder)来设置预览图像的显示,若没有Surface,camera不能开始预览;

6. 调用startPreview()来开始预览;

7. 想要停止预览则调用stopPreview();


拍照操作:

1. 确保camera已经在预览模式;

2. 调用takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback)来拍照;

3. 等待takePicture()函数设置的callback返回图片数据;

4. 当takePicture()函数被调用后,预览画面就会停止,想要继续预览或者拍照,则必须调用startPreview()开始预览;


视频录制操作:

1. 确保Camera已经在预览模式;

2. 调用unlock()通知cameraserver允许mediaserver进程访问Camera;

3. 调用MediaRecorder初始化MediaRecorder实例并设置相应的音频视频参数;

4. 调用MediaRecorder.setCamera(Camera)接口将此camera实例做为video datasource;

5. 调用MediaRecorder相关的函数进行视频录制;

6. 结束视频录制也是由MediaRecorder相关的函数来控制;

7. 调用reconnect()接口来对camera实例重新上锁;


介绍完大致的操作步骤后首先对Camera的内部类进行说明:

public static class CameraInfo {
    public static final int CAMERA_FACING_BACK = 0;              // 在屏幕的相反侧,也就是代表后置摄像头

    public static final int CAMERA_FACING_FRONT = 1;             // 在屏幕的同侧,代表前置摄像头       
    public int facing;                                           // 上面定义的两选其一,代表次摄像头的相对位置

    public int orientation;                                      // 相机的转角,一般有0,90,180,270.

    public boolean canDisableShutterSound;                       // 是否支持拍照关闭声音
};


若要想Camera参数设置生效,则必须调用Camera.setParameters(Camera.Parameters)接口来设置修改后的Camera参数集。例如:

当调用Camera.Parameters.setWhiteBalance()时,并不能让WB生效,必须通过调用Camera.setParameters(Camera.Parameters)来让修改后的参数集设置生效;不同的硬件有不同的参数功能,比如所支持的preview size和flash mode都是有所不同的,使用者必须首先获取所支持的参数信息,进一步根据所支持的信息来设置相应的参数。下面介绍camera的参数集Camera.Parameters内部类:

    @Deprecated
    public class Parameters {
        // 从下面的定义可以看出每一个参数都是通过key-value来存储的,代表了camera硬件设备的特性和性能,也有一部分是作为设置参数存在的
        // Parameter keys to communicate with the camera driver.

        // 预览画面大小,一般有默认值,可以通过调用getPreviewSize()来获取默认值,
        // 使用者调用getSupportedPreviewSizes()获取所支持的preview size,进而调用setPreviewSize(int width, int height)来设置预览大小;
        private static final String KEY_PREVIEW_SIZE = "preview-size";

        // previewCallback()返回数据格式,可以通过调用getPreviewFormat()来获取默认值,
        // 使用者调用getSupportedPreviewFormats()获取所支持的颜色格式,进而调用setPreviewFormat(int pixel_format)来设置callback数据格式;
        private static final String KEY_PREVIEW_FORMAT = "preview-format";

        // 预览帧率,使用者调用getPreviewFrameRate()来获取默认的预览帧率,
        // 使用者可以通过getSupportedPreviewFrameRates()来获取所支持的预览帧率,进而调用
        private static final String KEY_PREVIEW_FRAME_RATE = "preview-frame-rate";

        // 用来替代KEY_PREVIEW_FRAME_RATE而设置的,因为camera设备的帧率是不固定的,根据光照条件的差异,曝光时间是不同的,若想得到较好的图像质量,
        // 则必须牺牲帧率,所以此处的预览帧率是一个范围,有最大值和最小值之分,可以通过getPreviewFpsRange(int[] range)来获取默认值,
        // getSupportedPreviewFpsRange()来获取所支持的预览帧率范围,进而通过setPreviewFpsRange(int min, int max)来设置预览帧率范围,
        private static final String KEY_PREVIEW_FPS_RANGE = "preview-fps-range";

        // 拍照图片大小,可以通过getPictureSize()来获取默认值,
        // 使用者getSupportedPictureSizes()来获取所支持的拍照图片大小,进而通过setPictureSize(int width, int height)来设置拍照图片大小
        private static final String KEY_PICTURE_SIZE = "picture-size";

        // 拍照图像格式,可以通过getPictureFormat()来获取默认的拍照图片格式,
        // 使用者通过getSupportedPictureFormats()来获取所支持的拍照图片格式,进而通过setPictureFormat(int pixel_format)来设置拍照图片格式
        private static final String KEY_PICTURE_FORMAT = "picture-format";

        // 获取所支持的拍照Thumbnail大小,分别为width和height
        private static final String KEY_JPEG_THUMBNAIL_SIZE = "jpeg-thumbnail-size";
        // 拍照Thumbnail宽度,通过getJpegThumbnailSize()获取,通过setJpegThumbnailSize(int width, int height)来设置
        private static final String KEY_JPEG_THUMBNAIL_WIDTH = "jpeg-thumbnail-width";
        // 拍照Thumbnail高度,通过getJpegThumbnailSize()获取,通过setJpegThumbnailSize(int width, int height)来设置
        private static final String KEY_JPEG_THUMBNAIL_HEIGHT = "jpeg-thumbnail-height";

        // EXIF Thumbnail 图像质量级别[0~100], 100为最佳图像质量,
        // 可通过getJpegThumbnailQuality()和setJpegThumbnailQuality(int quality)来获取和设置Thumbnail图像的质量;
        private static final String KEY_JPEG_THUMBNAIL_QUALITY = "jpeg-thumbnail-quality";

        // 拍照图片JPEG图像质量, 通过setJpegQuality(int quality)和getJpegQuality()来设置或获取图片质量
        private static final String KEY_JPEG_QUALITY = "jpeg-quality";

        // 设置图像旋转角度,0,90,180,270.
        private static final String KEY_ROTATION = "rotation";

        // GPS纬度信息,用于拍照
        private static final String KEY_GPS_LATITUDE = "gps-latitude";
        // GPS经度信息,用于拍照
        private static final String KEY_GPS_LONGITUDE = "gps-longitude";
        // GPS海拔信息,用于拍照
        private static final String KEY_GPS_ALTITUDE = "gps-altitude";
        // GPS时间信息,用于拍照
        private static final String KEY_GPS_TIMESTAMP = "gps-timestamp";
        // GPS信息处理方式,用于拍照
        private static final String KEY_GPS_PROCESSING_METHOD = "gps-processing-method";

        // 相机WB模式,可通过getSupportedWhiteBalance()来获取所支持的模式,
        // 模式有:AUTO,INCANDESCENT,FLUORESCENT,WARM_FLUORESCENT,DAYLIGHT,CLOUDY_DAYLIGHT,TWILIGHT,SHADE,
        // 通过String getWhiteBalance()和setWhiteBalance(String value)来获取或设置WB模式
        private static final String KEY_WHITE_BALANCE = "whitebalance";

        // 预览色彩效果,可通过getSupportedColorEffects()获取所支持的色彩效果,
        // 色彩效果有NONE,MONO,NEGATIVE,SOLARIZE,SEPIA,POSTERIZE,WHITEBOARD,BLACKBOARD,AQUA,
        // 通过getColorEffect()和setColorEffect(String value)来获取和设置色彩效果
        private static final String KEY_EFFECT = "effect";

        // antibanding 模式, 可以通过getSupportedAntibanding()来获取所支持的antibanding,
        // Antibanding模式有:AUTO,50HZ,60HZ,OFF
        // 可以通过getAntibanding()和setAntibanding(String antibanding)来获取或者设置Antibanding模式,
        private static final String KEY_ANTIBANDING = "antibanding";

        // 场景模式,可以通过getSupportedSceneModes()来获取所支持的场景模式
        // 场景模式有: AUTO,ACTION,PORTRAIT,LANDSCAPE,NIGHT,NIGHT_PORTRAIT,
        // THEATRE,BEACH,SNOW,SUNSET,STEADYPHOTO,FIREWORKS,SPORTS,PARTY,
        // CANDLELIGHT, BARCODE
        // 可以通过getSceneMode()和setSceneMode(String value)来获取或设置场景模式,
        private static final String KEY_SCENE_MODE = "scene-mode";

        // 闪光灯模式,可以通过getSupportedFlashModes()来获取所支持的闪光灯模式
        // 闪光灯模式: OFF,AUTO,ON,RED_EYE,TORCH
        // 可以通过getFlashMode()和setFlashMode(String value)来获取或设置闪光灯模式,
        private static final String KEY_FLASH_MODE = "flash-mode";

        // 拍照对焦模式, 可以通过getSupportedFocusModes()来获取所支持的对焦模式,
        // 对焦模式有:AUTO,INFINITY,MACRO,FIXED,EDOF,CONTINUOUS_VIDEO
        // 可以通过getFocusMode()和setFocusMode(String value)来获取或设置对焦模式,
        private static final String KEY_FOCUS_MODE = "focus-mode";

        // 对焦区域, getFocusAreas()和setFocusAreas(List<Area> focusAreas)用来获取或设置对焦区域
        private static final String KEY_FOCUS_AREAS = "focus-areas";

        // 对焦区域的最大个数
        private static final String KEY_MAX_NUM_FOCUS_AREAS = "max-num-focus-areas";
        // 焦距, 可以调用getFocalLength()来获取焦距长度
        private static final String KEY_FOCAL_LENGTH = "focal-length";

        // 水平视角,通过getHorizontalViewAngle()获取
        private static final String KEY_HORIZONTAL_VIEW_ANGLE = "horizontal-view-angle";

        // 垂直视角, 通过getVerticalViewAngle()获取
        private static final String KEY_VERTICAL_VIEW_ANGLE = "vertical-view-angle";

        // 曝光补偿, 通过getExposureCompensation()和setExposureCompensation(int value)获取或设置曝光补偿序号,
        private static final String KEY_EXPOSURE_COMPENSATION = "exposure-compensation";

        // 最大曝光补偿序号, 通过getMaxExposureCompensation()获取,
        private static final String KEY_MAX_EXPOSURE_COMPENSATION = "max-exposure-compensation";

        // 最小曝光补偿序号,通过getMinExposureCompensation()获取,
        private static final String KEY_MIN_EXPOSURE_COMPENSATION = "min-exposure-compensation";

        // 曝光补偿步长,通过getExposureCompensationStep()获取,
        private static final String KEY_EXPOSURE_COMPENSATION_STEP = "exposure-compensation-step";

        // 自动曝光锁定,通过setAutoExposureLock(boolean toggle)和getAutoExposureLock()来设定或获取自动曝光锁定状态,
        private static final String KEY_AUTO_EXPOSURE_LOCK = "auto-exposure-lock";

        // 自动曝光锁定是否支持,通过isAutoExposureLockSupported()判定是否支持自动曝光锁定设置,
        private static final String KEY_AUTO_EXPOSURE_LOCK_SUPPORTED = "auto-exposure-lock-supported";

		// 自动白平衡锁定, 通过setAutoWhiteBalanceLock(boolean toggle)和getAutoWhiteBalanceLock()来设置或获取自动白平衡锁定状态,
        private static final String KEY_AUTO_WHITEBALANCE_LOCK = "auto-whitebalance-lock";

        // 自动白平衡锁定是否支持,通过isAutoWhiteBalanceLockSupported()判定是否支持自动白平衡锁定设置,
        private static final String KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED = "auto-whitebalance-lock-supported";

        // 曝光区域,通过getMeteringAreas()和setMeteringAreas(List<Area> meteringAreas)来获取或设置曝光区域,
        private static final String KEY_METERING_AREAS = "metering-areas";

        // 曝光区域的最大个数,通过getMaxNumMeteringAreas()来获取
        private static final String KEY_MAX_NUM_METERING_AREAS = "max-num-metering-areas";

        // 图像缩放,通过getZoom()和setZoom(int value)来获取或设定缩放值
        private static final String KEY_ZOOM = "zoom";

        // 最大缩放值,通过getMaxZoom()来获取
        private static final String KEY_MAX_ZOOM = "max-zoom";

        // 缩放比,需要除以100,来表示,3.2x--->320, 第一个值为100, 最后一个为最大缩放比
        private static final String KEY_ZOOM_RATIOS = "zoom-ratios";

        // 缩放是否支持,通过isZoomSupported()来判定
        private static final String KEY_ZOOM_SUPPORTED = "zoom-supported";

        // 平滑缩放是否支持,通过isSmoothZoomSupported()来判定
        private static final String KEY_SMOOTH_ZOOM_SUPPORTED = "smooth-zoom-supported";

        // 像距,对焦时物体到焦点的距离
        private static final String KEY_FOCUS_DISTANCES = "focus-distances";

        // 获取录像所需的图像大小,通过getSupportedVideoSizes()来获取
        private static final String KEY_VIDEO_SIZE = "video-size";

        // 获取被推荐的预览图像大小,通过getPreferredPreviewSizeForVideo()获取
        private static final String KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO =
                                            "preferred-preview-size-for-video";

        // 硬件加速人脸识别的支持的最大个数,通过getMaxNumDetectedFaces()来获取
        private static final String KEY_MAX_NUM_DETECTED_FACES_HW = "max-num-detected-faces-hw";

        // 软件人脸识别的支持的最大个数
        private static final String KEY_MAX_NUM_DETECTED_FACES_SW = "max-num-detected-faces-sw";

        // 暗示将会开启视频录制,而不是照相,通过setRecordingHint(boolean hint)来设置
        private static final String KEY_RECORDING_HINT = "recording-hint";

        // 视频录制时是否支持快照,通过isVideoSnapshotSupported()来获取值
        private static final String KEY_VIDEO_SNAPSHOT_SUPPORTED = "video-snapshot-supported";

        // 在相机预览或视频录制时开启或关闭抖动抑制,不能在拍照时抑制运动模糊
        private static final String KEY_VIDEO_STABILIZATION = "video-stabilization";

        // 视频稳定特性是否支持,通过isVideoStabilizationSupported()来获取
        private static final String KEY_VIDEO_STABILIZATION_SUPPORTED = "video-stabilization-supported";

        // Parameter key suffix for supported values.
        private static final String SUPPORTED_VALUES_SUFFIX = "-values";

        private static final String TRUE = "true";
        private static final String FALSE = "false";

        // Values for white balance settings.
        public static final String WHITE_BALANCE_AUTO = "auto";
        public static final String WHITE_BALANCE_INCANDESCENT = "incandescent";
        public static final String WHITE_BALANCE_FLUORESCENT = "fluorescent";
        public static final String WHITE_BALANCE_WARM_FLUORESCENT = "warm-fluorescent";
        public static final String WHITE_BALANCE_DAYLIGHT = "daylight";
        public static final String WHITE_BALANCE_CLOUDY_DAYLIGHT = "cloudy-daylight";
        public static final String WHITE_BALANCE_TWILIGHT = "twilight";
        public static final String WHITE_BALANCE_SHADE = "shade";

        // Values for color effect settings.
        public static final String EFFECT_NONE = "none";
        public static final String EFFECT_MONO = "mono";
        public static final String EFFECT_NEGATIVE = "negative";
        public static final String EFFECT_SOLARIZE = "solarize";
        public static final String EFFECT_SEPIA = "sepia";
        public static final String EFFECT_POSTERIZE = "posterize";
        public static final String EFFECT_WHITEBOARD = "whiteboard";
        public static final String EFFECT_BLACKBOARD = "blackboard";
        public static final String EFFECT_AQUA = "aqua";

        // Values for antibanding settings.
        public static final String ANTIBANDING_AUTO = "auto";
        public static final String ANTIBANDING_50HZ = "50hz";
        public static final String ANTIBANDING_60HZ = "60hz";
        public static final String ANTIBANDING_OFF = "off";

        // Values for flash mode settings.
        /**
         * Flash will not be fired.
         */
        public static final String FLASH_MODE_OFF = "off";

        /**
         * Flash will be fired automatically when required. The flash may be fired
         * during preview, auto-focus, or snapshot depending on the driver.
         */
        public static final String FLASH_MODE_AUTO = "auto";

        /**
         * Flash will always be fired during snapshot. The flash may also be
         * fired during preview or auto-focus depending on the driver.
         */
        public static final String FLASH_MODE_ON = "on";

        /**
         * Flash will be fired in red-eye reduction mode.
         */
        public static final String FLASH_MODE_RED_EYE = "red-eye";

        /**
         * Constant emission of light during preview, auto-focus and snapshot.
         * This can also be used for video recording.
         */
        public static final String FLASH_MODE_TORCH = "torch";

        /**
         * Scene mode is off.
         */
        public static final String SCENE_MODE_AUTO = "auto";

        /**
         * Take photos of fast moving objects. Same as {@link
         * #SCENE_MODE_SPORTS}.
         */
        public static final String SCENE_MODE_ACTION = "action";

        /**
         * Take people pictures.
         */
        public static final String SCENE_MODE_PORTRAIT = "portrait";

        /**
         * Take pictures on distant objects.
         */
        public static final String SCENE_MODE_LANDSCAPE = "landscape";

        /**
         * Take photos at night.
         */
        public static final String SCENE_MODE_NIGHT = "night";

        /**
         * Take people pictures at night.
         */
        public static final String SCENE_MODE_NIGHT_PORTRAIT = "night-portrait";

        /**
         * Take photos in a theater. Flash light is off.
         */
        public static final String SCENE_MODE_THEATRE = "theatre";

        /**
         * Take pictures on the beach.
         */
        public static final String SCENE_MODE_BEACH = "beach";

        /**
         * Take pictures on the snow.
         */
        public static final String SCENE_MODE_SNOW = "snow";

        /**
         * Take sunset photos.
         */
        public static final String SCENE_MODE_SUNSET = "sunset";

        /**
         * Avoid blurry pictures (for example, due to hand shake).
         */
        public static final String SCENE_MODE_STEADYPHOTO = "steadyphoto";

        /**
         * For shooting firework displays.
         */
        public static final String SCENE_MODE_FIREWORKS = "fireworks";

        /**
         * Take photos of fast moving objects. Same as {@link
         * #SCENE_MODE_ACTION}.
         */
        public static final String SCENE_MODE_SPORTS = "sports";

        /**
         * Take indoor low-light shot.
         */
        public static final String SCENE_MODE_PARTY = "party";

        /**
         * Capture the naturally warm color of scenes lit by candles.
         */
        public static final String SCENE_MODE_CANDLELIGHT = "candlelight";

        /**
         * Applications are looking for a barcode. Camera driver will be
         * optimized for barcode reading.
         */
        public static final String SCENE_MODE_BARCODE = "barcode";

        /**
         * Capture a scene using high dynamic range imaging techniques. The
         * camera will return an image that has an extended dynamic range
         * compared to a regular capture. Capturing such an image may take
         * longer than a regular capture.
         */
        public static final String SCENE_MODE_HDR = "hdr";

        /**
         * Auto-focus mode. Applications should call {@link
         * #autoFocus(AutoFocusCallback)} to start the focus in this mode.
         */
        public static final String FOCUS_MODE_AUTO = "auto";

        /**
         * Focus is set at infinity. Applications should not call
         * {@link #autoFocus(AutoFocusCallback)} in this mode.
         */
        public static final String FOCUS_MODE_INFINITY = "infinity";

        /**
         * Macro (close-up) focus mode. Applications should call
         * {@link #autoFocus(AutoFocusCallback)} to start the focus in this
         * mode.
         */
        public static final String FOCUS_MODE_MACRO = "macro";

        /**
         * Focus is fixed. The camera is always in this mode if the focus is not
         * adjustable. If the camera has auto-focus, this mode can fix the
         * focus, which is usually at hyperfocal distance. Applications should
         * not call {@link #autoFocus(AutoFocusCallback)} in this mode.
         */
        public static final String FOCUS_MODE_FIXED = "fixed";

        /**
         * Extended depth of field (EDOF). Focusing is done digitally and
         * continuously. Applications should not call {@link
         * #autoFocus(AutoFocusCallback)} in this mode.
         */
        public static final String FOCUS_MODE_EDOF = "edof";

        /**
         * Continuous auto focus mode intended for video recording. The camera
         * continuously tries to focus. This is the best choice for video
         * recording because the focus changes smoothly . Applications still can
         * call {@link #takePicture(Camera.ShutterCallback,
         * Camera.PictureCallback, Camera.PictureCallback)} in this mode but the
         * subject may not be in focus. Auto focus starts when the parameter is
         * set.
         *
         * <p>Since API level 14, applications can call {@link
         * #autoFocus(AutoFocusCallback)} in this mode. The focus callback will
         * immediately return with a boolean that indicates whether the focus is
         * sharp or not. The focus position is locked after autoFocus call. If
         * applications want to resume the continuous focus, cancelAutoFocus
         * must be called. Restarting the preview will not resume the continuous
         * autofocus. To stop continuous focus, applications should change the
         * focus mode to other modes.
         *
         * @see #FOCUS_MODE_CONTINUOUS_PICTURE
         */
        public static final String FOCUS_MODE_CONTINUOUS_VIDEO = "continuous-video";

        /**
         * Continuous auto focus mode intended for taking pictures. The camera
         * continuously tries to focus. The speed of focus change is more
         * aggressive than {@link #FOCUS_MODE_CONTINUOUS_VIDEO}. Auto focus
         * starts when the parameter is set.
         *
         * <p>Applications can call {@link #autoFocus(AutoFocusCallback)} in
         * this mode. If the autofocus is in the middle of scanning, the focus
         * callback will return when it completes. If the autofocus is not
         * scanning, the focus callback will immediately return with a boolean
         * that indicates whether the focus is sharp or not. The apps can then
         * decide if they want to take a picture immediately or to change the
         * focus mode to auto, and run a full autofocus cycle. The focus
         * position is locked after autoFocus call. If applications want to
         * resume the continuous focus, cancelAutoFocus must be called.
         * Restarting the preview will not resume the continuous autofocus. To
         * stop continuous focus, applications should change the focus mode to
         * other modes.
         *
         * @see #FOCUS_MODE_CONTINUOUS_VIDEO
         */
        public static final String FOCUS_MODE_CONTINUOUS_PICTURE = "continuous-picture";

        // Indices for focus distance array.
        /**
         * The array index of near focus distance for use with
         * {@link #getFocusDistances(float[])}.
         */
        public static final int FOCUS_DISTANCE_NEAR_INDEX = 0;

        /**
         * The array index of optimal focus distance for use with
         * {@link #getFocusDistances(float[])}.
         */
        public static final int FOCUS_DISTANCE_OPTIMAL_INDEX = 1;

        /**
         * The array index of far focus distance for use with
         * {@link #getFocusDistances(float[])}.
         */
        public static final int FOCUS_DISTANCE_FAR_INDEX = 2;

        /**
         * The array index of minimum preview fps for use with {@link
         * #getPreviewFpsRange(int[])} or {@link
         * #getSupportedPreviewFpsRange()}.
         */
        public static final int PREVIEW_FPS_MIN_INDEX = 0;

        /**
         * The array index of maximum preview fps for use with {@link
         * #getPreviewFpsRange(int[])} or {@link
         * #getSupportedPreviewFpsRange()}.
         */
        public static final int PREVIEW_FPS_MAX_INDEX = 1;

        // Formats for setPreviewFormat and setPictureFormat.
        private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp";
        private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp";
        private static final String PIXEL_FORMAT_YUV422I = "yuv422i-yuyv";
        private static final String PIXEL_FORMAT_YUV420P = "yuv420p";
        private static final String PIXEL_FORMAT_RGB565 = "rgb565";
        private static final String PIXEL_FORMAT_JPEG = "jpeg";
        private static final String PIXEL_FORMAT_BAYER_RGGB = "bayer-rggb";

        /**
         * Order matters: Keys that are {@link #set(String, String) set} later
         * will take precedence over keys that are set earlier (if the two keys
         * conflict with each other).
         *
         * <p>One example is {@link #setPreviewFpsRange(int, int)} , since it
         * conflicts with {@link #setPreviewFrameRate(int)} whichever key is set later
         * is the one that will take precedence.
         * </p>
         */
        private final LinkedHashMap<String, String> mMap;

        private Parameters() {
            mMap = new LinkedHashMap<String, String>(/*initialCapacity*/64);
        }

        /**
         * Overwrite existing parameters with a copy of the ones from {@code other}.
         *
         * <b>For use by the legacy shim only.</b>
         *
         * @hide
         */
        public void copyFrom(Parameters other) {
            if (other == null) {
                throw new NullPointerException("other must not be null");
            }

            mMap.putAll(other.mMap);
        }

        private Camera getOuter() {
            return Camera.this;
        }


        /**
         * Value equality check.
         *
         * @hide
         */
        public boolean same(Parameters other) {
            if (this == other) {
                return true;
            }
            return other != null && Parameters.this.mMap.equals(other.mMap);
        }

        /**
         * Writes the current Parameters to the log.
         * @hide
         * @deprecated
         */
        @Deprecated
        public void dump() {
            Log.e(TAG, "dump: size=" + mMap.size());
            for (String k : mMap.keySet()) {
                Log.e(TAG, "dump: " + k + "=" + mMap.get(k));
            }
        }

        /**
         * Creates a single string with all the parameters set in
         * this Parameters object.
         * <p>The {@link #unflatten(String)} method does the reverse.</p>
         *
         * @return a String with all values from this Parameters object, in
         *         semi-colon delimited key-value pairs
         */
        public String flatten() {
            StringBuilder flattened = new StringBuilder(128);
            for (String k : mMap.keySet()) {
                flattened.append(k);
                flattened.append("=");
                flattened.append(mMap.get(k));
                flattened.append(";");
            }
            // chop off the extra semicolon at the end
            flattened.deleteCharAt(flattened.length()-1);
            return flattened.toString();
        }

        /**
         * Takes a flattened string of parameters and adds each one to
         * this Parameters object.
         * <p>The {@link #flatten()} method does the reverse.</p>
         *
         * @param flattened a String of parameters (key-value paired) that
         *                  are semi-colon delimited
         */
        public void unflatten(String flattened) {
            mMap.clear();

            TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(';');
            splitter.setString(flattened);
            for (String kv : splitter) {
                int pos = kv.indexOf('=');
                if (pos == -1) {
                    continue;
                }
                String k = kv.substring(0, pos);
                String v = kv.substring(pos + 1);
                mMap.put(k, v);
            }
        }

        public void remove(String key) {
            mMap.remove(key);
        }

        /**
         * Sets a String parameter.
         *
         * @param key   the key name for the parameter
         * @param value the String value of the parameter
         */
        public void set(String key, String value) {
            if (key.indexOf('=') != -1 || key.indexOf(';') != -1 || key.indexOf(0) != -1) {
                Log.e(TAG, "Key \"" + key + "\" contains invalid character (= or ; or \\0)");
                return;
            }
            if (value.indexOf('=') != -1 || value.indexOf(';') != -1 || value.indexOf(0) != -1) {
                Log.e(TAG, "Value \"" + value + "\" contains invalid character (= or ; or \\0)");
                return;
            }

            put(key, value);
        }

        /**
         * Sets an integer parameter.
         *
         * @param key   the key name for the parameter
         * @param value the int value of the parameter
         */
        public void set(String key, int value) {
            put(key, Integer.toString(value));
        }

        private void put(String key, String value) {
            /*
             * Remove the key if it already exists.
             *
             * This way setting a new value for an already existing key will always move
             * that key to be ordered the latest in the map.
             */
            mMap.remove(key);
            mMap.put(key, value);
        }

        private void set(String key, List<Area> areas) {
            if (areas == null) {
                set(key, "(0,0,0,0,0)");
            } else {
                StringBuilder buffer = new StringBuilder();
                for (int i = 0; i < areas.size(); i++) {
                    Area area = areas.get(i);
                    Rect rect = area.rect;
                    buffer.append('(');
                    buffer.append(rect.left);
                    buffer.append(',');
                    buffer.append(rect.top);
                    buffer.append(',');
                    buffer.append(rect.right);
                    buffer.append(',');
                    buffer.append(rect.bottom);
                    buffer.append(',');
                    buffer.append(area.weight);
                    buffer.append(')');
                    if (i != areas.size() - 1) buffer.append(',');
                }
                set(key, buffer.toString());
            }
        }

        /**
         * Returns the value of a String parameter.
         *
         * @param key the key name for the parameter
         * @return the String value of the parameter
         */
        public String get(String key) {
            return mMap.get(key);
        }

        /**
         * Returns the value of an integer parameter.
         *
         * @param key the key name for the parameter
         * @return the int value of the parameter
         */
        public int getInt(String key) {
            return Integer.parseInt(mMap.get(key));
        }

        // 设置预览画面大小,若预览已经启动,则必须现停止预览,重新设置所需参数,
        // 设置此值需综合考虑显示旋转角度;
        public void setPreviewSize(int width, int height);

        // 获取预览画面大小;
        public Size getPreviewSize();

        // 获取所支持的预览画面大小参数值,返回一个列表;
        public List<Size> getSupportedPreviewSizes();

        // 获取所支持的录像图像大小,返回一个列表
        public List<Size> getSupportedVideoSizes();

        // 获取被推荐的预览图像大小用于预览和录像
        public Size getPreferredPreviewSizeForVideo();

        // JPEG thumbnail大小设置
        public void setJpegThumbnailSize(int width, int height);

        // JPEG thumbnail大小获取
        public Size getJpegThumbnailSize();

        // 获取所支持的拍照Thumbnail大小
        public List<Size> getSupportedJpegThumbnailSizes();

        // 设置Thumbnail图像质量[0~100], 100为最佳质量
        public void setJpegThumbnailQuality(int quality);

        // 获取当前Thumbnail图像质量
        public int getJpegThumbnailQuality();

        // 设置拍照图片图像质量
        public void setJpegQuality(int quality);

        // 获取拍照图片图像质量
        public int getJpegQuality();


        // 设置预览帧率,这只是一个预想值,具体要看驱动是否能达到, 后续被setPreviewFpsRange(int,int)替代
        public void setPreviewFrameRate(int fps);

        // 获取预览帧率,这只是一个预想值,具体要看驱动是否能达到, 后续被getPreviewFpsRange(int[])替代
        public int getPreviewFrameRate();

        // 获取所支持的预览帧率,返回一个list列表,后续被getSupportedPreviewFpsRange()替代
        public List<Integer> getSupportedPreviewFrameRates();

        // 设置预览帧率范围,最大值和最小值必须乘以1000,此值用来控制PreviewCallback速率
        public void setPreviewFpsRange(int min, int max);

        // 获取当前预览帧率最大值和最小值, 计算实际帧率必须除以1000,可以通过PREVIEW_FPS_MIN_INDEX
        // PREVIEW_FPS_MAX_INDEX来确定返回数组中那个是最大值,那个是最小值,
        public void getPreviewFpsRange(int[] range);

        // 获取所支持的预览帧率范围,每一个组值分别有最大值和最小值,返回的是一个列表,
        // 期望的实际帧率在所设置的帧率范围之内,
        public List<int[]> getSupportedPreviewFpsRange();

        // 设置preview时的video数据格式,若没有设置则默认为ImageFormat.NV21,因为在视频录制是所需格式为ImageFormat.NV21;
        // 可以通过getSupportedPreviewFormats()来获取所支持的video数据格式,返回一个列表;
        // 强烈建议使用ImageFormat.NV21和ImageFormat.YV12,因为绝大多数Camera都支持这两种数据格式;
        public void setPreviewFormat(int pixel_format);

        // 获取preview时的video数据格式;
        public int getPreviewFormat();

        // 获取所支持的video数据格式,返回一个列表;
        public List<Integer> getSupportedPreviewFormats();

        // 设置拍照图片大小
        public void setPictureSize(int width, int height);

        // 获取当前拍照图片大小
        public Size getPictureSize();

        // 获取所支持的拍照图片大小,返回一个列表
        public List<Size> getSupportedPictureSizes();

        // 设置拍照图片格式,期望支持的有ImageFormat.NV21, ImageFormat.RGB_565, ImageFormat.JPEG
        public void setPictureFormat(int pixel_format);

        // 获取当前拍照图片格式
        public int getPictureFormat();

        // 获取所支持的拍照图片格式,返回一个列表
        public List<Integer> getSupportedPictureFormats();

        private String cameraFormatForPixelFormat(int pixel_format) {
            switch(pixel_format) {
            case ImageFormat.NV16:      return PIXEL_FORMAT_YUV422SP;
            case ImageFormat.NV21:      return PIXEL_FORMAT_YUV420SP;
            case ImageFormat.YUY2:      return PIXEL_FORMAT_YUV422I;
            case ImageFormat.YV12:      return PIXEL_FORMAT_YUV420P;
            case ImageFormat.RGB_565:   return PIXEL_FORMAT_RGB565;
            case ImageFormat.JPEG:      return PIXEL_FORMAT_JPEG;
            default:                    return null;
            }
        }

        private int pixelFormatForCameraFormat(String format) {
            if (format == null)
                return ImageFormat.UNKNOWN;

            if (format.equals(PIXEL_FORMAT_YUV422SP))
                return ImageFormat.NV16;

            if (format.equals(PIXEL_FORMAT_YUV420SP))
                return ImageFormat.NV21;

            if (format.equals(PIXEL_FORMAT_YUV422I))
                return ImageFormat.YUY2;

            if (format.equals(PIXEL_FORMAT_YUV420P))
                return ImageFormat.YV12;

            if (format.equals(PIXEL_FORMAT_RGB565))
                return ImageFormat.RGB_565;

            if (format.equals(PIXEL_FORMAT_JPEG))
                return ImageFormat.JPEG;

            return ImageFormat.UNKNOWN;
        }


        // 设置图像旋转角度,0,90,180,270.
        public void setRotation(int rotation);

        // GPS纬度信息,用于拍照
        public void setGpsLatitude(double latitude);

        // GPS经度信息,用于拍照
        public void setGpsLongitude(double longitude);

        // GPS海拔信息,用于拍照
        public void setGpsAltitude(double altitude);

        // GPS时间信息,用于拍照
        public void setGpsTimestamp(long timestamp);

        // GPS信息处理方式,用于拍照
        public void setGpsProcessingMethod(String processing_method);

        /**
         * Removes GPS latitude, longitude, altitude, and timestamp from the
         * parameters.
         */
        public void removeGpsData() {
            remove(KEY_GPS_LATITUDE);
            remove(KEY_GPS_LONGITUDE);
            remove(KEY_GPS_ALTITUDE);
            remove(KEY_GPS_TIMESTAMP);
            remove(KEY_GPS_PROCESSING_METHOD);
        }

        // 获取当前WB模式
        public String getWhiteBalance();

        // 设置WB模式
        public void setWhiteBalance(String value);

        // 获取所支持的WB模式,模式有:AUTO,INCANDESCENT,FLUORESCENT,WARM_FLUORESCENT,DAYLIGHT,CLOUDY_DAYLIGHT,TWILIGHT,SHADE
        public List<String> getSupportedWhiteBalance();

        // 获取色彩效果
        public String getColorEffect();

        // 设置色彩效果
        public void setColorEffect(String value);

        // 获取camera设备所支持的色彩效果
        // 色彩效果有NONE,MONO,NEGATIVE,SOLARIZE,SEPIA,POSTERIZE,WHITEBOARD,BLACKBOARD,AQUA
        public List<String> getSupportedColorEffects();


        // 获取当前Antibinding模式
        public String getAntibanding();

        // 设置Antibinding模式
        public void setAntibanding(String antibanding);

        // 获取设备所支持的Antibinding模式
        public List<String> getSupportedAntibanding();

        // 获取当前的场景模式,场景模式有:AUTO,ACTION,PORTRAIT,LANDSCAPE,NIGHT,
        // NIGHT_PORTRAIT,THEATRE,BEACH, SNOW, SUNSET,STEADYPHOTO,FIREWORKS,SPORTS,PARTY,CANDLELIGHT, BARCODE
        public String getSceneMode();

        // 设置场景模式
        public void setSceneMode(String value);

        // 获取所支持的场景模式
        public List<String> getSupportedSceneModes();

        // 获取当前闪光灯模式
        // 闪光灯模式有: OFF,AUTO,ON,RED_EYE,TORCH
        public String getFlashMode() {
            return get(KEY_FLASH_MODE);
        }

        // 设置闪光灯模式
        public void setFlashMode(String value);

        // 设置系统设备所支持的闪光灯模式
        public List<String> getSupportedFlashModes();

        // 获取当前设备对应的对焦模式
        // 对焦模式有: AUTO,INFINITY,MACRO,FIXED,EDOF,CONTINUOUS_VIDEO
        public String getFocusMode();

        // 设置对焦模式
        public void setFocusMode(String value);

        // 获取系统所支持的对焦模式
        public List<String> getSupportedFocusModes();

        // 获取焦距
        public float getFocalLength();

        // 水平视角
        public float getHorizontalViewAngle();

        // 垂直视角
        public float getVerticalViewAngle();

        // 获取当前曝光补偿序号
        public int getExposureCompensation();

        // 设置曝光补偿序号
        public void setExposureCompensation(int value);

        // 获取支持的最大曝光补偿序号
        public int getMaxExposureCompensation();

        // 获取支持的最小曝光补偿序号
        public int getMinExposureCompensation();

        // 获取曝光补偿步长
        public float getExposureCompensationStep();

        // 自动曝光锁定,使用者调用前必须通过isAutoExposureLockSupported()判定是否支持该操作,
        // 若设置为true,自动曝光程序将立即暂停直到调用此接口设置为false,在自动曝光锁定时,曝光补偿设置仍然是有效的,
        // 重复设置自动曝光锁定不影响之前的设定,调用stopPreview()和takePicture()将不会改变锁定状态。
        public void setAutoExposureLock(boolean toggle);

        // 获取自动曝光锁定状态
        public boolean getAutoExposureLock();

        // 判定自动曝光锁定是否支持
        public boolean isAutoExposureLockSupported();

        // 自动白平衡锁定设置,使用者必须通过isAutoWhiteBalanceLockSupported()判定自动白平衡锁定设置是否支持,
        // 若设置为true,自动白平衡程序将立即暂停直到调用此接口设置为false,
        // 重复设置自动曝光锁定不影响之前的设定,调用stopPreview()和takePicture()将不会改变锁定状态。
        public void setAutoWhiteBalanceLock(boolean toggle);

        // 获取自动白平衡锁定状态
        public boolean getAutoWhiteBalanceLock();

        // 判定自动白平衡锁定是否支持
        public boolean isAutoWhiteBalanceLockSupported();

        // 获取当前的缩放值,范围[0~getMaxZoom()]. 0代表没有缩放,
        // 使用之前通过isZoomSupported()判定是否支持缩放
        public int getZoom();

        // 设置缩放值
        public void setZoom(int value);

        // 判定缩放是否支持
        public boolean isZoomSupported();

        // 获取最大缩放值
        public int getMaxZoom();

        // 缩放比,需要除以100,来表示,3.2x--->320, 第一个值为100, 最后一个为最大缩放比
        public List<Integer> getZoomRatios();

        // 判定是否支持平滑缩放
        public boolean isSmoothZoomSupported();

        // 对焦过程中 物体到焦点的距离,会时时变化
        public void getFocusDistances(float[] output);

        // 对焦区域的最大个数
        public int getMaxNumFocusAreas();

        // 获取camera的对焦区域
        public List<Area> getFocusAreas();

        // 设置对焦区域, camera驱动将会使用此区域来进行对焦
        public void setFocusAreas(List<Area> focusAreas);

        // 获取所支持曝光区域最大个数
        public int getMaxNumMeteringAreas();

        // 获取当前曝光区域设定
        public List<Area> getMeteringAreas();

        // 设置曝光区域
        public void setMeteringAreas(List<Area> meteringAreas);

        // 硬件加速人脸识别的支持的最大个数
        public int getMaxNumDetectedFaces();

        // 示将会开启视频录制,而不是照相
        public void setRecordingHint(boolean hint);

        // 视频录制时是否支持快照
        public boolean isVideoSnapshotSupported();

        // 在相机预览或视频录制时开启或关闭抖动抑制,不能在拍照时抑制运动模糊
        public void setVideoStabilization(boolean toggle);

        // 获取抖动抑制(视频稳定)状态
        public boolean getVideoStabilization();

        // 是否支持视频稳定设置
        public boolean isVideoStabilizationSupported();

        // Splits a comma delimited string to an ArrayList of String.
        // Return null if the passing string is null or the size is 0.
        private ArrayList<String> split(String str) {
            if (str == null) return null;

            TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
            splitter.setString(str);
            ArrayList<String> substrings = new ArrayList<String>();
            for (String s : splitter) {
                substrings.add(s);
            }
            return substrings;
        }

        // Splits a comma delimited string to an ArrayList of Integer.
        // Return null if the passing string is null or the size is 0.
        private ArrayList<Integer> splitInt(String str) {
            if (str == null) return null;

            TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
            splitter.setString(str);
            ArrayList<Integer> substrings = new ArrayList<Integer>();
            for (String s : splitter) {
                substrings.add(Integer.parseInt(s));
            }
            if (substrings.size() == 0) return null;
            return substrings;
        }

        private void splitInt(String str, int[] output) {
            if (str == null) return;

            TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
            splitter.setString(str);
            int index = 0;
            for (String s : splitter) {
                output[index++] = Integer.parseInt(s);
            }
        }

        // Splits a comma delimited string to an ArrayList of Float.
        private void splitFloat(String str, float[] output) {
            if (str == null) return;

            TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
            splitter.setString(str);
            int index = 0;
            for (String s : splitter) {
                output[index++] = Float.parseFloat(s);
            }
        }

        // Returns the value of a float parameter.
        private float getFloat(String key, float defaultValue) {
            try {
                return Float.parseFloat(mMap.get(key));
            } catch (NumberFormatException ex) {
                return defaultValue;
            }
        }

        // Returns the value of a integer parameter.
        private int getInt(String key, int defaultValue) {
            try {
                return Integer.parseInt(mMap.get(key));
            } catch (NumberFormatException ex) {
                return defaultValue;
            }
        }

        // Splits a comma delimited string to an ArrayList of Size.
        // Return null if the passing string is null or the size is 0.
        private ArrayList<Size> splitSize(String str) {
            if (str == null) return null;

            TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
            splitter.setString(str);
            ArrayList<Size> sizeList = new ArrayList<Size>();
            for (String s : splitter) {
                Size size = strToSize(s);
                if (size != null) sizeList.add(size);
            }
            if (sizeList.size() == 0) return null;
            return sizeList;
        }

        // Parses a string (ex: "480x320") to Size object.
        // Return null if the passing string is null.
        private Size strToSize(String str) {
            if (str == null) return null;

            int pos = str.indexOf('x');
            if (pos != -1) {
                String width = str.substring(0, pos);
                String height = str.substring(pos + 1);
                return new Size(Integer.parseInt(width),
                                Integer.parseInt(height));
            }
            Log.e(TAG, "Invalid size parameter string=" + str);
            return null;
        }

        // Splits a comma delimited string to an ArrayList of int array.
        // Example string: "(10000,26623),(10000,30000)". Return null if the
        // passing string is null or the size is 0.
        private ArrayList<int[]> splitRange(String str) {
            if (str == null || str.charAt(0) != '('
                    || str.charAt(str.length() - 1) != ')') {
                Log.e(TAG, "Invalid range list string=" + str);
                return null;
            }

            ArrayList<int[]> rangeList = new ArrayList<int[]>();
            int endIndex, fromIndex = 1;
            do {
                int[] range = new int[2];
                endIndex = str.indexOf("),(", fromIndex);
                if (endIndex == -1) endIndex = str.length() - 1;
                splitInt(str.substring(fromIndex, endIndex), range);
                rangeList.add(range);
                fromIndex = endIndex + 3;
            } while (endIndex != str.length() - 1);

            if (rangeList.size() == 0) return null;
            return rangeList;
        }

        // Splits a comma delimited string to an ArrayList of Area objects.
        // Example string: "(-10,-10,0,0,300),(0,0,10,10,700)". Return null if
        // the passing string is null or the size is 0 or (0,0,0,0,0).
        private ArrayList<Area> splitArea(String str) {
            if (str == null || str.charAt(0) != '('
                    || str.charAt(str.length() - 1) != ')') {
                Log.e(TAG, "Invalid area string=" + str);
                return null;
            }

            ArrayList<Area> result = new ArrayList<Area>();
            int endIndex, fromIndex = 1;
            int[] array = new int[5];
            do {
                endIndex = str.indexOf("),(", fromIndex);
                if (endIndex == -1) endIndex = str.length() - 1;
                splitInt(str.substring(fromIndex, endIndex), array);
                Rect rect = new Rect(array[0], array[1], array[2], array[3]);
                result.add(new Area(rect, array[4]));
                fromIndex = endIndex + 3;
            } while (endIndex != str.length() - 1);

            if (result.size() == 0) return null;

            if (result.size() == 1) {
                Area area = result.get(0);
                Rect rect = area.rect;
                if (rect.left == 0 && rect.top == 0 && rect.right == 0
                        && rect.bottom == 0 && area.weight == 0) {
                    return null;
                }
            }

            return result;
        }

        private boolean same(String s1, String s2) {
            if (s1 == null && s2 == null) return true;
            if (s1 != null && s1.equals(s2)) return true;
            return false;
        }
    };


 类似资料: