API pengelolaan buffer Kamera HAL3

Android 10 memperkenalkan API pengelolaan buffer camera HAL3 opsional yang memungkinkan Anda menerapkan logika pengelolaan buffer untuk mencapai berbagai kompromi latensi memori dan pengambilan dalam implementasi HAL kamera.

HAL kamera memerlukan permintaan N (dengan N sama dengan kedalaman pipeline) yang diantrekan dalam pipeline-nya, tetapi sering kali tidak memerlukan semua kumpulan buffer output N secara bersamaan.

Misalnya, HAL mungkin memiliki delapan permintaan yang diantrekan dalam pipeline, tetapi hanya memerlukan buffering output untuk dua permintaan di tahap terakhir pipeline. Pada perangkat yang menjalankan Android 9 dan yang lebih lama, framework kamera mengalokasikan buffer saat permintaan diantrekan di HAL sehingga mungkin ada enam kumpulan buffer di HAL yang tidak digunakan. Di Android 10, API pengelolaan buffering HAL3 kamera memungkinkan pemisahan buffering output untuk mengosongkan enam set buffering. Hal ini dapat menyebabkan penghematan memori hingga ratusan megabyte di perangkat kelas atas dan juga dapat bermanfaat bagi perangkat dengan memori rendah.

Gambar 1 menunjukkan diagram antarmuka HAL kamera untuk perangkat yang menjalankan Android 9 dan yang lebih lama. Gambar 2 menunjukkan antarmuka HAL kamera di Android 10 dengan API pengelolaan buffering HAL3 kamera yang diterapkan.

Pengelolaan buffering di 9 atau yang lebih rendah

Gambar 1. Antarmuka HAL kamera di Android 9 dan yang lebih lama

Pengelolaan buffering di Android 10

Gambar 2. Antarmuka HAL kamera di Android 10 menggunakan API pengelolaan buffer

Mengimplementasikan API pengelolaan buffering

Untuk menerapkan API pengelolaan buffering, HAL kamera harus:

HAL kamera menggunakan metode requestStreamBuffers dan returnStreamBuffers di ICameraDeviceCallback.hal untuk meminta dan menampilkan buffering. HAL juga harus menerapkan metode signalStreamFlush di ICameraDeviceSession.hal untuk memberi sinyal ke HAL kamera agar menampilkan buffering.

requestStreamBuffers

Gunakan metode requestStreamBuffers untuk meminta buffering dari framework kamera. Saat menggunakan API pengelolaan buffering HAL3 kamera, permintaan pengambilan dari framework kamera tidak berisi buffering output, yaitu kolom bufferId di StreamBuffer adalah 0. Oleh karena itu, HAL kamera harus menggunakan requestStreamBuffers untuk meminta buffer dari framework kamera.

Metode requestStreamBuffers memungkinkan pemanggil meminta beberapa buffering dari beberapa aliran output dalam satu panggilan, sehingga memungkinkan lebih sedikit panggilan IPC HIDL. Namun, panggilan memerlukan lebih banyak waktu jika lebih banyak buffering diminta secara bersamaan dan hal ini dapat berdampak negatif pada total latensi permintaan ke hasil. Selain itu, karena panggilan ke requestStreamBuffers diserialisasi dalam layanan kamera, sebaiknya HAL kamera menggunakan thread prioritas tinggi khusus untuk meminta buffering.

Jika permintaan buffering gagal, HAL kamera harus dapat menangani error non-fatal dengan benar. Daftar berikut menjelaskan alasan umum permintaan buffering gagal dan cara menanganinya oleh HAL kamera.

  • Aplikasi terputus dari aliran output: Ini adalah error non-fatal. HAL kamera harus mengirim ERROR_REQUEST untuk setiap permintaan pengambilan yang menargetkan streaming yang terputus dan siap memproses permintaan berikutnya secara normal.
  • Waktu tunggu habis: Hal ini dapat terjadi saat aplikasi sibuk melakukan pemrosesan intensif sambil menyimpan beberapa buffering. HAL kamera harus mengirim ERROR_REQUEST untuk permintaan pengambilan yang tidak dapat dipenuhi karena error waktu tunggu dan siap memproses permintaan berikutnya secara normal.
  • Framework kamera sedang menyiapkan konfigurasi streaming baru: HAL kamera harus menunggu hingga panggilan configureStreams berikutnya selesai sebelum memanggil requestStreamBuffers lagi.
  • HAL kamera telah mencapai batas buffering (kolom maxBuffers): HAL kamera harus menunggu hingga menampilkan setidaknya satu buffering streaming sebelum memanggil requestStreamBuffers lagi.

returnStreamBuffers

Gunakan metode returnStreamBuffers untuk menampilkan buffering tambahan ke framework kamera. HAL kamera biasanya menampilkan buffering ke framework kamera melalui metode processCaptureResult, tetapi hanya dapat memperhitungkan permintaan pengambilan yang telah dikirim ke HAL kamera. Dengan metode requestStreamBuffers, penerapan HAL kamera dapat mempertahankan lebih banyak buffering daripada yang telah diminta oleh framework kamera. Inilah saatnya metode returnStreamBuffers harus digunakan. Jika implementasi HAL tidak pernah menyimpan lebih banyak buffering daripada yang diminta, implementasi HAL kamera tidak perlu memanggil metode returnStreamBuffers.

signalStreamFlush

Metode signalStreamFlush dipanggil oleh framework kamera untuk memberi tahu HAL kamera agar menampilkan semua buffer yang ada. Ini biasanya dipanggil saat framework kamera akan memanggil configureStreams dan harus menghabiskan pipeline pengambilan gambar kamera. Serupa dengan metode returnStreamBuffers, jika implementasi HAL kamera tidak menyimpan lebih banyak buffering daripada yang diminta, implementasi metode ini mungkin kosong.

Setelah framework kamera memanggil signalStreamFlush, framework berhenti mengirim permintaan pengambilan baru ke HAL kamera hingga semua buffer telah dikembalikan ke framework kamera. Saat semua buffering ditampilkan, panggilan metode requestStreamBuffers akan gagal, dan framework kamera dapat melanjutkan pekerjaannya dalam status bersih. Framework kamera kemudian memanggil metode configureStreams atau processCaptureRequest. Jika framework kamera memanggil metode configureStreams, HAL kamera dapat mulai meminta buffering lagi setelah panggilan configureStreams berhasil ditampilkan. Jika framework kamera memanggil metode processCaptureRequest, HAL kamera dapat mulai meminta buffering selama panggilan processCaptureRequest.

Semantiknya berbeda untuk metode signalStreamFlush dan metode flush. Saat metode flush dipanggil, HAL dapat membatalkan permintaan pengambilan yang tertunda dengan ERROR_REQUEST untuk menghabiskan pipeline sesegera mungkin. Saat metode signalStreamFlush dipanggil, HAL harus menyelesaikan semua permintaan perekaman yang tertunda secara normal dan menampilkan semua buffering ke framework kamera.

Perbedaan lain antara metode signalStreamFlush dan metode lainnya adalah signalStreamFlush adalah metode HIDL satu arah, yang berarti bahwa framework kamera dapat memanggil API pemblokiran lainnya sebelum HAL menerima panggilan signalStreamFlush. Artinya, metode signalStreamFlush dan metode lainnya (khususnya metode configureStreams) mungkin tiba di HAL kamera dalam urutan yang berbeda dari urutan yang dipanggil dalam framework kamera. Untuk mengatasi masalah asinkron ini, kolom streamConfigCounter ditambahkan ke StreamConfiguration dan ditambahkan sebagai argumen ke metode signalStreamFlush. Implementasi HAL kamera harus menggunakan argumen streamConfigCounter untuk menentukan apakah panggilan signalStreamFlush tiba lebih lambat dari panggilan configureStreams yang sesuai. Lihat Gambar 3 untuk contohnya.

Menangani panggilan yang terlambat

Gambar 3. Cara HAL kamera mendeteksi dan menangani panggilan signalStreamFlush yang terlambat tiba

Perubahan perilaku saat menerapkan API pengelolaan buffering

Saat menggunakan API pengelolaan buffering untuk menerapkan logika pengelolaan buffering, pertimbangkan kemungkinan perubahan perilaku berikut pada implementasi HAL kamera dan kamera:

  • Permintaan pengambilan tiba di HAL kamera lebih cepat dan lebih sering: Tanpa API pengelolaan buffering, framework kamera meminta buffer output untuk setiap permintaan pengambilan sebelum mengirim permintaan pengambilan ke HAL kamera. Saat menggunakan API pengelolaan buffering, framework kamera tidak perlu lagi menunggu buffering sehingga dapat mengirim permintaan pengambilan ke HAL kamera lebih awal.

    Selain itu, tanpa API pengelolaan buffering, framework kamera berhenti mengirim permintaan pengambilan jika salah satu aliran output permintaan pengambilan telah mencapai jumlah maksimum buffering yang dapat disimpan HAL sekaligus (nilai ini ditetapkan oleh HAL kamera di kolom HalStream::maxBuffers dalam nilai yang ditampilkan dari panggilan configureStreams). Dengan API pengelolaan buffering, perilaku throttling ini tidak lagi ada dan implementasi HAL kamera tidak boleh menerima panggilan processCaptureRequest saat HAL memiliki terlalu banyak permintaan pengambilan yang diantrekan.

  • Latensi panggilan requestStreamBuffers bervariasi secara signifikan: Ada banyak alasan panggilan requestStreamBuffers mungkin memerlukan waktu lebih lama daripada rata-rata. Contoh:

    • Untuk beberapa buffer pertama dari streaming yang baru dibuat, panggilan dapat memerlukan waktu lebih lama karena perangkat perlu mengalokasikan memori.
    • Latensi yang diharapkan meningkat sebanding dengan jumlah buffer yang diminta dalam setiap panggilan.
    • Aplikasi menyimpan buffering dan sedang sibuk memproses. Hal ini dapat menyebabkan permintaan buffering melambat atau mengalami waktu tunggu habis karena kekurangan buffering atau CPU yang sibuk.

Strategi pengelolaan buffering

API pengelolaan buffering memungkinkan berbagai jenis strategi pengelolaan buffering diimplementasikan. Contohnya antara lain:

  • Kompatibel dengan versi lama: HAL meminta buffering untuk permintaan pengambilan selama panggilan processCaptureRequest. Strategi ini tidak memberikan penghematan memori, tetapi dapat berfungsi sebagai implementasi pertama API manajemen buffer, yang memerlukan sangat sedikit perubahan kode pada HAL kamera yang ada.
  • Penghematan memori yang dimaksimalkan: HAL kamera hanya meminta buffering output segera sebelum buffer diperlukan untuk diisi. Strategi ini memungkinkan penghematan memori yang dimaksimalkan. Kemungkinan kelemahannya adalah lebih banyak jank pipeline kamera saat permintaan buffering memerlukan waktu yang sangat lama untuk diselesaikan.
  • Di-cache: HAL kamera meng-cache beberapa buffering sehingga kemungkinan tidak dipengaruhi oleh permintaan buffering yang lambat sesekali.

HAL kamera dapat mengadopsi strategi yang berbeda untuk kasus penggunaan tertentu, misalnya, menggunakan strategi penghematan memori yang dimaksimalkan untuk kasus penggunaan yang menggunakan banyak memori dan menggunakan strategi yang kompatibel dengan versi lama untuk kasus penggunaan lainnya.

Contoh implementasi di HAL kamera eksternal

HAL kamera eksternal diperkenalkan di Android 9 dan dapat ditemukan di hierarki sumber di hardware/interfaces/camera/device/3.5/. Di Android 10, API ini telah diperbarui untuk menyertakan ExternalCameraDeviceSession.cpp, implementasi API pengelolaan buffering. HAL kamera eksternal ini menerapkan strategi penghematan memori yang dimaksimalkan yang disebutkan dalam Strategi manajemen buffer dalam beberapa ratus baris kode C++.