Nota: En esta página, se hace referencia al paquete Camera2. A menos que tu app requiera funciones específicas de bajo nivel de Camera2, te recomendamos que uses CameraX. CameraX y Camera2 admiten Android 5.0 (nivel de API 21) y versiones posteriores.
Las APIs de Camera2 admiten la captura de video de alto rango dinámico (HDR), que te permite obtener una vista previa y grabar contenido de video en HDR con la cámara. En comparación con el rango dinámico estándar (SDR), HDR ofrece un rango de colores más amplio y aumenta el rango dinámico del componente de luminancia (de los 100 cd/m2 actuales a miles de cd/m2). Esto da como resultado una calidad de video que se ajusta más a la vida real, con colores más nítidos, reflejos más brillantes y sombras más oscuras.
Mira cómo el video en HDR captura una puesta de sol con detalles más vibrantes.
Requisitos previos del dispositivo
No todos los dispositivos Android admiten la captura de video en HDR. Antes de capturar video en HDR en tu app, determina si tu dispositivo cumple con los siguientes requisitos previos:
- Se orienta a Android 13 (nivel de API 33).
- Tiene un sensor de cámara de 10 bits o superior. Para obtener más información sobre la compatibilidad con HDR, consulta Cómo comprobar la compatibilidad con HDR.
Como no todos los dispositivos cumplen con los requisitos previos, puedes agregar una ruta de código independiente cuando configures la captura de video en HDR en tu app. Esto permite que tu app vuelva a SDR en dispositivos incompatibles. Además, considera agregar una opción de IU para SDR. Luego, el usuario puede alternar entre SDR y HDR para sus necesidades de grabación de video.
Arquitectura de captura de HDR
En el siguiente diagrama, se muestran los componentes principales de la arquitectura de captura de HDR.
Cuando un dispositivo de cámara captura un fotograma en HDR, el framework de Camera2 asigna un búfer que almacena la salida procesada del sensor de la cámara.
También adjunta los metadatos HDR respectivos si el perfil HDR lo requiere.
Luego, el framework de Camera2 pone en cola el búfer propagado para la superficie de salida
a la que se hace referencia en CaptureRequest, como una pantalla o
un codificador de video, como se muestra en el diagrama.
Cómo comprobar la compatibilidad con HDR
Antes de capturar video en HDR en tu app, determina si el dispositivo admite el perfil HDR deseado.
Usa el método CameraManager getCameraCharacteristics() para obtener una
CameraCharacteristics
instancia, que puedes consultar para conocer las capacidades HDR de tu dispositivo.
En los siguientes pasos, se verifica si un dispositivo admite HLG10. HLG10 es el estándar HDR de referencia que los fabricantes de dispositivos deben admitir en cámaras con salida de 10 bits.
Primero, comprueba si el dispositivo admite perfiles de 10 bits (la profundidad de bits para 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 }
A continuación, comprueba si el dispositivo admite HLG10 (o cualquier otro perfil compatible):
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; }
Si el dispositivo admite HDR, isHLGSupported() siempre muestra true.
Para obtener más información, consulta la
CameraCharacteristics
documentación de referencia.
Cómo configurar la captura de HDR
Después de asegurarte de que tu dispositivo admita HDR, configura tu app para capturar una transmisión de video HDR sin procesar desde la cámara.
Usa setDynamicRangeProfile() para proporcionar el OutputConfiguration
de la transmisión con un perfil HDR compatible con el dispositivo, que luego se pasa
a CameraCaptureSession
cuando se crea.
Consulta la lista de perfiles HDR compatibles.
En la siguiente muestra de código, setupSessionDynamicRangeProfile() primero verifica que el dispositivo ejecute Android 13.
Luego, configura CameraCaptureSession con el perfil HDR compatible con el dispositivo como 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 } }
Cuando tu app de cámara inicializa la cámara, envía un
repetido
CaptureRequest
para obtener una vista previa de la grabación:
Kotlin
session.setRepeatingRequest(previewRequest, null, cameraHandler)
Y también para iniciar la grabación de 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)
Cómo codificar la transmisión de la cámara HDR
Para codificar la transmisión de la cámara HDR y escribir el archivo en el disco,
usa MediaCodec.
Primero, obtén el OutputSurface,
que se asigna a un búfer que almacena datos de video sin procesar.
Para MediaCodec,
usa createInputSurface().
Para inicializar MediaCodec, una app debe crear un
MediaFormat con un perfil de códec, un espacio de color, un rango de color y una función de transferencia especificados:
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)
Para obtener más detalles sobre la implementación, consulta la app de ejemplo Camera2Video
EncoderWrapper.kt.
Formatos HDR
A partir de Android 13, los dispositivos de cámara con capacidades de salida de 10 bits deben admitir HLG10 para la captura y reproducción de HDR. Además, los fabricantes de dispositivos pueden habilitar cualquier formato HDR que elijan con la arquitectura de captura de HDR.
En la siguiente tabla, se resumen los formatos HDR disponibles y sus capacidades para la captura de video en HDR.
| Formato | Función de transferencia (TF) | Metadatos | Códec | Profundidad de bits |
|---|---|---|---|---|
| HLG10 | HLG | No | HEVC | 10 bits |
| HDR10 | PQ | Estática | HEVC | 10 bits |
| HDR10+ | PQ | Dinámico | HEVC | 10 bits |
| Dolby Vision 8.4 | HLG | Dinámico | HEVC | 10 bits |
Recursos
Para obtener una app en funcionamiento con la funcionalidad de captura de video en HDR, consulta la muestra de Camera2Video en GitHub.