Hinweis: Diese Seite bezieht sich auf das Camera2-Paket. Sofern Ihre App keine speziellen, Low-Level-Funktionen von Camera2 benötigt, 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 Aufnahme von HDR-Videos (High Dynamic Range). Damit 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/m² auf Tausende von cd/m²). Das Ergebnis ist eine Videoqualität, die der Realität näher kommt, mit satteren Farben, helleren Highlights und dunkleren Schatten.
Sehen Sie sich an, wie ein Sonnenuntergang mit HDR-Video in lebendigen Details aufgenommen wird.
Voraussetzungen für Geräte
Nicht alle Android-Geräte unterstützen die HDR-Videoaufnahme. Bevor Sie HDR-Videos in Ihrer App aufnehmen, prüfen Sie, ob Ihr Gerät die folgenden Voraussetzungen erfüllt:
- Ist auf Android 13 (API-Level 33) ausgerichtet.
- Das Gerät hat einen Kamerasensor mit mindestens 10 Bit. 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. Erwäge auch, eine UI-Option für SDR hinzuzufügen. Der Nutzer kann dann je nach Bedarf zwischen SDR und HDR für die Videoaufnahme wechseln.
HDR-Aufnahmearchitektur
Das folgende Diagramm zeigt die Hauptkomponenten der HDR-Aufnahmearchitektur.
Wenn ein Kameragerät einen Frame in HDR aufnimmt, weist das Camera2-Framework einen Zwischenspeicher zu, in dem die verarbeitete Ausgabe des Kamerasensors gespeichert wird. Außerdem werden die entsprechenden HDR-Metadaten angehängt, falls dies für das HDR-Profil erforderlich ist. Das Camera2-Framework stellt dann den gefüllten Zwischenspeicher für die Ausgabeoberfläche, auf die im CaptureRequest verwiesen wird, in die Warteschlange, z. B. für ein Display oder einen Video-Encoder, wie im Diagramm dargestellt.
HDR-Unterstützung prüfen
Bevor du HDR-Videos in deiner App aufnimmst, solltest du prüfen, ob das Gerät das von dir gewählte HDR-Profil unterstützt.
Verwende die Methode CameraManager
getCameraCharacteristics(), um eine CameraCharacteristics-Instanz abzurufen, die du nach den HDR-Funktionen deines Geräts abfragen kannst.
Mit den folgenden Schritten kannst du prüfen, ob ein Gerät HLG10 unterstützt. HLG10 ist der grundlegende HDR-Standard, den Gerätehersteller auf Kameras mit 10-Bit-Ausgabe unterstützen müssen.
Prüfe zuerst, ob das Gerät 10-Bit-Profile unterstützt (die Bittiefe für 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 }Prüfe als Nächstes, ob das Gerät HLG10 (oder ein anderes unterstütztes Profil) unterstützt:
@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; }
Wenn das Gerät HDR unterstützt, gibt isHLGSupported() immer true zurück. Weitere Informationen finden Sie in der Referenzdokumentation zu CameraCharacteristics.
HDR-Aufnahme einrichten
Nachdem du dich vergewissert hast, dass dein Gerät HDR unterstützt, richte deine App so ein, dass sie einen RAW-HDR-Videostream von der Kamera aufnimmt. Verwende setDynamicRangeProfile(), um dem OutputConfiguration des Streams ein vom Gerät unterstütztes HDR-Profil bereitzustellen, das dann bei der Erstellung an die CameraCaptureSession übergeben wird. 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:
/**
* 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
}
}
Wenn die Kamera-App die Kamera initialisiert, sendet sie eine wiederholte CaptureRequest, um eine Vorschau der Aufnahme anzuzeigen:
session.setRepeatingRequest(previewRequest, null, cameraHandler)
Und so starten Sie die Videoaufnahme:
// 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 das Laufwerk zu schreiben.
Rufen Sie zuerst die Ausgabe Surface ab, die einem Zwischenspeicher zugeordnet ist, in dem Rohvideodaten gespeichert werden. Verwenden Sie für MediaCodec den Wert createInputSurface().
Zum Initialisieren von MediaCodec muss eine App ein MediaFormat mit einem angegebenen Codec-Profil, Farbraum, Farbbereich und einer Übertragungsfunktion erstellen:
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 findest du in der EncoderWrapper.kt der Beispiel-App „Camera2Video“.
HDR-Formate
Ab Android 13 müssen Kamerageräte mit 10-Bit-Ausgabefunktionen HLG10 für die HDR-Aufnahme und ‑Wiedergabe unterstützen. Außerdem können Gerätehersteller mithilfe der HDR-Aufnahmearchitektur ein beliebiges HDR-Format aktivieren.
In der folgenden Tabelle sind die verfügbaren HDR-Formate und ihre Funktionen für die HDR-Videoaufnahme zusammengefasst.
| Format | Transferfunktion (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.