L'API Frame Rate consente alle app di comunicare alla piattaforma Android il frame previsto ed è disponibile su app destinate ad Android 11 (livello API 30) o versioni successive. In genere, la maggior parte dei dispositivi supporta una sola frequenza di aggiornamento del display, tipicamente a 60 Hz, ma la situazione è cambiata. Molti dispositivi ora supportano di aggiornamento, come 90 Hz o 120 Hz. Alcuni dispositivi supportano una frequenza di aggiornamento continua mentre altri mostrano brevemente uno schermo nero, che in genere dura un secondo.
Lo scopo principale dell'API è consentire alle app di sfruttare al meglio tutti
le frequenze di aggiornamento del display supportate. Ad esempio, un'app che riproduce un video a 24 Hz
la chiamata a setFrameRate()
potrebbe comportare la modifica del display del dispositivo
frequenza di aggiornamento da 60 Hz a 120 Hz. Questa nuova frequenza di aggiornamento consente
Riproduzione senza sbalzi di video a 24 Hz, senza necessità di pulldown 3:2, come si farebbe
necessaria per riprodurre lo stesso video su un display a 60 Hz. Ciò si traduce in un miglioramento dell'esperienza utente
un'esperienza senza intervento manuale.
Utilizzo di base
Android presenta diversi modi per accedere alle piattaforme e controllarle, quindi ci sono
diverse versioni dell'API setFrameRate()
. Ogni versione dell'API utilizza
ha gli stessi parametri e funziona esattamente come gli altri:
Surface.setFrameRate()
SurfaceControl.Transaction.setFrameRate()
ANativeWindow_setFrameRate()
ASurfaceTransaction_setFrameRate()
L'app non deve considerare le effettive frequenze di aggiornamento del display supportate,
che puoi ottenere chiamando
Display.getSupportedModes()
,
per chiamare in sicurezza setFrameRate()
. Ad esempio, anche se il dispositivo
supporta 60 Hz, chiama setFrameRate()
con la frequenza fotogrammi preferita dalla tua app.
I dispositivi che non corrispondono meglio alla frequenza frame dell'app rimarranno su
l'attuale frequenza di aggiornamento.
Per verificare se una chiamata a setFrameRate()
determina una modifica dell'aggiornamento della visualizzazione
, registrati per ricevere le notifiche di modifica del display chiamando
DisplayManager.registerDisplayListener()
o AChoreographer_registerRefreshRateCallback()
.
Quando chiami il numero setFrameRate()
, è meglio passare la frequenza fotogrammi esatta anziché
rispetto all'arrotondamento a un numero intero. Ad esempio, quando esegui il rendering di un video registrato
29,97 Hz, passa a 29,97 anziché arrotondare a 30.
Per le app video, è necessario impostare il parametro di compatibilità trasmesso a setFrameRate()
a Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
per fornire un ulteriore suggerimento
la piattaforma Android che l'app utilizzerà il menu a discesa per adattarsi a una
frequenza di aggiornamento del display (che comporterà sbalzi).
In alcuni scenari, la piattaforma video interromperà l'invio dei frame, ma rimarrà
visibile sullo schermo per un po' di tempo. Gli scenari più comuni sono la riproduzione
raggiunge la fine del video o quando l'utente mette in pausa la riproduzione. In questi casi,
chiama setFrameRate()
con il parametro della frequenza fotogrammi impostato su 0 per cancellare il
ripristinare la frequenza fotogrammi al valore predefinito. Annullare l'impostazione della frequenza fotogrammi
come questa non è necessaria quando si distrugge la superficie o quando la superficie
nascosto perché l'utente passa a un'altra app. Cancella la frequenza fotogrammi
solo quando la superficie rimane visibile senza essere utilizzata.
Cambio di frequenza fotogrammi senza interruzioni
Su alcuni dispositivi, il cambio di frequenza di aggiornamento potrebbe presentare interruzioni visive, ad esempio il colore nero
schermo per un secondo o due. Questo solitamente si verifica su decoder, pannelli TV,
e dispositivi simili. Per impostazione predefinita, il framework Android non cambia modalità
quando Surface.setFrameRate()
viene chiamata l'API per evitare queste interruzioni visive.
Alcuni utenti preferiscono un'interruzione visiva all'inizio alla fine dei video più lunghi. In questo modo la frequenza di aggiornamento del display corrisponde la frequenza fotogrammi del video ed evitare artefatti di conversione da frequenza fotogrammi, come 3:2 menu a discesa per la riproduzione di film.
Per questo motivo, è possibile attivare i sensori della frequenza di aggiornamento non continui se sono attivazione di utenti e app:
- Utenti: per attivare questa opzione, gli utenti possono attivare l'opzione Adatta alla frequenza fotogrammi dei contenuti. dell'ambientazione.
- App: per attivarle, le app possono passare
CHANGE_FRAME_RATE_ALWAYS
: insetFrameRate()
.
Ti consigliamo di utilizzare sempre CHANGE_FRAME_RATE_ALWAYS
per i video di lunga durata come i film. Questo perché il vantaggio della corrispondenza
la frequenza fotogrammi del video supera l'interruzione che si verifica quando si cambia il
e la frequenza di aggiornamento.
Altri consigli
Segui questi consigli per gli scenari più comuni.
Più piattaforme
La piattaforma Android è progettata per gestire correttamente scenari in cui
più piattaforme con impostazioni
di frequenza fotogrammi diverse. Se l'app include più
piattaforme con frequenze fotogrammi diverse, chiama setFrameRate()
con il corretto
per ogni superficie. Anche se il dispositivo esegue più app in
una volta sola, usando la modalità schermo diviso o Picture in picture, ogni app può chiamare
setFrameRate()
per le proprie piattaforme.
La piattaforma non cambia la frequenza fotogrammi dell'app
Anche se il dispositivo supporta la frequenza fotogrammi specificata dall'app in una chiamata
setFrameRate()
, ci sono casi in cui il dispositivo non esegue il passaggio del display a
che la frequenza di aggiornamento. Ad esempio, una piattaforma con priorità più elevata potrebbe avere un
frequenza fotogrammi oppure il dispositivo potrebbe essere in modalità di risparmio energetico (l'impostazione di
limitazione della frequenza di aggiornamento del display per risparmiare batteria). L'app deve comunque
funzionano correttamente quando il dispositivo non passa la frequenza di aggiornamento del display
all'impostazione della frequenza frame dell'app, anche se il dispositivo passa al livello normale
circostanze.
Sta all'app decidere come rispondere al momento della frequenza di aggiornamento del display.
non corrisponde alla frequenza fotogrammi dell'app. Per i video, la frequenza fotogrammi è fissata su quella
il video sorgente e il menu a discesa sarà necessario per mostrare i contenuti del video. R
potrebbe invece scegliere di eseguire un test alla frequenza di aggiornamento del display anziché
con la sua frequenza fotogrammi preferita. L'app non deve modificarne il valore
trasmette a setFrameRate()
in base alle azioni compiute dalla piattaforma. Dovrebbe rimanere impostato
alla frequenza fotogrammi preferita dell'app, indipendentemente dal modo in cui l'app gestisce i casi in cui
la piattaforma non si adatta alla richiesta dell'app. In questo modo, se il dispositivo
cambiano le condizioni per consentire l'utilizzo di altre frequenze di aggiornamento del display,
piattaforma abbia le informazioni corrette per passare al frame preferito dell'app
di conversione.
Nei casi in cui l'app non può essere eseguita o non può essere eseguita con la frequenza di aggiornamento del display, devi specificare i timestamp della presentazione per ogni frame, utilizzando uno dei dei meccanismi della piattaforma per impostare timestamp delle presentazioni:
L'uso di questi timestamp impedisce alla piattaforma di presentare anche un frame dell'app in anticipo, il che provocherebbe urti inutili. Uso corretto del frame i timestamp della presentazione sono un po' difficili. Per i giochi, consulta le nostre guida al pacing del frame per ulteriori informazioni su come evitare i colpi di scena e considera l'utilizzo del Libreria di pacing frame Android.
In alcuni casi, la piattaforma può passare a un multiplo della frequenza fotogrammi dell'app
specificato in setFrameRate()
. Ad esempio, un'app potrebbe chiamare setFrameRate()
a 60 Hz e il dispositivo può impostare il display a 120 Hz. Uno dei motivi per cui
succede se un'altra app ha una piattaforma con una frequenza fotogrammi di 24 Hz. Nella
in questo caso, l'esecuzione del display a 120 Hz consentirà sia alla superficie a 60 Hz che
Superficie a 24 Hz per l'esecuzione senza pulldown.
Quando il display è a un multiplo della frequenza fotogrammi dell'app, l'app devi specificare i timestamp della presentazione per ogni frame per evitare sbalorditivi. Per i giochi, la libreria del pacing del frame Android è utile per impostare i timestamp di presentazione del frame.
setFrameRate() e preferredDisplayModeId
WindowManager.LayoutParams.preferredDisplayModeId
è un altro modo con cui le app possono indicare la frequenza fotogrammi alla piattaforma. Alcune
le app vogliono modificare solo la frequenza di aggiornamento del display anziché cambiare altre
impostazioni della modalità di visualizzazione, come la risoluzione. In generale, usa
setFrameRate()
anziché preferredDisplayModeId
. setFrameRate()
è più facile da usare perché l'app non ha bisogno di eseguire ricerche nella
elenco di modalità di visualizzazione per trovare una modalità con una frequenza fotogrammi specifica.
setFrameRate()
offre alla piattaforma più opportunità di scegliere un modello compatibile
frame rate in scenari in cui sono presenti più piattaforme
diverse frequenze fotogrammi. Ad esempio, considera uno scenario in cui due app vengono
in modalità schermo diviso su Pixel 4, su cui un'app riproduce un video a 24 Hz
e l'altra mostra all'utente un elenco scorrevole. Pixel 4 supporta due
frequenza di aggiornamento del display: 60 Hz e 90 Hz. Utilizzando l'API preferredDisplayModeId
,
la superficie video deve selezionare 60 Hz o 90 Hz. Chiamando
setFrameRate()
a 24 Hz, la superficie video offre alla piattaforma più
informazioni sulla frequenza fotogrammi del video sorgente, consentendo alla piattaforma
scegliere 90 Hz per la frequenza di aggiornamento del display, migliore di 60 Hz
in questo scenario.
Tuttavia, esistono casi in cui è necessario utilizzare preferredDisplayModeId
anziché setFrameRate()
, come ad esempio:
- Se l'app vuole modificare la risoluzione o altre impostazioni della modalità di visualizzazione,
usa
preferredDisplayModeId
. - La piattaforma cambia modalità di visualizzazione solo in risposta a una chiamata a
setFrameRate()
se il cambio di modalità è leggero e probabilmente non lo è evidente per l'utente. Se l'app preferisce cambiare l'aggiornamento del display anche se richiede un'opzione di modalità Intensa (ad esempio, su un dispositivo Android TV) dispositivo), usapreferredDisplayModeId
. - App che non possono gestire il display in esecuzione in più frame dell'app
rapida, che richiede l'impostazione dei timestamp della presentazione su ogni frame,
usa
preferredDisplayModeId
.
setFrameRate() e preferredRefreshRate
WindowManager.LayoutParams#preferredRefreshRate
imposta una frequenza fotogrammi preferita nella finestra dell'app e la frequenza è applicabile
a tutte le superfici all'interno della finestra. L'app deve specificare la sua
frequenza fotogrammi indipendentemente dalle frequenze di aggiornamento supportate dal dispositivo, simile a
setFrameRate()
, per dare allo scheduler un suggerimento migliore sulle esigenze dell'app
frequenza fotogrammi.
preferredRefreshRate
viene ignorato per le piattaforme che utilizzano setFrameRate()
. Nella
uso generico di setFrameRate()
, se possibile.
preferredRefreshRate e preferredDisplayModeId
Se le app vogliono modificare solo la frequenza di aggiornamento preferita, è preferibile usare
preferredRefreshRate
anziché preferredDisplayModeId
.
Evitare di chiamare setFrameRate() troppo spesso
Anche se la chiamata a setFrameRate()
non è molto costosa in termini di prestazioni,
le app dovrebbero evitare di chiamare setFrameRate()
a ogni frame o più volte
secondo. È probabile che le chiamate a setFrameRate()
comportino una modifica al
frequenza di aggiornamento del display, che potrebbe causare
un calo dei frame durante la transizione.
Dovresti capire in anticipo la frequenza fotogrammi corretta e chiamare
setFrameRate()
una volta.
Utilizzo di giochi e altre app non video
Sebbene i video siano il caso d'uso principale per l'API setFrameRate()
, è possibile
usata per altre app. Ad esempio, un gioco che non intende essere eseguito più in alto di
60 Hz (per ridurre il consumo di energia e ottenere sessioni di riproduzione più lunghe) può chiamare
Surface.setFrameRate(60, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT)
. In questo
un dispositivo che funziona a 90 Hz per impostazione predefinita userà invece a 60 Hz mentre
che il gioco sia attivo, per evitare sbalzi che altrimenti si verificherebbero se
del gioco funzionava a 60 Hz, mentre il display a 90 Hz.
Utilizzo di FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
è destinato solo alle app video. Per
per utilizzo non video, usa FRAME_RATE_COMPATIBILITY_DEFAULT
.
Scelta di una strategia per modificare la frequenza fotogrammi
- Consigliamo vivamente alle app, quando mostrano video di lunga durata come
film, chiamata a
setFrameRate(
f/s, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS)
dove f/s è la frequenza fotogrammi del video. - Sconsigliamo vivamente di app che chiamano
setFrameRate()
conCHANGE_FRAME_RATE_ALWAYS
quando si prevede che la riproduzione del video duri diversi minuti o anche meno.
Integrazione di esempio per le app di riproduzione video
Consigliamo di seguire questi passaggi per integrare le opzioni della frequenza di aggiornamento nelle app di riproduzione video:
- Decidi i
changeFrameRateStrategy
:- Se riproduci un video di lunga durata, ad esempio un film, utilizza
MATCH_CONTENT_FRAMERATE_ALWAYS
- Se riproduci un breve video, ad esempio il trailer di un movimento, utilizza
CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS
- Se riproduci un video di lunga durata, ad esempio un film, utilizza
- Se
changeFrameRateStrategy
èCHANGE_FRAME_RATE_ONLY_IF_SEAMLESS
, vai al passaggio 4. - Rileva se sta per verificarsi un cambio di frequenza di aggiornamento non continuo controllando
che entrambe le cose sono vere:
- Con la frequenza di aggiornamento corrente non è possibile cambiare modalità senza interruzioni
C) alla frequenza fotogrammi del video (che chiameremo V). In questo modo
anche se C e V sono diversi
Display.getMode().getAlternativeRefreshRates
non contiene un multiplo di V. - L'utente ha attivato le modifiche alla frequenza di aggiornamento non continue. Puoi rilevare
questo controllando se
DisplayManager.getMatchContentFrameRateUserPreference
resiMATCH_CONTENT_FRAMERATE_ALWAYS
- Con la frequenza di aggiornamento corrente non è possibile cambiare modalità senza interruzioni
C) alla frequenza fotogrammi del video (che chiameremo V). In questo modo
anche se C e V sono diversi
- Se il passaggio non avverrà senza problemi:
- Chiama il numero
setFrameRate
e lo superifps
,FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
, echangeFrameRateStrategy
, dovefps
è la frequenza fotogrammi del video. - Avvia riproduzione video
- Chiama il numero
- Se sta per essere effettuato un cambio di modalità senza soluzione di continuità:
- Mostra UX per inviare una notifica all'utente. Ti consigliamo di implementare un metodo all'utente di ignorare questa UX e saltare l'ulteriore ritardo nel passaggio 5.d. Questo è perché il ritardo consigliato è maggiore del necessario sui display che tempi di passaggio più rapidi.
- Chiama il numero
setFrameRate
e lo superifps
,FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
, eCHANGE_FRAME_RATE_ALWAYS
, dovefps
è la frequenza fotogrammi del video. - Attendi
onDisplayChanged
di Google. - Attendi 2 secondi per il completamento del passaggio alla modalità.
- Avvia riproduzione video
Lo pseudo-codice per supportare solo il passaggio senza interruzioni è il seguente:
SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
transaction.setFrameRate(surfaceControl,
contentFrameRate,
FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
transaction.apply();
beginPlayback();
Lo pseudo-codice per supportare il passaggio fluido e fluido come descritto sopra:
SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
if (isSeamlessSwitch(contentFrameRate)) {
transaction.setFrameRate(surfaceControl,
contentFrameRate,
FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
transaction.apply();
beginPlayback();
} else if (displayManager.getMatchContentFrameRateUserPreference()
== MATCH_CONTENT_FRAMERATE_ALWAYS) {
showRefreshRateSwitchUI();
sleep(shortDelaySoUserSeesUi);
displayManager.registerDisplayListener(…);
transaction.setFrameRate(surfaceControl,
contentFrameRate,
FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
CHANGE_FRAME_RATE_ALWAYS);
transaction.apply();
waitForOnDisplayChanged();
sleep(twoSeconds);
hideRefreshRateSwitchUI();
beginPlayback();
}