Capture vidéo HDR

Remarque : Cette page fait référence au package Camera2. Sauf si votre application nécessite des fonctionnalités spécifiques de bas niveau de Camera2, nous vous recommandons d'utiliser CameraX. CameraX et Camera2 sont compatibles avec Android 5.0 (niveau d'API 21) ou version ultérieure.

Les API Camera2 sont compatibles avec la capture vidéo HDR (High Dynamic Range), ce qui vous permet de prévisualiser et d'enregistrer du contenu vidéo HDR à l'aide de votre appareil photo. Par rapport à la plage dynamique standard (SDR), la technologie HDR offre une plus large gamme de couleurs et augmente la plage dynamique de la composante de luminance (de 100 cd/m2 actuellement à des milliers de cd/m2). La qualité vidéo est ainsi plus proche de la réalité, avec des couleurs plus riches, des zones claires plus lumineuses et des zones sombres plus sombres.

Découvrez comment la vidéo HDR capture un coucher de soleil avec des détails plus éclatants.

Coucher de soleil capturé en qualité vidéo SDR Un coucher de soleil capturé en qualité vidéo HDR
Figure 1. Comparaison de la qualité vidéo SDR (en haut) et HDR (en bas).

Conditions préalables concernant l'appareil

Tous les appareils Android ne sont pas compatibles avec l'enregistrement vidéo HDR. Avant de capturer une vidéo HDR dans votre application, déterminez si votre appareil répond aux conditions préalables suivantes :

  • Cible Android 13 (niveau d'API 33).
  • Il est équipé d'un capteur d'appareil photo de 10 bits ou plus. Pour en savoir plus sur la compatibilité HDR, consultez Vérifier la compatibilité HDR.

Comme tous les appareils ne remplissent pas les conditions préalables, vous pouvez ajouter un chemin de code distinct lors de la configuration de la capture vidéo HDR dans votre application. Cela permet à votre application de revenir au SDR sur les appareils incompatibles. Envisagez également d'ajouter une option d'interface utilisateur pour le SDR. L'utilisateur peut ensuite basculer entre SDR et HDR pour ses besoins d'enregistrement vidéo.

Architecture de capture HDR

Le schéma suivant montre les principaux composants de l'architecture de capture HDR.

Schéma de l'architecture de capture HDR.
Figure 2 : Schéma de l'architecture de capture HDR.

Lorsqu'un appareil photo capture une image en HDR, le framework Camera2 alloue un tampon qui stocke la sortie traitée du capteur de l'appareil photo. Il associe également les métadonnées HDR respectives si le profil HDR l'exige. Le framework Camera2 met ensuite en file d'attente le tampon renseigné pour la surface de sortie référencée dans CaptureRequest, comme un écran ou un encodeur vidéo, comme illustré dans le schéma.

Vérifier la compatibilité HDR

Avant de capturer une vidéo HDR dans votre application, déterminez si l'appareil est compatible avec le profil HDR que vous avez choisi.

Utilisez la méthode getCameraCharacteristics() de CameraManager pour obtenir une instance CameraCharacteristics, que vous pouvez interroger pour connaître les fonctionnalités HDR de votre appareil.

Les étapes suivantes permettent de vérifier si un appareil est compatible avec HLG10. HLG10 est la norme HDR de référence que les fabricants d'appareils doivent prendre en charge sur les caméras avec une sortie 10 bits.

  1. Commencez par vérifier si l'appareil est compatible avec les profils 10 bits (profondeur de bits pour HLG10) :

    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. Ensuite, vérifiez si l'appareil est compatible avec HLG10 (ou un autre profil compatible) :

    @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 chosen profile, in this case HLG10
        return availableProfiles.contains(DynamicRangeProfiles.HLG10)
      }
      return false;
    }
    

Si l'appareil est compatible avec le HDR, isHLGSupported() renvoie toujours true. Pour plus d'informations, consultez la documentation de référence CameraCharacteristics.

Configurer la capture HDR

Après vous être assuré que votre appareil est compatible avec le HDR, configurez votre application pour capturer un flux vidéo HDR brut à partir de la caméra. Utilisez setDynamicRangeProfile() pour fournir à l'objet OutputConfiguration du flux un profil HDR compatible avec l'appareil, qui est ensuite transmis à l'objet CameraCaptureSession lors de sa création. Consultez la liste des profils HDR compatibles.

Dans l'exemple de code suivant, setupSessionDynamicRangeProfile() vérifie d'abord que l'appareil exécute Android 13. Ensuite, il configure le CameraCaptureSession avec le profil HDR compatible avec l'appareil en tant que OutputConfiguration :

  /**
   * Creates a [CameraCaptureSession] with a dynamic range profile.
   */
  private fun setupSessionWithDynamicRangeProfile(
      dynamicRange: Long,
      device: CameraDevice,
      targets: List<Surface>,
      handler: Handler? = null,
      stateCallback: CameraCaptureSession.StateCallback
  ): Boolean {
      if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
          val outputConfigs = mutableListOf<OutputConfiguration>()
          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
      }
  }

Lorsque votre application Appareil photo initialise l'appareil photo, elle envoie une requête CaptureRequest répétée pour prévisualiser l'enregistrement :

session.setRepeatingRequest(previewRequest, null, cameraHandler)

Pour démarrer l'enregistrement vidéo :

// 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)

Encoder le flux de la caméra HDR

Pour encoder le flux de la caméra HDR et écrire le fichier sur le disque, utilisez MediaCodec.

Commencez par obtenir la sortie Surface, qui correspond à un tampon stockant les données vidéo brutes. Pour MediaCodec, utilisez createInputSurface().

Pour initialiser MediaCodec, une application doit créer un MediaFormat avec un profil de codec, un espace colorimétrique, une gamme de couleurs et une fonction de transfert spécifiés :

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)

Pour en savoir plus sur l'implémentation, consultez le fichier EncoderWrapper.kt de l'application exemple Camera2Video.

Formats HDR

À partir d'Android 13, les appareils photo dotés de capacités de sortie 10 bits doivent être compatibles avec HLG10 pour la capture et la lecture HDR. De plus, les fabricants d'appareils peuvent activer le format HDR de leur choix à l'aide de l'architecture de capture HDR.

Le tableau suivant récapitule les formats HDR disponibles et leurs fonctionnalités pour la capture vidéo HDR.

Format Fonction de transfert (TF) Métadonnées Codec Profondeur de bit
HLG10 HLG Non HEVC 10 bits
HDR10 PQ Statique HEVC 10 bits
HDR10+ PQ Dynamique HEVC 10 bits
Dolby Vision 8.4 HLG Dynamique HEVC 10 bits

Ressources

Pour découvrir une application fonctionnelle intégrant les fonctionnalités de capture vidéo HDR, consultez l'exemple Camera2Video sur GitHub.