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