1 /* 2 * Copyright (C) 2018 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 android.hardware.camera2.params; 18 19 import static com.android.internal.R.string.hardware; 20 21 import android.annotation.IntDef; 22 import android.annotation.IntRange; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.graphics.ImageFormat; 26 import android.graphics.ImageFormat.Format; 27 import android.graphics.PixelFormat; 28 import android.hardware.camera2.CameraCharacteristics; 29 import android.hardware.camera2.CameraDevice; 30 import android.hardware.camera2.CameraMetadata; 31 import android.hardware.camera2.CaptureRequest; 32 import android.util.ArraySet; 33 import android.util.Range; 34 import android.util.Size; 35 import android.view.Surface; 36 37 import java.lang.annotation.Retention; 38 import java.lang.annotation.RetentionPolicy; 39 40 import java.util.Arrays; 41 import java.util.Collections; 42 import java.util.Set; 43 44 /** 45 * Immutable class to store the recommended stream configurations to set up 46 * {@link android.view.Surface Surfaces} for creating a 47 * {@link android.hardware.camera2.CameraCaptureSession capture session} with 48 * {@link android.hardware.camera2.CameraDevice#createCaptureSession}. 49 * 50 * <p>The recommended list does not replace or deprecate the exhaustive complete list found in 51 * {@link StreamConfigurationMap}. It is a suggestion about available power and performance 52 * efficient stream configurations for a specific use case. Per definition it is only a subset 53 * of {@link StreamConfigurationMap} and can be considered by developers for optimization 54 * purposes.</p> 55 * 56 * <p>This also duplicates the minimum frame durations and stall durations from the 57 * {@link StreamConfigurationMap} for each format/size combination that can be used to calculate 58 * effective frame rate when submitting multiple captures. 59 * </p> 60 * 61 * <p>An instance of this object is available by invoking 62 * {@link CameraCharacteristics#getRecommendedStreamConfigurationMap} and passing a respective 63 * usecase id. For more information about supported use case constants see 64 * {@link #USECASE_PREVIEW}.</p> 65 * 66 * <pre><code>{@code 67 * CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId); 68 * RecommendedStreamConfigurationMap configs = characteristics.getRecommendedStreamConfigurationMap( 69 * RecommendedStreamConfigurationMap.USECASE_PREVIEW); 70 * }</code></pre> 71 * 72 * @see CameraCharacteristics#getRecommendedStreamConfigurationMap 73 * @see CameraDevice#createCaptureSession 74 */ 75 public final class RecommendedStreamConfigurationMap { 76 77 private static final String TAG = "RecommendedStreamConfigurationMap"; 78 private int mUsecase; 79 private boolean mSupportsPrivate; 80 private StreamConfigurationMap mRecommendedMap; 81 82 /** @hide */ 83 public static final int MAX_USECASE_COUNT = 32; 84 85 /** 86 * The recommended stream configuration map for use case preview must contain a subset of 87 * efficient, non-stalling configurations that must include both 88 * {@link android.graphics.ImageFormat#PRIVATE} and 89 * {@link android.graphics.ImageFormat#YUV_420_888} output formats. Even if available for the 90 * camera device, high speed or input configurations will be absent. 91 */ 92 public static final int USECASE_PREVIEW = 0x0; 93 94 /** 95 * The recommended stream configuration map for recording must contain a subset of efficient 96 * video configurations that include {@link android.graphics.ImageFormat#PRIVATE} 97 * output format for at least all supported {@link android.media.CamcorderProfile profiles}. 98 * High speed configurations if supported will be available as well. Even if available for the 99 * camera device, input configurations will be absent. 100 */ 101 public static final int USECASE_RECORD = 0x1; 102 103 /** 104 * The recommended stream configuration map for use case video snapshot must only contain a 105 * subset of efficient liveshot configurations that include 106 * {@link android.graphics.ImageFormat#JPEG} output format. The sizes will match at least 107 * the maximum resolution of usecase record and will not cause any preview glitches. Even 108 * if available for the camera device, high speed or input configurations will be absent. 109 */ 110 public static final int USECASE_VIDEO_SNAPSHOT = 0x2; 111 112 /** 113 * The recommended stream configuration map for use case snapshot must contain a subset of 114 * efficient still capture configurations that must include 115 * {@link android.graphics.ImageFormat#JPEG} output format and at least one configuration with 116 * size approximately equal to the sensor pixel array size 117 * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}. 118 * Even if available for the camera device, high speed or input configurations will be absent. 119 */ 120 public static final int USECASE_SNAPSHOT = 0x3; 121 122 /** 123 * In case the device supports 124 * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING} and/or 125 * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING}, 126 * the recommended stream configuration map for use case ZSL must contain a subset of efficient 127 * configurations that include the suggested input and output format mappings. Even if 128 * available for the camera device, high speed configurations will be absent. 129 */ 130 public static final int USECASE_ZSL = 0x4; 131 132 /** 133 * In case the device supports 134 * {@link android.hardware.camera2.CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW}, the 135 * recommended stream configuration map for use case RAW must contain a subset of efficient 136 * configurations that include the {@link android.graphics.ImageFormat#RAW_SENSOR} and other 137 * RAW output formats. Even if available for the camera device, high speed and input 138 * configurations will be absent. 139 */ 140 public static final int USECASE_RAW = 0x5; 141 142 /** 143 * The recommended stream configuration map for use case low latency snapshot must contain 144 * subset of configurations with end-to-end latency that does not exceed 200 ms. under standard 145 * operating conditions (reasonable light levels, not loaded system). The expected output format 146 * will be primarily {@link android.graphics.ImageFormat#JPEG} however other image formats can 147 * be present as well. Even if available for the camera device, high speed and input 148 * configurations will be absent. This suggested configuration map may be absent on some devices 149 * that can not support any low latency requests. 150 */ 151 public static final int USECASE_LOW_LATENCY_SNAPSHOT = 0x6; 152 153 /** 154 * If supported, the recommended 10-bit output stream configurations must include 155 * a subset of the advertised {@link android.graphics.ImageFormat#YCBCR_P010} and 156 * {@link android.graphics.ImageFormat#PRIVATE} outputs that are optimized for power 157 * and performance when registered along with a supported 10-bit dynamic range profile. 158 * {@see android.hardware.camera2.params.OutputConfiguration#setDynamicRangeProfile} for 159 * details. 160 */ 161 public static final int USECASE_10BIT_OUTPUT = 0x8; 162 163 /** 164 * Device specific use cases. 165 * @hide 166 */ 167 public static final int USECASE_VENDOR_START = 0x18; 168 169 /** @hide */ 170 @Retention(RetentionPolicy.SOURCE) 171 @IntDef(prefix = {"USECASE_"}, value = 172 {USECASE_PREVIEW, 173 USECASE_RECORD, 174 USECASE_VIDEO_SNAPSHOT, 175 USECASE_SNAPSHOT, 176 USECASE_ZSL, 177 USECASE_RAW, 178 USECASE_LOW_LATENCY_SNAPSHOT, 179 USECASE_10BIT_OUTPUT}) 180 public @interface RecommendedUsecase {}; 181 182 /** 183 * Create a new {@link RecommendedStreamConfigurationMap}. 184 * 185 * @param recommendedMap stream configuration map that contains for the specific use case 186 * @param usecase Recommended use case 187 * @param supportsPrivate Flag indicating private format support. 188 * 189 * @hide 190 */ RecommendedStreamConfigurationMap(StreamConfigurationMap recommendedMap, int usecase, boolean supportsPrivate)191 public RecommendedStreamConfigurationMap(StreamConfigurationMap recommendedMap, int usecase, 192 boolean supportsPrivate) { 193 mRecommendedMap = recommendedMap; 194 mUsecase = usecase; 195 mSupportsPrivate = supportsPrivate; 196 } 197 198 /** 199 * Get the use case value for the recommended stream configurations. 200 * 201 * @return Use case id. 202 */ getRecommendedUseCase()203 public @RecommendedUsecase int getRecommendedUseCase() { 204 return mUsecase; 205 } 206 getUnmodifiableIntegerSet(int[] intArray)207 private Set<Integer> getUnmodifiableIntegerSet(int[] intArray) { 208 if ((intArray != null) && (intArray.length > 0)) { 209 ArraySet<Integer> integerSet = new ArraySet<Integer>(); 210 integerSet.ensureCapacity(intArray.length); 211 for (int intEntry : intArray) { 212 integerSet.add(intEntry); 213 } 214 215 return Collections.unmodifiableSet(integerSet); 216 } 217 218 return null; 219 } 220 221 /** 222 * Get the image {@code format} output formats in this stream configuration. 223 * 224 * <p> 225 * For more information refer to {@link StreamConfigurationMap#getOutputFormats}. 226 * </p> 227 * 228 * @return a non-modifiable set of Integer formats 229 */ getOutputFormats()230 public @NonNull Set<Integer> getOutputFormats() { 231 return getUnmodifiableIntegerSet(mRecommendedMap.getOutputFormats()); 232 } 233 234 /** 235 * Get the image {@code format} output formats for a reprocessing input format. 236 * 237 * <p> 238 * For more information refer to {@link StreamConfigurationMap#getValidOutputFormatsForInput}. 239 * </p> 240 * 241 * @return a non-modifiable set of Integer formats 242 */ getValidOutputFormatsForInput(@ormat int inputFormat)243 public @Nullable Set<Integer> getValidOutputFormatsForInput(@Format int inputFormat) { 244 return getUnmodifiableIntegerSet(mRecommendedMap.getValidOutputFormatsForInput( 245 inputFormat)); 246 } 247 248 /** 249 * Get the image {@code format} input formats in this stream configuration. 250 * 251 * <p>All image formats returned by this function will be defined in either {@link ImageFormat} 252 * or in {@link PixelFormat} (and there is no possibility of collision).</p> 253 * 254 * @return a non-modifiable set of Integer formats 255 */ getInputFormats()256 public @Nullable Set<Integer> getInputFormats() { 257 return getUnmodifiableIntegerSet(mRecommendedMap.getInputFormats()); 258 } 259 getUnmodifiableSizeSet(Size[] sizeArray)260 private Set<Size> getUnmodifiableSizeSet(Size[] sizeArray) { 261 if ((sizeArray != null) && (sizeArray.length > 0)) { 262 ArraySet<Size> sizeSet = new ArraySet<Size>(); 263 sizeSet.addAll(Arrays.asList(sizeArray)); 264 return Collections.unmodifiableSet(sizeSet); 265 } 266 267 return null; 268 } 269 270 /** 271 * Get the supported input sizes for this input format. 272 * 273 * <p>The format must have come from {@link #getInputFormats}; otherwise 274 * {@code null} is returned.</p> 275 * 276 * @param format a format from {@link #getInputFormats} 277 * @return a non-modifiable set of sizes, or {@code null} if the format was not available. 278 */ getInputSizes(@ormat int format)279 public @Nullable Set<Size> getInputSizes(@Format int format) { 280 return getUnmodifiableSizeSet(mRecommendedMap.getInputSizes(format)); 281 } 282 283 /** 284 * Determine whether or not output surfaces with a particular user-defined format can be passed 285 * {@link CameraDevice#createCaptureSession createCaptureSession}. 286 * 287 * <p> 288 * For further information refer to {@link StreamConfigurationMap#isOutputSupportedFor}. 289 * </p> 290 * 291 * 292 * @param format an image format from either {@link ImageFormat} or {@link PixelFormat} 293 * @return 294 * {@code true} if using a {@code surface} with this {@code format} will be 295 * supported with {@link CameraDevice#createCaptureSession} 296 * 297 * @throws IllegalArgumentException 298 * if the image format was not a defined named constant 299 * from either {@link ImageFormat} or {@link PixelFormat} 300 */ isOutputSupportedFor(@ormat int format)301 public boolean isOutputSupportedFor(@Format int format) { 302 return mRecommendedMap.isOutputSupportedFor(format); 303 } 304 305 /** 306 * Get a list of sizes compatible with the requested image {@code format}. 307 * 308 * <p> 309 * For more information refer to {@link StreamConfigurationMap#getOutputSizes}. 310 * </p> 311 * 312 * 313 * @param format an image format from {@link ImageFormat} or {@link PixelFormat} 314 * @return a non-modifiable set of supported sizes, 315 * or {@code null} if the {@code format} is not a supported output 316 */ getOutputSizes(@ormat int format)317 public @Nullable Set<Size> getOutputSizes(@Format int format) { 318 return getUnmodifiableSizeSet(mRecommendedMap.getOutputSizes(format)); 319 } 320 321 /** 322 * Get a list of supported high speed video recording sizes. 323 * <p> 324 * For more information refer to {@link StreamConfigurationMap#getHighSpeedVideoSizes}. 325 * </p> 326 * 327 * @return a non-modifiable set of supported high speed video recording sizes 328 */ getHighSpeedVideoSizes()329 public @Nullable Set<Size> getHighSpeedVideoSizes() { 330 return getUnmodifiableSizeSet(mRecommendedMap.getHighSpeedVideoSizes()); 331 } 332 getUnmodifiableRangeSet(Range<Integer>[] rangeArray)333 private Set<Range<Integer>> getUnmodifiableRangeSet(Range<Integer>[] rangeArray) { 334 if ((rangeArray != null) && (rangeArray.length > 0)) { 335 ArraySet<Range<Integer>> rangeSet = new ArraySet<Range<Integer>>(); 336 rangeSet.addAll(Arrays.asList(rangeArray)); 337 return Collections.unmodifiableSet(rangeSet); 338 } 339 340 return null; 341 } 342 343 /** 344 * Get the frame per second ranges (fpsMin, fpsMax) for input high speed video size. 345 * 346 * <p> 347 * For further information refer to 348 * {@link StreamConfigurationMap#getHighSpeedVideoFpsRangesFor}. 349 * </p> 350 * @param size one of the sizes returned by {@link #getHighSpeedVideoSizes()} 351 * @return a non-modifiable set of supported high speed video recording FPS ranges The upper 352 * bound of returned ranges is guaranteed to be greater than or equal to 120. 353 * @throws IllegalArgumentException if input size does not exist in the return value of 354 * getHighSpeedVideoSizes 355 */ getHighSpeedVideoFpsRangesFor(@onNull Size size)356 public @Nullable Set<Range<Integer>> getHighSpeedVideoFpsRangesFor(@NonNull Size size) { 357 return getUnmodifiableRangeSet(mRecommendedMap.getHighSpeedVideoFpsRangesFor(size)); 358 } 359 360 /** 361 * Get a list of supported high speed video recording FPS ranges. 362 * <p> 363 * For further information refer to {@link StreamConfigurationMap#getHighSpeedVideoFpsRanges}. 364 * </p> 365 * @return a non-modifiable set of supported high speed video recording FPS ranges The upper 366 * bound of returned ranges is guaranteed to be larger or equal to 120. 367 */ getHighSpeedVideoFpsRanges()368 public @Nullable Set<Range<Integer>> getHighSpeedVideoFpsRanges() { 369 return getUnmodifiableRangeSet(mRecommendedMap.getHighSpeedVideoFpsRanges()); 370 } 371 372 /** 373 * Get the supported video sizes for an input high speed FPS range. 374 * 375 * <p> 376 * For further information refer to {@link StreamConfigurationMap#getHighSpeedVideoSizesFor}. 377 * </p> 378 * 379 * @param fpsRange one of the FPS ranges returned by {@link #getHighSpeedVideoFpsRanges()} 380 * @return A non-modifiable set of video sizes to create high speed capture sessions for high 381 * speed streaming use cases. 382 * 383 * @throws IllegalArgumentException if input FPS range does not exist in the return value of 384 * getHighSpeedVideoFpsRanges 385 */ getHighSpeedVideoSizesFor(@onNull Range<Integer> fpsRange)386 public @Nullable Set<Size> getHighSpeedVideoSizesFor(@NonNull Range<Integer> fpsRange) { 387 return getUnmodifiableSizeSet(mRecommendedMap.getHighSpeedVideoSizesFor(fpsRange)); 388 } 389 390 /** 391 * Get a list of supported high resolution sizes, which cannot operate at full BURST_CAPTURE 392 * rate. 393 * 394 * <p> 395 * For further information refer to {@link StreamConfigurationMap#getHighResolutionOutputSizes}. 396 * </p> 397 * 398 * @return a non-modifiable set of supported slower high-resolution sizes, or {@code null} if 399 * the BURST_CAPTURE capability is not supported 400 */ getHighResolutionOutputSizes(@ormat int format)401 public @Nullable Set<Size> getHighResolutionOutputSizes(@Format int format) { 402 return getUnmodifiableSizeSet(mRecommendedMap.getHighResolutionOutputSizes(format)); 403 } 404 405 /** 406 * Get the minimum 407 * {@link android.hardware.camera2.CaptureRequest#SENSOR_FRAME_DURATION frame duration} 408 * for the format/size combination (in nanoseconds). 409 * 410 * <p> 411 * For further information refer to {@link StreamConfigurationMap#getOutputMinFrameDuration}. 412 * </p> 413 * 414 * @param format an image format from {@link ImageFormat} or {@link PixelFormat} 415 * @param size an output-compatible size 416 * @return a minimum frame duration {@code >} 0 in nanoseconds, or 417 * 0 if the minimum frame duration is not available. 418 * 419 * @throws IllegalArgumentException if {@code format} or {@code size} was not supported 420 */ getOutputMinFrameDuration(@ormat int format, @NonNull Size size)421 public @IntRange(from = 0) long getOutputMinFrameDuration(@Format int format, 422 @NonNull Size size) { 423 return mRecommendedMap.getOutputMinFrameDuration(format, size); 424 } 425 426 /** 427 * Get the stall duration for the format/size combination (in nanoseconds). 428 * 429 * <p> 430 * For further information refer to {@link StreamConfigurationMap#getOutputStallDuration}. 431 * </p> 432 * 433 * @param format an image format from {@link ImageFormat} or {@link PixelFormat} 434 * @param size an output-compatible size 435 * @return a stall duration {@code >=} 0 in nanoseconds 436 * 437 * @throws IllegalArgumentException if {@code format} or {@code size} was not supported 438 */ getOutputStallDuration(@ormat int format, @NonNull Size size)439 public @IntRange(from = 0) long getOutputStallDuration(@Format int format, @NonNull Size size) { 440 return mRecommendedMap.getOutputStallDuration(format, size); 441 } 442 443 /** 444 * Get a list of sizes compatible with {@code klass} to use as an output. 445 * 446 * <p>For further information refer to {@link StreamConfigurationMap#getOutputSizes(Class)}. 447 * </p> 448 * 449 * @param klass 450 * a {@link Class} object reference 451 * @return 452 * a non-modifiable set of supported sizes for {@link ImageFormat#PRIVATE} format, 453 * or {@code null} if the {@code klass} is not a supported output. 454 */ getOutputSizes(@onNull Class<T> klass)455 public @Nullable <T> Set<Size> getOutputSizes(@NonNull Class<T> klass) { 456 if (mSupportsPrivate) { 457 return getUnmodifiableSizeSet(mRecommendedMap.getOutputSizes(klass)); 458 } 459 460 return null; 461 } 462 463 /** 464 * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration} 465 * for the class/size combination (in nanoseconds). 466 * 467 * <p>For more information refer to 468 * {@link StreamConfigurationMap#getOutputMinFrameDuration(Class, Size)}.</p> 469 * 470 * @param klass 471 * a class which has a non-empty array returned by {@link #getOutputSizes(Class)} 472 * @param size an output-compatible size 473 * @return a minimum frame duration {@code >} 0 in nanoseconds, or 474 * 0 if the minimum frame duration is not available. 475 * 476 * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported 477 */ getOutputMinFrameDuration(@onNull final Class<T> klass, @NonNull final Size size)478 public @IntRange(from = 0) <T> long getOutputMinFrameDuration(@NonNull final Class<T> klass, 479 @NonNull final Size size) { 480 if (mSupportsPrivate) { 481 return mRecommendedMap.getOutputMinFrameDuration(klass, size); 482 } 483 484 return 0; 485 } 486 487 /** 488 * Get the stall duration for the class/size combination (in nanoseconds). 489 * 490 * <p>For more information refer to 491 * {@link StreamConfigurationMap#getOutputStallDuration(Class, Size)}. 492 * 493 * @param klass 494 * a class which has a non-empty array returned by {@link #getOutputSizes(Class)}. 495 * @param size an output-compatible size 496 * @return a minimum frame duration {@code >} 0 in nanoseconds, or 0 if the stall duration is 497 * not available. 498 * 499 * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported 500 */ getOutputStallDuration(@onNull final Class<T> klass, @NonNull final Size size)501 public @IntRange(from = 0) <T> long getOutputStallDuration(@NonNull final Class<T> klass, 502 @NonNull final Size size) { 503 if (mSupportsPrivate) { 504 return mRecommendedMap.getOutputStallDuration(klass, size); 505 } 506 507 return 0; 508 } 509 510 /** 511 * Determine whether or not the {@code surface} in its current state is suitable to be included 512 * in a {@link CameraDevice#createCaptureSession capture session} as an output. 513 * 514 * <p>For more information refer to {@link StreamConfigurationMap#isOutputSupportedFor}. 515 * </p> 516 * 517 * @param surface a {@link Surface} object reference 518 * @return {@code true} if this is supported, {@code false} otherwise 519 * 520 * @throws IllegalArgumentException if the Surface endpoint is no longer valid 521 * 522 */ isOutputSupportedFor(@onNull Surface surface)523 public boolean isOutputSupportedFor(@NonNull Surface surface) { 524 return mRecommendedMap.isOutputSupportedFor(surface); 525 } 526 527 } 528