注意:本页介绍的是 Camera2 软件包。除非您的应用需要 Camera2 中的特定低级功能,否则我们建议您使用 CameraX。CameraX 和 Camera2 都支持 Android 5.0(API 级别 21)及更高版本。
Camera2 API 支持
高动态范围 (HDR) 视频拍摄,可让您预览并
使用相机录制 HDR 视频内容。与标准动态相比
范围 (SDR)、HDR 提供的色彩范围更广
亮度分量的范围(从当前的 100 cd/m2 到 1000 cd/m2)。
这样生成的视频质量更接近真实情况,
更丰富的色彩、更明亮的高光和更深的阴影。
看看 HDR 视频如何以更鲜艳的细节展现日落美景。
图 1.SDR(顶部)与 HDR(底部)视频质量的比较。
。
注意: 从 Android 13 开始,具有 10 位相机输出的相机设备
必须支持 HLG10 格式进行 HDR 拍摄和播放。
如需了解详情,请参阅 HDR 格式。
设备前提条件
并非所有 Android 设备都支持 HDR 视频拍摄。
在应用中拍摄 HDR 视频之前,请先确定您的设备是否符合
以下前提条件:
以 Android 13(API 级别 33)为目标平台。
具有支持 10 位或更高级别的相机传感器。如需详细了解 HDR,
有关是否支持,请参阅检查 HDR 支持情况。
由于并非所有设备都满足前提条件,因此您可以单独添加代码
路径。
这样一来,您的应用便可以在不兼容的设备上回退到 SDR。
此外,请考虑为 SDR 添加界面选项。然后,用户可以
SDR 和 HDR 之间的联系,以满足他们的视频录制需求。
HDR 拍摄架构
下图显示了 HDR 拍摄架构的主要组件。
图 2. HDR 拍摄架构图。
当相机设备以 HDR 格式拍摄帧时,Camera2 框架会分配
用于存储处理的相机传感器输出的缓冲区。
如果 HDR 配置文件需要,它还会附加相应的 HDR 元数据。
然后,Camera2 框架会将已填充的缓冲区加入输出 Surface 的队列
CaptureRequest 中引用,例如 display 或
如图所示。
注意: 相机应用无法通过 Camera2 API 或任何
媒体 API
。
检查是否支持 HDR
在应用中拍摄 HDR 视频之前,请先确定设备是否支持
设置所需的 HDR 配置文件
使用 CameraManager getCameraCharacteristics() 方法获取
CameraCharacteristics
您可以查询设备的 HDR 功能。
以下步骤用于检查设备是否支持 HLG10。
HLG10 是设备制造商必须支持的基准 HDR 标准
在具有 10 位输出的相机上。
首先,检查设备是否支持 10 位配置文件(HLG10 的位深):
Kotlin
private fun isTenBitProfileSupported(cameraId: String): Boolean {
val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId)
val availableCapabilities = cameraCharacteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
for (capability in availableCapabilities!!) {
if (capability == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) {
return true
}
}
return false
}
接下来,检查设备是否支持 HLG10(或其他受支持的配置文件):
Kotlin
@RequiresApi(api = 33)
private fun isHLGSupported(cameraId: String): Boolean {
if (isTenBitProfileSupported(cameraId)) {
Val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId)
val availableProfiles = cameraCharacteristics
.get(CameraCharacteristics.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES)!!
.getSupportedProfiles()
// Checks for the desired profile, in this case HLG10
return availableProfiles.contains(DynamicRangeProfiles.HLG10)
}
return false;
}
如果设备支持 HDR,isHLGSupported() 始终返回 true。
有关详情,请参阅
CameraCharacteristics
参考文档。
设置 HDR 拍摄
确保您的设备支持 HDR 后,设置您的应用以拍摄
来自相机的原始 HDR 视频串流。
使用 setDynamicRangeProfile() 提供数据流的 OutputConfiguration
然后向该配置文件传递
发送至CameraCaptureSession
。
请参阅支持的 HDR 配置文件列表。
在以下代码示例中,setupSessionDynamicRangeProfile() 首先检查
确认设备搭载的是 Android 13。
然后,它会使用设备支持的 CameraCaptureSession 设置
HDR 配置文件,如 OutputConfiguration:
Kotlin
/**
* Creates a [CameraCaptureSession] with a dynamic range profile.
*/
private fun setupSessionWithDynamicRangeProfile(
dynamicRange: Long,
device: CameraDevice,
targets: List,
handler: Handler? = null,
stateCallback: CameraCaptureSession.StateCallback
): Boolean {
if (android.os.Build.VERSION.SDK_INT >=
android.os.Build.VERSION_CODES.TIRAMISU) {
val outputConfigs = mutableListOf()
for (target in targets) {
val outputConfig = OutputConfiguration(target)
//sets the dynamic range profile, for example DynamicRangeProfiles.HLG10
outputConfig.setDynamicRangeProfile(dynamicRange)
outputConfigs.add(outputConfig)
}
device.createCaptureSessionByOutputConfigurations(
outputConfigs, stateCallback, handler)
return true
} else {
device.createCaptureSession(targets, stateCallback, handler)
return false
}
}
}
当相机应用初始化相机时,它会发送一个
正在重复
CaptureRequest
预览录制内容:
Kotlin
session.setRepeatingRequest(previewRequest, null, cameraHandler)
此外,要开始录制视频,请执行以下操作:
Kotlin
// Start recording repeating requests, which stops the ongoing preview
// repeating requests without having to explicitly call
// `session.stopRepeating`
session.setRepeatingRequest(recordRequest,
object : CameraCaptureSession.CaptureCallback() {
override fun onCaptureCompleted(session: CameraCaptureSession,
request: CaptureRequest, result: TotalCaptureResult) {
if (currentlyRecording) {
encoder.frameAvailable()
}
}
}, cameraHandler)
对 HDR 摄像头视频流进行编码
如需对 HDR 相机数据流进行编码并将文件写入磁盘,请执行以下操作:
请使用 MediaCodec。
首先,获取 OutputSurface,
映射到存储原始视频数据的缓冲区。
对于MediaCodec,
请使用 createInputSurface()。
要初始化 MediaCodec,应用必须创建一个
MediaFormat,其中包含指定的
编解码器配置文件、颜色空间、颜色范围和转换函数:
Kotlin
val mimeType = when {
dynamicRange == DynamicRangeProfiles.STANDARD -> MediaFormat.MIMETYPE_VIDEO_AVC
dynamicRange < DynamicRangeProfiles.PUBLIC_MAX ->
MediaFormat.MIMETYPE_VIDEO_HEVC
else -> throw IllegalArgumentException("Unknown dynamic range format")
}
val codecProfile = when {
dynamicRange == DynamicRangeProfiles.HLG10 ->
MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10
dynamicRange == DynamicRangeProfiles.HDR10 ->
MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10
dynamicRange == DynamicRangeProfiles.HDR10_PLUS ->
MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10Plus
else -> -1
}
// Failing to correctly set color transfer causes quality issues
// for example, washout and color clipping
val transferFunction = when (codecProfile) {
MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10 ->
MediaFormat.COLOR_TRANSFER_HLG
MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10 ->
MediaFormat.COLOR_TRANSFER_ST2084
MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10Plus ->
MediaFormat.COLOR_TRANSFER_ST2084
else -> MediaFormat.COLOR_TRANSFER_SDR_VIDEO
}
val format = MediaFormat.createVideoFormat(mimeType, width, height)
// Set some properties. Failing to specify some of these can cause the MediaCodec
// configure() call to throw an exception.
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate)
format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate)
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL)
if (codecProfile != -1) {
format.setInteger(MediaFormat.KEY_PROFILE, codecProfile)
format.setInteger(MediaFormat.KEY_COLOR_STANDARD,
MediaFormat.COLOR_STANDARD_BT2020)
format.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_LIMITED)
format.setInteger(MediaFormat.KEY_COLOR_TRANSFER, transferFunction)
format.setFeatureEnabled(MediaCodecInfo.CodecCapabilities.FEATURE_HdrEditing,
true)
}
mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
有关实现的详情,请参见 Camera2Video 示例应用的
EncoderWrapper.kt。
HDR 格式
从 Android 13 开始,具有 10 位输出功能的相机设备
必须支持 HLG10 进行 HDR 拍摄,并且
playback(播放)。
此外,设备制造商可以启用他们选择的任何 HDR 格式
使用 HDR 拍摄架构。
下表总结了可用的 HDR 格式及其功能
。
格式
传递函数 (TF)
元数据
编解码器
位元深度
HLG10
HLG
否
HEVC
10 位
HDR10
PQ
静态
HEVC
10 位
HDR10+
PQ
动态
HEVC
10 位
杜比视界 8.4
HLG
动态
HEVC
10 位
资源
如需了解具有 HDR 视频拍摄功能且能正常运行的应用,请参阅
Camera2Video 示例
。