API kecepatan frame memungkinkan aplikasi memberi tahu platform Android tentang kecepatan frame yang diinginkannya dan tersedia di aplikasi yang menargetkan Android 11 (level API 30) atau yang lebih tinggi. Biasanya, sebagian besar perangkat hanya mendukung satu rasio pembaruan tampilan, biasanya 60 Hz, tetapi hal ini telah berubah. Sekarang banyak perangkat mendukung rasio pembaruan tambahan seperti 90 Hz atau 120 Hz. Beberapa perangkat mendukung peralihan kecepatan refresh yang lancar, sementara perangkat lain menampilkan layar hitam sebentar, biasanya selama satu detik.
Tujuan utama API ini adalah agar aplikasi dapat memanfaatkan semua rasio pembaruan tampilan yang didukung dengan lebih baik. Misalnya, aplikasi yang memutar video 24 Hz yang memanggil setFrameRate()
dapat menyebabkan perangkat mengubah rasio refresh layar dari 60 Hz menjadi 120 Hz. Kecepatan refresh baru ini memungkinkan pemutaran video 24 Hz yang lancar dan bebas gangguan, tanpa perlu penarikan 3:2 seperti yang diperlukan untuk memutar video yang sama di layar 60 Hz. Hal ini menghasilkan pengalaman pengguna yang lebih baik.
Penggunaan dasar
Android menyediakan beberapa cara untuk mengakses dan mengontrol permukaan, sehingga terdapat beberapa versi setFrameRate()
API. Setiap versi API menggunakan
parameter yang sama dan berfungsi sama seperti yang lain:
Surface.setFrameRate()
SurfaceControl.Transaction.setFrameRate()
ANativeWindow_setFrameRate()
ASurfaceTransaction_setFrameRate()
Aplikasi tidak perlu mempertimbangkan kecepatan refresh layar yang didukung sebenarnya, yang dapat diperoleh dengan memanggil
Display.getSupportedModes()
,
agar dapat memanggil setFrameRate()
dengan aman. Misalnya, meskipun perangkat hanya mendukung 60 Hz, panggil setFrameRate()
dengan kecepatan frame yang diinginkan aplikasi Anda.
Perangkat yang tidak memiliki kecocokan yang lebih baik untuk kecepatan frame aplikasi akan tetap menggunakan kecepatan refresh layar saat ini.
Untuk melihat apakah panggilan ke setFrameRate()
menghasilkan perubahan pada kecepatan refresh tampilan, daftarkan notifikasi perubahan tampilan dengan memanggil
DisplayManager.registerDisplayListener()
atau AChoreographer_registerRefreshRateCallback()
.
Saat memanggil setFrameRate()
, sebaiknya teruskan frekuensi frame yang tepat, bukan membulatkannya ke bilangan bulat. Misalnya, saat merender video yang direkam pada
29,97 Hz, teruskan 29,97, bukan membulatkannya menjadi 30.
Untuk aplikasi video, parameter kompatibilitas yang diteruskan ke setFrameRate()
harus ditetapkan
ke Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
untuk memberikan petunjuk tambahan kepada
platform Android bahwa aplikasi akan menggunakan pull-down untuk beradaptasi dengan kecepatan refresh layar yang tidak cocok (yang akan menyebabkan guncangan).
Dalam beberapa skenario, platform video akan berhenti mengirimkan frame, tetapi akan tetap
terlihat di layar selama beberapa waktu. Skenario umum mencakup saat pemutaran mencapai akhir video atau saat pengguna menjeda pemutaran. Dalam kasus ini,
panggil setFrameRate()
dengan parameter kecepatan frame yang disetel ke 0 untuk menghapus setelan kecepatan frame permukaan kembali ke nilai default. Menghapus setelan kecepatan frame
seperti ini tidak diperlukan saat menghancurkan platform, atau saat platform
disembunyikan karena pengguna beralih ke aplikasi lain. Hapus setelan kecepatan frame
hanya saat platform tetap terlihat tanpa digunakan.
Pengalihan frame rate yang tidak lancar
Pada beberapa perangkat, peralihan kecepatan refresh mungkin mengalami gangguan visual seperti layar
hitam selama satu atau dua detik. Hal ini biasanya terjadi pada dekoder, panel TV, dan perangkat serupa. Secara default, framework Android tidak beralih mode
saat API Surface.setFrameRate()
dipanggil, untuk menghindari gangguan visual tersebut.
Beberapa pengguna lebih menyukai gangguan visual di awal dan akhir video yang lebih panjang. Hal ini memungkinkan kecepatan refresh layar cocok dengan kecepatan frame video, dan menghindari artefak konversi kecepatan frame seperti jeda 3:2 untuk pemutaran film.
Oleh karena itu, peralihan kecepatan refresh yang tidak lancar dapat diaktifkan jika pengguna dan aplikasi memilih untuk mengaktifkannya:
- Pengguna: Untuk ikut serta, pengguna dapat mengaktifkan setelan pengguna Cocokkan kecepatan frame konten.
- Aplikasi: Untuk mengaktifkan fitur ini, aplikasi dapat meneruskan
CHANGE_FRAME_RATE_ALWAYS
kesetFrameRate()
.
Sebaiknya Anda selalu menggunakan CHANGE_FRAME_RATE_ALWAYS
untuk video yang panjang seperti film. Hal ini karena manfaat mencocokkan kecepatan frame video lebih besar daripada gangguan yang terjadi saat mengubah kecepatan refresh.
Rekomendasi tambahan
Ikuti rekomendasi berikut untuk skenario umum.
Beberapa permukaan
Platform Android didesain untuk menangani skenario dengan benar jika ada
beberapa platform dengan setelan kecepatan frame yang berbeda. Jika aplikasi Anda memiliki beberapa platform dengan kecepatan frame yang berbeda, panggil setFrameRate()
dengan kecepatan frame yang benar untuk setiap platform. Meskipun perangkat menjalankan beberapa aplikasi sekaligus, menggunakan mode layar terpisah atau picture-in-picture, setiap aplikasi dapat memanggil setFrameRate()
dengan aman untuk platformnya sendiri.
Platform tidak berubah ke kecepatan frame aplikasi
Meskipun perangkat mendukung kecepatan frame yang ditentukan aplikasi dalam panggilan ke
setFrameRate()
, ada kasus saat perangkat tidak akan mengalihkan tampilan ke
kecepatan refresh tersebut. Misalnya, platform prioritas yang lebih tinggi mungkin memiliki setelan kecepatan frame yang berbeda, atau perangkat mungkin dalam mode penghemat baterai (menetapkan batasan pada kecepatan refresh layar untuk menghemat baterai). Aplikasi harus tetap berfungsi dengan benar saat perangkat tidak mengalihkan kecepatan refresh layar ke setelan kecepatan frame aplikasi, meskipun perangkat mengalihkan kecepatan refresh layar dalam keadaan normal.
Aplikasi dapat memutuskan cara merespons saat kecepatan refresh layar tidak cocok dengan kecepatan frame aplikasi. Untuk video, kecepatan frame ditetapkan ke kecepatan frame video sumber, dan pulldown akan diperlukan untuk menampilkan konten video. Game
dapat memilih untuk mencoba berjalan pada kecepatan refresh layar, bukan
tetap menggunakan kecepatan frame yang diinginkan. Aplikasi tidak boleh mengubah nilai yang diteruskan ke setFrameRate()
berdasarkan tindakan platform. Setelan ini harus tetap disetel
ke kecepatan frame pilihan aplikasi, terlepas dari cara aplikasi menangani kasus saat
platform tidak menyesuaikan untuk mencocokkan permintaan aplikasi. Dengan begitu, jika kondisi perangkat berubah sehingga memungkinkan penggunaan kecepatan refresh tampilan tambahan, platform akan memiliki informasi yang benar untuk beralih ke kecepatan frame pilihan aplikasi.
Jika aplikasi tidak akan atau tidak dapat berjalan pada kecepatan refresh layar, aplikasi harus menentukan stempel waktu presentasi untuk setiap frame, menggunakan salah satu mekanisme platform untuk menyetel stempel waktu presentasi:
Dengan menggunakan stempel waktu ini, platform tidak akan menampilkan frame aplikasi terlalu awal, yang akan menyebabkan jiter yang tidak perlu. Penggunaan stempel waktu presentasi frame yang benar agak rumit. Untuk game, lihat panduan pengaturan kecepatan frame kami untuk mengetahui info selengkapnya tentang cara menghindari tersendat, dan pertimbangkan untuk menggunakan library Frame Pacing Android.
Dalam beberapa kasus, platform dapat beralih ke kelipatan kecepatan frame yang ditentukan aplikasi di setFrameRate()
. Misalnya, aplikasi dapat memanggil setFrameRate()
dengan 60 Hz dan perangkat dapat mengalihkan tampilan ke 120 Hz. Salah satu alasan hal ini dapat terjadi adalah jika aplikasi lain memiliki platform dengan setelan kecepatan frame 24 Hz. Dalam
hal ini, menjalankan layar pada 120 Hz akan memungkinkan platform 60 Hz dan
24 Hz berjalan tanpa memerlukan penarikan ke bawah.
Saat berjalan pada kelipatan kecepatan frame aplikasi, aplikasi harus menentukan stempel waktu presentasi untuk setiap frame guna menghindari jeda yang tidak perlu. Untuk game, library Android Frame Pacing berguna untuk menyetel stempel waktu presentasi frame dengan benar.
setFrameRate() vs. preferredDisplayModeId
WindowManager.LayoutParams.preferredDisplayModeId
adalah cara lain bagi aplikasi untuk menunjukkan kecepatan frame ke platform. Beberapa
aplikasi hanya ingin mengubah kecepatan refresh layar, bukan mengubah setelan
mode tampilan lainnya, seperti resolusi layar. Secara umum, gunakan
setFrameRate()
, bukan preferredDisplayModeId
. Fungsi setFrameRate()
lebih mudah digunakan karena aplikasi tidak perlu menelusuri daftar mode tampilan untuk menemukan mode dengan kecepatan frame tertentu.
setFrameRate()
memberi platform lebih banyak peluang untuk memilih kecepatan frame yang kompatibel dalam skenario ketika ada beberapa platform yang berjalan pada kecepatan frame yang berbeda. Misalnya, pertimbangkan skenario saat dua aplikasi berjalan dalam mode layar terpisah di Pixel 4, dengan satu aplikasi memutar video 24 Hz dan aplikasi lainnya menampilkan daftar yang dapat di-scroll kepada pengguna. Pixel 4 mendukung dua kecepatan refresh layar: 60 Hz dan 90 Hz. Dengan menggunakan API preferredDisplayModeId
, permukaan video dipaksa untuk memilih 60 Hz atau 90 Hz. Dengan memanggil
setFrameRate()
dengan 24 Hz, permukaan video memberikan lebih banyak
informasi tentang kecepatan frame video sumber kepada platform, sehingga platform dapat
memilih 90 Hz untuk kecepatan refresh layar, yang lebih baik daripada 60 Hz dalam
skenario ini.
Namun, ada skenario saat preferredDisplayModeId
harus digunakan
alih-alih setFrameRate()
, seperti berikut:
- Jika aplikasi ingin mengubah resolusi atau setelan mode tampilan lainnya,
gunakan
preferredDisplayModeId
. - Platform hanya akan beralih mode tampilan sebagai respons terhadap panggilan ke
setFrameRate()
jika peralihan mode ringan dan kemungkinan tidak terlihat oleh pengguna. Jika aplikasi lebih memilih untuk mengganti kecepatan refresh layar meskipun memerlukan peralihan mode yang berat (misalnya, di perangkat Android TV), gunakanpreferredDisplayModeId
. - Aplikasi yang tidak dapat menangani tampilan yang berjalan pada kelipatan kecepatan frame aplikasi, yang memerlukan setelan stempel waktu presentasi pada setiap frame, harus menggunakan
preferredDisplayModeId
.
setFrameRate() vs. preferredRefreshRate
WindowManager.LayoutParams#preferredRefreshRate
menetapkan kecepatan frame pilihan di jendela aplikasi, dan kecepatan ini berlaku
untuk semua permukaan dalam jendela. Aplikasi harus menentukan kecepatan frame yang diinginkan, terlepas dari kecepatan refresh yang didukung perangkat, mirip dengan setFrameRate()
, untuk memberikan petunjuk yang lebih baik kepada penjadwal tentang kecepatan frame yang diinginkan aplikasi.
preferredRefreshRate
diabaikan untuk Platform yang menggunakan setFrameRate()
. Secara umum, gunakan setFrameRate()
jika memungkinkan.
preferredRefreshRate vs. preferredDisplayModeId
Jika aplikasi hanya ingin mengubah kecepatan refresh pilihan, sebaiknya gunakan
preferredRefreshRate
, bukan preferredDisplayModeId
.
Menghindari pemanggilan setFrameRate() terlalu sering
Meskipun panggilan setFrameRate()
tidak terlalu mahal dalam hal performa, aplikasi harus menghindari pemanggilan setFrameRate()
setiap frame atau beberapa kali per detik. Panggilan ke setFrameRate()
kemungkinan akan menyebabkan perubahan pada kecepatan refresh layar, yang dapat menyebabkan penurunan frame selama transisi.
Anda harus menentukan kecepatan frame yang benar sebelumnya dan memanggil
setFrameRate()
sekali.
Penggunaan untuk game atau aplikasi non-video lainnya
Meskipun video adalah kasus penggunaan utama untuk setFrameRate()
API, API ini dapat digunakan untuk aplikasi lain. Misalnya, game yang tidak ingin berjalan lebih tinggi dari
60 Hz (untuk mengurangi penggunaan daya dan mencapai sesi permainan yang lebih lama) dapat memanggil
Surface.setFrameRate(60, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT)
. Dengan
cara ini, perangkat yang berjalan pada 90 Hz secara default akan berjalan pada 60 Hz saat
game aktif, sehingga menghindari guncangan yang akan terjadi jika
game berjalan pada 60 Hz saat layar berjalan pada 90 Hz.
Penggunaan FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
hanya ditujukan untuk aplikasi video. Untuk
penggunaan non-video, gunakan FRAME_RATE_COMPATIBILITY_DEFAULT
.
Memilih strategi untuk mengubah kecepatan frame
- Sebaiknya aplikasi, saat menampilkan video yang berjalan lama seperti
film, memanggil
setFrameRate(
fps, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS)
dengan fps adalah kecepatan frame video. - Sebaiknya jangan panggil
setFrameRate()
denganCHANGE_FRAME_RATE_ALWAYS
jika Anda memperkirakan pemutaran video akan berlangsung selama beberapa menit atau kurang.
Contoh integrasi untuk aplikasi pemutaran video
Sebaiknya ikuti langkah-langkah berikut untuk mengintegrasikan peralihan kecepatan refresh di aplikasi pemutaran video:
- Tentukan
changeFrameRateStrategy
:- Jika memutar video yang panjang seperti film, gunakan
MATCH_CONTENT_FRAMERATE_ALWAYS
- Jika memutar video singkat seperti trailer film, gunakan
CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS
- Jika memutar video yang panjang seperti film, gunakan
- Jika
changeFrameRateStrategy
adalahCHANGE_FRAME_RATE_ONLY_IF_SEAMLESS
, lanjutkan ke langkah 4. - Deteksi apakah peralihan kecepatan refresh yang tidak lancar akan terjadi dengan memeriksa
bahwa kedua fakta ini benar:
- Peralihan mode yang lancar tidak dapat dilakukan dari kecepatan refresh saat ini (sebut saja C) ke kecepatan frame video (sebut saja V). Hal ini akan
terjadi jika C dan V berbeda dan
Display.getMode().getAlternativeRefreshRates
tidak berisi kelipatan V. - Pengguna telah memilih untuk mengaktifkan perubahan kecepatan refresh yang tidak lancar. Anda dapat mendeteksinya dengan memeriksa apakah
DisplayManager.getMatchContentFrameRateUserPreference
menampilkanMATCH_CONTENT_FRAMERATE_ALWAYS
- Peralihan mode yang lancar tidak dapat dilakukan dari kecepatan refresh saat ini (sebut saja C) ke kecepatan frame video (sebut saja V). Hal ini akan
terjadi jika C dan V berbeda dan
- Jika peralihan akan dilakukan secara lancar, lakukan hal berikut:
- Panggil
setFrameRate
dan teruskanfps
,FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
, danchangeFrameRateStrategy
, denganfps
adalah kecepatan frame video. - Mulai pemutaran video
- Panggil
- Jika perubahan mode non-mulus akan terjadi, lakukan hal berikut:
- Tampilkan UX untuk memberi tahu pengguna. Perhatikan bahwa sebaiknya Anda menerapkan cara agar pengguna dapat menutup UX ini dan melewati penundaan tambahan di langkah 5.d. Hal ini terjadi karena penundaan yang kami rekomendasikan lebih besar dari yang diperlukan pada layar yang menunjukkan waktu peralihan yang lebih cepat.
- Panggil
setFrameRate
dan teruskanfps
,FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
, danCHANGE_FRAME_RATE_ALWAYS
, denganfps
adalah kecepatan frame video. - Tunggu callback
onDisplayChanged
. - Tunggu 2 detik hingga peralihan mode selesai.
- Mulai pemutaran video
Kode semu untuk mendukung pengalihan yang lancar saja adalah sebagai berikut:
SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
transaction.setFrameRate(surfaceControl,
contentFrameRate,
FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
transaction.apply();
beginPlayback();
Kode semu untuk mendukung peralihan yang lancar dan tidak lancar seperti yang dijelaskan di atas adalah sebagai berikut:
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();
}