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