Acquisizione video HDR

Nota: questa pagina fa riferimento al pacchetto Fotocamera2. A meno che la tua app non richieda funzionalità specifiche di basso livello di Fotocamera2, ti consigliamo di utilizzare FotocameraX. Sia CameraX che Camera2 supportano Android 5.0 (livello API 21) e versioni successive.

Le API Camera2 supportano l'acquisizione video HDR (High Dynamic Range), che consente di visualizzare in anteprima e registrare i contenuti video HDR utilizzando la fotocamera. Rispetto all'SDR (Standard Dynamic Range), l'HDR offre una gamma più ampia di colori e aumenta l'intervallo dinamico del componente luminanza (dagli attuali 100 cd/m2 a 1000s di cd/m2). Il risultato è una qualità video più fedele alla realtà, con colori più intensi, alte luci più luminose e ombre più scure.

Scopri come i video HDR catturano un tramonto con un maggiore dettaglio.

Figura 1. Confronto della qualità video in SDR (in alto) e in HDR (in basso).

Prerequisiti del dispositivo

Non tutti i dispositivi Android supportano l'acquisizione video HDR. Prima di acquisire video HDR nella tua app, determina se il tuo dispositivo soddisfa i seguenti prerequisiti:

  • Ha come target Android 13 (livello API 33).
  • Dispone di un sensore della fotocamera con capacità da 10 bit o superiore. Per ulteriori informazioni sul supporto HDR, vedi Verificare il supporto dell'HDR.

Poiché non tutti i dispositivi soddisfano i prerequisiti, puoi aggiungere un percorso codice separato quando configuri l'acquisizione video HDR nella tua app. In questo modo la tua app può ricorrere alla tecnologia SDR su dispositivi non compatibili. Inoltre, ti consigliamo di aggiungere un'opzione dell'interfaccia utente per SDR. L'utente può quindi passare da SDR a HDR e viceversa per le proprie esigenze di registrazione video.

Architettura di acquisizione HDR

Il seguente diagramma mostra i componenti principali dell'architettura di acquisizione HDR.

Diagramma dell'architettura dell'acquisizione HDR.
Figura 2. Diagramma dell'architettura dell'acquisizione HDR.

Quando una videocamera acquisisce un fotogramma in HDR, il framework Camera2 alloca un buffer che memorizza l'output del sensore della videocamera elaborato. Vengono inoltre allegati i rispettivi metadati HDR, se richiesto dal profilo HDR. Il framework Camera2 accoda quindi il buffer compilato per la superficie di output a cui viene fatto riferimento nella sezione CaptureRequest, ad esempio un display o un codificatore video, come mostrato nel diagramma.

Verificare il supporto dell'HDR

Prima di acquisire video HDR nell'app, stabilisci se il dispositivo supporta il profilo HDR desiderato.

Utilizza il metodo CameraManager getCameraCharacteristics() per ottenere un'istanza CameraCharacteristics su cui puoi eseguire query per le funzionalità HDR del tuo dispositivo.

I seguenti passaggi consentono di verificare se un dispositivo supporta HLG10. HLG10 è lo standard HDR di base che i produttori di dispositivi devono supportare nelle fotocamere con output a 10 bit.

  1. Innanzitutto, controlla se il dispositivo supporta profili a 10 bit (la profondità in bit per 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. Ora controlla se il dispositivo supporta HLG10 (o un altro profilo supportato):

    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 il dispositivo supporta la tecnologia HDR, isHLGSupported() restituisce sempre true. Per ulteriori informazioni, consulta la documentazione di riferimento di CameraCharacteristics.

Configura l'acquisizione HDR

Dopo aver verificato che il dispositivo supporti la tecnologia HDR, configura l'app per acquisire uno stream video HDR non elaborato dalla fotocamera. Utilizza setDynamicRangeProfile() per fornire all'elemento OutputConfiguration dello stream un profilo HDR supportato dal dispositivo, che viene poi trasmesso a CameraCaptureSession al momento della creazione. Consulta l'elenco dei profili HDR supportati.

Nel seguente esempio di codice, setupSessionDynamicRangeProfile() verifica innanzitutto che sul dispositivo sia in esecuzione Android 13. Quindi, configura CameraCaptureSession con il profilo HDR supportato dal dispositivo come 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 l'app della fotocamera inizializza la fotocamera, invia una ripetizione CaptureRequest per visualizzare l'anteprima della registrazione:

Kotlin

session.setRepeatingRequest(previewRequest, null, cameraHandler)

E anche per avviare la registrazione video:

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)

Codificare lo stream della videocamera HDR

Per codificare lo stream della videocamera HDR e scrivere il file su disco, utilizza MediaCodec.

Innanzitutto, prendi OutputSurface, che esegue la mappatura di un buffer che memorizza i dati video non elaborati. Per MediaCodec, utilizza createInputSurface().

Per inizializzare MediaCodec, un'app deve creare un MediaFormat con un profilo codec, uno spazio colore, un intervallo di colori e una funzione di trasferimento specificati:

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)

Per maggiori dettagli sull'implementazione, consulta EncoderWrapper.kt dell'app di esempio Camera2Video.

Formati HDR

A partire da Android 13, le fotocamere con capacità di output a 10 bit devono supportare il protocollo HLG10 per l'acquisizione e la riproduzione HDR. Inoltre, i produttori di dispositivi possono attivare qualsiasi formato HDR a scelta utilizzando l'architettura di acquisizione HDR.

La tabella seguente riassume i formati HDR disponibili e le loro funzionalità per l'acquisizione video HDR.

Formato Funzione di trasferimento (TF) Metadati Codec Profondità di bit
HLG10 HLG No HEVC 10 bit
HDR10 PQ Statico HEVC 10 bit
HDR10+ PQ Dinamico HEVC 10 bit
Dolby Vision 8.4 HLG Dinamico HEVC 10 bit

Risorse

Per un'app funzionante con funzionalità di acquisizione video HDR, vedi l'esempio di Camera2Video su GitHub.