FileDocCategorySizeDatePackage
AndroidCamera2Capabilities.javaAPI DocAndroid 5.1 API10024Thu Mar 12 22:22:48 GMT 2015com.android.ex.camera2.portability

AndroidCamera2Capabilities.java

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.ex.camera2.portability;

import static android.hardware.camera2.CameraCharacteristics.*;

import android.graphics.ImageFormat;
import android.graphics.Point;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.MediaRecorder;
import android.util.Range;
import android.util.Rational;

import com.android.ex.camera2.portability.debug.Log;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * The subclass of {@link CameraCapabilities} for Android Camera 2 API.
 */
public class AndroidCamera2Capabilities extends CameraCapabilities {
    private static Log.Tag TAG = new Log.Tag("AndCam2Capabs");

    AndroidCamera2Capabilities(CameraCharacteristics p) {
        super(new Stringifier());

        StreamConfigurationMap s = p.get(SCALER_STREAM_CONFIGURATION_MAP);

        for (Range<Integer> fpsRange : p.get(CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES)) {
            mSupportedPreviewFpsRange.add(new int[] { fpsRange.getLower(), fpsRange.getUpper() });
        }

        // TODO: We only support TextureView preview rendering
        mSupportedPreviewSizes.addAll(Size.buildListFromAndroidSizes(Arrays.asList(
                s.getOutputSizes(SurfaceTexture.class))));
        for (int format : s.getOutputFormats()) {
            mSupportedPreviewFormats.add(format);
        }

        // TODO: We only support MediaRecorder video capture
        mSupportedVideoSizes.addAll(Size.buildListFromAndroidSizes(Arrays.asList(
                s.getOutputSizes(MediaRecorder.class))));

        // TODO: We only support JPEG image capture
        mSupportedPhotoSizes.addAll(Size.buildListFromAndroidSizes(Arrays.asList(
                s.getOutputSizes(ImageFormat.JPEG))));
        mSupportedPhotoFormats.addAll(mSupportedPreviewFormats);

        buildSceneModes(p);
        buildFlashModes(p);
        buildFocusModes(p);
        buildWhiteBalances(p);
        // TODO: Populate mSupportedFeatures

        // TODO: Populate mPreferredPreviewSizeForVideo

        Range<Integer> ecRange = p.get(CONTROL_AE_COMPENSATION_RANGE);
        mMinExposureCompensation = ecRange.getLower();
        mMaxExposureCompensation = ecRange.getUpper();

        Rational ecStep = p.get(CONTROL_AE_COMPENSATION_STEP);
        mExposureCompensationStep = (float) ecStep.getNumerator() / ecStep.getDenominator();

        mMaxNumOfFacesSupported = p.get(STATISTICS_INFO_MAX_FACE_COUNT);
        mMaxNumOfMeteringArea = p.get(CONTROL_MAX_REGIONS_AE);

        mMaxZoomRatio = p.get(SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
        // TODO: Populate mHorizontalViewAngle
        // TODO: Populate mVerticalViewAngle
        // TODO: Populate mZoomRatioList
        // TODO: Populate mMaxZoomIndex

        if (supports(FocusMode.AUTO)) {
            mMaxNumOfFocusAreas = p.get(CONTROL_MAX_REGIONS_AF);
            if (mMaxNumOfFocusAreas > 0) {
                mSupportedFeatures.add(Feature.FOCUS_AREA);
            }
        }
        if (mMaxNumOfMeteringArea > 0) {
            mSupportedFeatures.add(Feature.METERING_AREA);
        }

        if (mMaxZoomRatio > CameraCapabilities.ZOOM_RATIO_UNZOOMED) {
            mSupportedFeatures.add(Feature.ZOOM);
        }

        // TODO: Detect other features
    }

    private void buildSceneModes(CameraCharacteristics p) {
        int[] scenes = p.get(CONTROL_AVAILABLE_SCENE_MODES);
        if (scenes != null) {
            for (int scene : scenes) {
                SceneMode equiv = sceneModeFromInt(scene);
                if (equiv != null) {
                    mSupportedSceneModes.add(equiv);
                }
            }
        }
    }

    private void buildFlashModes(CameraCharacteristics p) {
        mSupportedFlashModes.add(FlashMode.OFF);
        if (p.get(FLASH_INFO_AVAILABLE)) {
            mSupportedFlashModes.add(FlashMode.AUTO);
            mSupportedFlashModes.add(FlashMode.ON);
            mSupportedFlashModes.add(FlashMode.TORCH);
            for (int expose : p.get(CONTROL_AE_AVAILABLE_MODES)) {
                if (expose == CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE) {
                    mSupportedFlashModes.add(FlashMode.RED_EYE);
                }
            }
        }
    }

    private void buildFocusModes(CameraCharacteristics p) {
        int[] focuses = p.get(CONTROL_AF_AVAILABLE_MODES);
        if (focuses != null) {
            for (int focus : focuses) {
                FocusMode equiv = focusModeFromInt(focus);
                if (equiv != null) {
                    mSupportedFocusModes.add(equiv);
                }
            }
        }
    }

    private void buildWhiteBalances(CameraCharacteristics p) {
        int[] bals = p.get(CONTROL_AWB_AVAILABLE_MODES);
        if (bals != null) {
            for (int bal : bals) {
                WhiteBalance equiv = whiteBalanceFromInt(bal);
                if (equiv != null) {
                    mSupportedWhiteBalances.add(equiv);
                }
            }
        }
    }

    /**
     * Converts the API-related integer representation of the focus mode to the
     * abstract representation.
     *
     * @param fm The integral representation.
     * @return The mode represented by the input integer, or {@code null} if it
     *         cannot be converted.
     */
    public static FocusMode focusModeFromInt(int fm) {
        switch (fm) {
            case CONTROL_AF_MODE_AUTO:
                return FocusMode.AUTO;
            case CONTROL_AF_MODE_CONTINUOUS_PICTURE:
                return FocusMode.CONTINUOUS_PICTURE;
            case CONTROL_AF_MODE_CONTINUOUS_VIDEO:
                return FocusMode.CONTINUOUS_VIDEO;
            case CONTROL_AF_MODE_EDOF:
                return FocusMode.EXTENDED_DOF;
            case CONTROL_AF_MODE_OFF:
                return FocusMode.FIXED;
            // TODO: We cannot support INFINITY
            case CONTROL_AF_MODE_MACRO:
                return FocusMode.MACRO;
        }
        Log.w(TAG, "Unable to convert from API 2 focus mode: " + fm);
        return null;
    }

    /**
     * Converts the API-related integer representation of the scene mode to the
     * abstract representation.
     *
     * @param sm The integral representation.
     * @return The mode represented by the input integer, or {@code null} if it
     *         cannot be converted.
     */
    public static SceneMode sceneModeFromInt(int sm) {
        switch (sm) {
            case CONTROL_SCENE_MODE_DISABLED:
                return SceneMode.AUTO;
            case CONTROL_SCENE_MODE_ACTION:
                return SceneMode.ACTION;
            case CONTROL_SCENE_MODE_BARCODE:
                return SceneMode.BARCODE;
            case CONTROL_SCENE_MODE_BEACH:
                return SceneMode.BEACH;
            case CONTROL_SCENE_MODE_CANDLELIGHT:
                return SceneMode.CANDLELIGHT;
            case CONTROL_SCENE_MODE_FIREWORKS:
                return SceneMode.FIREWORKS;
            case CONTROL_SCENE_MODE_LANDSCAPE:
                return SceneMode.LANDSCAPE;
            case CONTROL_SCENE_MODE_NIGHT:
                return SceneMode.NIGHT;
            // TODO: We cannot support NIGHT_PORTRAIT
            case CONTROL_SCENE_MODE_PARTY:
                return SceneMode.PARTY;
            case CONTROL_SCENE_MODE_PORTRAIT:
                return SceneMode.PORTRAIT;
            case CONTROL_SCENE_MODE_SNOW:
                return SceneMode.SNOW;
            case CONTROL_SCENE_MODE_SPORTS:
                return SceneMode.SPORTS;
            case CONTROL_SCENE_MODE_STEADYPHOTO:
                return SceneMode.STEADYPHOTO;
            case CONTROL_SCENE_MODE_SUNSET:
                return SceneMode.SUNSET;
            case CONTROL_SCENE_MODE_THEATRE:
                return SceneMode.THEATRE;
            // TODO: We cannot expose FACE_PRIORITY, or HIGH_SPEED_VIDEO
        }

        if (sm == LegacyVendorTags.CONTROL_SCENE_MODE_HDR) {
            return SceneMode.HDR;
        }

        Log.w(TAG, "Unable to convert from API 2 scene mode: " + sm);
        return null;
    }

    /**
     * Converts the API-related integer representation of the white balance to
     * the abstract representation.
     *
     * @param wb The integral representation.
     * @return The balance represented by the input integer, or {@code null} if
     *         it cannot be converted.
     */
    public static WhiteBalance whiteBalanceFromInt(int wb) {
        switch (wb) {
            case CONTROL_AWB_MODE_AUTO:
                return WhiteBalance.AUTO;
            case CONTROL_AWB_MODE_CLOUDY_DAYLIGHT:
                return WhiteBalance.CLOUDY_DAYLIGHT;
            case CONTROL_AWB_MODE_DAYLIGHT:
                return WhiteBalance.DAYLIGHT;
            case CONTROL_AWB_MODE_FLUORESCENT:
                return WhiteBalance.FLUORESCENT;
            case CONTROL_AWB_MODE_INCANDESCENT:
                return WhiteBalance.INCANDESCENT;
            case CONTROL_AWB_MODE_SHADE:
                return WhiteBalance.SHADE;
            case CONTROL_AWB_MODE_TWILIGHT:
                return WhiteBalance.TWILIGHT;
            case CONTROL_AWB_MODE_WARM_FLUORESCENT:
                return WhiteBalance.WARM_FLUORESCENT;
        }
        Log.w(TAG, "Unable to convert from API 2 white balance: " + wb);
        return null;
    }
}