Android NDK开发详解相机之HDR 视频拍摄

注意:本页介绍的是 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 支持情况。

由于并非所有设备都满足这些前提条件,因此在应用中设置 HDR 视频拍摄功能时,您可以添加一个单独的代码路径。这样,您的应用就可以在不兼容的设备上回退为使用 SDR。此外,您还可以考虑为 SDR 添加界面选项。然后,用户可以根据自己的视频录制需求在 SDR 和 HDR 之间切换。

HDR 拍摄架构

下图显示了 HDR 拍摄架构的主要组成部分。
HDR 拍摄架构图。
在这里插入图片描述

图 2. HDR 拍摄架构图。

当相机设备拍摄 HDR 格式的帧时,Camera2 框架会分配一个缓冲区来存储处理后的相机传感器输出。如果 HDR 配置文件要求,还会附加相应的 HDR 元数据。 然后,Camera2 框架会针对 CaptureRequest 中引用的输出 surface(例如屏幕编码器或视频编码器)将填充的缓冲区加入队列,如图所示。
注意 :相机应用无法通过 Android 13 中的 Camera2 API 或任何媒体 API 访问 HDR 元数据。

检查是否支持 HDR

在您的应用中拍摄 HDR 视频之前,请确定设备是否支持您所需的 HDR 配置。

使用 CameraManager getCameraCharacteristics() 方法获取 CameraCharacteristics 实例,您可以查询其设备的 HDR 功能。

您可按照以下步骤检查设备是否支持 HLG10。HLG10 是设备制造商必须在具有 10 位输出的相机上支持的基准 HDR 标准。

首先,检查设备是否支持 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 提供设备支持的 HDR 配置文件,然后在创建时将其传递给 CameraCaptureSession。请参阅支持的 HDR 配置文件列表。

在以下代码示例中,setupSessionDynamicRangeProfile() 首先检查设备是否搭载的是 Android 13。然后,它会使用设备支持的 HDR 配置文件将 CameraCaptureSession 设置为 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 拍摄和播放操作。此外,设备制造商可以使用 HDR 拍摄架构启用他们选择的任何 HDR 格式。

下表汇总了可用的 HDR 格式及其用于拍摄 HDR 视频的功能。
在这里插入图片描述

资源

如需获取具有 HDR 视频拍摄功能且能正常运行的应用,请参阅 GitHub 上的 Camera2Video 示例。

本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。

最后更新时间 (UTC):2023-10-31。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
更新时间:2015-07-27资费提示:已付费版当前版本:6.7.0软件语言:多语言软件类别:特效相机软件大小:3.88 MB适用固件:2.3.3及更高固件内置广告:没有广告适用平台:Android 软件介绍 Snap Camera(快照相机)是一款基于Nexus 4(Android 4.2)相机的图库和相机应用。Snap Camera的整体界面非常简洁,而且完全使用Android 4.2上的Holo风格。一键拍摄照片和录制视频,没有凌乱的预览界面,仅有两个您真正需要的按钮! 简洁、强大的用户界面: - 触摸可对焦 - 开合两根手指可缩放/变焦 - 滑动可查看照片/视频 - 触摸并按住可使用照片控制器来调整照片设置 照片控制器包括: - 颜色和对比度(如果硬件支持) - 关闭快门声 - 连拍模式 - 自拍定时器 - 全景模式 - 闪光灯模式 - 白平衡 - 曝光 - 网格线 - 快速拍摄模式 - HDR - 其他设置 其他设置菜单包括: - 照片和视频大小 - 取景模式 - 自拍定时器延时 - 连拍模式设置 - 延时拍摄 - 视频对焦方式 - JPEG质量 - 效果 - ISO - 防闪烁 - 取景检测 - 视频比特率 - 音频设置 照片编辑器包括: - 添加颜色效果 - 添加边框 - 修剪、旋转、镜像 - 拉直 - 添加图片效果 - 直方图修改 - 晕影 其他功能: - 您可通过历史记录菜单随时查看和撤销应用的效果 - 触摸分享图标可使用其他应用来分享图片javascript:; - 触摸全景图标可创建全景照片(Android 4.0及以上) - 快速拍摄模式可以预览分辨率快速捕获照片 - 在视频录制期间捕获快照 - 使用音量键来缩放和拍摄照片 - 在光线不足的环境下录制视频时自动打开闪光灯 - 可将界面更改为左手习惯模式 - 使用高级视频设置来录制其他相机不允许的分辨率的视频
Android NDK开发是指利用NDK(Native Development Kit)将C/C++开发的代码编译成so库,然后通过JNI(Java Native Interface)让Java程序调用。在Android开发中,默认使用的是Android SDK进行Java语言的开发,而对于一些需要使用C/C++的高性能计算、底层操作或跨平台需求的场景,可以使用NDK进行开发。 在Android Studio中进行NDK开发相对于Eclipse来说更加方便,特别是在Android Studio 3.0及以上版本中,配置更加简化,并引入了CMake等工具,使得开发更加便捷。首先要进行NDK开发,需要配置环境,包括导入NDK、LLDB和CMake等工具。可以通过打开Android Studio的SDK Manager,选择SDK Tools,在其中选中相应的工具进行导入。 在项目的build.gradle文件中,可以配置一些NDK相关的参数,例如编译版本、ABI过滤器等。其中,可以通过externalNativeBuild配置CMake的相关设置,包括CMakeLists.txt文件的路径和版本号。此外,在sourceSets.main中还可以设置jniLibs.srcDirs,指定so库的位置。 在进行NDK开发时,可以在jni文件夹中编写C/C++代码,并通过JNI调用相关的函数。通过JNI接口,可以实现Java与C/C++之间的相互调用,从而实现跨语言的开发。 综上所述,Android NDK开发是指利用NDK将C/C++开发的代码编译成so库,并通过JNI实现与Java的相互调用。在Android Studio中进行NDK开发相对方便,可以通过配置环境和相应的参数来进行开发。<span class="em">1</span><span class="em">2</span><span class="em">3</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五一编程

程序之路有我与你同行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值