Captura de vídeo HDR

Observação:esta página se refere ao pacote Camera2. A menos que seu app exija recursos específicos e de baixo nível do Camera2, recomendamos o uso do CameraX. CameraX e Camera2 oferecem suporte ao Android 5.0 (nível 21 da API) e versões mais recentes.

O suporte às APIs Camera2 Captura de vídeo em High Dynamic Range (HDR), que permite visualizar e gravar conteúdo de vídeo em HDR usando a câmera. Em comparação com a abordagem dinâmica padrão de alcance (SDR), o HDR oferece uma gama mais ampla de cores e aumenta do componente de luminância (dos atuais 100 cd/m2 a 1.000 s de cd/m2). Isso resulta em uma qualidade de vídeo que se aproxima mais da vida real, com cores mais vivas, destaques mais brilhantes e sombras mais escuras.

Veja como um vídeo em HDR captura o pôr do sol com mais detalhes.

Figura 1. Comparação entre a qualidade de vídeo SDR (parte superior) x HDR (inferior).
.

Pré-requisitos do dispositivo

Nem todos os dispositivos Android são compatíveis com a captura de vídeo HDR. Antes de capturar vídeos em HDR no app, determine se o dispositivo atende os seguintes pré-requisitos:

Como nem todos os dispositivos atendem aos pré-requisitos, você pode adicionar um código separado ao configurar a captura de vídeo HDR no app. Isso permite que o app use SDR em dispositivos incompatíveis. Além disso, considere adicionar uma opção de interface para SDR. O usuário pode então alternar entre SDR e HDR para as necessidades de gravação de vídeo.

Arquitetura de captura HDR

O diagrama a seguir mostra os principais componentes da arquitetura de captura HDR.

Diagrama da arquitetura de captura em HDR.
Figura 2. Diagrama da arquitetura de captura em HDR.

Quando um dispositivo de câmera captura um frame em HDR, o framework Camera2 aloca um buffer que armazena a saída processada do sensor da câmera; Ele também anexa os respectivos metadados HDR se exigido pelo perfil HDR. Em seguida, o framework Camera2 enfileira o buffer preenchido para a superfície de saída. referenciadas no CaptureRequest, como uma tela ou em um codificador de vídeo, como mostra o diagrama.

Verificar o suporte a HDR

Antes de capturar vídeos em HDR no app, verifique se o dispositivo oferece suporte o perfil HDR desejado.

Use o método CameraManager getCameraCharacteristics() para acessar uma CameraCharacteristics que você pode consultar para saber os recursos de HDR do dispositivo.

As etapas a seguir verificam se um dispositivo é compatível com HLG10. HLG10 é o padrão HDR de referência com que os fabricantes de dispositivos precisam oferecer suporte em câmeras com saída de 10 bits.

  1. Primeiro, verifique se o dispositivo oferece suporte a perfis de 10 bits (a profundidade de bits para 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. Em seguida, verifique se o dispositivo é compatível com HLG10 ou outro perfil compatível:

    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;
    }
    

Se o dispositivo for compatível com HDR, isHLGSupported() sempre retornará true. Para mais informações, consulte a CameraCharacteristics documentação de referência.

Configurar captura HDR

Depois de garantir que seu dispositivo seja compatível com HDR, configure o app para capturar um stream de vídeo bruto em HDR a partir da câmera. Use setDynamicRangeProfile() para fornecer o OutputConfiguration da transmissão. com um perfil HDR compatível com o dispositivo, que é transmitido para o CameraCaptureSession na criação. Veja a lista de perfis HDR compatíveis.

No exemplo de código abaixo, setupSessionDynamicRangeProfile() verifica primeiro que o dispositivo está executando o Android 13. Em seguida, ele configura o CameraCaptureSession com o ambiente Perfil HDR como um 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
      }
  }

}

Quando o app inicializa a câmera, ela envia uma recorrente CaptureRequest para visualizar a gravação:

Kotlin

session.setRepeatingRequest(previewRequest, null, cameraHandler)

E também para iniciar a gravação de vídeo:

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)

Codificar o stream da câmera em HDR

Para codificar o stream da câmera HDR e gravar o arquivo em disco, use MediaCodec.

Primeiro, acesse o OutputSurface, que mapeia para um buffer que armazena dados brutos de vídeo. Para o MediaCodec, use createInputSurface().

Para inicializar o MediaCodec, um app precisa criar uma MediaFormat com o tipo perfil do codec, espaço de cores, intervalo de cores e função de transferência:

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)

Para mais detalhes sobre a implementação, consulte a documentação do app de exemplo Camera2Video EncoderWrapper.kt

Formatos HDR

No Android 13 e versões mais recentes, dispositivos de câmera com recursos de saída de 10 bits precisa oferecer suporte a HLG10 para captura HDR e playback. Além disso, os fabricantes de dispositivos podem ativar o formato HDR que quiserem usando a arquitetura de captura HDR.

A tabela a seguir resume os formatos HDR disponíveis e os respectivos recursos para captura de vídeo HDR.

Formato Função de transferência (TF) Metadados Codec Profundidade de bit
HLG10 HLG Não HEVC 10 bits
HDR10 PQ Estático HEVC 10 bits
HDR10+ PQ Dinâmico HEVC 10 bits
Dolby Vision 8.4 HLG Dinâmico HEVC 10 bits

Recursos

Para um app que funcione com a funcionalidade de captura de vídeo HDR, consulte a Exemplo de Camera2Video (link em inglês) no GitHub.