Nota: questa pagina fa riferimento al pacchetto Camera2. A meno che la tua app non richieda funzionalità specifiche di basso livello di Camera2, ti consigliamo di utilizzare CameraX. Sia CameraX che Camera2 supportano Android 5.0 (livello API 21) e versioni successive.
Le API Camera2 supportano l'acquisizione di video High Dynamic Range (HDR), che ti consente di visualizzare l'anteprima e registrare contenuti video HDR utilizzando la fotocamera. Rispetto allo Standard Dynamic Range (SDR), l'HDR offre una gamma più ampia di colori e aumenta la gamma dinamica della componente di luminanza (dagli attuali 100 cd/m2 a migliaia di cd/m2). In questo modo, la qualità video è più vicina alla realtà, con colori più ricchi, punti luce più luminosi e ombre più scure.
Guarda come i video HDR catturano un tramonto con dettagli più vivaci.
Prerequisiti del dispositivo
Non tutti i dispositivi Android supportano l'acquisizione di video HDR. Prima di acquisire video HDR nella tua app, verifica se il tuo dispositivo soddisfa i seguenti prerequisiti:
- Ha come target Android 13 (livello API 33).
- Ha un sensore della fotocamera con capacità di almeno 10 bit. Per ulteriori informazioni sul supporto HDR, consulta Verifica il supporto HDR.
Poiché non tutti i dispositivi soddisfano i prerequisiti, puoi aggiungere un percorso del codice separato quando configuri l'acquisizione di video HDR nella tua app. In questo modo, l'app può tornare a SDR sui dispositivi incompatibili. Inoltre, valuta la possibilità di aggiungere un'opzione UI per SDR. L'utente può quindi passare da SDR a HDR in base alle proprie esigenze di registrazione video.
Architettura di acquisizione HDR
Il seguente diagramma mostra i componenti principali dell'architettura di acquisizione HDR.
Quando un dispositivo con fotocamera acquisisce un frame in HDR, il framework Camera2 alloca un buffer che memorizza l'output elaborato del sensore della fotocamera. Inoltre, allega i rispettivi metadati HDR, se richiesto dal profilo HDR. Il framework Camera2
quindi mette in coda il buffer compilato per la superficie di output a cui viene fatto riferimento in
CaptureRequest, ad esempio un display o un codificatore
video, come mostrato nel diagramma.
Controlla il supporto HDR
Prima di acquisire video HDR nella tua app, determina se il dispositivo supporta il profilo HDR scelto.
Utilizza il metodo CameraManager
getCameraCharacteristics() per ottenere un'istanza
CameraCharacteristics, su cui puoi eseguire query
per le funzionalità HDR del tuo dispositivo.
I passaggi seguenti consentono di verificare se un dispositivo supporta HLG10. HLG10 è lo standard HDR di base che i produttori di dispositivi devono supportare sulle fotocamere con output a 10 bit.
Innanzitutto, controlla se il dispositivo supporta i profili a 10 bit (la profondità di bit per 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 }Successivamente, controlla se il dispositivo supporta HLG10 (o un altro profilo supportato):
@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; }
Se il dispositivo supporta l'HDR, isHLGSupported() restituisce sempre true. Per saperne di più, consulta la documentazione di riferimento di CameraCharacteristics.
Configura l'acquisizione HDR
Dopo aver verificato che il tuo dispositivo supporta l'HDR, configura l'app per acquisire uno stream video HDR non elaborato dalla fotocamera. Utilizza setDynamicRangeProfile() per fornire a OutputConfiguration dello stream un profilo HDR supportato dal dispositivo, che viene poi passato a CameraCaptureSession al momento della creazione. Consulta l'elenco dei profili HDR supportati.
Nel seguente esempio di codice, setupSessionDynamicRangeProfile() verifica innanzitutto che sul dispositivo sia installato Android 13. Poi, configura
CameraCaptureSession con il profilo HDR supportato dal dispositivo come
OutputConfiguration:
/**
* 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
}
}
Quando l'app Fotocamera inizializza la fotocamera, invia un CaptureRequest ripetuto per visualizzare l'anteprima della registrazione:
session.setRepeatingRequest(previewRequest, null, cameraHandler)
E anche per avviare la registrazione video:
// 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)
Codifica lo stream della videocamera HDR
Per codificare lo stream della videocamera HDR e scrivere il file sul disco, utilizza
MediaCodec.
Innanzitutto, ottieni l'output Surface, che mappa a un buffer che memorizza i dati video non elaborati. Per MediaCodec, utilizza createInputSurface().
Per inizializzare MediaCodec, un'app deve creare un MediaFormat con un profilo codec, uno spazio dei colori, una gamma di colori e una funzione di trasferimento specificati:
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)
Per maggiori dettagli sull'implementazione, consulta il file EncoderWrapper.kt dell'app di esempio Camera2Video.
Formati HDR
A partire da Android 13, i dispositivi con fotocamera con funzionalità di output a 10 bit devono supportare HLG10 per l'acquisizione e la riproduzione HDR. Inoltre, i produttori di dispositivi possono attivare qualsiasi formato HDR di loro scelta utilizzando l'architettura di acquisizione HDR.
La tabella seguente riassume i formati HDR disponibili e le relative funzionalità per l'acquisizione di video HDR.
| Formato | Funzione di trasferimento (TF) | Metadati | Codec | Profondità di bit |
|---|---|---|---|---|
| HLG10 | HLG | No | HEVC | 10 bit |
| HDR10 | PQ | Statico | HEVC | 10 bit |
| HDR10+ | PQ | Dinamico | HEVC | 10 bit |
| Dolby Vision 8.4 | HLG | Dinamico | HEVC | 10 bit |
Risorse
Per un'app funzionante con funzionalità di acquisizione video HDR, consulta l'esempio Camera2Video su GitHub.