API kecepatan frame memungkinkan aplikasi memberi tahu platform Android tentang kecepatan frame yang diinginkan dan tersedia di aplikasi yang menargetkan Android 11 (API level 30) atau yang lebih tinggi. Secara tradisional, sebagian besar perangkat hanya mendukung satu kecepatan refresh tampilan, biasanya 60 Hz, tetapi hal ini telah berubah. Kini banyak perangkat mendukung kecepatan refresh tambahan seperti 90 Hz atau 120 Hz. Beberapa perangkat mendukung tombol kecepatan refresh yang lancar, sementara perangkat lainnya menampilkan layar hitam secara singkat, biasanya berlangsung selama satu detik.
Tujuan utama dari API ini adalah agar aplikasi dapat memanfaatkan semua
kecepatan refresh tampilan yang didukung dengan lebih baik. Misalnya, aplikasi yang memutar video 24 Hz
yang memanggil setFrameRate()
dapat menyebabkan perangkat mengubah kecepatan refresh
layar dari 60 Hz menjadi 120 Hz. Kecepatan refresh baru ini memungkinkan
pemutaran video 24 Hz yang lancar dan bebas guncangan, tanpa memerlukan pulldown 3:2 seperti yang
diperlukan untuk memutar video yang sama pada layar 60 Hz. Ini menghasilkan pengalaman pengguna
yang lebih baik.
Penggunaan dasar
Android mengekspos beberapa cara untuk mengakses dan mengontrol platform, sehingga ada
beberapa versi setFrameRate()
API. Setiap versi API menggunakan parameter yang sama dan berfungsi sama seperti versi lainnya:
Surface.setFrameRate()
SurfaceControl.Transaction.setFrameRate()
ANativeWindow_setFrameRate()
ASurfaceTransaction_setFrameRate()
Aplikasi tidak perlu mempertimbangkan kecepatan refresh tampilan sebenarnya yang didukung,
yang dapat diperoleh dengan memanggil
Display.getSupportedModes()
,
untuk 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 tampilan saat ini.
Untuk melihat apakah panggilan ke setFrameRate()
menyebabkan perubahan pada kecepatan refresh
tampilan, daftar untuk menerima notifikasi perubahan tampilan dengan memanggil
DisplayManager.registerDisplayListener()
atau AChoreographer_registerRefreshRateCallback()
.
Saat memanggil setFrameRate()
, sebaiknya teruskan kecepatan frame yang tepat, bukan
membulatkan ke bilangan bulat. Misalnya, saat merender video yang direkam pada
29,97 Hz, teruskan 29,97, bukan pembulatan ke 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 pulldown untuk beradaptasi dengan kecepatan refresh
tampilan yang tidak cocok (yang akan mengakibatkan judder).
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 ditetapkan ke 0 untuk menghapus setelan kecepatan frame
platform kembali ke nilai default. Menghapus setelan kecepatan frame
seperti ini tidak diperlukan saat menghancurkan permukaan, atau saat permukaan
tersembunyi karena pengguna beralih ke aplikasi yang berbeda. Hapus setelan kecepatan frame
hanya saat permukaan tetap terlihat tanpa digunakan.
Tombol kecepatan frame tidak lancar
Pada beberapa perangkat, pengalihan 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 Surface.setFrameRate()
API dipanggil untuk menghindari gangguan visual tersebut.
Beberapa pengguna lebih memilih gangguan visual di awal dan akhir video yang lebih panjang. Hal ini memungkinkan kecepatan refresh tampilan agar sesuai dengan kecepatan frame video, dan menghindari artefak konversi kecepatan frame seperti goyangan pulldown 3:2 untuk pemutaran film.
Karena alasan ini, tombol kecepatan refresh yang tidak lancar dapat diaktifkan jika pengguna dan aplikasi memilih ikut serta:
- Pengguna: Untuk memilih ikut serta, pengguna dapat mengaktifkan setelan pengguna Kecepatan frame konten yang cocok.
- Aplikasi: Untuk ikut serta, aplikasi dapat meneruskan
CHANGE_FRAME_RATE_ALWAYS
kesetFrameRate()
.
Sebaiknya selalu gunakan CHANGE_FRAME_RATE_ALWAYS
untuk video berdurasi 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 ini untuk skenario umum.
Beberapa platform
Platform Android dirancang untuk menangani skenario dengan benar saat 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 layar ke
kecepatan refresh tersebut. Misalnya, platform dengan prioritas yang lebih tinggi mungkin memiliki setelan
kecepatan frame yang berbeda, atau perangkat mungkin dalam mode penghemat baterai (menyetel
batasan pada kecepatan refresh layar untuk menghemat baterai). Aplikasi harus tetap
berfungsi dengan benar saat perangkat tidak mengalihkan kecepatan refresh tampilan ke
setelan kecepatan frame aplikasi, meskipun perangkat beralih dalam keadaan
normal.
Aplikasi dapat memutuskan cara merespons jika kecepatan refresh tampilan
tidak cocok dengan kecepatan frame aplikasi. Untuk video, kecepatan frame akan ditetapkan ke kecepatan
video sumber, dan pulldown akan diperlukan untuk menampilkan konten video. Sebuah
game dapat memilih untuk mencoba berjalan pada kecepatan refresh tampilan, bukan
tetap dengan kecepatan frame yang diinginkannya. Aplikasi tidak boleh mengubah nilai yang
diteruskan ke setFrameRate()
berdasarkan fungsi yang dilakukan platform. Frekuensi harus tetap
ke kecepatan frame yang diinginkan aplikasi, terlepas dari cara aplikasi menangani kasus saat
platform tidak menyesuaikan agar cocok dengan permintaan aplikasi. Dengan demikian, jika kondisi
perangkat berubah untuk memungkinkan kecepatan refresh tampilan tambahan digunakan, platform akan memiliki informasi yang benar untuk beralih ke kecepatan frame
yang diinginkan aplikasi.
Jika aplikasi tidak dapat atau tidak dapat berjalan pada kecepatan refresh tampilan, aplikasi harus menentukan stempel waktu presentasi untuk setiap frame, dengan menggunakan salah satu mekanisme platform untuk menyetel stempel waktu presentasi:
Menggunakan stempel waktu ini akan menghentikan platform menampilkan frame aplikasi terlalu awal, yang akan mengakibatkan getaran yang tidak perlu. Penggunaan stempel waktu presentasi {i> frame<i} yang benar agak rumit. Untuk game, lihat panduan kecepatan frame kami untuk mengetahui informasi selengkapnya tentang cara menghindari getaran, dan pertimbangkan untuk menggunakan library Android Frame Pacing.
Pada beberapa kasus, platform dapat beralih ke beberapa 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 mungkin
terjadi adalah jika aplikasi lain memiliki platform dengan setelan kecepatan frame 24 Hz. Dalam
hal ini, menjalankan layar pada 120 Hz akan memungkinkan permukaan 60 Hz dan
permukaan 24 Hz berjalan tanpa perlu pulldown.
Saat layar berjalan pada beberapa kecepatan frame aplikasi, aplikasi harus menentukan stempel waktu presentasi untuk setiap frame guna menghindari getaran 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 yang dapat digunakan aplikasi untuk menunjukkan kecepatan frame ke platform. Beberapa
aplikasi hanya ingin mengubah kecepatan refresh tampilan, 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, saat satu aplikasi memutar video 24 Hz
dan aplikasi lainnya menampilkan daftar yang dapat di-scroll kepada pengguna. Pixel 4 mendukung dua
kecepatan refresh tampilan: 60 Hz dan 90 Hz. Dengan menggunakan preferredDisplayModeId
API,
platform video dipaksa untuk memilih 60 Hz atau 90 Hz. Dengan memanggil
setFrameRate()
dengan 24 Hz, platform video memberi platform informasi
selengkapnya tentang kecepatan frame video sumber, sehingga platform dapat
memilih 90 Hz untuk kecepatan refresh tampilan, yang lebih baik dari 60 Hz dalam
skenario ini.
Namun, ada skenario saat preferredDisplayModeId
harus digunakan,
bukan 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 tombol mode ringan dan tidak mungkin terlihat oleh pengguna. Jika aplikasi lebih memilih untuk mengubah kecepatan refresh layar meskipun memerlukan tombol mode berat (misalnya, di perangkat Android TV), gunakanpreferredDisplayModeId
. - Aplikasi yang tidak dapat menangani tampilan yang berjalan pada beberapa kecepatan frame
aplikasi, yang memerlukan penetapan stempel waktu presentasi pada setiap frame, harus
menggunakan
preferredDisplayModeId
.
setFrameRate() vs PreferredRefreshRate
WindowManager.LayoutParams#preferredRefreshRate
menetapkan kecepatan frame yang diinginkan di jendela aplikasi, dan kecepatan tersebut berlaku
untuk semua platform dalam jendela. Aplikasi harus menentukan kecepatan frame
yang diinginkannya, terlepas dari kecepatan refresh yang didukung perangkat, seperti
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 selectedDisplayModeId
Jika aplikasi hanya ingin mengubah kecepatan refresh yang diinginkan, sebaiknya gunakan
preferredRefreshRate
, bukan preferredDisplayModeId
.
Menghindari memanggil setFrameRate() terlalu sering
Meskipun panggilan setFrameRate()
tidak terlalu mahal dalam hal performa,
aplikasi harus menghindari memanggil setFrameRate()
setiap frame atau beberapa kali per
detik. Panggilan ke setFrameRate()
kemungkinan akan mengakibatkan perubahan
pada kecepatan refresh layar, yang dapat mengakibatkan penurunan frame selama transisi.
Anda harus mengetahui 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, video dapat
digunakan untuk aplikasi lain. Misalnya, game yang bermaksud untuk tidak berjalan di atas
60 Hz (untuk mengurangi penggunaan daya dan mencapai sesi bermain 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, yang akan 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 berdurasi panjang seperti film, memanggil
setFrameRate(
fps, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS)
dengan fps adalah kecepatan frame video. - Sebaiknya jangan aplikasi yang memanggil
setFrameRate()
denganCHANGE_FRAME_RATE_ALWAYS
jika Anda memperkirakan pemutaran video akan berlangsung selama beberapa menit atau kurang.
Contoh integrasi untuk aplikasi pemutaran video
Sebaiknya langkah-langkah berikut untuk mengintegrasikan tombol kecepatan refresh di aplikasi pemutaran video:
- Tentukan
changeFrameRateStrategy
:- Jika memutar video berdurasi panjang seperti film, gunakan
MATCH_CONTENT_FRAMERATE_ALWAYS
- Jika memutar video singkat seperti cuplikan gerakan, gunakan
CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS
- Jika memutar video berdurasi panjang seperti film, gunakan
- Jika
changeFrameRateStrategy
adalahCHANGE_FRAME_RATE_ONLY_IF_SEAMLESS
, lanjutkan ke langkah 4. - Deteksi apakah tombol kecepatan refresh yang tidak lancar akan terjadi dengan memeriksa
bahwa kedua fakta ini benar:
- Beralih mode tanpa hambatan tidak dimungkinkan 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 ikut serta dalam perubahan kecepatan refresh yang tidak lancar. Anda dapat mendeteksi
hal ini dengan memeriksa apakah
DisplayManager.getMatchContentFrameRateUserPreference
menampilkanMATCH_CONTENT_FRAMERATE_ALWAYS
- Beralih mode tanpa hambatan tidak dimungkinkan 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 tersebut berjalan lancar, lakukan langkah berikut:
- Panggil
setFrameRate
dan teruskanfps
,FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
, danchangeFrameRateStrategy
, denganfps
adalah kecepatan frame video. - Mulai pemutaran video
- Panggil
- Jika akan terjadi perubahan mode yang tidak lancar, lakukan langkah berikut:
- Menampilkan UX untuk memberi tahu pengguna. Perhatikan bahwa sebaiknya terapkan cara bagi pengguna untuk menutup UX ini dan lewati penundaan tambahan pada langkah 5.d. Hal ini karena penundaan yang direkomendasikan 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 pseudo untuk hanya mendukung peralihan yang lancar 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 mulus dan tidak mulus sebagaimana 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();
}