blob: 37150eb556759f392c4996c10ddfa1e1766d04d6 [file] [log] [blame]
/*
* Copyright 2023 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 androidx.camera.camera2.pipe.integration.compat
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.params.DynamicRangeProfiles
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.camera.camera2.pipe.CameraMetadata
import androidx.camera.camera2.pipe.core.checkApi
import androidx.camera.core.DynamicRange
/**
* Helper for accessing features in DynamicRangeProfiles in a backwards compatible fashion.
*/
@RequiresApi(21)
class DynamicRangeProfilesCompat internal constructor(
private val impl: DynamicRangeProfilesCompatImpl
) {
/** The set of supported dynamic ranges. */
val supportedDynamicRanges: Set<DynamicRange>
get() = impl.supportedDynamicRanges
/**
* Returns a set of supported [DynamicRange] that can be referenced in a single
* capture request.
*
* For example if a particular 10-bit output capable device returns (STANDARD,
* HLG10, HDR10) as result from calling [supportedDynamicRanges] and
* [DynamicRangeProfiles.getProfileCaptureRequestConstraints]
* returns (STANDARD, HLG10) when given an argument
* of STANDARD. This means that the corresponding camera device will only accept and process
* capture requests that reference outputs configured using HDR10 dynamic range or
* alternatively some combination of STANDARD and HLG10. However trying to queue capture
* requests to outputs that reference both HDR10 and STANDARD/HLG10 will result in
* IllegalArgumentException.
*
* The list will be empty in case there are no constraints for the given dynamic range.
*
* @param dynamicRange The dynamic range that will be checked for constraints
* @return non-modifiable set of dynamic ranges
* @throws IllegalArgumentException If the dynamic range argument is not within the set
* returned by [supportedDynamicRanges].
*/
fun getDynamicRangeCaptureRequestConstraints(
dynamicRange: DynamicRange
): Set<DynamicRange> {
return impl.getDynamicRangeCaptureRequestConstraints(dynamicRange)
}
/**
* Checks whether a given dynamic range is suitable for latency sensitive use cases.
*
* 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 dynamic ranges for latency sensitive use cases such as camera preview is not
* recommended. Dynamic ranges that have such extra streaming delay are typically utilized for
* scenarios such as offscreen video recording.
*
* @param dynamicRange The dynamic range to check for extra latency
* @return `true` if the given profile is not suitable for latency sensitive use cases,
* `false` otherwise.
* @throws IllegalArgumentException If the dynamic range argument is not within the set
* returned by [supportedDynamicRanges].
*/
fun isExtraLatencyPresent(dynamicRange: DynamicRange): Boolean {
return impl.isExtraLatencyPresent(dynamicRange)
}
/**
* Returns the underlying framework
* [DynamicRangeProfiles].
*
* @return the underlying [DynamicRangeProfiles] or
* `null` if the device doesn't support 10 bit dynamic range.
*/
@RequiresApi(33)
fun toDynamicRangeProfiles(): DynamicRangeProfiles? {
checkApi(
33, "DynamicRangesCompat can only be " +
"converted to DynamicRangeProfiles on API 33 or higher."
)
return impl.unwrap()
}
internal interface DynamicRangeProfilesCompatImpl {
val supportedDynamicRanges: Set<DynamicRange>
fun getDynamicRangeCaptureRequestConstraints(
dynamicRange: DynamicRange
): Set<DynamicRange>
fun isExtraLatencyPresent(dynamicRange: DynamicRange): Boolean
fun unwrap(): DynamicRangeProfiles?
}
companion object {
/**
* Returns a [DynamicRangeProfilesCompat] using the capabilities derived from the provided
* characteristics.
*
* @param cameraMetadata the metaData used to derive dynamic range information.
* @return a [DynamicRangeProfilesCompat] object.
*/
fun fromCameraMetaData(
cameraMetadata: CameraMetadata
): DynamicRangeProfilesCompat {
var rangesCompat: DynamicRangeProfilesCompat? = null
if (Build.VERSION.SDK_INT >= 33) {
rangesCompat = toDynamicRangesCompat(
cameraMetadata[CameraCharacteristics.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES]
)
}
return rangesCompat ?: DynamicRangeProfilesCompatBaseImpl.COMPAT_INSTANCE
}
/**
* Creates an instance from a framework [DynamicRangeProfiles]
* object.
*
* @param dynamicRangeProfiles a [DynamicRangeProfiles].
* @return an equivalent [DynamicRangeProfilesCompat] object.
*/
@RequiresApi(33)
fun toDynamicRangesCompat(
dynamicRangeProfiles: DynamicRangeProfiles?
): DynamicRangeProfilesCompat? {
if (dynamicRangeProfiles == null) {
return null
}
checkApi(
33, "DynamicRangeProfiles can only " +
"be converted to DynamicRangesCompat on API 33 or higher."
)
return DynamicRangeProfilesCompat(
DynamicRangeProfilesCompatApi33Impl(
dynamicRangeProfiles
)
)
}
}
}