Observação:esta página se refere ao pacote Camera2. A menos que seu app exija recursos específicos e 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 à captura de vídeo em 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, na sigla em inglês), 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 uma qualidade de vídeo que se aproxima mais da vida real, com cores mais vivas, destaques mais brilhantes e sombras mais escuras.
Confira como vídeos em HDR capturam um pôr do sol com mais detalhes.
Pré-requisitos do dispositivo
Nem todos os dispositivos Android são compatíveis com a captura de vídeo HDR. Antes de capturar vídeos em HDR no seu app, verifique se o dispositivo atende aos seguintes pré-requisitos:
- É destinado ao Android 13 (nível 33 da API).
- Tem um sensor de câmera de 10 bits ou superior. Para mais informações sobre o suporte a HDR, consulte Verificar o suporte a HDR.
Como nem todos os dispositivos atendem aos pré-requisitos, é possível adicionar um caminho de código separado ao configurar a captura de vídeo HDR no app. Isso permite que o app use 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 de acordo com 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 respectivos metadados HDR, se exigido pelo perfil de HDR.
O framework do Camera2 coloca o buffer preenchido para a superfície de saída
referenciada em CaptureRequest
, como um codificador de
tela ou vídeo, conforme mostrado no diagrama.
Conferir a compatibilidade com HDR
Antes de capturar vídeos em HDR no seu app, determine se o dispositivo oferece suporte ao perfil HDR desejado.
Use o método CameraManager
getCameraCharacteristics()
para acessar uma instância
CameraCharacteristics
, que pode ser consultada sobre os recursos HDR do dispositivo.
As etapas a seguir verificam se um dispositivo é compatível com HLG10. HLG10 é o padrão HDR de referência com 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 é compatível com 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 tiver suporte a HDR, o isHLGSupported()
sempre retornará true
.
Para mais informações, consulte a
documentação de referência
CameraCharacteristics
.
Configurar a captura HDR
Depois de garantir que o dispositivo ofereça suporte a HDR, configure o app para capturar
um stream de vídeo em HDR bruto da câmera.
Use setDynamicRangeProfile()
para fornecer ao OutputConfiguration
da transmissão
um perfil HDR compatível com o dispositivo, que será transmitido
para o CameraCaptureSession
durante a criação.
Veja a lista de perfis HDR compatíveis.
No exemplo de código abaixo, o setupSessionDynamicRangeProfile()
primeiro verifica
se o dispositivo está executando o Android 13.
Em seguida, ele configura o CameraCaptureSession
com o perfil HDR
compatível com o dispositivo como um 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 inicializa a câmera, ele envia um
CaptureRequest
repetitivo
para visualizar a gravação:
Kotlin
session.setRepeatingRequest(previewRequest, null, cameraHandler)
Para iniciar a gravação do 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, acesse o OutputSurface
,
que é mapeado para um buffer que armazena dados brutos de vídeo.
Para MediaCodec
,
use createInputSurface()
.
Para inicializar MediaCodec
, um app precisa criar uma
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 saber mais sobre a implementação, consulte a EncoderWrapper.kt
do app de exemplo Camera2Video.
Formatos HDR
No Android 13 e versões mais recentes, dispositivos de câmera com recursos de saída de 10 bits precisam oferecer suporte a HLG10 para captura HDR e reprodução. Além disso, os fabricantes de dispositivos podem ativar qualquer formato HDR que quiserem usando a arquitetura de captura HDR.
A tabela a seguir resume os formatos HDR disponíveis e os recursos deles para captura de vídeo HDR.
Formato | Função de transferência (TF) | Metadados | Codec | Profundidade de bit |
---|---|---|---|---|
Hl 10 | 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 a funcionalidade de captura de vídeo HDR, consulte o exemplo Camera2Video no GitHub (link em inglês).