Uwaga: ta strona dotyczy pakietu Camera2. Jeśli aplikacja nie wymaga określonych, niskiego poziomu funkcji z Aparatu2, zalecamy użycie CameraX. Zarówno aplikacja CameraX, jak i Aparat 2 obsługują Androida 5.0 (poziom interfejsu API 21) i nowsze wersje.
Interfejsy Camera2 API obsługują nagrywanie filmów w trybie High Dynamic Range (HDR), dzięki czemu możesz wyświetlać podgląd filmów w trybie HDR i nagrywać je za pomocą kamery. W porównaniu ze standardowym zakresem dynamiki (SDR) HDR oferuje szerszy zakres kolorów i zwiększa zakres dynamiczny komponentu luminancji (od 100 cd/m2 do 1000 s pojemności cd/m2). W rezultacie film o jakości bardziej przypominającej obraz w rzeczywistości – ma bogatsze kolory, jaśniejsze podświetlenia i ciemniejsze cienie.
Zobacz, jak filmy HDR uchwycą zachód słońca z większą ostrością.
Wymagania wstępne urządzenia
Nie wszystkie urządzenia z Androidem obsługują nagrywanie filmów w technologii HDR. Przed nagraniem filmów HDR w swojej aplikacji sprawdź, czy Twoje urządzenie spełnia te wymagania wstępne:
- Aplikacja jest kierowana na Androida 13 (poziom API 33).
- Ma czujnik 10-bitowy lub szybszy. Więcej informacji o obsłudze HDR znajdziesz w artykule Sprawdzanie obsługi HDR.
Nie wszystkie urządzenia spełniają wymagania wstępne, dlatego podczas konfigurowania nagrywania filmów HDR w aplikacji możesz dodać osobną ścieżkę kodu. Dzięki temu na niezgodnych urządzeniach aplikacja będzie wracała do SDR. Zastanów się też nad dodaniem opcji interfejsu do obsługi SDR. Następnie użytkownik może przełączać się między SDR a HDR w zależności od potrzeb związanych z nagrywaniem filmów.
Architektura nagrywania HDR
Poniższy schemat przedstawia główne elementy architektury HDR.
Gdy aparat rejestruje klatkę w trybie HDR, platforma Camera2 przydziela bufor, w którym przechowywane są przetworzone dane wyjściowe czujnika aparatu.
Dołącza też odpowiednie metadane HDR, jeśli jest to wymagane przez profil HDR.
Platforma Camera2 doda do kolejki wypełniony bufor dla platformy wyjściowej określonej w CaptureRequest
, takiej jak wyświetlacz lub koder wideo, jak widać na schemacie.
Sprawdzanie obsługi HDR
Przed nagraniem filmu HDR w aplikacji sprawdź, czy urządzenie obsługuje wybrany profil HDR.
Aby uzyskać instancję CameraCharacteristics
, do której możesz wysyłać zapytania o funkcje HDR Twojego urządzenia, użyj metody CameraManager
getCameraCharacteristics()
.
Wykonaj te czynności, aby sprawdzić, czy urządzenie obsługuje HLG10. HLG10 to podstawowy standard HDR, który producenci urządzeń muszą obsługiwać w przypadku kamer z 10-bitowym wyjściem.
Najpierw sprawdź, czy urządzenie obsługuje 10-bitowe profile (głębokość bitową w przypadku 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 }
Następnie sprawdź, czy urządzenie obsługuje HLG10 (lub inny obsługiwany profil):
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; }
Jeśli urządzenie obsługuje HDR, isHLGSupported()
zawsze zwraca wartość true
.
Więcej informacji znajdziesz w dokumentacji referencyjnej CameraCharacteristics
.
Skonfiguruj robienie zdjęć HDR
Gdy upewnisz się, że Twoje urządzenie obsługuje HDR, skonfiguruj aplikację, aby nagrywać nieprzetworzony strumień wideo HDR z aparatu.
Za pomocą setDynamicRangeProfile()
możesz udostępnić do strumienia OutputConfiguration
profil HDR obsługiwany przez urządzenie, który po utworzeniu jest przekazywany do CameraCaptureSession
.
Zobacz listę obsługiwanych profili HDR.
W tym przykładowym kodzie setupSessionDynamicRangeProfile()
najpierw sprawdza, czy na urządzeniu działa Android 13.
Następnie konfiguruje CameraCaptureSession
z profilem HDR obsługiwanym przez urządzenie jako 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 } }
}
Gdy aplikacja aparatu uruchamia kamerę, wysyła powtarzający się kod CaptureRequest
w celu wyświetlenia podglądu nagrania:
Kotlin
session.setRepeatingRequest(previewRequest, null, cameraHandler)
Aby rozpocząć nagrywanie filmu:
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)
Kodowanie strumienia danych HDR z kamery
Aby zakodować strumień z kamery HDR i zapisać plik na dysku, użyj narzędzia MediaCodec
.
Najpierw pobierz parametr OutputSurface
, który jest mapowany na bufor przechowujący nieprzetworzone dane wideo.
W przypadku MediaCodec
użyj createInputSurface()
.
Aby zainicjować MediaCodec
, aplikacja musi utworzyć MediaFormat
z określonym profilem kodeka, przestrzenią kolorów, zakresem kolorów i funkcją transferu:
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)
Więcej informacji o implementacji znajdziesz w dokumencie EncoderWrapper.kt
dotyczącym przykładowej aplikacji Camera2Video.
Formaty HDR
Od Androida 13 aparaty z 10-bitowym wyjściem muszą obsługiwać HLG10, aby można było robić zdjęcia w trybie HDR i odtwarzać treści. Producenci urządzeń mogą też włączyć dowolny wybrany przez siebie format HDR za pomocą architektury nagrywania HDR.
W tabeli poniżej znajdziesz podsumowanie dostępnych formatów HDR oraz ich możliwości w zakresie nagrywania filmów HDR.
Format | Funkcja transferu (TF) | Metadane | Kodek | Głębia bitowa |
---|---|---|---|---|
HLG10 | HLG | Nie | Ogrzewanie, wentylacja i klimatyzacja | 10-bitowy |
HDR10 | PQ | Statyczne | Ogrzewanie, wentylacja i klimatyzacja | 10-bitowy |
HDR10+ | PQ | Dynamiczne | Ogrzewanie, wentylacja i klimatyzacja | 10-bitowy |
Dolby Vision 8.4 | HLG | Dynamiczne | Ogrzewanie, wentylacja i klimatyzacja | 10-bitowy |
Zasoby
Informacje o działającej aplikacji z funkcją nagrywania filmów HDR znajdziesz w tym artykule na GitHubie.