• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.LongDef;
20 import android.annotation.NonNull;
21 
22 import android.hardware.camera2.CameraMetadata;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.Set;
31 
32 /**
33  * Immutable class with information about supported 10-bit dynamic range profiles.
34  *
35  * <p>An instance of this class can be queried by retrieving the value of
36  * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES}.
37  * </p>
38  *
39  * <p>All camera devices supporting the
40  * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT}
41  * capability must advertise the supported 10-bit dynamic range profiles in
42  * {@link #getSupportedProfiles}</p>
43  *
44  * <p>Some devices may not be able to support 8-bit and/or 10-bit output with different dynamic
45  * range profiles within the same capture request. Such device specific constraints can be queried
46  * by calling {@link #getProfileCaptureRequestConstraints}. Do note that unsupported
47  * combinations will result in {@link IllegalArgumentException} when trying to submit a capture
48  * request. Capture requests that only reference outputs configured using the same dynamic range
49  * profile value will never fail due to such constraints.</p>
50  *
51  * @see OutputConfiguration#setDynamicRangeProfile
52  */
53 public final class DynamicRangeProfiles {
54     /**
55      * This the default 8-bit standard profile that will be used in case where camera clients do not
56      * explicitly configure a supported dynamic range profile by calling
57      * {@link OutputConfiguration#setDynamicRangeProfile}.
58      */
59     public static final long STANDARD =
60             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
61 
62     /**
63      * 10-bit pixel samples encoded using the Hybrid log-gamma transfer function
64      *
65      * <p>All 10-bit output capable devices are required to support this profile.</p>
66      */
67     public static final long HLG10  =
68             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10;
69 
70     /**
71      * 10-bit pixel samples encoded using the SMPTE ST 2084 transfer function.
72      *
73      * <p>This profile utilizes internal static metadata to increase the quality
74      * of the capture.</p>
75      */
76     public static final long HDR10  =
77             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10;
78 
79     /**
80      * 10-bit pixel samples encoded using the SMPTE ST 2084 transfer function.
81      *
82      * <p>In contrast to HDR10, this profile uses internal per-frame metadata
83      * to further enhance the quality of the capture.</p>
84      */
85     public static final long HDR10_PLUS =
86             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS;
87 
88     /**
89      * <p>This is a camera mode for Dolby Vision capture optimized for a more scene
90      * accurate capture. This would typically differ from what a specific device
91      * might want to tune for a consumer optimized Dolby Vision general capture.</p>
92      */
93     public static final long DOLBY_VISION_10B_HDR_REF =
94             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF;
95 
96     /**
97      * <p>This is the power optimized mode for 10-bit Dolby Vision HDR Reference Mode.</p>
98      */
99     public static final long DOLBY_VISION_10B_HDR_REF_PO =
100             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO;
101 
102     /**
103      * <p>This is the camera mode for the default Dolby Vision capture mode for the
104      * specific device. This would be tuned by each specific device for consumer
105      * pleasing results that resonate with their particular audience. We expect
106      * that each specific device would have a different look for their default
107      * Dolby Vision capture.</p>
108      */
109     public static final long DOLBY_VISION_10B_HDR_OEM =
110             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM;
111 
112     /**
113      * <p>This is the power optimized mode for 10-bit Dolby Vision HDR device specific capture
114      * Mode.</p>
115      */
116     public static final long DOLBY_VISION_10B_HDR_OEM_PO =
117             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO;
118 
119     /**
120      * <p>This is the 8-bit version of the Dolby Vision reference capture mode optimized
121      * for scene accuracy.</p>
122      */
123     public static final long DOLBY_VISION_8B_HDR_REF =
124             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF;
125 
126     /**
127      * <p>This is the power optimized mode for 8-bit Dolby Vision HDR Reference Mode.</p>
128      */
129     public static final long DOLBY_VISION_8B_HDR_REF_PO =
130             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO;
131 
132     /**
133      * <p>This is the 8-bit version of device specific tuned and optimized Dolby Vision
134      * capture mode.</p>
135      */
136     public static final long DOLBY_VISION_8B_HDR_OEM =
137             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM;
138 
139     /**
140      * <p>This is the power optimized mode for 8-bit Dolby Vision HDR device specific
141      * capture Mode.</p>
142      */
143     public static final long DOLBY_VISION_8B_HDR_OEM_PO =
144             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO;
145 
146     /*
147      * @hide
148      */
149     public static final long PUBLIC_MAX =
150             CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_MAX;
151 
152      /** @hide */
153     @Retention(RetentionPolicy.SOURCE)
154     @LongDef(prefix = {"PROFILE_"}, value =
155             {STANDARD,
156              HLG10,
157              HDR10,
158              HDR10_PLUS,
159              DOLBY_VISION_10B_HDR_REF,
160              DOLBY_VISION_10B_HDR_REF_PO,
161              DOLBY_VISION_10B_HDR_OEM,
162              DOLBY_VISION_10B_HDR_OEM_PO,
163              DOLBY_VISION_8B_HDR_REF,
164              DOLBY_VISION_8B_HDR_REF_PO,
165              DOLBY_VISION_8B_HDR_OEM,
166              DOLBY_VISION_8B_HDR_OEM_PO})
167     public @interface Profile {
168     }
169 
170     private final HashMap<Long, Set<Long>> mProfileMap = new HashMap<>();
171     private final HashMap<Long, Boolean> mLookahedLatencyMap = new HashMap<>();
172 
173     /**
174      * Create a new immutable DynamicRangeProfiles instance.
175      *
176      * <p>This constructor takes over the array; do not write to the array afterwards.</p>
177      *
178      * <p>Do note that the constructor is available for testing purposes only!
179      * Camera clients must always retrieve the value of
180      * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES}.
181      * for a given camera id in order to retrieve the device capabilities.</p>
182      *
183      * @param elements
184      *          An array of elements describing the map. It contains two elements per entry which
185      *          describe the supported dynamic range profile value in the first element and in the
186      *          second element a bitmap of concurrently supported dynamic range profiles within the
187      *          same capture request. Bitmap values of 0 indicate that there are no constraints.
188      *
189      * @throws IllegalArgumentException
190      *            if the {@code elements} array length is invalid, not divisible by 2 or contains
191      *            invalid element values
192      * @throws NullPointerException
193      *            if {@code elements} is {@code null}
194      *
195      */
DynamicRangeProfiles(@onNull final long[] elements)196     public DynamicRangeProfiles(@NonNull final long[] elements) {
197         if ((elements.length % 3) != 0) {
198             throw new IllegalArgumentException("Dynamic range profile map length " +
199                     elements.length + " is not even!");
200         }
201 
202         for (int i = 0; i < elements.length; i += 3) {
203             checkProfileValue(elements[i]);
204             // STANDARD is not expected to be included
205             if (elements[i] == STANDARD) {
206                 throw new IllegalArgumentException("Dynamic range profile map must not include a"
207                         + " STANDARD profile entry!");
208             }
209             HashSet<Long> profiles = new HashSet<>();
210 
211             if (elements[i+1] != 0) {
212                 for (long profile = STANDARD; profile < PUBLIC_MAX; profile <<= 1) {
213                     if ((elements[i+1] & profile) != 0) {
214                         profiles.add(profile);
215                     }
216                 }
217             }
218 
219             mProfileMap.put(elements[i], profiles);
220             mLookahedLatencyMap.put(elements[i], elements[i+2] != 0L);
221         }
222 
223         // Build the STANDARD constraints depending on the advertised 10-bit limitations
224         HashSet<Long> standardConstraints = new HashSet<>();
225         standardConstraints.add(STANDARD);
226         for(Long profile : mProfileMap.keySet()) {
227             if (mProfileMap.get(profile).isEmpty() || mProfileMap.get(profile).contains(STANDARD)) {
228                 standardConstraints.add(profile);
229             }
230         }
231 
232         mProfileMap.put(STANDARD, standardConstraints);
233         mLookahedLatencyMap.put(STANDARD, false);
234     }
235 
236 
237     /**
238      * @hide
239      */
checkProfileValue(long profile)240     public static void checkProfileValue(long profile) {
241         if (profile == STANDARD || profile == HLG10 || profile == HDR10 || profile == HDR10_PLUS
242                 || profile == DOLBY_VISION_10B_HDR_REF || profile == DOLBY_VISION_10B_HDR_REF_PO
243                 || profile == DOLBY_VISION_10B_HDR_OEM || profile == DOLBY_VISION_10B_HDR_OEM_PO
244                 || profile == DOLBY_VISION_8B_HDR_REF || profile == DOLBY_VISION_8B_HDR_REF_PO
245                 || profile == DOLBY_VISION_8B_HDR_OEM
246                 || profile == DOLBY_VISION_8B_HDR_OEM_PO) {//No-op
247         } else {
248             throw new IllegalArgumentException("Unknown profile " + profile);
249         }
250     }
251 
252     /**
253      * Return a set of supported dynamic range profiles.
254      *
255      * @return non-modifiable set of dynamic range profiles
256      */
getSupportedProfiles()257      public @NonNull Set<Long> getSupportedProfiles() {
258          return Collections.unmodifiableSet(mProfileMap.keySet());
259      }
260 
261     /**
262      * Return a list of supported dynamic range profiles that
263      * can be referenced in a single capture request along with a given
264      * profile.
265      *
266      * <p>For example if assume that a particular 10-bit output capable device
267      * returns ({@link #STANDARD}, {@link #HLG10}, {@link #HDR10}) as result from calling
268      * {@link #getSupportedProfiles()} and {@link #getProfileCaptureRequestConstraints}
269      * returns ({@link #STANDARD}, {@link #HLG10}) when given an argument of {@link #STANDARD}.
270      * This means that the corresponding camera device will only accept and process capture requests
271      * that reference outputs configured using {@link #HDR10} dynamic profile or alternatively
272      * some combination of {@link #STANDARD} and {@link #HLG10}. However trying to
273      * queue capture requests to outputs that reference both {@link #HDR10} and
274      * {@link #STANDARD}/{@link #HLG10} will result in {@link IllegalArgumentException}.</p>
275      *
276      * <p>The list will be empty in case there are no constraints for the given
277      * profile.</p>
278      *
279      * @return non-modifiable set of dynamic range profiles
280      * @throws IllegalArgumentException   If the profile argument is not
281      *                                    within the list returned by
282      *                                    getSupportedProfiles()
283      *
284      * @see OutputConfiguration#setDynamicRangeProfile
285      */
getProfileCaptureRequestConstraints(@rofile long profile)286      public @NonNull Set<Long> getProfileCaptureRequestConstraints(@Profile long profile) {
287          Set<Long> ret = mProfileMap.get(profile);
288          if (ret == null) {
289              throw new IllegalArgumentException("Unsupported profile!");
290          }
291 
292          return Collections.unmodifiableSet(ret);
293      }
294 
295     /**
296      * Check whether a given dynamic range profile is suitable for latency sensitive use cases.
297      *
298      * <p>Due to internal lookahead logic, camera outputs configured with some dynamic range
299      * profiles may experience additional latency greater than 3 buffers. Using camera outputs
300      * with such profiles for latency sensitive use cases such as camera preview is not
301      * recommended. Profiles that have such extra streaming delay are typically utilized for
302      * scenarios such as offscreen video recording.</p>
303      *
304      * @return true if the given profile is not suitable for latency sensitive use cases, false
305      *         otherwise
306      * @throws IllegalArgumentException   If the profile argument is not
307      *                                    within the list returned by
308      *                                    getSupportedProfiles()
309      *
310      * @see OutputConfiguration#setDynamicRangeProfile
311      */
isExtraLatencyPresent(@rofile long profile)312     public boolean isExtraLatencyPresent(@Profile long profile) {
313         Boolean ret = mLookahedLatencyMap.get(profile);
314         if (ret == null) {
315             throw new IllegalArgumentException("Unsupported profile!");
316         }
317 
318         return ret;
319     }
320 }
321