HDR 影片擷取

注意:本頁面所述是指 Camera2 套件。除非應用程式需要 Camera2 的特定低階功能,否則建議使用 CameraX。CameraX 和 Camera2 均支援 Android 5.0 (API 級別 21) 以上版本。

Camera2 API 支援 高動態範圍 (HDR) 影片擷取功能,可讓您預覽 使用相機錄製 HDR 影片內容。相較於標準動態 範圍 (SDR),HDR 能提供更廣泛的色彩,並增加動態 亮度元件的範圍 (從目前的 100 cd/m2 到 cd/m2 的 1000s)。 這麼做可以讓影片畫質更貼近現實 色彩更豐富、高亮度和較暗的陰影。

看 HDR 影片如何捕捉夕陽畫面,細節也更鮮豔。

圖 1.比較 SDR (頂端) 與 HDR (底部) 影片的畫質。
,瞭解如何調查及移除這項存取權。

裝置必要條件

並非所有 Android 裝置都支援 HDR 錄影功能。 在應用程式中拍攝 HDR 影片前,請先確認裝置是否符合 下列先決條件:

  • 以 Android 13 (API 級別 33) 為目標。
  • 配備 10 位元以上相機感應器。進一步瞭解 HDR 支援請參閱「檢查 HDR 支援情形」。

由於並非所有裝置都符合先決條件,因此您可以另外新增程式碼 在應用程式中設定 HDR 影片擷取路徑 這麼做可讓應用程式在不相容裝置上改回使用 SDR 模式。 此外,建議您為 SDR 新增 UI 選項。接著,使用者可以切換 能滿足他們的錄影需求

HDR 拍攝架構

下圖顯示 HDR 拍攝架構的主要元件。

HDR 拍攝架構圖。
圖 2 HDR 拍攝架構圖。

當相機裝置以 HDR 模式擷取畫面時,Camera2 架構會進行配置 儲存處理過的相機感應器輸出內容的緩衝區。 如果 HDR 設定檔有需要,還可附加個別的 HDR 中繼資料。 接著 Camera2 架構會將填入的緩衝區排入佇列,供輸出介面使用 CaptureRequest 中參照的媒體檔案,例如「多媒體」或 與這個圖表所示

確認 HDR 支援情形

在應用程式中擷取 HDR 影片前,請先確認裝置是否支援 所需的 HDR 設定檔

使用 CameraManager getCameraCharacteristics() 方法取得 CameraCharacteristics 例如,您可以查詢裝置的 HDR 功能。

下列步驟會檢查裝置是否支援 HLG10。 HLG10 是裝置製造商必須支援的基準 HDR 標準標準 輸出至 10 位元輸出相機

  1. 首先,請檢查裝置是否支援 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
    }
    
  2. 接下來,請確認裝置是否支援 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。 然後再透過支援的裝置設定 CameraCaptureSession 做為 OutputConfiguration 的 HDR 設定檔:

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 影片拍攝功能

格式 轉移函式 (TF) 中繼資料 轉碼器 位元深度
HTTP 10 HLG HEVC 10 位元
HDR10 PQ 靜態 HEVC 10 位元
HDR10+ PQ 動態 HEVC 10 位元
Dolby Vision 8.4 HLG 動態 HEVC 10 位元

資源

如果應用程式具有 HDR 影片擷取功能,請參閱 Camera2 影片範例