Android 10 introduce API di gestione dei buffer HAL3 della videocamera facoltative che ti consentono di implementare la logica di gestione dei buffer per ottenere diversi compromessi tra memoria e latenza di acquisizione nelle implementazioni HAL della videocamera.
L'HAL della fotocamera richiede N richieste (dove N è uguale alla profondità della pipeline) in coda nella pipeline, ma spesso non richiede tutti gli N set di buffer di output contemporaneamente.
Ad esempio, l'HAL potrebbe avere otto richieste in coda nella pipeline, ma richiede buffer di output solo per le due richieste nelle fasi finali della pipeline. Sui dispositivi con Android 9 e versioni precedenti, il framework della videocamera alloca i buffer quando la richiesta viene accodata nell'HAL, quindi potrebbero esserci sei set di buffer nell'HAL che non sono in uso. In Android 10, le API di gestione dei buffer HAL3 della fotocamera consentono di separare i buffer di output per liberare i sei set di buffer. Ciò può portare a un risparmio di centinaia di megabyte di memoria sui dispositivi di fascia alta e può essere utile anche per i dispositivi con poca memoria.
La Figura 1 mostra un diagramma dell'interfaccia HAL della videocamera per i dispositivi con Android 9 e versioni precedenti. La figura 2 mostra l'interfaccia HAL della fotocamera in Android 10 con le API di gestione dei buffer HAL3 della fotocamera implementate.
Figura 1. Interfaccia HAL della fotocamera in Android 9 e versioni precedenti
Figura 2. Interfaccia HAL della fotocamera in Android 10 che utilizza le API di gestione dei buffer
Implementa le API di gestione dei buffer
Per implementare le API di gestione dei buffer, l'HAL della videocamera deve:
- Implementa HIDL
ICameraDevice@3.5
. - Imposta la chiave delle caratteristiche della fotocamera
android.info.supportedBufferManagementVersion
suHIDL_DEVICE_3_5
.
L'HAL della fotocamera utilizza i metodi
requestStreamBuffers
e
returnStreamBuffers
in
ICameraDeviceCallback.hal
per richiedere e restituire i buffer. L'HAL deve anche implementare il metodo
signalStreamFlush
in
ICameraDeviceSession.hal
per segnalare all'HAL della videocamera di restituire i buffer.
requestStreamBuffers
Utilizza il metodo
requestStreamBuffers
per richiedere buffer dal framework della videocamera. Quando utilizzi le API di gestione dei buffer HAL3 della fotocamera, le richieste di acquisizione dal framework della fotocamera non contengono buffer di output, ovvero il campo bufferId
in StreamBuffer
è 0
. Pertanto, l'HAL della fotocamera deve utilizzare requestStreamBuffers
per richiedere
i buffer dal framework della fotocamera.
Il metodo requestStreamBuffers
consente al chiamante di richiedere più buffer
da più flussi di output in una singola chiamata, consentendo un numero inferiore di chiamate
HIDL IPC. Tuttavia, le chiamate richiedono più tempo quando vengono richiesti più buffer contemporaneamente e ciò potrebbe influire negativamente sulla latenza totale dalla richiesta al risultato.
Inoltre, poiché le chiamate a requestStreamBuffers
vengono serializzate nel servizio della videocamera, è consigliabile che l'HAL della videocamera utilizzi un thread dedicato ad alta priorità per richiedere i buffer.
Se una richiesta di buffer non va a buon fine, l'HAL della fotocamera deve essere in grado di gestire correttamente gli errori non fatali. L'elenco seguente descrive i motivi comuni per cui le richieste di buffer non vanno a buon fine e come devono essere gestite dall'HAL della fotocamera.
- L'app si disconnette dallo stream di output:
Si tratta di un errore non irreversibile. L'HAL della videocamera deve inviare
ERROR_REQUEST
per qualsiasi richiesta di acquisizione che ha come target uno stream disconnesso ed essere pronto a elaborare normalmente le richieste successive. - Timeout:questo può verificarsi quando un'app è impegnata in un'elaborazione intensiva mentre mantiene alcuni buffer. L'HAL della fotocamera deve
inviare
ERROR_REQUEST
per le richieste di acquisizione che non possono essere soddisfatte a causa di un errore di timeout ed essere pronto a elaborare normalmente le richieste successive. - Il framework della videocamera sta preparando una nuova configurazione dello stream:
l'HAL della videocamera deve attendere il completamento della successiva chiamata
configureStreams
prima di chiamare di nuovorequestStreamBuffers
. - L'HAL della videocamera ha raggiunto il
limite del buffer
(il campo
maxBuffers
): l'HAL della videocamera deve attendere di restituire almeno un buffer dello stream prima di chiamare di nuovorequestStreamBuffers
.
returnStreamBuffers
Utilizza il metodo
returnStreamBuffers
per restituire i buffer aggiuntivi al framework della videocamera. Normalmente, la fotocamera HAL
restituisce i buffer al framework della fotocamera tramite il metodo
processCaptureResult
, ma può tenere conto solo delle richieste di acquisizione inviate alla
fotocamera HAL. Con il metodo requestStreamBuffers
, l'implementazione HAL della videocamera può conservare più buffer di quelli richiesti dal framework della videocamera. È in questi casi che conviene utilizzare il metodo returnStreamBuffers
. Se l'implementazione HAL non contiene mai più buffer di quelli richiesti, l'implementazione HAL della videocamera non deve chiamare il metodo returnStreamBuffers
.
signalStreamFlush
Il metodo
signalStreamFlush
viene chiamato dal framework della videocamera per notificare all'HAL della videocamera di restituire tutti
i buffer a disposizione. Questo metodo viene normalmente chiamato quando il framework della videocamera sta per
chiamare
configureStreams
e deve svuotare la pipeline di acquisizione della videocamera. Analogamente al metodo returnStreamBuffers
, se un'implementazione HAL della fotocamera non contiene più buffer di quelli richiesti, è possibile avere un'implementazione vuota di questo metodo.
Dopo che il framework della videocamera chiama
signalStreamFlush
,
il framework smette di inviare nuove richieste di acquisizione all'HAL della videocamera finché tutti
i buffer non vengono restituiti al framework della videocamera. Quando tutti i buffer vengono
restituiti, le chiamate al metodo requestStreamBuffers
non vanno a buon fine e il framework della videocamera
può continuare il suo lavoro in uno stato pulito. Il framework della videocamera chiama quindi il metodo configureStreams
o processCaptureRequest
. Se il framework della videocamera chiama il metodo configureStreams
, l'HAL della videocamera
può iniziare a richiedere nuovamente i buffer dopo che la chiamata configureStreams
viene restituita
correttamente. Se il framework della fotocamera chiama il metodo processCaptureRequest
,
l'HAL della fotocamera può iniziare a richiedere buffer durante la chiamata processCaptureRequest
.
La semantica è diversa per il metodo signalStreamFlush
e per il metodo
flush
. Quando viene chiamato il metodo flush
, l'HAL può interrompere le richieste di acquisizione in attesa con
ERROR_REQUEST
per svuotare la pipeline il prima possibile. Quando viene chiamato il metodo signalStreamFlush
, l'HAL deve completare normalmente tutte le richieste di acquisizione in attesa e restituire tutti i buffer al framework della fotocamera.
Un'altra differenza tra il metodo signalStreamFlush
e gli altri metodi è che signalStreamFlush
è un metodo HIDL unidirezionale, il che significa che il framework della videocamera potrebbe chiamare altre API di blocco prima che l'HAL riceva la chiamata signalStreamFlush
. Ciò significa che
il metodo signalStreamFlush
e altri metodi (in particolare il
metodo configureStreams
) potrebbero arrivare all'HAL della fotocamera in un ordine diverso
rispetto all'ordine in cui sono stati chiamati nel framework della fotocamera. Per risolvere questo problema di
asincronia, il campo streamConfigCounter
è stato aggiunto a
StreamConfiguration
ed è stato aggiunto come argomento al metodo
signalStreamFlush
. L'implementazione dell'HAL della fotocamera deve utilizzare l'argomento streamConfigCounter
per determinare se una chiamata signalStreamFlush
arriva dopo la chiamata configureStreams
corrispondente. Vedi un esempio nella Figura 3.
Figura 3. In che modo l'HAL della videocamera deve rilevare e gestire le chiamate signalStreamFlush che arrivano in ritardo
Modifiche al comportamento durante l'implementazione delle API di gestione del buffer
Quando utilizzi le API di gestione del buffer per implementare la logica di gestione del buffer, considera i seguenti possibili cambiamenti di comportamento della fotocamera e dell'implementazione HAL della fotocamera:
Le richieste di acquisizione arrivano all'HAL della videocamera più velocemente e più frequentemente:senza le API di gestione dei buffer, il framework della videocamera richiede buffer di output per ogni richiesta di acquisizione prima di inviare una richiesta di acquisizione all'HAL della videocamera. Quando si utilizzano le API di gestione dei buffer, il framework della fotocamera non deve più attendere i buffer e può quindi inviare richieste di acquisizione all'HAL della fotocamera in precedenza.
Inoltre, senza le API di gestione dei buffer, il framework della videocamera smette di inviare richieste di acquisizione se uno degli stream di output della richiesta di acquisizione ha raggiunto il numero massimo di buffer che l'HAL può contenere contemporaneamente (questo valore è designato dall'HAL della videocamera nel campo
HalStream::maxBuffers
nel valore restituito di una chiamataconfigureStreams
). Con le API di gestione del buffer, questo comportamento di limitazione non esiste più e l'implementazione HAL della fotocamera non deve accettare chiamateprocessCaptureRequest
quando HAL ha troppe richieste di acquisizione in coda.La latenza delle chiamate
requestStreamBuffers
varia in modo significativo:ci sono molti motivi per cui una chiamatarequestStreamBuffers
potrebbe richiedere più tempo della media. Ad esempio:- Per i primi buffer di un flusso appena creato, le chiamate possono richiedere più tempo perché il dispositivo deve allocare la memoria.
- La latenza prevista aumenta in proporzione al numero di buffer richiesti in ogni chiamata.
- L'app sta memorizzando i buffer ed è impegnata nell'elaborazione. Ciò può causare un rallentamento o un timeout delle richieste di buffer a causa di una mancanza di buffer o di una CPU occupata.
Strategie di gestione del buffer
Le API di gestione dei buffer consentono di implementare diversi tipi di strategie di gestione dei buffer. Ecco alcuni esempi:
- Compatibile con le versioni precedenti: l'HAL richiede buffer per una richiesta di acquisizione
durante la chiamata
processCaptureRequest
. Questa strategia non offre alcun risparmio di memoria, ma può fungere da prima implementazione delle API di gestione dei buffer, richiedendo pochissime modifiche al codice dell'HAL della fotocamera esistente. - Risparmio di memoria massimizzato:l'HAL della fotocamera richiede buffer di output immediatamente prima che sia necessario riempirne uno. Questa strategia consente di massimizzare il risparmio di memoria. Il potenziale svantaggio è un maggiore sfarfallio della pipeline della videocamera quando le richieste di buffer richiedono un tempo insolitamente lungo per essere completate.
- Memorizzato nella cache:l'HAL della videocamera memorizza nella cache alcuni buffer in modo che sia meno probabile che venga interessato da una richiesta di buffer lenta occasionale.
L'HAL della fotocamera può adottare strategie diverse per casi d'uso particolari, ad esempio utilizzando la strategia di risparmio di memoria massimizzato per i casi d'uso che utilizzano molta memoria e la strategia compatibile con le versioni precedenti per altri casi d'uso.
Esempio di implementazione nell'HAL della fotocamera esterna
L'HAL della videocamera esterna è stato introdotto in Android 9 e si trova nell'albero delle origini all'indirizzo
hardware/interfaces/camera/device/3.5/
.
In Android 10 è stato aggiornato per includere
ExternalCameraDeviceSession.cpp
,
un'implementazione dell'API di gestione dei buffer. Questo HAL della videocamera esterna
implementa la strategia di risparmio di memoria massimizzato menzionata in Strategie di gestione dei buffer in poche centinaia di righe di
codice C++.