HDR 동영상 캡처

참고: 이 페이지에서는 Camera2 패키지를 다룹니다. 앱에 Camera2의 특정 하위 수준 기능이 필요하지 않다면 CameraX를 사용하는 것이 좋습니다. CameraX와 Camera2는 모두 Android 5.0(API 수준 21) 이상을 지원합니다.

Camera2 API는 HDR (High Dynamic Range) 동영상 캡처를 사용하면 카메라를 사용하여 HDR 동영상 콘텐츠를 녹화합니다. 표준 동적 광고 대비 HDR (범위: SDR), HDR은 더 광범위한 색상을 제공하고 역동적인 휘도 성분의 범위 (현재의 100cd/m2 ~ 수백 cd/m2) 이를 통해 실생활에 더 가까운 동영상 품질을 제공할 수 있으며 색이 더 풍부해지고 밝은톤으로 변경되고 어두운 그림자가 들어갑니다.

HDR 동영상으로 일몰을 더 선명하게 촬영하는 방법을 확인해 보세요.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder"></ph> <ph type="x-smartling-placeholder">
</ph> 그림 1. SDR (상단) 및 HDR (하단) 동영상 화질 비교.
를 통해 개인정보처리방침을 정의할 수 있습니다.
를 통해 개인정보처리방침을 정의할 수 있습니다.

기기 기본 요건

일부 Android 기기에서는 HDR 동영상 캡처를 지원하지 않습니다. 앱에서 HDR 동영상을 촬영하기 전에 기기가 다음 기본 요건을 충족해야 합니다.

  • Android 13 (API 수준 33)을 타겟팅합니다.
  • 10비트 이상을 지원하는 카메라 센서가 있어야 합니다. 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을 지원하는지 확인한 후 앱에서 캡처하도록 설정합니다. 카메라에서 RAW 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비트 출력 기능이 있는 카메라 기기 HDR 캡처를 위해 HLG10을 지원해야 하며 playback에 전달되어야 합니다. 또한 기기 제조업체는 원하는 모든 HDR 형식을 사용 설정할 수 있습니다. HDR 캡처 아키텍처 사용

다음 표에는 사용 가능한 HDR 형식과 기능이 요약되어 있습니다. HDR 동영상 캡처용입니다.

형식 전송 함수 (TF) Metadata 코덱 비트 심도
HLG10 HLG 아니요 HEVC 10비트
HDR10 PQ 정적 HEVC 10비트
HDR10+ PQ 동적 HEVC 10비트
Dolby Vision 8.4 HLG 동적 HEVC 10비트

리소스

HDR 동영상 캡처 기능이 있는 작동하는 앱은 다음을 참고하세요. Camera2Video 샘플 를 참조하세요.