323 lines
14 KiB
Java
323 lines
14 KiB
Java
/*
|
|
* Copyright (C) 2021 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.hardware.camera2.params;
|
|
|
|
import android.annotation.LongDef;
|
|
import android.annotation.NonNull;
|
|
|
|
import android.hardware.camera2.CameraMetadata;
|
|
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* Immutable class with information about supported 10-bit dynamic range profiles.
|
|
*
|
|
* <p>An instance of this class can be queried by retrieving the value of
|
|
* {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES}.
|
|
* </p>
|
|
*
|
|
* <p>All camera devices supporting the
|
|
* {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT}
|
|
* capability must advertise the supported 10-bit dynamic range profiles in
|
|
* {@link #getSupportedProfiles}</p>
|
|
*
|
|
* <p>Some devices may not be able to support 8-bit and/or 10-bit output with different dynamic
|
|
* range profiles within the same capture request. Such device specific constraints can be queried
|
|
* by calling {@link #getProfileCaptureRequestConstraints}. Do note that unsupported
|
|
* combinations will result in {@link IllegalArgumentException} when trying to submit a capture
|
|
* request. Capture requests that only reference outputs configured using the same dynamic range
|
|
* profile value will never fail due to such constraints.</p>
|
|
*
|
|
* @see OutputConfiguration#setDynamicRangeProfile
|
|
*/
|
|
public final class DynamicRangeProfiles {
|
|
/**
|
|
* This the default 8-bit standard profile that will be used in case where camera clients do not
|
|
* explicitly configure a supported dynamic range profile by calling
|
|
* {@link OutputConfiguration#setDynamicRangeProfile}.
|
|
*/
|
|
public static final long STANDARD =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
|
|
|
|
/**
|
|
* 10-bit pixel samples encoded using the Hybrid log-gamma transfer function
|
|
*
|
|
* <p>All 10-bit output capable devices are required to support this profile.</p>
|
|
*/
|
|
public static final long HLG10 =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10;
|
|
|
|
/**
|
|
* 10-bit pixel samples encoded using the SMPTE ST 2084 transfer function.
|
|
*
|
|
* <p>This profile utilizes internal static metadata to increase the quality
|
|
* of the capture.</p>
|
|
*/
|
|
public static final long HDR10 =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10;
|
|
|
|
/**
|
|
* 10-bit pixel samples encoded using the SMPTE ST 2084 transfer function.
|
|
*
|
|
* <p>In contrast to HDR10, this profile uses internal per-frame metadata
|
|
* to further enhance the quality of the capture.</p>
|
|
*/
|
|
public static final long HDR10_PLUS =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS;
|
|
|
|
/**
|
|
* <p>This is a camera mode for Dolby Vision capture optimized for a more scene
|
|
* accurate capture. This would typically differ from what a specific device
|
|
* might want to tune for a consumer optimized Dolby Vision general capture.</p>
|
|
*/
|
|
public static final long DOLBY_VISION_10B_HDR_REF =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF;
|
|
|
|
/**
|
|
* <p>This is the power optimized mode for 10-bit Dolby Vision HDR Reference Mode.</p>
|
|
*/
|
|
public static final long DOLBY_VISION_10B_HDR_REF_PO =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO;
|
|
|
|
/**
|
|
* <p>This is the camera mode for the default Dolby Vision capture mode for the
|
|
* specific device. This would be tuned by each specific device for consumer
|
|
* pleasing results that resonate with their particular audience. We expect
|
|
* that each specific device would have a different look for their default
|
|
* Dolby Vision capture.</p>
|
|
*/
|
|
public static final long DOLBY_VISION_10B_HDR_OEM =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM;
|
|
|
|
/**
|
|
* <p>This is the power optimized mode for 10-bit Dolby Vision HDR device specific capture
|
|
* Mode.</p>
|
|
*/
|
|
public static final long DOLBY_VISION_10B_HDR_OEM_PO =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO;
|
|
|
|
/**
|
|
* <p>This is the 8-bit version of the Dolby Vision reference capture mode optimized
|
|
* for scene accuracy.</p>
|
|
*/
|
|
public static final long DOLBY_VISION_8B_HDR_REF =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF;
|
|
|
|
/**
|
|
* <p>This is the power optimized mode for 8-bit Dolby Vision HDR Reference Mode.</p>
|
|
*/
|
|
public static final long DOLBY_VISION_8B_HDR_REF_PO =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO;
|
|
|
|
/**
|
|
* <p>This is the 8-bit version of device specific tuned and optimized Dolby Vision
|
|
* capture mode.</p>
|
|
*/
|
|
public static final long DOLBY_VISION_8B_HDR_OEM =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM;
|
|
|
|
/**
|
|
* <p>This is the power optimized mode for 8-bit Dolby Vision HDR device specific
|
|
* capture Mode.</p>
|
|
*/
|
|
public static final long DOLBY_VISION_8B_HDR_OEM_PO =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO;
|
|
|
|
/*
|
|
* @hide
|
|
*/
|
|
public static final long PUBLIC_MAX =
|
|
CameraMetadata.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_MAX;
|
|
|
|
/** @hide */
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
@LongDef(prefix = {"PROFILE_"}, value =
|
|
{STANDARD,
|
|
HLG10,
|
|
HDR10,
|
|
HDR10_PLUS,
|
|
DOLBY_VISION_10B_HDR_REF,
|
|
DOLBY_VISION_10B_HDR_REF_PO,
|
|
DOLBY_VISION_10B_HDR_OEM,
|
|
DOLBY_VISION_10B_HDR_OEM_PO,
|
|
DOLBY_VISION_8B_HDR_REF,
|
|
DOLBY_VISION_8B_HDR_REF_PO,
|
|
DOLBY_VISION_8B_HDR_OEM,
|
|
DOLBY_VISION_8B_HDR_OEM_PO})
|
|
public @interface Profile {
|
|
}
|
|
|
|
private final HashMap<Long, Set<Long>> mProfileMap = new HashMap<>();
|
|
private final HashMap<Long, Boolean> mLookahedLatencyMap = new HashMap<>();
|
|
|
|
/**
|
|
* Create a new immutable DynamicRangeProfiles instance.
|
|
*
|
|
* <p>This constructor takes over the array; do not write to the array afterwards.</p>
|
|
*
|
|
* <p>Do note that the constructor is available for testing purposes only!
|
|
* Camera clients must always retrieve the value of
|
|
* {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES}.
|
|
* for a given camera id in order to retrieve the device capabilities.</p>
|
|
*
|
|
* @param elements
|
|
* An array of elements describing the map. It contains three elements per entry. The
|
|
* first element describes the supported dynamic range profile value. The
|
|
* second element contains a bitmap of concurrently supported dynamic range profiles
|
|
* within the same capture request. The third element contains a hint about
|
|
* extra latency associated with the corresponding dynamic range. Bitmap values of 0
|
|
* indicate that there are no constraints.
|
|
*
|
|
* @throws IllegalArgumentException
|
|
* if the {@code elements} array length is invalid, not divisible by 3 or contains
|
|
* invalid element values
|
|
* @throws NullPointerException
|
|
* if {@code elements} is {@code null}
|
|
*
|
|
*/
|
|
public DynamicRangeProfiles(@NonNull final long[] elements) {
|
|
if ((elements.length % 3) != 0) {
|
|
throw new IllegalArgumentException("Dynamic range profile map length " +
|
|
elements.length + " is not even!");
|
|
}
|
|
|
|
for (int i = 0; i < elements.length; i += 3) {
|
|
checkProfileValue(elements[i]);
|
|
// STANDARD is not expected to be included
|
|
if (elements[i] == STANDARD) {
|
|
throw new IllegalArgumentException("Dynamic range profile map must not include a"
|
|
+ " STANDARD profile entry!");
|
|
}
|
|
HashSet<Long> profiles = new HashSet<>();
|
|
|
|
if (elements[i+1] != 0) {
|
|
for (long profile = STANDARD; profile < PUBLIC_MAX; profile <<= 1) {
|
|
if ((elements[i+1] & profile) != 0) {
|
|
profiles.add(profile);
|
|
}
|
|
}
|
|
}
|
|
|
|
mProfileMap.put(elements[i], profiles);
|
|
mLookahedLatencyMap.put(elements[i], elements[i+2] != 0L);
|
|
}
|
|
|
|
// Build the STANDARD constraints depending on the advertised 10-bit limitations
|
|
HashSet<Long> standardConstraints = new HashSet<>();
|
|
standardConstraints.add(STANDARD);
|
|
for(Long profile : mProfileMap.keySet()) {
|
|
if (mProfileMap.get(profile).isEmpty() || mProfileMap.get(profile).contains(STANDARD)) {
|
|
standardConstraints.add(profile);
|
|
}
|
|
}
|
|
|
|
mProfileMap.put(STANDARD, standardConstraints);
|
|
mLookahedLatencyMap.put(STANDARD, false);
|
|
}
|
|
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
public static void checkProfileValue(long profile) {
|
|
if (profile == STANDARD || profile == HLG10 || profile == HDR10 || profile == HDR10_PLUS
|
|
|| profile == DOLBY_VISION_10B_HDR_REF || profile == DOLBY_VISION_10B_HDR_REF_PO
|
|
|| profile == DOLBY_VISION_10B_HDR_OEM || profile == DOLBY_VISION_10B_HDR_OEM_PO
|
|
|| profile == DOLBY_VISION_8B_HDR_REF || profile == DOLBY_VISION_8B_HDR_REF_PO
|
|
|| profile == DOLBY_VISION_8B_HDR_OEM
|
|
|| profile == DOLBY_VISION_8B_HDR_OEM_PO) {//No-op
|
|
} else {
|
|
throw new IllegalArgumentException("Unknown profile " + profile);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return a set of supported dynamic range profiles.
|
|
*
|
|
* @return non-modifiable set of dynamic range profiles
|
|
*/
|
|
public @NonNull Set<Long> getSupportedProfiles() {
|
|
return Collections.unmodifiableSet(mProfileMap.keySet());
|
|
}
|
|
|
|
/**
|
|
* Return a list of supported dynamic range profiles that
|
|
* can be referenced in a single capture request along with a given
|
|
* profile.
|
|
*
|
|
* <p>For example if assume that a particular 10-bit output capable device
|
|
* returns ({@link #STANDARD}, {@link #HLG10}, {@link #HDR10}) as result from calling
|
|
* {@link #getSupportedProfiles()} and {@link #getProfileCaptureRequestConstraints}
|
|
* returns ({@link #STANDARD}, {@link #HLG10}) when given an argument of {@link #STANDARD}.
|
|
* This means that the corresponding camera device will only accept and process capture requests
|
|
* that reference outputs configured using {@link #HDR10} dynamic profile or alternatively
|
|
* some combination of {@link #STANDARD} and {@link #HLG10}. However trying to
|
|
* queue capture requests to outputs that reference both {@link #HDR10} and
|
|
* {@link #STANDARD}/{@link #HLG10} will result in {@link IllegalArgumentException}.</p>
|
|
*
|
|
* <p>The list will be empty in case there are no constraints for the given
|
|
* profile.</p>
|
|
*
|
|
* @return non-modifiable set of dynamic range profiles
|
|
* @throws IllegalArgumentException If the profile argument is not
|
|
* within the list returned by
|
|
* getSupportedProfiles()
|
|
*
|
|
* @see OutputConfiguration#setDynamicRangeProfile
|
|
*/
|
|
public @NonNull Set<Long> getProfileCaptureRequestConstraints(@Profile long profile) {
|
|
Set<Long> ret = mProfileMap.get(profile);
|
|
if (ret == null) {
|
|
throw new IllegalArgumentException("Unsupported profile!");
|
|
}
|
|
|
|
return Collections.unmodifiableSet(ret);
|
|
}
|
|
|
|
/**
|
|
* Check whether a given dynamic range profile is suitable for latency sensitive use cases.
|
|
*
|
|
* <p>Due to internal lookahead logic, camera outputs configured with some dynamic range
|
|
* profiles may experience additional latency greater than 3 buffers. Using camera outputs
|
|
* with such profiles for latency sensitive use cases such as camera preview is not
|
|
* recommended. Profiles that have such extra streaming delay are typically utilized for
|
|
* scenarios such as offscreen video recording.</p>
|
|
*
|
|
* @return true if the given profile is not suitable for latency sensitive use cases, false
|
|
* otherwise
|
|
* @throws IllegalArgumentException If the profile argument is not
|
|
* within the list returned by
|
|
* getSupportedProfiles()
|
|
*
|
|
* @see OutputConfiguration#setDynamicRangeProfile
|
|
*/
|
|
public boolean isExtraLatencyPresent(@Profile long profile) {
|
|
Boolean ret = mLookahedLatencyMap.get(profile);
|
|
if (ret == null) {
|
|
throw new IllegalArgumentException("Unsupported profile!");
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
}
|