• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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