/*
|
* 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;
|
case CONTROL_SCENE_MODE_HDR:
|
return SceneMode.HDR;
|
// TODO: We cannot expose FACE_PRIORITY, or HIGH_SPEED_VIDEO
|
}
|
|
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;
|
}
|
}
|