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}. 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 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 * Device specific use cases. 153 * @hide 154 */ 155 public static final int USECASE_VENDOR_START = 0x18; 156 157 /** @hide */ 158 @Retention(RetentionPolicy.SOURCE) 159 @IntDef(prefix = {"USECASE_"}, value = 160 {USECASE_PREVIEW, 161 USECASE_RECORD, 162 USECASE_VIDEO_SNAPSHOT, 163 USECASE_SNAPSHOT, 164 USECASE_ZSL, 165 USECASE_RAW, 166 USECASE_LOW_LATENCY_SNAPSHOT}) 167 public @interface RecommendedUsecase {}; 168 169 /** 170 * Create a new {@link RecommendedStreamConfigurationMap}. 171 * 172 * @param recommendedMap stream configuration map that contains for the specific use case 173 * @param usecase Recommended use case 174 * @param supportsPrivate Flag indicating private format support. 175 * 176 * @hide 177 */ RecommendedStreamConfigurationMap(StreamConfigurationMap recommendedMap, int usecase, boolean supportsPrivate)178 public RecommendedStreamConfigurationMap(StreamConfigurationMap recommendedMap, int usecase, 179 boolean supportsPrivate) { 180 mRecommendedMap = recommendedMap; 181 mUsecase = usecase; 182 mSupportsPrivate = supportsPrivate; 183 } 184 185 /** 186 * Get the use case value for the recommended stream configurations. 187 * 188 * @return Use case id. 189 */ getRecommendedUseCase()190 public @RecommendedUsecase int getRecommendedUseCase() { 191 return mUsecase; 192 } 193 getUnmodifiableIntegerSet(int[] intArray)194 private Set<Integer> getUnmodifiableIntegerSet(int[] intArray) { 195 if ((intArray != null) && (intArray.length > 0)) { 196 ArraySet<Integer> integerSet = new ArraySet<Integer>(); 197 integerSet.ensureCapacity(intArray.length); 198 for (int intEntry : intArray) { 199 integerSet.add(intEntry); 200 } 201 202 return Collections.unmodifiableSet(integerSet); 203 } 204 205 return null; 206 } 207 208 /** 209 * Get the image {@code format} output formats in this stream configuration. 210 * 211 * <p> 212 * For more information refer to {@link StreamConfigurationMap#getOutputFormats}. 213 * </p> 214 * 215 * @return a non-modifiable set of Integer formats 216 */ getOutputFormats()217 public @NonNull Set<Integer> getOutputFormats() { 218 return getUnmodifiableIntegerSet(mRecommendedMap.getOutputFormats()); 219 } 220 221 /** 222 * Get the image {@code format} output formats for a reprocessing input format. 223 * 224 * <p> 225 * For more information refer to {@link StreamConfigurationMap#getValidOutputFormatsForInput}. 226 * </p> 227 * 228 * @return a non-modifiable set of Integer formats 229 */ getValidOutputFormatsForInput(@ormat int inputFormat)230 public @Nullable Set<Integer> getValidOutputFormatsForInput(@Format int inputFormat) { 231 return getUnmodifiableIntegerSet(mRecommendedMap.getValidOutputFormatsForInput( 232 inputFormat)); 233 } 234 235 /** 236 * Get the image {@code format} input formats in this stream configuration. 237 * 238 * <p>All image formats returned by this function will be defined in either {@link ImageFormat} 239 * or in {@link PixelFormat} (and there is no possibility of collision).</p> 240 * 241 * @return a non-modifiable set of Integer formats 242 */ getInputFormats()243 public @Nullable Set<Integer> getInputFormats() { 244 return getUnmodifiableIntegerSet(mRecommendedMap.getInputFormats()); 245 } 246 getUnmodifiableSizeSet(Size[] sizeArray)247 private Set<Size> getUnmodifiableSizeSet(Size[] sizeArray) { 248 if ((sizeArray != null) && (sizeArray.length > 0)) { 249 ArraySet<Size> sizeSet = new ArraySet<Size>(); 250 sizeSet.addAll(Arrays.asList(sizeArray)); 251 return Collections.unmodifiableSet(sizeSet); 252 } 253 254 return null; 255 } 256 257 /** 258 * Get the supported input sizes for this input format. 259 * 260 * <p>The format must have come from {@link #getInputFormats}; otherwise 261 * {@code null} is returned.</p> 262 * 263 * @param format a format from {@link #getInputFormats} 264 * @return a non-modifiable set of sizes, or {@code null} if the format was not available. 265 */ getInputSizes(@ormat int format)266 public @Nullable Set<Size> getInputSizes(@Format int format) { 267 return getUnmodifiableSizeSet(mRecommendedMap.getInputSizes(format)); 268 } 269 270 /** 271 * Determine whether or not output surfaces with a particular user-defined format can be passed 272 * {@link CameraDevice#createCaptureSession createCaptureSession}. 273 * 274 * <p> 275 * For further information refer to {@link StreamConfigurationMap#isOutputSupportedFor}. 276 * </p> 277 * 278 * 279 * @param format an image format from either {@link ImageFormat} or {@link PixelFormat} 280 * @return 281 * {@code true} if using a {@code surface} with this {@code format} will be 282 * supported with {@link CameraDevice#createCaptureSession} 283 * 284 * @throws IllegalArgumentException 285 * if the image format was not a defined named constant 286 * from either {@link ImageFormat} or {@link PixelFormat} 287 */ isOutputSupportedFor(@ormat int format)288 public boolean isOutputSupportedFor(@Format int format) { 289 return mRecommendedMap.isOutputSupportedFor(format); 290 } 291 292 /** 293 * Get a list of sizes compatible with the requested image {@code format}. 294 * 295 * <p> 296 * For more information refer to {@link StreamConfigurationMap#getOutputSizes}. 297 * </p> 298 * 299 * 300 * @param format an image format from {@link ImageFormat} or {@link PixelFormat} 301 * @return a non-modifiable set of supported sizes, 302 * or {@code null} if the {@code format} is not a supported output 303 */ getOutputSizes(@ormat int format)304 public @Nullable Set<Size> getOutputSizes(@Format int format) { 305 return getUnmodifiableSizeSet(mRecommendedMap.getOutputSizes(format)); 306 } 307 308 /** 309 * Get a list of supported high speed video recording sizes. 310 * <p> 311 * For more information refer to {@link StreamConfigurationMap#getHighSpeedVideoSizes}. 312 * </p> 313 * 314 * @return a non-modifiable set of supported high speed video recording sizes 315 */ getHighSpeedVideoSizes()316 public @Nullable Set<Size> getHighSpeedVideoSizes() { 317 return getUnmodifiableSizeSet(mRecommendedMap.getHighSpeedVideoSizes()); 318 } 319 getUnmodifiableRangeSet(Range<Integer>[] rangeArray)320 private Set<Range<Integer>> getUnmodifiableRangeSet(Range<Integer>[] rangeArray) { 321 if ((rangeArray != null) && (rangeArray.length > 0)) { 322 ArraySet<Range<Integer>> rangeSet = new ArraySet<Range<Integer>>(); 323 rangeSet.addAll(Arrays.asList(rangeArray)); 324 return Collections.unmodifiableSet(rangeSet); 325 } 326 327 return null; 328 } 329 330 /** 331 * Get the frame per second ranges (fpsMin, fpsMax) for input high speed video size. 332 * 333 * <p> 334 * For further information refer to 335 * {@link StreamConfigurationMap#getHighSpeedVideoFpsRangesFor}. 336 * </p> 337 * @param size one of the sizes returned by {@link #getHighSpeedVideoSizes()} 338 * @return a non-modifiable set of supported high speed video recording FPS ranges The upper 339 * bound of returned ranges is guaranteed to be greater than or equal to 120. 340 * @throws IllegalArgumentException if input size does not exist in the return value of 341 * getHighSpeedVideoSizes 342 */ getHighSpeedVideoFpsRangesFor(@onNull Size size)343 public @Nullable Set<Range<Integer>> getHighSpeedVideoFpsRangesFor(@NonNull Size size) { 344 return getUnmodifiableRangeSet(mRecommendedMap.getHighSpeedVideoFpsRangesFor(size)); 345 } 346 347 /** 348 * Get a list of supported high speed video recording FPS ranges. 349 * <p> 350 * For further information refer to {@link StreamConfigurationMap#getHighSpeedVideoFpsRanges}. 351 * </p> 352 * @return a non-modifiable set of supported high speed video recording FPS ranges The upper 353 * bound of returned ranges is guaranteed to be larger or equal to 120. 354 */ getHighSpeedVideoFpsRanges()355 public @Nullable Set<Range<Integer>> getHighSpeedVideoFpsRanges() { 356 return getUnmodifiableRangeSet(mRecommendedMap.getHighSpeedVideoFpsRanges()); 357 } 358 359 /** 360 * Get the supported video sizes for an input high speed FPS range. 361 * 362 * <p> 363 * For further information refer to {@link StreamConfigurationMap#getHighSpeedVideoSizesFor}. 364 * </p> 365 * 366 * @param fpsRange one of the FPS ranges returned by {@link #getHighSpeedVideoFpsRanges()} 367 * @return A non-modifiable set of video sizes to create high speed capture sessions for high 368 * speed streaming use cases. 369 * 370 * @throws IllegalArgumentException if input FPS range does not exist in the return value of 371 * getHighSpeedVideoFpsRanges 372 */ getHighSpeedVideoSizesFor(@onNull Range<Integer> fpsRange)373 public @Nullable Set<Size> getHighSpeedVideoSizesFor(@NonNull Range<Integer> fpsRange) { 374 return getUnmodifiableSizeSet(mRecommendedMap.getHighSpeedVideoSizesFor(fpsRange)); 375 } 376 377 /** 378 * Get a list of supported high resolution sizes, which cannot operate at full BURST_CAPTURE 379 * rate. 380 * 381 * <p> 382 * For further information refer to {@link StreamConfigurationMap#getHighResolutionOutputSizes}. 383 * </p> 384 * 385 * @return a non-modifiable set of supported slower high-resolution sizes, or {@code null} if 386 * the BURST_CAPTURE capability is not supported 387 */ getHighResolutionOutputSizes(@ormat int format)388 public @Nullable Set<Size> getHighResolutionOutputSizes(@Format int format) { 389 return getUnmodifiableSizeSet(mRecommendedMap.getHighResolutionOutputSizes(format)); 390 } 391 392 /** 393 * Get the minimum 394 * {@link android.hardware.camera2.CaptureRequest#SENSOR_FRAME_DURATION frame duration} 395 * for the format/size combination (in nanoseconds). 396 * 397 * <p> 398 * For further information refer to {@link StreamConfigurationMap#getOutputMinFrameDuration}. 399 * </p> 400 * 401 * @param format an image format from {@link ImageFormat} or {@link PixelFormat} 402 * @param size an output-compatible size 403 * @return a minimum frame duration {@code >} 0 in nanoseconds, or 404 * 0 if the minimum frame duration is not available. 405 * 406 * @throws IllegalArgumentException if {@code format} or {@code size} was not supported 407 */ getOutputMinFrameDuration(@ormat int format, @NonNull Size size)408 public @IntRange(from = 0) long getOutputMinFrameDuration(@Format int format, 409 @NonNull Size size) { 410 return mRecommendedMap.getOutputMinFrameDuration(format, size); 411 } 412 413 /** 414 * Get the stall duration for the format/size combination (in nanoseconds). 415 * 416 * <p> 417 * For further information refer to {@link StreamConfigurationMap#getOutputStallDuration}. 418 * </p> 419 * 420 * @param format an image format from {@link ImageFormat} or {@link PixelFormat} 421 * @param size an output-compatible size 422 * @return a stall duration {@code >=} 0 in nanoseconds 423 * 424 * @throws IllegalArgumentException if {@code format} or {@code size} was not supported 425 */ getOutputStallDuration(@ormat int format, @NonNull Size size)426 public @IntRange(from = 0) long getOutputStallDuration(@Format int format, @NonNull Size size) { 427 return mRecommendedMap.getOutputStallDuration(format, size); 428 } 429 430 /** 431 * Get a list of sizes compatible with {@code klass} to use as an output. 432 * 433 * <p>For further information refer to {@link StreamConfigurationMap#getOutputSizes(Class)}. 434 * </p> 435 * 436 * @param klass 437 * a {@link Class} object reference 438 * @return 439 * a non-modifiable set of supported sizes for {@link ImageFormat#PRIVATE} format, 440 * or {@code null} if the {@code klass} is not a supported output. 441 */ getOutputSizes(@onNull Class<T> klass)442 public @Nullable <T> Set<Size> getOutputSizes(@NonNull Class<T> klass) { 443 if (mSupportsPrivate) { 444 return getUnmodifiableSizeSet(mRecommendedMap.getOutputSizes(klass)); 445 } 446 447 return null; 448 } 449 450 /** 451 * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration} 452 * for the class/size combination (in nanoseconds). 453 * 454 * <p>For more information refer to 455 * {@link StreamConfigurationMap#getOutputMinFrameDuration(Class, Size)}.</p> 456 * 457 * @param klass 458 * a class which has a non-empty array returned by {@link #getOutputSizes(Class)} 459 * @param size an output-compatible size 460 * @return a minimum frame duration {@code >} 0 in nanoseconds, or 461 * 0 if the minimum frame duration is not available. 462 * 463 * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported 464 */ getOutputMinFrameDuration(@onNull final Class<T> klass, @NonNull final Size size)465 public @IntRange(from = 0) <T> long getOutputMinFrameDuration(@NonNull final Class<T> klass, 466 @NonNull final Size size) { 467 if (mSupportsPrivate) { 468 return mRecommendedMap.getOutputMinFrameDuration(klass, size); 469 } 470 471 return 0; 472 } 473 474 /** 475 * Get the stall duration for the class/size combination (in nanoseconds). 476 * 477 * <p>For more information refer to 478 * {@link StreamConfigurationMap#getOutputStallDuration(Class, Size)}. 479 * 480 * @param klass 481 * a class which has a non-empty array returned by {@link #getOutputSizes(Class)}. 482 * @param size an output-compatible size 483 * @return a minimum frame duration {@code >} 0 in nanoseconds, or 0 if the stall duration is 484 * not available. 485 * 486 * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported 487 */ getOutputStallDuration(@onNull final Class<T> klass, @NonNull final Size size)488 public @IntRange(from = 0) <T> long getOutputStallDuration(@NonNull final Class<T> klass, 489 @NonNull final Size size) { 490 if (mSupportsPrivate) { 491 return mRecommendedMap.getOutputStallDuration(klass, size); 492 } 493 494 return 0; 495 } 496 497 /** 498 * Determine whether or not the {@code surface} in its current state is suitable to be included 499 * in a {@link CameraDevice#createCaptureSession capture session} as an output. 500 * 501 * <p>For more information refer to {@link StreamConfigurationMap#isOutputSupportedFor}. 502 * </p> 503 * 504 * @param surface a {@link Surface} object reference 505 * @return {@code true} if this is supported, {@code false} otherwise 506 * 507 * @throws IllegalArgumentException if the Surface endpoint is no longer valid 508 * 509 */ isOutputSupportedFor(@onNull Surface surface)510 public boolean isOutputSupportedFor(@NonNull Surface surface) { 511 return mRecommendedMap.isOutputSupportedFor(surface); 512 } 513 514 } 515