Observação: esta página se refere ao pacote Camera2. A menos que seu app exija recursos específicos de baixo nível do Camera2, recomendamos o uso do CameraX. CameraX e Camera2 oferecem suporte ao Android 5.0 (nível 21 da API) e versões mais recentes.
As APIs Camera2 oferecem suporte a captura de vídeo High Dynamic Range (HDR), o que permite visualizar e gravar conteúdo de vídeo em HDR usando a câmera. Em comparação com o intervalo dinâmico padrão (SDR), o HDR oferece uma variedade maior de cores e aumenta o intervalo dinâmico do componente de luminância (dos 100 cd/m2 atuais para 1.000 s de cd/m2). Isso resulta em qualidade de vídeo que se aproxima mais da vida real, com cores mais ricas, realces mais brilhantes e sombras mais escuras.
Saiba como o vídeo HDR captura um pôr do sol com detalhes mais vibrantes.
Pré-requisitos do dispositivo
Nem todos os dispositivos Android oferecem suporte à captura de vídeo HDR. Antes de capturar vídeo HDR no seu app, determine se o dispositivo atende aos seguintes pré-requisitos:
- Tem como destino o Android 13 (nível 33 da API).
- Tem um sensor de câmera de 10 bits ou mais. Para mais informações sobre o suporte a HDR, consulte Verificar o suporte a HDR.
Como nem todos os dispositivos atendem aos pré-requisitos, você pode adicionar um caminho de código separado ao configurar a captura de vídeo HDR no seu app. Isso permite que o app volte para SDR em dispositivos incompatíveis. Além disso, considere adicionar uma opção de interface para SDR. O usuário pode alternar entre SDR e HDR para as necessidades de gravação de vídeo.
Arquitetura de captura HDR
O diagrama a seguir mostra os principais componentes da arquitetura de captura HDR.
Quando um dispositivo de câmera captura um frame em HDR, o framework Camera2 aloca um buffer que armazena a saída processada do sensor da câmera.
Ele também anexa os metadados HDR respectivos, se exigido pelo perfil HDR.
Em seguida, o framework Camera2 enfileira o buffer preenchido para a superfície de saída
referenciada no CaptureRequest, como um display ou
codificador de vídeo, conforme mostrado no diagrama.
Verificar o suporte a HDR
Antes de capturar vídeo HDR no seu app, determine se o dispositivo oferece suporte ao perfil HDR desejado.
Use o método CameraManager getCameraCharacteristics() para receber uma
CameraCharacteristics
instância, que pode ser consultada para as capacidades HDR do dispositivo.
As etapas a seguir verificam se um dispositivo oferece suporte a HLG10. HLG10 é o padrão HDR de linha de base que os fabricantes de dispositivos precisam oferecer suporte em câmeras com saída de 10 bits.
Primeiro, verifique se o dispositivo oferece suporte a perfis de 10 bits (a profundidade 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 }
Em seguida, verifique se o dispositivo oferece suporte a HLG10 (ou outro perfil compatível):
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; }
Se o dispositivo oferece suporte a HDR, isHLGSupported() sempre retorna true.
Para mais informações, consulte a
CameraCharacteristics
documentação de referência.
Configurar a captura HDR
Depois de garantir que o dispositivo oferece suporte a HDR, configure o app para capturar um stream de vídeo HDR bruto da câmera.
Use setDynamicRangeProfile() para fornecer o OutputConfiguration
do stream com um perfil HDR compatível com o dispositivo, que é transmitido
para a CameraCaptureSession
após a criação.
Consulte a lista de perfis HDR compatíveis.
No exemplo de código a seguir, setupSessionDynamicRangeProfile() primeiro verifica se o dispositivo está executando o Android 13.
Em seguida, ele configura a CameraCaptureSession com o perfil HDR compatível com o dispositivo como uma 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 } }
Quando o app de câmera inicializa a câmera, ele envia um
repetido
CaptureRequest
para visualizar a gravação:
Kotlin
session.setRepeatingRequest(previewRequest, null, cameraHandler)
E também para iniciar a gravação de vídeo:
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)
Codificar o stream da câmera HDR
Para codificar o stream da câmera HDR e gravar o arquivo no disco,
use MediaCodec.
Primeiro, receba a OutputSurface,
que é mapeada para um buffer que armazena dados de vídeo brutos.
Para MediaCodec,
use createInputSurface().
Para inicializar MediaCodec, um app precisa criar um
MediaFormat com um perfil de codec, espaço de cor, intervalo de cores e função de transferência 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 mais detalhes sobre a implementação, consulte o app de exemplo Camera2Video
EncoderWrapper.kt.
Formatos HDR
A partir do Android 13, os dispositivos de câmera com recursos de saída de 10 bits precisam oferecer suporte a HLG10 para captura e reprodução de HDR. Além disso, os fabricantes de dispositivos podem ativar qualquer formato HDR de sua escolha usando a arquitetura de captura HDR.
A tabela a seguir resume os formatos HDR disponíveis e seus recursos para captura de vídeo HDR.
| Formato | Função de transferência (TF, na sigla em inglês) | Metadados | Codec | Profundidade de bit |
|---|---|---|---|---|
| HLG10 | HLG | Não | HEVC | 10 bits |
| HDR10 | PQ | Estático | HEVC | 10 bits |
| HDR10+ | PQ | Dinâmico | HEVC | 10 bits |
| Dolby Vision 8.4 | HLG | Dinâmico | HEVC | 10 bits |
Recursos
Para um app funcional com funcionalidade de captura de vídeo HDR, consulte o exemplo Camera2Video no GitHub.