LegacyMetadataMapper.java revision e663cb77281c4c76241b820f6126543f1c2d859f
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 17package android.hardware.camera2.legacy; 18 19import android.graphics.ImageFormat; 20import android.graphics.PixelFormat; 21import android.graphics.Rect; 22import android.hardware.Camera; 23import android.hardware.Camera.CameraInfo; 24import android.hardware.Camera.Parameters; 25import android.hardware.camera2.CameraCharacteristics; 26import android.hardware.camera2.CameraDevice; 27import android.hardware.camera2.CameraMetadata; 28import android.hardware.camera2.CaptureRequest; 29import android.hardware.camera2.CaptureResult; 30import android.hardware.camera2.impl.CameraMetadataNative; 31import android.hardware.camera2.params.MeteringRectangle; 32import android.hardware.camera2.params.StreamConfiguration; 33import android.hardware.camera2.params.StreamConfigurationDuration; 34import android.hardware.camera2.utils.ArrayUtils; 35import android.hardware.camera2.utils.ListUtils; 36import android.hardware.camera2.utils.ParamsUtils; 37import android.hardware.camera2.utils.SizeAreaComparator; 38import android.util.Log; 39import android.util.Range; 40import android.util.Size; 41import android.util.SizeF; 42 43import java.util.ArrayList; 44import java.util.Arrays; 45import java.util.Collections; 46import java.util.Comparator; 47import java.util.List; 48 49import static com.android.internal.util.Preconditions.*; 50import static android.hardware.camera2.CameraCharacteristics.*; 51import static android.hardware.camera2.legacy.ParameterUtils.*; 52 53/** 54 * Provide legacy-specific implementations of camera2 metadata for legacy devices, such as the 55 * camera characteristics. 56 */ 57@SuppressWarnings("deprecation") 58public class LegacyMetadataMapper { 59 private static final String TAG = "LegacyMetadataMapper"; 60 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 61 62 private static final long NS_PER_MS = 1000000; 63 64 // from graphics.h 65 public static final int HAL_PIXEL_FORMAT_RGBA_8888 = PixelFormat.RGBA_8888; 66 public static final int HAL_PIXEL_FORMAT_BGRA_8888 = 0x5; 67 public static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22; 68 public static final int HAL_PIXEL_FORMAT_BLOB = 0x21; 69 70 // for metadata 71 private static final float LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS = 0.0f; 72 73 private static final int REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_RAW = 0; // no raw support 74 private static final int REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC = 3; // preview, video, cb 75 private static final int REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC_STALL = 1; // 1 jpeg only 76 private static final int REQUEST_MAX_NUM_INPUT_STREAMS_COUNT = 0; // no reprocessing 77 78 /** Assume 3 HAL1 stages: Exposure, Read-out, Post-Processing */ 79 private static final int REQUEST_PIPELINE_MAX_DEPTH_HAL1 = 3; 80 /** Assume 3 shim stages: Preview input, Split output, Format conversion for output */ 81 private static final int REQUEST_PIPELINE_MAX_DEPTH_OURS = 3; 82 /* TODO: Update above maxDepth values once we do more performance measurements */ 83 84 // For approximating JPEG stall durations 85 private static final long APPROXIMATE_CAPTURE_DELAY_MS = 200; // 200 milliseconds 86 private static final long APPROXIMATE_SENSOR_AREA_PX = (1 << 23); // 8 megapixels 87 private static final long APPROXIMATE_JPEG_ENCODE_TIME_MS = 600; // 600 milliseconds 88 89 static final int UNKNOWN_MODE = -1; 90 91 /* 92 * Development hijinks: Lie about not supporting certain capabilities 93 * 94 * - Unblock some CTS tests from running whose main intent is not the metadata itself 95 * 96 * TODO: Remove these constants and strip out any code that previously relied on them 97 * being set to true. 98 */ 99 static final boolean LIE_ABOUT_AE_STATE = false; 100 static final boolean LIE_ABOUT_AE_MAX_REGIONS = false; 101 static final boolean LIE_ABOUT_AF = false; 102 static final boolean LIE_ABOUT_AF_MAX_REGIONS = false; 103 static final boolean LIE_ABOUT_AWB_STATE = false; 104 static final boolean LIE_ABOUT_AWB = false; 105 106 /** 107 * Create characteristics for a legacy device by mapping the {@code parameters} 108 * and {@code info} 109 * 110 * @param parameters A non-{@code null} parameters set 111 * @param info Camera info with camera facing direction and angle of orientation 112 * 113 * @return static camera characteristics for a camera device 114 * 115 * @throws NullPointerException if any of the args were {@code null} 116 */ 117 public static CameraCharacteristics createCharacteristics(Camera.Parameters parameters, 118 CameraInfo info) { 119 checkNotNull(parameters, "parameters must not be null"); 120 checkNotNull(info, "info must not be null"); 121 122 String paramStr = parameters.flatten(); 123 android.hardware.CameraInfo outerInfo = new android.hardware.CameraInfo(); 124 outerInfo.info = info; 125 126 return createCharacteristics(paramStr, outerInfo); 127 } 128 129 /** 130 * Create characteristics for a legacy device by mapping the {@code parameters} 131 * and {@code info} 132 * 133 * @param parameters A string parseable by {@link Camera.Parameters#unflatten} 134 * @param info Camera info with camera facing direction and angle of orientation 135 * @return static camera characteristics for a camera device 136 * 137 * @throws NullPointerException if any of the args were {@code null} 138 */ 139 public static CameraCharacteristics createCharacteristics(String parameters, 140 android.hardware.CameraInfo info) { 141 checkNotNull(parameters, "parameters must not be null"); 142 checkNotNull(info, "info must not be null"); 143 checkNotNull(info.info, "info.info must not be null"); 144 145 CameraMetadataNative m = new CameraMetadataNative(); 146 147 mapCharacteristicsFromInfo(m, info.info); 148 149 Camera.Parameters params = Camera.getEmptyParameters(); 150 params.unflatten(parameters); 151 mapCharacteristicsFromParameters(m, params); 152 153 if (VERBOSE) { 154 Log.v(TAG, "createCharacteristics metadata:"); 155 Log.v(TAG, "--------------------------------------------------- (start)"); 156 m.dumpToLog(); 157 Log.v(TAG, "--------------------------------------------------- (end)"); 158 } 159 160 return new CameraCharacteristics(m); 161 } 162 163 private static void mapCharacteristicsFromInfo(CameraMetadataNative m, CameraInfo i) { 164 m.set(LENS_FACING, i.facing == CameraInfo.CAMERA_FACING_BACK ? 165 LENS_FACING_BACK : LENS_FACING_FRONT); 166 m.set(SENSOR_ORIENTATION, i.orientation); 167 } 168 169 private static void mapCharacteristicsFromParameters(CameraMetadataNative m, 170 Camera.Parameters p) { 171 172 /* 173 * colorCorrection.* 174 */ 175 m.set(COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, 176 new int[] { COLOR_CORRECTION_ABERRATION_MODE_FAST }); 177 /* 178 * control.ae* 179 */ 180 mapControlAe(m, p); 181 /* 182 * control.af* 183 */ 184 mapControlAf(m, p); 185 /* 186 * control.awb* 187 */ 188 mapControlAwb(m, p); 189 /* 190 * control.* 191 * - Anything that doesn't have a set of related fields 192 */ 193 mapControlOther(m, p); 194 /* 195 * lens.* 196 */ 197 mapLens(m, p); 198 /* 199 * flash.* 200 */ 201 mapFlash(m, p); 202 /* 203 * jpeg.* 204 */ 205 mapJpeg(m, p); 206 207 /* 208 * noiseReduction.* 209 */ 210 m.set(NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES, 211 new int[] { NOISE_REDUCTION_MODE_FAST }); 212 213 /* 214 * scaler.* 215 */ 216 mapScaler(m, p); 217 218 /* 219 * sensor.* 220 */ 221 mapSensor(m, p); 222 223 /* 224 * statistics.* 225 */ 226 mapStatistics(m, p); 227 228 /* 229 * sync.* 230 */ 231 mapSync(m, p); 232 233 /* 234 * info.supportedHardwareLevel 235 */ 236 m.set(INFO_SUPPORTED_HARDWARE_LEVEL, INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY); 237 238 /* 239 * scaler.availableStream*, scaler.available*Durations, sensor.info.maxFrameDuration 240 */ 241 mapScalerStreamConfigs(m, p); 242 243 // Order matters below: Put this last so that we can read the metadata set previously 244 245 /* 246 * request.* 247 */ 248 mapRequest(m, p); 249 250 } 251 252 private static void mapScalerStreamConfigs(CameraMetadataNative m, Camera.Parameters p) { 253 254 ArrayList<StreamConfiguration> availableStreamConfigs = new ArrayList<>(); 255 /* 256 * Implementation-defined (preview, recording, etc) -> use camera1 preview sizes 257 * YUV_420_888 cpu callbacks -> use camera1 preview sizes 258 * Other preview callbacks (CPU) -> use camera1 preview sizes 259 * JPEG still capture -> use camera1 still capture sizes 260 * 261 * Use platform-internal format constants here, since StreamConfigurationMap does the 262 * remapping to public format constants. 263 */ 264 List<Camera.Size> previewSizes = p.getSupportedPreviewSizes(); 265 appendStreamConfig(availableStreamConfigs, 266 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, previewSizes); 267 appendStreamConfig(availableStreamConfigs, 268 ImageFormat.YUV_420_888, previewSizes); 269 for (int format : p.getSupportedPreviewFormats()) { 270 if (ImageFormat.isPublicFormat(format)) { 271 appendStreamConfig(availableStreamConfigs, format, previewSizes); 272 } else { 273 /* 274 * Do not add any formats unknown to us 275 * (since it would fail runtime checks in StreamConfigurationMap) 276 */ 277 Log.w(TAG, 278 String.format("mapStreamConfigs - Skipping non-public format %x", format)); 279 } 280 } 281 282 List<Camera.Size> jpegSizes = p.getSupportedPictureSizes(); 283 appendStreamConfig(availableStreamConfigs, 284 HAL_PIXEL_FORMAT_BLOB, p.getSupportedPictureSizes()); 285 /* 286 * scaler.availableStreamConfigurations 287 */ 288 m.set(SCALER_AVAILABLE_STREAM_CONFIGURATIONS, 289 availableStreamConfigs.toArray(new StreamConfiguration[0])); 290 291 /* 292 * scaler.availableMinFrameDurations 293 */ 294 // No frame durations available 295 m.set(SCALER_AVAILABLE_MIN_FRAME_DURATIONS, new StreamConfigurationDuration[0]); 296 297 StreamConfigurationDuration[] jpegStalls = 298 new StreamConfigurationDuration[jpegSizes.size()]; 299 int i = 0; 300 long longestStallDuration = -1; 301 for (Camera.Size s : jpegSizes) { 302 long stallDuration = calculateJpegStallDuration(s); 303 jpegStalls[i++] = new StreamConfigurationDuration(HAL_PIXEL_FORMAT_BLOB, s.width, 304 s.height, stallDuration); 305 if (longestStallDuration < stallDuration) { 306 longestStallDuration = stallDuration; 307 } 308 } 309 /* 310 * scaler.availableStallDurations 311 */ 312 // Set stall durations for jpeg, other formats use default stall duration 313 m.set(SCALER_AVAILABLE_STALL_DURATIONS, jpegStalls); 314 315 /* 316 * sensor.info.maxFrameDuration 317 */ 318 m.set(SENSOR_INFO_MAX_FRAME_DURATION, longestStallDuration); 319 } 320 321 @SuppressWarnings({"unchecked"}) 322 private static void mapControlAe(CameraMetadataNative m, Camera.Parameters p) { 323 /* 324 * control.aeAvailableAntiBandingModes 325 */ 326 List<String> antiBandingModes = p.getSupportedAntibanding(); 327 if (antiBandingModes != null && antiBandingModes.size() > 0) { // antibanding is optional 328 int[] modes = new int[antiBandingModes.size()]; 329 int j = 0; 330 for (String mode : antiBandingModes) { 331 int convertedMode = convertAntiBandingMode(mode); 332 if (convertedMode == -1) { 333 Log.w(TAG, "Antibanding mode " + ((mode == null) ? "NULL" : mode) + 334 " not supported, skipping..."); 335 } else { 336 modes[j++] = convertedMode; 337 } 338 } 339 m.set(CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, Arrays.copyOf(modes, j)); 340 } else { 341 m.set(CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, new int[0]); 342 } 343 344 /* 345 * control.aeAvailableTargetFpsRanges 346 */ 347 { 348 List<int[]> fpsRanges = p.getSupportedPreviewFpsRange(); 349 if (fpsRanges == null) { 350 throw new AssertionError("Supported FPS ranges cannot be null."); 351 } 352 int rangesSize = fpsRanges.size(); 353 if (rangesSize <= 0) { 354 throw new AssertionError("At least one FPS range must be supported."); 355 } 356 Range<Integer>[] ranges = new Range[rangesSize]; 357 int i = 0; 358 for (int[] r : fpsRanges) { 359 ranges[i++] = Range.create(r[Camera.Parameters.PREVIEW_FPS_MIN_INDEX], 360 r[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]); 361 } 362 m.set(CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, ranges); 363 } 364 365 /* 366 * control.aeAvailableModes 367 */ 368 { 369 List<String> flashModes = p.getSupportedFlashModes(); 370 371 String[] flashModeStrings = new String[] { 372 Camera.Parameters.FLASH_MODE_OFF, 373 Camera.Parameters.FLASH_MODE_AUTO, 374 Camera.Parameters.FLASH_MODE_ON, 375 Camera.Parameters.FLASH_MODE_RED_EYE, 376 // Map these manually 377 Camera.Parameters.FLASH_MODE_TORCH, 378 }; 379 int[] flashModeInts = new int[] { 380 CONTROL_AE_MODE_ON, 381 CONTROL_AE_MODE_ON_AUTO_FLASH, 382 CONTROL_AE_MODE_ON_ALWAYS_FLASH, 383 CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE 384 }; 385 int[] aeAvail = ArrayUtils.convertStringListToIntArray( 386 flashModes, flashModeStrings, flashModeInts); 387 388 // No flash control -> AE is always on 389 if (aeAvail == null || aeAvail.length == 0) { 390 aeAvail = new int[] { 391 CONTROL_AE_MODE_ON 392 }; 393 } 394 395 // Note that AE_MODE_OFF is never available. 396 m.set(CONTROL_AE_AVAILABLE_MODES, aeAvail); 397 } 398 399 /* 400 * control.aeCompensationRanges 401 */ 402 { 403 int min = p.getMinExposureCompensation(); 404 int max = p.getMaxExposureCompensation(); 405 406 m.set(CONTROL_AE_COMPENSATION_RANGE, Range.create(min, max)); 407 } 408 409 /* 410 * control.aeCompensationStep 411 */ 412 { 413 float step = p.getExposureCompensationStep(); 414 415 m.set(CONTROL_AE_COMPENSATION_STEP, ParamsUtils.createRational(step)); 416 } 417 } 418 419 420 @SuppressWarnings({"unchecked"}) 421 private static void mapControlAf(CameraMetadataNative m, Camera.Parameters p) { 422 /* 423 * control.afAvailableModes 424 */ 425 { 426 List<String> focusModes = p.getSupportedFocusModes(); 427 428 String[] focusModeStrings = new String[] { 429 Camera.Parameters.FOCUS_MODE_AUTO, 430 Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE, 431 Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO, 432 Camera.Parameters.FOCUS_MODE_EDOF, 433 Camera.Parameters.FOCUS_MODE_INFINITY, 434 Camera.Parameters.FOCUS_MODE_MACRO, 435 Camera.Parameters.FOCUS_MODE_FIXED, 436 }; 437 438 int[] focusModeInts = new int[] { 439 CONTROL_AF_MODE_AUTO, 440 CONTROL_AF_MODE_CONTINUOUS_PICTURE, 441 CONTROL_AF_MODE_CONTINUOUS_VIDEO, 442 CONTROL_AF_MODE_EDOF, 443 CONTROL_AF_MODE_OFF, 444 CONTROL_AF_MODE_MACRO, 445 CONTROL_AF_MODE_OFF 446 }; 447 448 List<Integer> afAvail = ArrayUtils.convertStringListToIntList( 449 focusModes, focusModeStrings, focusModeInts); 450 451 // No AF modes supported? That's unpossible! 452 if (afAvail == null || afAvail.size() == 0) { 453 Log.w(TAG, "No AF modes supported (HAL bug); defaulting to AF_MODE_OFF only"); 454 afAvail = new ArrayList<Integer>(/*capacity*/1); 455 afAvail.add(CONTROL_AF_MODE_OFF); 456 } 457 458 m.set(CONTROL_AF_AVAILABLE_MODES, ArrayUtils.toIntArray(afAvail)); 459 460 if (VERBOSE) { 461 Log.v(TAG, "mapControlAf - control.afAvailableModes set to " + 462 ListUtils.listToString(afAvail)); 463 } 464 } 465 } 466 467 private static void mapControlAwb(CameraMetadataNative m, Camera.Parameters p) { 468 /* 469 * control.awbAvailableModes 470 */ 471 472 { 473 List<String> wbModes = p.getSupportedWhiteBalance(); 474 475 String[] wbModeStrings = new String[] { 476 Camera.Parameters.WHITE_BALANCE_AUTO , 477 Camera.Parameters.WHITE_BALANCE_INCANDESCENT , 478 Camera.Parameters.WHITE_BALANCE_FLUORESCENT , 479 Camera.Parameters.WHITE_BALANCE_WARM_FLUORESCENT , 480 Camera.Parameters.WHITE_BALANCE_DAYLIGHT , 481 Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT , 482 Camera.Parameters.WHITE_BALANCE_TWILIGHT , 483 Camera.Parameters.WHITE_BALANCE_SHADE , 484 }; 485 486 int[] wbModeInts = new int[] { 487 CONTROL_AWB_MODE_AUTO, 488 CONTROL_AWB_MODE_INCANDESCENT , 489 CONTROL_AWB_MODE_FLUORESCENT , 490 CONTROL_AWB_MODE_WARM_FLUORESCENT , 491 CONTROL_AWB_MODE_DAYLIGHT , 492 CONTROL_AWB_MODE_CLOUDY_DAYLIGHT , 493 CONTROL_AWB_MODE_TWILIGHT , 494 CONTROL_AWB_MODE_SHADE , 495 // Note that CONTROL_AWB_MODE_OFF is unsupported 496 }; 497 498 List<Integer> awbAvail = ArrayUtils.convertStringListToIntList( 499 wbModes, wbModeStrings, wbModeInts); 500 501 // No AWB modes supported? That's unpossible! 502 if (awbAvail == null || awbAvail.size() == 0) { 503 Log.w(TAG, "No AWB modes supported (HAL bug); defaulting to AWB_MODE_AUTO only"); 504 awbAvail = new ArrayList<Integer>(/*capacity*/1); 505 awbAvail.add(CONTROL_AWB_MODE_AUTO); 506 } 507 508 m.set(CONTROL_AWB_AVAILABLE_MODES, ArrayUtils.toIntArray(awbAvail)); 509 510 if (VERBOSE) { 511 Log.v(TAG, "mapControlAwb - control.awbAvailableModes set to " + 512 ListUtils.listToString(awbAvail)); 513 } 514 } 515 } 516 517 private static void mapControlOther(CameraMetadataNative m, Camera.Parameters p) { 518 /* 519 * android.control.availableVideoStabilizationModes 520 */ 521 { 522 int stabModes[] = p.isVideoStabilizationSupported() ? 523 new int[] { CONTROL_VIDEO_STABILIZATION_MODE_OFF, 524 CONTROL_VIDEO_STABILIZATION_MODE_ON } : 525 new int[] { CONTROL_VIDEO_STABILIZATION_MODE_OFF }; 526 527 m.set(CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, stabModes); 528 } 529 530 /* 531 * android.control.maxRegions 532 */ 533 final int AE = 0, AWB = 1, AF = 2; 534 535 int[] maxRegions = new int[3]; 536 maxRegions[AE] = p.getMaxNumMeteringAreas(); 537 maxRegions[AWB] = 0; // AWB regions not supported in API1 538 maxRegions[AF] = p.getMaxNumFocusAreas(); 539 540 if (LIE_ABOUT_AE_MAX_REGIONS) { 541 maxRegions[AE] = 0; 542 } 543 if (LIE_ABOUT_AF_MAX_REGIONS) { 544 maxRegions[AF] = 0; 545 } 546 547 m.set(CONTROL_MAX_REGIONS, maxRegions); 548 549 /* 550 * android.control.availableEffects 551 */ 552 List<String> effectModes = p.getSupportedColorEffects(); 553 int[] supportedEffectModes = (effectModes == null) ? new int[0] : 554 ArrayUtils.convertStringListToIntArray(effectModes, sLegacyEffectMode, 555 sEffectModes); 556 m.set(CONTROL_AVAILABLE_EFFECTS, supportedEffectModes); 557 558 /* 559 * android.control.availableSceneModes 560 */ 561 List<String> sceneModes = p.getSupportedSceneModes(); 562 List<Integer> supportedSceneModes = 563 ArrayUtils.convertStringListToIntList(sceneModes, sLegacySceneModes, sSceneModes); 564 if (supportedSceneModes == null) { // camera1 doesn't support scene mode settings 565 supportedSceneModes = new ArrayList<Integer>(); 566 supportedSceneModes.add(CONTROL_SCENE_MODE_DISABLED); // disabled is always available 567 } 568 if (p.getMaxNumDetectedFaces() > 0) { // always supports FACE_PRIORITY when face detecting 569 supportedSceneModes.add(CONTROL_SCENE_MODE_FACE_PRIORITY); 570 } 571 m.set(CONTROL_AVAILABLE_SCENE_MODES, ArrayUtils.toIntArray(supportedSceneModes)); 572 } 573 574 private static void mapLens(CameraMetadataNative m, Camera.Parameters p) { 575 /* 576 * We can tell if the lens is fixed focus; 577 * but if it's not, we can't tell the minimum focus distance, so leave it null then. 578 */ 579 if (VERBOSE) { 580 Log.v(TAG, "mapLens - focus-mode='" + p.getFocusMode() + "'"); 581 } 582 583 if (Camera.Parameters.FOCUS_MODE_FIXED.equals(p.getFocusMode())) { 584 /* 585 * lens.info.minimumFocusDistance 586 */ 587 m.set(LENS_INFO_MINIMUM_FOCUS_DISTANCE, LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS); 588 589 if (VERBOSE) { 590 Log.v(TAG, "mapLens - lens.info.minimumFocusDistance = 0"); 591 } 592 } else { 593 if (VERBOSE) { 594 Log.v(TAG, "mapLens - lens.info.minimumFocusDistance is unknown"); 595 } 596 } 597 598 float[] focalLengths = new float[] { p.getFocalLength() }; 599 m.set(LENS_INFO_AVAILABLE_FOCAL_LENGTHS, focalLengths); 600 } 601 602 private static void mapFlash(CameraMetadataNative m, Camera.Parameters p) { 603 boolean flashAvailable = false; 604 List<String> supportedFlashModes = p.getSupportedFlashModes(); 605 606 if (supportedFlashModes != null) { 607 // If only 'OFF' is available, we don't really have flash support 608 flashAvailable = !ListUtils.listElementsEqualTo( 609 supportedFlashModes, Camera.Parameters.FLASH_MODE_OFF); 610 } 611 612 /* 613 * flash.info.available 614 */ 615 m.set(FLASH_INFO_AVAILABLE, flashAvailable); 616 } 617 618 private static void mapJpeg(CameraMetadataNative m, Camera.Parameters p) { 619 List<Camera.Size> thumbnailSizes = p.getSupportedJpegThumbnailSizes(); 620 621 if (thumbnailSizes != null) { 622 Size[] sizes = convertSizeListToArray(thumbnailSizes); 623 Arrays.sort(sizes, new SizeAreaComparator()); 624 m.set(JPEG_AVAILABLE_THUMBNAIL_SIZES, sizes); 625 } 626 } 627 628 private static void mapRequest(CameraMetadataNative m, Parameters p) { 629 /* 630 * request.availableCapabilities 631 */ 632 int[] capabilities = { REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE }; 633 m.set(REQUEST_AVAILABLE_CAPABILITIES, capabilities); 634 635 /* 636 * request.availableCharacteristicsKeys 637 */ 638 { 639 // TODO: check if the underlying key is supported before listing a key as available 640 641 // Note: We only list public keys. Native HALs should list ALL keys regardless of visibility. 642 643 Key<?> availableKeys[] = new Key<?>[] { 644 CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES , 645 CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES , 646 CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES , 647 CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES , 648 CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE , 649 CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP , 650 CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES , 651 CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS , 652 CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES , 653 CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES , 654 CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES , 655 CameraCharacteristics.CONTROL_MAX_REGIONS , 656 CameraCharacteristics.FLASH_INFO_AVAILABLE , 657 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL , 658 CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES , 659 CameraCharacteristics.LENS_FACING , 660 CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS , 661 CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES , 662 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES , 663 CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS , 664 CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT , 665 CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH , 666 CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM , 667// CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP , 668 CameraCharacteristics.SCALER_CROPPING_TYPE , 669 CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES , 670 CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE , 671 CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE , 672 CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE , 673 CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE , 674 CameraCharacteristics.SENSOR_ORIENTATION , 675 CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES , 676 CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT , 677 CameraCharacteristics.SYNC_MAX_LATENCY , 678 }; 679 List<Key<?>> characteristicsKeys = new ArrayList<>(Arrays.asList(availableKeys)); 680 681 /* 682 * Add the conditional keys 683 */ 684 if (m.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE) != null) { 685 characteristicsKeys.add(LENS_INFO_MINIMUM_FOCUS_DISTANCE); 686 } 687 688 m.set(REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, 689 getTagsForKeys(characteristicsKeys.toArray(new Key<?>[0]))); 690 } 691 692 /* 693 * request.availableRequestKeys 694 */ 695 { 696 CaptureRequest.Key<?> defaultAvailableKeys[] = new CaptureRequest.Key<?>[] { 697 CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE, 698 CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, 699 CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 700 CaptureRequest.CONTROL_AE_LOCK, 701 CaptureRequest.CONTROL_AE_MODE, 702 CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, 703 CaptureRequest.CONTROL_AF_MODE, 704 CaptureRequest.CONTROL_AF_TRIGGER, 705 CaptureRequest.CONTROL_AWB_LOCK, 706 CaptureRequest.CONTROL_AWB_MODE, 707 CaptureRequest.CONTROL_CAPTURE_INTENT, 708 CaptureRequest.CONTROL_EFFECT_MODE, 709 CaptureRequest.CONTROL_MODE, 710 CaptureRequest.CONTROL_SCENE_MODE, 711 CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, 712 CaptureRequest.FLASH_MODE, 713 CaptureRequest.JPEG_GPS_COORDINATES, 714 CaptureRequest.JPEG_GPS_PROCESSING_METHOD, 715 CaptureRequest.JPEG_GPS_TIMESTAMP, 716 CaptureRequest.JPEG_ORIENTATION, 717 CaptureRequest.JPEG_QUALITY, 718 CaptureRequest.JPEG_THUMBNAIL_QUALITY, 719 CaptureRequest.JPEG_THUMBNAIL_SIZE, 720 CaptureRequest.LENS_FOCAL_LENGTH, 721 CaptureRequest.NOISE_REDUCTION_MODE, 722 CaptureRequest.SCALER_CROP_REGION, 723 CaptureRequest.STATISTICS_FACE_DETECT_MODE, 724 }; 725 ArrayList<CaptureRequest.Key<?>> availableKeys = 726 new ArrayList<CaptureRequest.Key<?>>(Arrays.asList(defaultAvailableKeys)); 727 728 if (p.getMaxNumMeteringAreas() > 0) { 729 availableKeys.add(CaptureRequest.CONTROL_AE_REGIONS); 730 } 731 if (p.getMaxNumFocusAreas() > 0) { 732 availableKeys.add(CaptureRequest.CONTROL_AF_REGIONS); 733 } 734 735 CaptureRequest.Key<?> availableRequestKeys[] = 736 new CaptureRequest.Key<?>[availableKeys.size()]; 737 availableKeys.toArray(availableRequestKeys); 738 m.set(REQUEST_AVAILABLE_REQUEST_KEYS, getTagsForKeys(availableRequestKeys)); 739 } 740 741 /* 742 * request.availableResultKeys 743 */ 744 { 745 CaptureResult.Key<?> defaultAvailableKeys[] = new CaptureResult.Key<?>[] { 746 CaptureResult.COLOR_CORRECTION_ABERRATION_MODE , 747 CaptureResult.CONTROL_AE_ANTIBANDING_MODE , 748 CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION , 749 CaptureResult.CONTROL_AE_LOCK , 750 CaptureResult.CONTROL_AE_MODE , 751 CaptureResult.CONTROL_AF_MODE , 752 CaptureResult.CONTROL_AF_STATE , 753 CaptureResult.CONTROL_AWB_MODE , 754 CaptureResult.CONTROL_AWB_LOCK , 755 CaptureResult.CONTROL_MODE , 756 CaptureResult.FLASH_MODE , 757 CaptureResult.JPEG_GPS_COORDINATES , 758 CaptureResult.JPEG_GPS_PROCESSING_METHOD , 759 CaptureResult.JPEG_GPS_TIMESTAMP , 760 CaptureResult.JPEG_ORIENTATION , 761 CaptureResult.JPEG_QUALITY , 762 CaptureResult.JPEG_THUMBNAIL_QUALITY , 763 CaptureResult.LENS_FOCAL_LENGTH , 764 CaptureResult.NOISE_REDUCTION_MODE , 765 CaptureResult.REQUEST_PIPELINE_DEPTH , 766 CaptureResult.SCALER_CROP_REGION , 767 CaptureResult.SENSOR_TIMESTAMP , 768 CaptureResult.STATISTICS_FACE_DETECT_MODE , 769// CaptureResult.STATISTICS_FACES , 770 }; 771 List<CaptureResult.Key<?>> availableKeys = 772 new ArrayList<CaptureResult.Key<?>>(Arrays.asList(defaultAvailableKeys)); 773 774 if (p.getMaxNumMeteringAreas() > 0) { 775 availableKeys.add(CaptureResult.CONTROL_AE_REGIONS); 776 } 777 if (p.getMaxNumFocusAreas() > 0) { 778 availableKeys.add(CaptureResult.CONTROL_AF_REGIONS); 779 } 780 781 CaptureResult.Key<?> availableResultKeys[] = 782 new CaptureResult.Key<?>[availableKeys.size()]; 783 availableKeys.toArray(availableResultKeys); 784 m.set(REQUEST_AVAILABLE_RESULT_KEYS, getTagsForKeys(availableResultKeys)); 785 } 786 787 /* 788 * request.maxNumOutputStreams 789 */ 790 int[] outputStreams = { 791 /* RAW */ 792 REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_RAW, 793 /* Processed & Not-Stalling */ 794 REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC, 795 /* Processed & Stalling */ 796 REQUEST_MAX_NUM_OUTPUT_STREAMS_COUNT_PROC_STALL, 797 }; 798 m.set(REQUEST_MAX_NUM_OUTPUT_STREAMS, outputStreams); 799 800 /* 801 * request.maxNumInputStreams 802 */ 803 m.set(REQUEST_MAX_NUM_INPUT_STREAMS, REQUEST_MAX_NUM_INPUT_STREAMS_COUNT); 804 805 /* 806 * request.partialResultCount 807 */ 808 m.set(REQUEST_PARTIAL_RESULT_COUNT, 1); // No partial results supported 809 810 /* 811 * request.pipelineMaxDepth 812 */ 813 m.set(REQUEST_PIPELINE_MAX_DEPTH, 814 (byte)(REQUEST_PIPELINE_MAX_DEPTH_HAL1 + REQUEST_PIPELINE_MAX_DEPTH_OURS)); 815 } 816 817 private static void mapScaler(CameraMetadataNative m, Parameters p) { 818 /* 819 * scaler.availableMaxDigitalZoom 820 */ 821 m.set(SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, ParameterUtils.getMaxZoomRatio(p)); 822 823 /* 824 * scaler.croppingType = CENTER_ONLY 825 */ 826 m.set(SCALER_CROPPING_TYPE, SCALER_CROPPING_TYPE_CENTER_ONLY); 827 } 828 829 private static void mapSensor(CameraMetadataNative m, Parameters p) { 830 // Use the largest jpeg size (by area) for both active array and pixel array 831 Size largestJpegSize = getLargestSupportedJpegSizeByArea(p); 832 /* 833 * sensor.info.activeArraySize 834 */ 835 { 836 Rect activeArrayRect = ParamsUtils.createRect(largestJpegSize); 837 m.set(SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArrayRect); 838 } 839 840 /* 841 * sensor.availableTestPatternModes 842 */ 843 { 844 // Only "OFF" test pattern mode is available 845 m.set(SENSOR_AVAILABLE_TEST_PATTERN_MODES, new int[] { SENSOR_TEST_PATTERN_MODE_OFF }); 846 } 847 848 /* 849 * sensor.info.pixelArraySize 850 */ 851 m.set(SENSOR_INFO_PIXEL_ARRAY_SIZE, largestJpegSize); 852 853 /* 854 * sensor.info.physicalSize 855 */ 856 { 857 /* 858 * Assume focal length is at infinity focus and that the lens is rectilinear. 859 */ 860 float focalLength = p.getFocalLength(); // in mm 861 double angleHor = p.getHorizontalViewAngle() * Math.PI / 180; // to radians 862 double angleVer = p.getVerticalViewAngle() * Math.PI / 180; // to radians 863 864 float height = (float)Math.abs(2 * focalLength * Math.tan(angleVer / 2)); 865 float width = (float)Math.abs(2 * focalLength * Math.tan(angleHor / 2)); 866 867 m.set(SENSOR_INFO_PHYSICAL_SIZE, new SizeF(width, height)); // in mm 868 } 869 870 /* 871 * sensor.info.timestampSource 872 */ 873 { 874 m.set(SENSOR_INFO_TIMESTAMP_SOURCE, SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN); 875 } 876 } 877 878 private static void mapStatistics(CameraMetadataNative m, Parameters p) { 879 /* 880 * statistics.info.availableFaceDetectModes 881 */ 882 int[] fdModes; 883 884 if (p.getMaxNumDetectedFaces() > 0) { 885 fdModes = new int[] { 886 STATISTICS_FACE_DETECT_MODE_OFF, 887 STATISTICS_FACE_DETECT_MODE_SIMPLE 888 // FULL is never-listed, since we have no way to query it statically 889 }; 890 } else { 891 fdModes = new int[] { 892 STATISTICS_FACE_DETECT_MODE_OFF 893 }; 894 } 895 m.set(STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, fdModes); 896 897 /* 898 * statistics.info.maxFaceCount 899 */ 900 m.set(STATISTICS_INFO_MAX_FACE_COUNT, p.getMaxNumDetectedFaces()); 901 } 902 903 private static void mapSync(CameraMetadataNative m, Parameters p) { 904 /* 905 * sync.maxLatency 906 */ 907 m.set(SYNC_MAX_LATENCY, SYNC_MAX_LATENCY_UNKNOWN); 908 } 909 910 private static void appendStreamConfig( 911 ArrayList<StreamConfiguration> configs, int format, List<Camera.Size> sizes) { 912 for (Camera.Size size : sizes) { 913 StreamConfiguration config = 914 new StreamConfiguration(format, size.width, size.height, /*input*/false); 915 configs.add(config); 916 } 917 } 918 919 private final static String[] sLegacySceneModes = { 920 Parameters.SCENE_MODE_AUTO, 921 Parameters.SCENE_MODE_ACTION, 922 Parameters.SCENE_MODE_PORTRAIT, 923 Parameters.SCENE_MODE_LANDSCAPE, 924 Parameters.SCENE_MODE_NIGHT, 925 Parameters.SCENE_MODE_NIGHT_PORTRAIT, 926 Parameters.SCENE_MODE_THEATRE, 927 Parameters.SCENE_MODE_BEACH, 928 Parameters.SCENE_MODE_SNOW, 929 Parameters.SCENE_MODE_SUNSET, 930 Parameters.SCENE_MODE_STEADYPHOTO, 931 Parameters.SCENE_MODE_FIREWORKS, 932 Parameters.SCENE_MODE_SPORTS, 933 Parameters.SCENE_MODE_PARTY, 934 Parameters.SCENE_MODE_CANDLELIGHT, 935 Parameters.SCENE_MODE_BARCODE, 936 Parameters.SCENE_MODE_HDR, 937 }; 938 939 private final static int[] sSceneModes = { 940 CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED, 941 CameraCharacteristics.CONTROL_SCENE_MODE_ACTION, 942 CameraCharacteristics.CONTROL_SCENE_MODE_PORTRAIT, 943 CameraCharacteristics.CONTROL_SCENE_MODE_LANDSCAPE, 944 CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT, 945 CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT_PORTRAIT, 946 CameraCharacteristics.CONTROL_SCENE_MODE_THEATRE, 947 CameraCharacteristics.CONTROL_SCENE_MODE_BEACH, 948 CameraCharacteristics.CONTROL_SCENE_MODE_SNOW, 949 CameraCharacteristics.CONTROL_SCENE_MODE_SUNSET, 950 CameraCharacteristics.CONTROL_SCENE_MODE_STEADYPHOTO, 951 CameraCharacteristics.CONTROL_SCENE_MODE_FIREWORKS, 952 CameraCharacteristics.CONTROL_SCENE_MODE_SPORTS, 953 CameraCharacteristics.CONTROL_SCENE_MODE_PARTY, 954 CameraCharacteristics.CONTROL_SCENE_MODE_CANDLELIGHT, 955 CameraCharacteristics.CONTROL_SCENE_MODE_BARCODE, 956 CameraCharacteristics.CONTROL_SCENE_MODE_HDR, 957 }; 958 959 static int convertSceneModeFromLegacy(String mode) { 960 if (mode == null) { 961 return CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED; 962 } 963 int index = ArrayUtils.getArrayIndex(sLegacySceneModes, mode); 964 if (index < 0) { 965 return UNKNOWN_MODE; 966 } 967 return sSceneModes[index]; 968 } 969 970 static String convertSceneModeToLegacy(int mode) { 971 if (mode == CONTROL_SCENE_MODE_FACE_PRIORITY) { 972 // OK: Let LegacyFaceDetectMapper handle turning face detection on/off 973 return Parameters.SCENE_MODE_AUTO; 974 } 975 976 int index = ArrayUtils.getArrayIndex(sSceneModes, mode); 977 if (index < 0) { 978 return null; 979 } 980 return sLegacySceneModes[index]; 981 } 982 983 private final static String[] sLegacyEffectMode = { 984 Parameters.EFFECT_NONE, 985 Parameters.EFFECT_MONO, 986 Parameters.EFFECT_NEGATIVE, 987 Parameters.EFFECT_SOLARIZE, 988 Parameters.EFFECT_SEPIA, 989 Parameters.EFFECT_POSTERIZE, 990 Parameters.EFFECT_WHITEBOARD, 991 Parameters.EFFECT_BLACKBOARD, 992 Parameters.EFFECT_AQUA, 993 }; 994 995 private final static int[] sEffectModes = { 996 CameraCharacteristics.CONTROL_EFFECT_MODE_OFF, 997 CameraCharacteristics.CONTROL_EFFECT_MODE_MONO, 998 CameraCharacteristics.CONTROL_EFFECT_MODE_NEGATIVE, 999 CameraCharacteristics.CONTROL_EFFECT_MODE_SOLARIZE, 1000 CameraCharacteristics.CONTROL_EFFECT_MODE_SEPIA, 1001 CameraCharacteristics.CONTROL_EFFECT_MODE_POSTERIZE, 1002 CameraCharacteristics.CONTROL_EFFECT_MODE_WHITEBOARD, 1003 CameraCharacteristics.CONTROL_EFFECT_MODE_BLACKBOARD, 1004 CameraCharacteristics.CONTROL_EFFECT_MODE_AQUA, 1005 }; 1006 1007 static int convertEffectModeFromLegacy(String mode) { 1008 if (mode == null) { 1009 return CameraCharacteristics.CONTROL_EFFECT_MODE_OFF; 1010 } 1011 int index = ArrayUtils.getArrayIndex(sLegacyEffectMode, mode); 1012 if (index < 0) { 1013 return UNKNOWN_MODE; 1014 } 1015 return sEffectModes[index]; 1016 } 1017 1018 static String convertEffectModeToLegacy(int mode) { 1019 int index = ArrayUtils.getArrayIndex(sEffectModes, mode); 1020 if (index < 0) { 1021 return null; 1022 } 1023 return sLegacyEffectMode[index]; 1024 } 1025 1026 /** 1027 * Convert the ae antibanding mode from api1 into api2. 1028 * 1029 * @param mode the api1 mode, {@code null} is allowed and will return {@code -1}. 1030 * 1031 * @return The api2 value, or {@code -1} by default if conversion failed 1032 */ 1033 private static int convertAntiBandingMode(String mode) { 1034 if (mode == null) { 1035 return -1; 1036 } 1037 1038 switch (mode) { 1039 case Camera.Parameters.ANTIBANDING_OFF: { 1040 return CONTROL_AE_ANTIBANDING_MODE_OFF; 1041 } 1042 case Camera.Parameters.ANTIBANDING_50HZ: { 1043 return CONTROL_AE_ANTIBANDING_MODE_50HZ; 1044 } 1045 case Camera.Parameters.ANTIBANDING_60HZ: { 1046 return CONTROL_AE_ANTIBANDING_MODE_60HZ; 1047 } 1048 case Camera.Parameters.ANTIBANDING_AUTO: { 1049 return CONTROL_AE_ANTIBANDING_MODE_AUTO; 1050 } 1051 default: { 1052 Log.w(TAG, "convertAntiBandingMode - Unknown antibanding mode " + mode); 1053 return -1; 1054 } 1055 } 1056 } 1057 1058 /** 1059 * Convert the ae antibanding mode from api1 into api2. 1060 * 1061 * @param mode the api1 mode, {@code null} is allowed and will return {@code MODE_OFF}. 1062 * 1063 * @return The api2 value, or {@code MODE_OFF} by default if conversion failed 1064 */ 1065 static int convertAntiBandingModeOrDefault(String mode) { 1066 int antiBandingMode = convertAntiBandingMode(mode); 1067 if (antiBandingMode == -1) { 1068 return CONTROL_AE_ANTIBANDING_MODE_OFF; 1069 } 1070 1071 return antiBandingMode; 1072 } 1073 1074 private static int[] convertAeFpsRangeToLegacy(Range<Integer> fpsRange) { 1075 int[] legacyFps = new int[2]; 1076 legacyFps[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] = fpsRange.getLower(); 1077 legacyFps[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] = fpsRange.getUpper(); 1078 return legacyFps; 1079 } 1080 1081 /** 1082 * Return the stall duration for a given output jpeg size in nanoseconds. 1083 * 1084 * <p>An 8mp image is chosen to have a stall duration of 0.8 seconds.</p> 1085 */ 1086 private static long calculateJpegStallDuration(Camera.Size size) { 1087 long baseDuration = APPROXIMATE_CAPTURE_DELAY_MS * NS_PER_MS; // 200ms for capture 1088 long area = size.width * (long) size.height; 1089 long stallPerArea = APPROXIMATE_JPEG_ENCODE_TIME_MS * NS_PER_MS / 1090 APPROXIMATE_SENSOR_AREA_PX; // 600ms stall for 8mp 1091 return baseDuration + area * stallPerArea; 1092 } 1093 1094 /** 1095 * Set the legacy parameters using the {@link LegacyRequest legacy request}. 1096 * 1097 * <p>The legacy request's parameters are changed as a side effect of calling this 1098 * method.</p> 1099 * 1100 * @param request a non-{@code null} legacy request 1101 */ 1102 public static void convertRequestMetadata(LegacyRequest request) { 1103 LegacyRequestMapper.convertRequestMetadata(request); 1104 } 1105 1106 private static final int[] sAllowedTemplates = { 1107 CameraDevice.TEMPLATE_PREVIEW, 1108 CameraDevice.TEMPLATE_STILL_CAPTURE, 1109 CameraDevice.TEMPLATE_RECORD, 1110 // Disallowed templates in legacy mode: 1111 // CameraDevice.TEMPLATE_VIDEO_SNAPSHOT, 1112 // CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG, 1113 // CameraDevice.TEMPLATE_MANUAL 1114 }; 1115 1116 /** 1117 * Create a request template 1118 * 1119 * @param c a non-{@code null} camera characteristics for this camera 1120 * @param templateId a non-negative template ID 1121 * 1122 * @return a non-{@code null} request template 1123 * 1124 * @throws IllegalArgumentException if {@code templateId} was invalid 1125 * 1126 * @see android.hardware.camera2.CameraDevice#TEMPLATE_MANUAL 1127 */ 1128 public static CameraMetadataNative createRequestTemplate( 1129 CameraCharacteristics c, int templateId) { 1130 if (!ArrayUtils.contains(sAllowedTemplates, templateId)) { 1131 throw new IllegalArgumentException("templateId out of range"); 1132 } 1133 1134 CameraMetadataNative m = new CameraMetadataNative(); 1135 1136 /* 1137 * NOTE: If adding new code here and it needs to query the static info, 1138 * query the camera characteristics, so we can reuse this for api2 code later 1139 * to create our own templates in the framework 1140 */ 1141 1142 /* 1143 * control.* 1144 */ 1145 1146 // control.awbMode 1147 m.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO); 1148 // AWB is always unconditionally available in API1 devices 1149 1150 // control.aeAntibandingMode 1151 m.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, CONTROL_AE_ANTIBANDING_MODE_AUTO); 1152 1153 // control.aeExposureCompensation 1154 m.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0); 1155 1156 // control.aeLock 1157 m.set(CaptureRequest.CONTROL_AE_LOCK, false); 1158 1159 // control.aePrecaptureTrigger 1160 m.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CONTROL_AE_PRECAPTURE_TRIGGER_IDLE); 1161 1162 // control.afTrigger 1163 m.set(CaptureRequest.CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_IDLE); 1164 1165 // control.awbMode 1166 m.set(CaptureRequest.CONTROL_AWB_MODE, CONTROL_AWB_MODE_AUTO); 1167 1168 // control.awbLock 1169 m.set(CaptureRequest.CONTROL_AWB_LOCK, false); 1170 1171 // control.aeRegions, control.awbRegions, control.afRegions 1172 { 1173 Rect activeArray = c.get(SENSOR_INFO_ACTIVE_ARRAY_SIZE); 1174 MeteringRectangle[] activeRegions = new MeteringRectangle[] { 1175 new MeteringRectangle(/*x*/0, /*y*/0, /*width*/activeArray.width() - 1, 1176 /*height*/activeArray.height() - 1,/*weight*/0)}; 1177 m.set(CaptureRequest.CONTROL_AE_REGIONS, activeRegions); 1178 m.set(CaptureRequest.CONTROL_AWB_REGIONS, activeRegions); 1179 m.set(CaptureRequest.CONTROL_AF_REGIONS, activeRegions); 1180 } 1181 1182 // control.captureIntent 1183 { 1184 int captureIntent; 1185 switch (templateId) { 1186 case CameraDevice.TEMPLATE_PREVIEW: 1187 captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW; 1188 break; 1189 case CameraDevice.TEMPLATE_STILL_CAPTURE: 1190 captureIntent = CONTROL_CAPTURE_INTENT_STILL_CAPTURE; 1191 break; 1192 case CameraDevice.TEMPLATE_RECORD: 1193 captureIntent = CONTROL_CAPTURE_INTENT_VIDEO_RECORD; 1194 break; 1195 default: 1196 // Can't get anything else since it's guarded by the IAE check 1197 throw new AssertionError("Impossible; keep in sync with sAllowedTemplates"); 1198 } 1199 m.set(CaptureRequest.CONTROL_CAPTURE_INTENT, captureIntent); 1200 } 1201 1202 // control.aeMode 1203 m.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON); 1204 // AE is always unconditionally available in API1 devices 1205 1206 // control.mode 1207 m.set(CaptureRequest.CONTROL_MODE, CONTROL_MODE_AUTO); 1208 1209 // control.afMode 1210 { 1211 Float minimumFocusDistance = c.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE); 1212 1213 int afMode; 1214 if (minimumFocusDistance != null && 1215 minimumFocusDistance == LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS) { 1216 // Cannot control auto-focus with fixed-focus cameras 1217 afMode = CameraMetadata.CONTROL_AF_MODE_OFF; 1218 } else { 1219 // If a minimum focus distance is reported; the camera must have AF 1220 afMode = CameraMetadata.CONTROL_AF_MODE_AUTO; 1221 1222 if (templateId == CameraDevice.TEMPLATE_RECORD || 1223 templateId == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) { 1224 if (ArrayUtils.contains(c.get(CONTROL_AF_AVAILABLE_MODES), 1225 CONTROL_AF_MODE_CONTINUOUS_VIDEO)) { 1226 afMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO; 1227 } 1228 } else if (templateId == CameraDevice.TEMPLATE_PREVIEW || 1229 templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) { 1230 if (ArrayUtils.contains(c.get(CONTROL_AF_AVAILABLE_MODES), 1231 CONTROL_AF_MODE_CONTINUOUS_PICTURE)) { 1232 afMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE; 1233 } 1234 } 1235 } 1236 1237 if (VERBOSE) { 1238 Log.v(TAG, "createRequestTemplate (templateId=" + templateId + ")," + 1239 " afMode=" + afMode + ", minimumFocusDistance=" + minimumFocusDistance); 1240 } 1241 1242 m.set(CaptureRequest.CONTROL_AF_MODE, afMode); 1243 } 1244 1245 { 1246 // control.aeTargetFpsRange 1247 Range<Integer>[] availableFpsRange = c. 1248 get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); 1249 1250 // Pick FPS range with highest max value, tiebreak on higher min value 1251 Range<Integer> bestRange = availableFpsRange[0]; 1252 for (Range<Integer> r : availableFpsRange) { 1253 if (bestRange.getUpper() < r.getUpper()) { 1254 bestRange = r; 1255 } else if (bestRange.getUpper() == r.getUpper() && 1256 bestRange.getLower() < r.getLower()) { 1257 bestRange = r; 1258 } 1259 } 1260 m.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, bestRange); 1261 } 1262 1263 // control.sceneMode -- DISABLED is always available 1264 m.set(CaptureRequest.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_DISABLED); 1265 1266 /* 1267 * statistics.* 1268 */ 1269 1270 // statistics.faceDetectMode 1271 m.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, STATISTICS_FACE_DETECT_MODE_OFF); 1272 1273 /* 1274 * flash.* 1275 */ 1276 1277 // flash.mode 1278 m.set(CaptureRequest.FLASH_MODE, FLASH_MODE_OFF); 1279 1280 /* 1281 * noiseReduction.* 1282 */ 1283 m.set(CaptureRequest.NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_FAST); 1284 1285 /* 1286 * lens.* 1287 */ 1288 1289 // lens.focalLength 1290 m.set(CaptureRequest.LENS_FOCAL_LENGTH, 1291 c.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS)[0]); 1292 1293 // TODO: map other request template values 1294 return m; 1295 } 1296 1297 private static int[] getTagsForKeys(Key<?>[] keys) { 1298 int[] tags = new int[keys.length]; 1299 1300 for (int i = 0; i < keys.length; ++i) { 1301 tags[i] = keys[i].getNativeKey().getTag(); 1302 } 1303 1304 return tags; 1305 } 1306 1307 private static int[] getTagsForKeys(CaptureRequest.Key<?>[] keys) { 1308 int[] tags = new int[keys.length]; 1309 1310 for (int i = 0; i < keys.length; ++i) { 1311 tags[i] = keys[i].getNativeKey().getTag(); 1312 } 1313 1314 return tags; 1315 } 1316 1317 private static int[] getTagsForKeys(CaptureResult.Key<?>[] keys) { 1318 int[] tags = new int[keys.length]; 1319 1320 for (int i = 0; i < keys.length; ++i) { 1321 tags[i] = keys[i].getNativeKey().getTag(); 1322 } 1323 1324 return tags; 1325 } 1326 1327 /** 1328 * Convert the requested AF mode into its equivalent supported parameter. 1329 * 1330 * @param mode {@code CONTROL_AF_MODE} 1331 * @param supportedFocusModes list of camera1's supported focus modes 1332 * @return the stringified af mode, or {@code null} if its not supported 1333 */ 1334 static String convertAfModeToLegacy(int mode, List<String> supportedFocusModes) { 1335 if (supportedFocusModes == null || supportedFocusModes.isEmpty()) { 1336 Log.w(TAG, "No focus modes supported; API1 bug"); 1337 return null; 1338 } 1339 1340 String param = null; 1341 switch (mode) { 1342 case CONTROL_AF_MODE_AUTO: 1343 param = Parameters.FOCUS_MODE_AUTO; 1344 break; 1345 case CONTROL_AF_MODE_CONTINUOUS_PICTURE: 1346 param = Parameters.FOCUS_MODE_CONTINUOUS_PICTURE; 1347 break; 1348 case CONTROL_AF_MODE_CONTINUOUS_VIDEO: 1349 param = Parameters.FOCUS_MODE_CONTINUOUS_VIDEO; 1350 break; 1351 case CONTROL_AF_MODE_EDOF: 1352 param = Parameters.FOCUS_MODE_EDOF; 1353 break; 1354 case CONTROL_AF_MODE_MACRO: 1355 param = Parameters.FOCUS_MODE_MACRO; 1356 break; 1357 case CONTROL_AF_MODE_OFF: 1358 if (supportedFocusModes.contains(Parameters.FOCUS_MODE_FIXED)) { 1359 param = Parameters.FOCUS_MODE_FIXED; 1360 } else { 1361 param = Parameters.FOCUS_MODE_INFINITY; 1362 } 1363 } 1364 1365 if (!supportedFocusModes.contains(param)) { 1366 // Weed out bad user input by setting to the first arbitrary focus mode 1367 String defaultMode = supportedFocusModes.get(0); 1368 Log.w(TAG, 1369 String.format( 1370 "convertAfModeToLegacy - ignoring unsupported mode %d, " + 1371 "defaulting to %s", mode, defaultMode)); 1372 param = defaultMode; 1373 } 1374 1375 return param; 1376 } 1377} 1378