HDR-Videoaufnahme

Hinweis: Auf dieser Seite wird auf das Camera2-Paket verwiesen. Wenn Ihre App keine bestimmten Low-Level-Funktionen von Camera2 erfordert, empfehlen wir die Verwendung von CameraX. Sowohl CameraX als auch Camera2 unterstützen Android 5.0 (API-Level 21) und höher.

Die Camera2 APIs unterstützen die HDR-Videoaufnahme (High Dynamic Range). So können Sie HDR-Videoinhalte mit Ihrer Kamera in der Vorschau ansehen und aufnehmen. Im Vergleich zu SDR (Standard Dynamic Range) bietet HDR eine größere Farbpalette und erhöht den Dynamikbereich der Luminanzkomponente (von derzeit 100 cd/m2 auf Tausende von cd/m2). Das Ergebnis ist eine Videoqualität, die der Realität näher kommt, mit satteren Farben, helleren Lichtern und dunkleren Schatten.

Hier sehen Sie, wie ein Sonnenuntergang in einem HDR-Video mit lebendigeren Details aufgenommen wird.

Abbildung 1 Vergleich der Videoqualität von SDR (oben) und HDR (unten)

Gerätevoraussetzungen

Nicht alle Android-Geräte unterstützen die HDR-Videoaufnahme. Bevor Sie in Ihrer App HDR-Videos aufnehmen, prüfen Sie, ob Ihr Gerät die folgenden Voraussetzungen erfüllt:

  • Android 13 (API-Level 33) als Ziel.
  • Ein Kamerasensor mit 10 Bit oder höher. Weitere Informationen zur HDR Unterstützung finden Sie unter HDR-Unterstützung prüfen.

Da nicht alle Geräte die Voraussetzungen erfüllen, können Sie beim Einrichten der HDR-Videoaufnahme in Ihrer App einen separaten Codepfad hinzufügen. So kann Ihre App auf inkompatiblen Geräten auf SDR zurückgreifen. Sie sollten auch eine UI-Option für SDR hinzufügen. Der Nutzer kann dann je nach Bedarf zwischen SDR und HDR für seine Videoaufnahmen wechseln.

Architektur für die HDR-Aufnahme

Das folgende Diagramm zeigt die Hauptkomponenten der Architektur für die HDR-Aufnahme.

Architekturdiagramm der HDR-Aufnahme
Abbildung 2 Architekturdiagramm für die HDR-Aufnahme

Wenn ein Kameragerät ein Bild in HDR aufnimmt, weist das Camera2-Framework einen Puffer zu, in dem die verarbeitete Ausgabe des Kamerasensors gespeichert wird. Außerdem werden die entsprechenden HDR-Metadaten angehängt, wenn dies vom HDR-Profil erforderlich ist. Das Camera2-Framework stellt den gefüllten Puffer dann für die Ausgabefläche in die Warteschlange, auf die in der CaptureRequest verwiesen wird, z. B. ein Display oder ein Video-Encoder, wie im Diagramm dargestellt.

HDR-Unterstützung prüfen

Bevor Sie in Ihrer App HDR-Videos aufnehmen, prüfen Sie, ob das Gerät Ihr gewünschtes HDR-Profil unterstützt.

Verwenden Sie die CameraManager getCameraCharacteristics() Methode, um eine CameraCharacteristics Instanz abzurufen, mit der Sie die HDR-Funktionen Ihres Geräts abfragen können.

In den folgenden Schritten wird geprüft, ob ein Gerät HLG10 unterstützt. HLG10 ist der HDR-Standard, den Gerätehersteller auf Kameras mit 10-Bit-Ausgabe unterstützen müssen.

  1. Prüfen Sie zuerst, ob das Gerät 10-Bit-Profile unterstützt (die Bittiefe für 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. Prüfen Sie als Nächstes, ob das Gerät HLG10 (oder ein anderes unterstütztes Profil) unterstützt:

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

Wenn das Gerät HDR unterstützt, gibt isHLGSupported() immer true zurück. Weitere Informationen finden Sie in der CameraCharacteristics Referenzdokumentation.

HDR-Aufnahme einrichten

Nachdem Sie geprüft haben, ob Ihr Gerät HDR unterstützt, richten Sie Ihre App so ein, dass ein roher HDR-Videostream von der Kamera aufgenommen wird. Verwenden Sie setDynamicRangeProfile(), um die OutputConfiguration des Streams mit einem vom Gerät unterstützten HDR-Profil zu versehen, das dann bei der Erstellung an die CameraCaptureSession übergeben wird. Hier finden Sie eine Liste der unterstützten HDR-Profile.

Im folgenden Codebeispiel prüft setupSessionDynamicRangeProfile() zuerst, ob auf dem Gerät Android 13 ausgeführt wird. Anschließend wird die CameraCaptureSession mit dem vom Gerät unterstützten HDR-Profil als OutputConfiguration eingerichtet:

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

Wenn Ihre Kamera-App die Kamera initialisiert, sendet sie eine wiederholte CaptureRequest um eine Vorschau der Aufnahme zu erhalten:

Kotlin

session.setRepeatingRequest(previewRequest, null, cameraHandler)

Und auch, um die Videoaufnahme zu starten:

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-Kamerastream codieren

Verwenden Sie MediaCodec, um den HDR-Kamerastream zu codieren und die Datei auf die Festplatte zu schreiben, .

Rufen Sie zuerst die OutputSurface, die einem Puffer zugeordnet ist, in dem Rohvideodaten gespeichert werden, ab. Verwenden Sie für MediaCodec, die Funktion createInputSurface().

Um MediaCodec zu initialisieren, muss eine App ein MediaFormat mit einem angegebenen Codec-Profil, Farbraum, Farbbereich und einer Übertragungsfunktion erstellen:

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)

Weitere Informationen zur Implementierung finden Sie in der Beispiel-App Camera2Video unter EncoderWrapper.kt.

HDR-Formate

Ab Android 13 müssen Kamerageräte mit 10-Bit-Ausgabe HLG10 für die HDR-Aufnahme und Wiedergabe unterstützen. Außerdem können Gerätehersteller mit der Architektur für die HDR-Aufnahme jedes beliebige HDR-Format aktivieren.

In der folgenden Tabelle sind die verfügbaren HDR-Formate und ihre Funktionen für die HDR-Videoaufnahme zusammengefasst.

Format Übertragungsfunktion (TF) Metadaten Codec Bittiefe
HLG10 HLG Nein HEVC 10 Bit
HDR10 PQ Statisch HEVC 10 Bit
HDR10+ PQ Dynamisch HEVC 10 Bit
Dolby Vision 8.4 HLG Dynamisch HEVC 10 Bit

Ressourcen

Eine funktionierende App mit HDR-Videoaufnahmefunktion finden Sie im Camera2Video-Beispiel auf GitHub.