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 di pipeline, tetapi hanya memerlukan buffer output untuk dua permintaan pada 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 menghemat memori hingga ratusan megabyte pada perangkat kelas atas dan juga bermanfaat untuk 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 buffer dalam 9 atau lebih rendah

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

Pengelolaan buffering di Android 10

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

Mengimplementasikan API pengelolaan buffering

Untuk mengimplementasikan API pengelolaan buffer, 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 buffer dari beberapa stream output dalam satu panggilan, sehingga panggilan IPC HIDL dapat lebih sedikit. Namun, panggilan memerlukan waktu lebih lama jika lebih banyak buffer diminta secara bersamaan dan hal ini dapat berdampak negatif terhadap 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 ini menjelaskan alasan umum kegagalan permintaan buffer dan cara menanganinya oleh HAL kamera.

  • Aplikasi terputus dari aliran data output: Ini adalah error nonfatal. 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 habis dan siap memproses permintaan berikutnya secara normal.
  • Framework kamera sedang menyiapkan konfigurasi streaming baru: Kamera HAL harus menunggu hingga panggilan configureStreams berikutnya selesai sebelum memanggil requestStreamBuffers lagi.
  • Kamera HAL telah mencapai batas buffer (kolom maxBuffers): HAL kamera harus menunggu hingga menampilkan setidaknya satu buffer streaming sebelum memanggil requestStreamBuffers lagi.

returnStreamBuffers

Gunakan metode returnStreamBuffers untuk menampilkan buffering tambahan ke framework kamera. HAL kamera biasanya menampilkan buffer ke framework kamera melalui metode processCaptureResult, tetapi hanya dapat memperhitungkan permintaan pengambilan gambar 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.

sinyalStreamFlush

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 kamera. Serupa dengan metode returnStreamBuffers, jika implementasi HAL kamera tidak menyimpan lebih banyak buffering daripada yang diminta, Anda dapat memiliki implementasi metode ini yang 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 buffer 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. Ini berarti bahwa metode signalStreamFlush dan metode lainnya (khususnya metode configureStreams) mungkin sampai di HAL kamera dalam urutan yang berbeda dari urutan pemanggilan 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 daripada panggilan configureStreams yang sesuai. Lihat Gambar 3 untuk mengetahui 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 kamera dan penerapan HAL 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 buffer melambat atau mencapai waktu tunggu karena kurangnya buffer 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 akan dipengaruhi oleh permintaan buffering yang lambat sesekali.

HAL kamera dapat menggunakan 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 dalam 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++.