• 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 three elements per entry. The
185      *          first element describes the supported dynamic range profile value. The
186      *          second element contains a bitmap of concurrently supported dynamic range profiles
187      *          within the same capture request. The third element contains a hint about
188      *          extra latency associated with the corresponding dynamic range. Bitmap values of 0
189      *          indicate that there are no constraints.
190      *
191      * @throws IllegalArgumentException
192      *            if the {@code elements} array length is invalid, not divisible by 3 or contains
193      *            invalid element values
194      * @throws NullPointerException
195      *            if {@code elements} is {@code null}
196      *
197      */
DynamicRangeProfiles(@onNull final long[] elements)198     public DynamicRangeProfiles(@NonNull final long[] elements) {
199         if ((elements.length % 3) != 0) {
200             throw new IllegalArgumentException("Dynamic range profile map length " +
201                     elements.length + " is not even!");
202         }
203 
204         for (int i = 0; i < elements.length; i += 3) {
205             checkProfileValue(elements[i]);
206             // STANDARD is not expected to be included
207             if (elements[i] == STANDARD) {
208                 throw new IllegalArgumentException("Dynamic range profile map must not include a"
209                         + " STANDARD profile entry!");
210             }
211             HashSet<Long> profiles = new HashSet<>();
212 
213             if (elements[i+1] != 0) {
214                 for (long profile = STANDARD; profile < PUBLIC_MAX; profile <<= 1) {
215                     if ((elements[i+1] & profile) != 0) {
216                         profiles.add(profile);
217                     }
218                 }
219             }
220 
221             mProfileMap.put(elements[i], profiles);
222             mLookahedLatencyMap.put(elements[i], elements[i+2] != 0L);
223         }
224 
225         // Build the STANDARD constraints depending on the advertised 10-bit limitations
226         HashSet<Long> standardConstraints = new HashSet<>();
227         standardConstraints.add(STANDARD);
228         for(Long profile : mProfileMap.keySet()) {
229             if (mProfileMap.get(profile).isEmpty() || mProfileMap.get(profile).contains(STANDARD)) {
230                 standardConstraints.add(profile);
231             }
232         }
233 
234         mProfileMap.put(STANDARD, standardConstraints);
235         mLookahedLatencyMap.put(STANDARD, false);
236     }
237 
238 
239     /**
240      * @hide
241      */
checkProfileValue(long profile)242     public static void checkProfileValue(long profile) {
243         if (profile == STANDARD || profile == HLG10 || profile == HDR10 || profile == HDR10_PLUS
244                 || profile == DOLBY_VISION_10B_HDR_REF || profile == DOLBY_VISION_10B_HDR_REF_PO
245                 || profile == DOLBY_VISION_10B_HDR_OEM || profile == DOLBY_VISION_10B_HDR_OEM_PO
246                 || profile == DOLBY_VISION_8B_HDR_REF || profile == DOLBY_VISION_8B_HDR_REF_PO
247                 || profile == DOLBY_VISION_8B_HDR_OEM
248                 || profile == DOLBY_VISION_8B_HDR_OEM_PO) {//No-op
249         } else {
250             throw new IllegalArgumentException("Unknown profile " + profile);
251         }
252     }
253 
254     /**
255      * Return a set of supported dynamic range profiles.
256      *
257      * @return non-modifiable set of dynamic range profiles
258      */
getSupportedProfiles()259      public @NonNull Set<Long> getSupportedProfiles() {
260          return Collections.unmodifiableSet(mProfileMap.keySet());
261      }
262 
263     /**
264      * Return a list of supported dynamic range profiles that
265      * can be referenced in a single capture request along with a given
266      * profile.
267      *
268      * <p>For example if assume that a particular 10-bit output capable device
269      * returns ({@link #STANDARD}, {@link #HLG10}, {@link #HDR10}) as result from calling
270      * {@link #getSupportedProfiles()} and {@link #getProfileCaptureRequestConstraints}
271      * returns ({@link #STANDARD}, {@link #HLG10}) when given an argument of {@link #STANDARD}.
272      * This means that the corresponding camera device will only accept and process capture requests
273      * that reference outputs configured using {@link #HDR10} dynamic profile or alternatively
274      * some combination of {@link #STANDARD} and {@link #HLG10}. However trying to
275      * queue capture requests to outputs that reference both {@link #HDR10} and
276      * {@link #STANDARD}/{@link #HLG10} will result in {@link IllegalArgumentException}.</p>
277      *
278      * <p>The list will be empty in case there are no constraints for the given
279      * profile.</p>
280      *
281      * @return non-modifiable set of dynamic range profiles
282      * @throws IllegalArgumentException   If the profile argument is not
283      *                                    within the list returned by
284      *                                    getSupportedProfiles()
285      *
286      * @see OutputConfiguration#setDynamicRangeProfile
287      */
getProfileCaptureRequestConstraints(@rofile long profile)288      public @NonNull Set<Long> getProfileCaptureRequestConstraints(@Profile long profile) {
289          Set<Long> ret = mProfileMap.get(profile);
290          if (ret == null) {
291              throw new IllegalArgumentException("Unsupported profile!");
292          }
293 
294          return Collections.unmodifiableSet(ret);
295      }
296 
297     /**
298      * Check whether a given dynamic range profile is suitable for latency sensitive use cases.
299      *
300      * <p>Due to internal lookahead logic, camera outputs configured with some dynamic range
301      * profiles may experience additional latency greater than 3 buffers. Using camera outputs
302      * with such profiles for latency sensitive use cases such as camera preview is not
303      * recommended. Profiles that have such extra streaming delay are typically utilized for
304      * scenarios such as offscreen video recording.</p>
305      *
306      * @return true if the given profile is not suitable for latency sensitive use cases, false
307      *         otherwise
308      * @throws IllegalArgumentException   If the profile argument is not
309      *                                    within the list returned by
310      *                                    getSupportedProfiles()
311      *
312      * @see OutputConfiguration#setDynamicRangeProfile
313      */
isExtraLatencyPresent(@rofile long profile)314     public boolean isExtraLatencyPresent(@Profile long profile) {
315         Boolean ret = mLookahedLatencyMap.get(profile);
316         if (ret == null) {
317             throw new IllegalArgumentException("Unsupported profile!");
318         }
319 
320         return ret;
321     }
322 }
323