1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ex.camera2.portability; 18 19 import static android.hardware.camera2.CameraCharacteristics.*; 20 21 import android.graphics.ImageFormat; 22 import android.graphics.Point; 23 import android.graphics.SurfaceTexture; 24 import android.hardware.camera2.CameraCharacteristics; 25 import android.hardware.camera2.params.StreamConfigurationMap; 26 import android.media.MediaRecorder; 27 import android.util.Range; 28 import android.util.Rational; 29 30 import com.android.ex.camera2.portability.debug.Log; 31 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 35 /** 36 * The subclass of {@link CameraCapabilities} for Android Camera 2 API. 37 */ 38 public class AndroidCamera2Capabilities extends CameraCapabilities { 39 private static Log.Tag TAG = new Log.Tag("AndCam2Capabs"); 40 AndroidCamera2Capabilities(CameraCharacteristics p)41 AndroidCamera2Capabilities(CameraCharacteristics p) { 42 super(new Stringifier()); 43 44 StreamConfigurationMap s = p.get(SCALER_STREAM_CONFIGURATION_MAP); 45 46 for (Range<Integer> fpsRange : p.get(CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES)) { 47 mSupportedPreviewFpsRange.add(new int[] { fpsRange.getLower(), fpsRange.getUpper() }); 48 } 49 50 // TODO: We only support TextureView preview rendering 51 mSupportedPreviewSizes.addAll(Size.buildListFromAndroidSizes(Arrays.asList( 52 s.getOutputSizes(SurfaceTexture.class)))); 53 for (int format : s.getOutputFormats()) { 54 mSupportedPreviewFormats.add(format); 55 } 56 57 // TODO: We only support MediaRecorder video capture 58 mSupportedVideoSizes.addAll(Size.buildListFromAndroidSizes(Arrays.asList( 59 s.getOutputSizes(MediaRecorder.class)))); 60 61 // TODO: We only support JPEG image capture 62 mSupportedPhotoSizes.addAll(Size.buildListFromAndroidSizes(Arrays.asList( 63 s.getOutputSizes(ImageFormat.JPEG)))); 64 mSupportedPhotoFormats.addAll(mSupportedPreviewFormats); 65 66 buildSceneModes(p); 67 buildFlashModes(p); 68 buildFocusModes(p); 69 buildWhiteBalances(p); 70 // TODO: Populate mSupportedFeatures 71 72 // TODO: Populate mPreferredPreviewSizeForVideo 73 74 Range<Integer> ecRange = p.get(CONTROL_AE_COMPENSATION_RANGE); 75 mMinExposureCompensation = ecRange.getLower(); 76 mMaxExposureCompensation = ecRange.getUpper(); 77 78 Rational ecStep = p.get(CONTROL_AE_COMPENSATION_STEP); 79 mExposureCompensationStep = (float) ecStep.getNumerator() / ecStep.getDenominator(); 80 81 mMaxNumOfFacesSupported = p.get(STATISTICS_INFO_MAX_FACE_COUNT); 82 mMaxNumOfMeteringArea = p.get(CONTROL_MAX_REGIONS_AE); 83 84 mMaxZoomRatio = p.get(SCALER_AVAILABLE_MAX_DIGITAL_ZOOM); 85 // TODO: Populate mHorizontalViewAngle 86 // TODO: Populate mVerticalViewAngle 87 // TODO: Populate mZoomRatioList 88 // TODO: Populate mMaxZoomIndex 89 90 if (supports(FocusMode.AUTO)) { 91 mMaxNumOfFocusAreas = p.get(CONTROL_MAX_REGIONS_AF); 92 if (mMaxNumOfFocusAreas > 0) { 93 mSupportedFeatures.add(Feature.FOCUS_AREA); 94 } 95 } 96 if (mMaxNumOfMeteringArea > 0) { 97 mSupportedFeatures.add(Feature.METERING_AREA); 98 } 99 100 if (mMaxZoomRatio > CameraCapabilities.ZOOM_RATIO_UNZOOMED) { 101 mSupportedFeatures.add(Feature.ZOOM); 102 } 103 104 // TODO: Detect other features 105 } 106 buildSceneModes(CameraCharacteristics p)107 private void buildSceneModes(CameraCharacteristics p) { 108 int[] scenes = p.get(CONTROL_AVAILABLE_SCENE_MODES); 109 if (scenes != null) { 110 for (int scene : scenes) { 111 SceneMode equiv = sceneModeFromInt(scene); 112 if (equiv != null) { 113 mSupportedSceneModes.add(equiv); 114 } 115 } 116 } 117 } 118 buildFlashModes(CameraCharacteristics p)119 private void buildFlashModes(CameraCharacteristics p) { 120 mSupportedFlashModes.add(FlashMode.OFF); 121 if (p.get(FLASH_INFO_AVAILABLE)) { 122 mSupportedFlashModes.add(FlashMode.AUTO); 123 mSupportedFlashModes.add(FlashMode.ON); 124 mSupportedFlashModes.add(FlashMode.TORCH); 125 for (int expose : p.get(CONTROL_AE_AVAILABLE_MODES)) { 126 if (expose == CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE) { 127 mSupportedFlashModes.add(FlashMode.RED_EYE); 128 } 129 } 130 } 131 } 132 buildFocusModes(CameraCharacteristics p)133 private void buildFocusModes(CameraCharacteristics p) { 134 int[] focuses = p.get(CONTROL_AF_AVAILABLE_MODES); 135 if (focuses != null) { 136 for (int focus : focuses) { 137 FocusMode equiv = focusModeFromInt(focus); 138 if (equiv != null) { 139 mSupportedFocusModes.add(equiv); 140 } 141 } 142 } 143 } 144 buildWhiteBalances(CameraCharacteristics p)145 private void buildWhiteBalances(CameraCharacteristics p) { 146 int[] bals = p.get(CONTROL_AWB_AVAILABLE_MODES); 147 if (bals != null) { 148 for (int bal : bals) { 149 WhiteBalance equiv = whiteBalanceFromInt(bal); 150 if (equiv != null) { 151 mSupportedWhiteBalances.add(equiv); 152 } 153 } 154 } 155 } 156 157 /** 158 * Converts the API-related integer representation of the focus mode to the 159 * abstract representation. 160 * 161 * @param fm The integral representation. 162 * @return The mode represented by the input integer, or {@code null} if it 163 * cannot be converted. 164 */ focusModeFromInt(int fm)165 public static FocusMode focusModeFromInt(int fm) { 166 switch (fm) { 167 case CONTROL_AF_MODE_AUTO: 168 return FocusMode.AUTO; 169 case CONTROL_AF_MODE_CONTINUOUS_PICTURE: 170 return FocusMode.CONTINUOUS_PICTURE; 171 case CONTROL_AF_MODE_CONTINUOUS_VIDEO: 172 return FocusMode.CONTINUOUS_VIDEO; 173 case CONTROL_AF_MODE_EDOF: 174 return FocusMode.EXTENDED_DOF; 175 case CONTROL_AF_MODE_OFF: 176 return FocusMode.FIXED; 177 // TODO: We cannot support INFINITY 178 case CONTROL_AF_MODE_MACRO: 179 return FocusMode.MACRO; 180 } 181 Log.w(TAG, "Unable to convert from API 2 focus mode: " + fm); 182 return null; 183 } 184 185 /** 186 * Converts the API-related integer representation of the scene mode to the 187 * abstract representation. 188 * 189 * @param sm The integral representation. 190 * @return The mode represented by the input integer, or {@code null} if it 191 * cannot be converted. 192 */ sceneModeFromInt(int sm)193 public static SceneMode sceneModeFromInt(int sm) { 194 switch (sm) { 195 case CONTROL_SCENE_MODE_DISABLED: 196 return SceneMode.AUTO; 197 case CONTROL_SCENE_MODE_ACTION: 198 return SceneMode.ACTION; 199 case CONTROL_SCENE_MODE_BARCODE: 200 return SceneMode.BARCODE; 201 case CONTROL_SCENE_MODE_BEACH: 202 return SceneMode.BEACH; 203 case CONTROL_SCENE_MODE_CANDLELIGHT: 204 return SceneMode.CANDLELIGHT; 205 case CONTROL_SCENE_MODE_FIREWORKS: 206 return SceneMode.FIREWORKS; 207 case CONTROL_SCENE_MODE_LANDSCAPE: 208 return SceneMode.LANDSCAPE; 209 case CONTROL_SCENE_MODE_NIGHT: 210 return SceneMode.NIGHT; 211 // TODO: We cannot support NIGHT_PORTRAIT 212 case CONTROL_SCENE_MODE_PARTY: 213 return SceneMode.PARTY; 214 case CONTROL_SCENE_MODE_PORTRAIT: 215 return SceneMode.PORTRAIT; 216 case CONTROL_SCENE_MODE_SNOW: 217 return SceneMode.SNOW; 218 case CONTROL_SCENE_MODE_SPORTS: 219 return SceneMode.SPORTS; 220 case CONTROL_SCENE_MODE_STEADYPHOTO: 221 return SceneMode.STEADYPHOTO; 222 case CONTROL_SCENE_MODE_SUNSET: 223 return SceneMode.SUNSET; 224 case CONTROL_SCENE_MODE_THEATRE: 225 return SceneMode.THEATRE; 226 case CONTROL_SCENE_MODE_HDR: 227 return SceneMode.HDR; 228 // TODO: We cannot expose FACE_PRIORITY, or HIGH_SPEED_VIDEO 229 } 230 231 Log.w(TAG, "Unable to convert from API 2 scene mode: " + sm); 232 return null; 233 } 234 235 /** 236 * Converts the API-related integer representation of the white balance to 237 * the abstract representation. 238 * 239 * @param wb The integral representation. 240 * @return The balance represented by the input integer, or {@code null} if 241 * it cannot be converted. 242 */ whiteBalanceFromInt(int wb)243 public static WhiteBalance whiteBalanceFromInt(int wb) { 244 switch (wb) { 245 case CONTROL_AWB_MODE_AUTO: 246 return WhiteBalance.AUTO; 247 case CONTROL_AWB_MODE_CLOUDY_DAYLIGHT: 248 return WhiteBalance.CLOUDY_DAYLIGHT; 249 case CONTROL_AWB_MODE_DAYLIGHT: 250 return WhiteBalance.DAYLIGHT; 251 case CONTROL_AWB_MODE_FLUORESCENT: 252 return WhiteBalance.FLUORESCENT; 253 case CONTROL_AWB_MODE_INCANDESCENT: 254 return WhiteBalance.INCANDESCENT; 255 case CONTROL_AWB_MODE_SHADE: 256 return WhiteBalance.SHADE; 257 case CONTROL_AWB_MODE_TWILIGHT: 258 return WhiteBalance.TWILIGHT; 259 case CONTROL_AWB_MODE_WARM_FLUORESCENT: 260 return WhiteBalance.WARM_FLUORESCENT; 261 } 262 Log.w(TAG, "Unable to convert from API 2 white balance: " + wb); 263 return null; 264 } 265 } 266