4.15. Framebuffer¶
Setelah sensor kamera diinisialisasi, sensor tersebut memancarkan bingkai secara terus-menerus pada laju bingkainya -- satu bingkai baru setiap periode bingkai, terlepas dari apakah aplikasi siap atau tidak. Setiap bingkai membutuhkan tempat di RAM untuk disimpan, atau bingkai tersebut akan hilang. Pool framebuffer adalah tempat di mana bingkai-bingkai tersebut berada antara saat meninggalkan DMA dan saat diproses oleh kode pengguna, dan berapa banyak framebuffer yang disimpan kamera dalam pool tersebut mengontrol bagaimana DMA dan aplikasi berbagi bingkai tersebut. Pilihan ini ditampilkan melalui framebuffers(), dan empat mode tersedia, dipilih berdasarkan jumlah buffer.
4.15.1. Buffer tunggal (count = 1)¶
Satu framebuffer di RAM. DMA mengisinya; aplikasi membaca darinya; panggilan berikutnya ke snapshot() tidak dapat dimulai sampai aplikasi melepaskan buffer, karena buffer yang sama dibutuhkan untuk keduanya.
Kamera dan aplikasi berjalan secara sinkron (lock-step). DMA harus menunggu aplikasi selesai, dan aplikasi harus menunggu DMA selesai, yang berarti laju bingkai yang dapat dicapai paling baik adalah setengah dari laju bingkai sensor -- setiap bingkai lain yang dipancarkan sensor tiba saat buffer sedang sibuk dan hilang.
Mode ini paling kecil dalam penggunaan RAM dan paling lambat dalam throughput. Gunakan hanya ketika RAM terlalu terbatas untuk mengalokasikan buffer kedua.
4.15.2. Buffer ganda (count = 2)¶
Dua framebuffer di RAM: satu buffer back yang diisi DMA, dan satu buffer front yang dibaca aplikasi. Ketika aplikasi selesai dengan buffer front, kedua peran saling bertukar, dan DMA mulai mengisi buffer yang baru dilepaskan sementara aplikasi membaca dari yang baru diisi.
Selama aplikasi memproses setiap bingkai dalam waktu kurang dari satu periode bingkai kamera, aplikasi melihat laju bingkai penuh sensor -- bingkai berikutnya dari DMA sudah menunggu di buffer back saat aplikasi memanggil snapshot() lagi. Namun, begitu waktu pemrosesan melebihi satu periode bingkai, lajunya menjadi setengah: kamera akan menghasilkan dua bingkai dalam waktu yang dibutuhkan aplikasi untuk memproses satu bingkai, dan hanya bingkai kedua dari dua bingkai tersebut yang akan disampaikan.
Setelah titik tersebut, lajunya menurun secara halus seiring waktu pemrosesan. Setiap kali DMA menyelesaikan bingkai back-buffer baru sementara aplikasi masih bekerja pada buffer front, bingkai baru menimpa capture sebelumnya di tempat yang sama daripada dibuang. Aplikasi selalu mendapatkan bingkai terbaru yang dihasilkan kamera pada snapshot() berikutnya, dan laju aplikasi yang dapat dicapai menjadi kebalikan dari waktu pemrosesannya.
4.15.3. Buffer tiga (count = 3)¶
Tiga framebuffer di RAM: dua buffer back yang diputar oleh DMA dan satu buffer front yang sedang dikerjakan aplikasi. Ini adalah mode default yang dipilih OpenMV Cam ketika ada cukup RAM tersedia, dengan fallback otomatis ke buffer ganda atau tunggal ketika tidak ada.
Buffer ketiga sepenuhnya memisahkan laju bingkai kamera dari laju bingkai aplikasi. DMA selalu memiliki buffer untuk ditulis; aplikasi selalu memiliki buffer untuk dibaca; pada setiap snapshot() buffer back terbaru yang siap menjadi buffer front baru dan buffer front sebelumnya dibebaskan untuk DMA. Laju bingkai aplikasi sesuai dengan waktu yang sebenarnya dibutuhkan untuk memproses setiap bingkai -- tanpa penurunan 1/2-langkah yang terjadi pada buffer ganda ketika waktu pemrosesan sedikit melewati satu periode bingkai.
4.15.4. Video FIFO (count = 4 atau lebih)¶
Empat atau lebih framebuffer di RAM, disusun sebagai ring bingkai yang di-capture secara berurutan. Setiap bingkai yang dikirimkan kamera dimasukkan ke dalam antrian FIFO, dan snapshot() mengembalikan bingkai tertua yang ada dalam antrian, bukan yang paling terbaru. Aplikasi berjalan melalui bingkai yang di-capture dalam urutan capture, dalam waktu yang sebenarnya dimilikinya untuk mengerjakan masing-masing bingkai.
Mode ini adalah pilihan yang tepat ketika setiap bingkai penting dan jeda pemrosesan singkat diperkirakan terjadi: menulis video ke kartu SD yang stack penyimpanannya dapat memblokir selama puluhan milidetik selama penghapusan, streaming melalui USB ke host yang sesekali berhenti membaca, atau mem-buffer burst pendek dari peristiwa cepat untuk diperiksa dalam kode.
Dua kebijakan menangani kasus di mana FIFO penuh sebelum aplikasi mengosongkannya.
Buang bingkai lama (default). Ketika FIFO penuh, semua bingkai yang ada dalam antrian kecuali yang aktif dibuang sehingga
snapshot()berikutnya mengembalikan bingkai terkini daripada yang usang. DMA terus melakukan capture sepanjang waktu, sehingga aplikasi selalu melihat data terbaru setelah jeda. Ini adalah kebijakan yang tepat ketika tujuannya adalah menjaga aliran capture tetap terkini -- perekaman video, live streaming.Hentikan capture saat overflow. Teruskan
fflush=Falseke konstruktorCSIdan DMA berhenti mengisi FIFO ketika sudah penuh, membiarkan bingkai yang ada dalam antrian tetap utuh.snapshot()terus mengembalikan bingkai dalam urutan capture hingga aplikasi mengosongkannya, setelah itu DMA dilanjutkan. Ini adalah kebijakan yang tepat ketika tujuannya adalah mempertahankan setiap bingkai dari burst pendek -- menangkap gerakan cepat untuk diperiksa bingkai demi bingkai dalam kode setelahnya.
Lihat csi.CSI.framebuffers() untuk API lengkapnya.
4.15.5. Mode triggered¶
Alternatif untuk mode yang selalu berjalan di atas adalah capture triggered, di mana sensor memancarkan bingkai hanya ketika snapshot() memintanya. Kamera diam di antara snapshot dan memulai eksposur baru setiap kali aplikasi memanggilnya.
Biayanya adalah throughput: capture triggered tidak dapat tumpang tindih dengan yang sebelumnya, sehingga laju bingkai maksimum yang dapat dicapai adalah setengah dari laju normal sensor. Keuntungannya adalah waktu eksposur. Snapshot mengontrol dengan tepat kapan eksposur dimulai, yang diinginkan aplikasi ketika eksposur harus selaras dengan peristiwa eksternal -- strobe flash, sensor posisi konveyor, pulsa pada pin GPIO -- daripada jatuh di manapun bingkai rolling sensor yang berjalan bebas berada saat aplikasi siap membacanya.
Mode triggered bersifat spesifik per sensor. Pada sensor yang mendukungnya, mode ini diaktifkan dengan memanggil csi0.ioctl(csi.IOCTL_SET_TRIGGERED_MODE, True) dan dinonaktifkan dengan meneruskan False.