4.15. Framebuffery¶
Jakmile je senzor kamery inicializován, vysílá snímky nepřetržitě svou snímkovou frekvencí – jeden nový snímek za každou snímkovou periodu, ať už je na něj aplikace připravena, nebo ne. Každý snímek potřebuje někde v RAM přistát, jinak je ztracen. Fond framebufferů je místo, kde tyto snímky žijí mezi opuštěním DMA a zpracováním uživatelským kódem, a počet framebufferů, které kamera v tomto fondu udržuje, řídí, jak si je DMA a aplikace rozdělují. Tato volba je dostupná prostřednictvím framebuffers() a jsou k dispozici čtyři režimy, vybírané podle počtu bufferů.
4.15.1. Jeden buffer (count = 1)¶
Jeden framebuffer v RAM. DMA jej plní; aplikace z něj čte; další volání snapshot() nemůže začít, dokud aplikace buffer neuvolní, protože stejný buffer je potřeba pro obojí.
Kamera a aplikace běží v pevném kroku. DMA musí čekat, až aplikace dokončí svou práci, a aplikace musí čekat, až DMA dokončí svou, což znamená, že dosažitelná snímková frekvence je v nejlepším případě poloviční oproti snímkové frekvenci senzoru – každý druhý snímek, který senzor vyšle, dorazí ve chvíli, kdy je buffer zaneprázdněn, a je ztracen.
Tento režim je nejmenší co do RAM a nejpomalejší co do propustnosti. Používejte jej pouze tehdy, když je RAM příliš omezená na alokaci druhého bufferu.
4.15.2. Dvojitý buffer (count = 2)¶
Dva framebuffery v RAM: jeden zadní (back) buffer, který plní DMA, a jeden přední (front) buffer, ze kterého čte aplikace. Když aplikace dokončí přední buffer, obě role se vymění a DMA začne plnit právě uvolněný buffer, zatímco aplikace čte z toho čerstvě naplněného.
Dokud aplikace zpracuje každý snímek za méně než jednu snímkovou periodu kamery, aplikace vidí plnou snímkovou frekvenci senzoru – další snímek DMA již čeká v zadním bufferu, když aplikace znovu zavolá snapshot(). Jakmile však doba zpracování překročí jednu snímkovou periodu, frekvence se zpomalí na polovinu: kamera vyprodukuje dva snímky za dobu, kterou aplikace potřebuje na zpracování jednoho, a doručen bude pouze druhý z těchto dvou.
Za tímto bodem se frekvence plynule zhoršuje s dobou zpracování. Pokaždé, když DMA dokončí nový snímek v zadním bufferu, zatímco aplikace stále pracuje na předním bufferu, nový snímek přepíše předchozí zachycení na místě, místo aby byl zahozen. Aplikace při svém dalším snapshot() vždy dostane nejnovější snímek, který kamera vyprodukovala, a dosažitelná frekvence aplikace se stává převrácenou hodnotou doby jejího zpracování.
4.15.3. Trojitý buffer (count = 3)¶
Tři framebuffery v RAM: dva zadní (back) buffery, kterými DMA cyklicky prochází, a jeden přední (front) buffer, na kterém aplikace právě pracuje. Toto je výchozí režim, který OpenMV Cam zvolí, když je k dispozici dostatek RAM, s automatickým návratem na dvojitý nebo jeden buffer, když není.
Třetí buffer zcela odděluje snímkovou frekvenci kamery od snímkové frekvence aplikace. DMA má vždy buffer, do kterého může zapisovat; aplikace má vždy buffer, ze kterého může číst; při každém snapshot() se nejnovější připravený zadní buffer stane novým předním bufferem a předchozí přední buffer se uvolní pro DMA. Snímková frekvence aplikace odpovídá době, kterou skutečně potřebuje na zpracování každého snímku – bez polovičního kroku, do kterého dvojitý buffer upadne, když doba zpracování jen mírně překročí jednu snímkovou periodu.
4.15.4. Video FIFO (count = 4 nebo více)¶
Čtyři nebo více framebufferů v RAM, uspořádaných jako kruh snímků zachycených těsně po sobě. Každý snímek, který kamera doručí, je zařazen do FIFO a snapshot() vrací nejstarší zařazený snímek namísto nejnovějšího. Aplikace prochází zachycené snímky v pořadí zachycení, v čase, který na každý z nich skutečně má.
Tento režim je správnou volbou, když záleží na každém snímku a očekávají se krátká pozdržení zpracování: zápis videa na SD kartu, jejíž úložný zásobník se může během mazání zablokovat na desítky milisekund, streamování přes USB do hostitele, který krátce přestane číst, nebo bufferování krátkého shluku rychlé události pro inspekci v kódu.
Případ, kdy se FIFO zaplní dříve, než jej aplikace stihne vyprázdnit, řeší dvě politiky.
Zahazování starých snímků (výchozí). Když se FIFO zaplní, všechny zařazené snímky kromě aktivního jsou zahozeny, takže další
snapshot()vrátí nedávný snímek namísto zastaralého. DMA po celou dobu pokračuje v zachytávání, takže aplikace po pozdržení vždy uvidí čerstvá data. Toto je správná politika, když je cílem udržet zachycený proud aktuální – nahrávání videa, živé streamování.Zastavení zachytávání při přetečení. Předejte
fflush=FalsekonstruktoruCSIa DMA přestane plnit FIFO, když je plné, přičemž zařazené snímky ponechá nedotčené.snapshot()pokračuje ve vracení snímků v pořadí zachycení, dokud je aplikace nevyprázdní, načež DMA pokračuje. Toto je správná politika, když je cílem zachovat každý snímek krátkého shluku – zachycení rychlého pohybu pro pozdější inspekci snímek po snímku v kódu.
Kompletní API najdete v csi.CSI.framebuffers().
4.15.5. Spouštěný režim¶
Alternativou k výše uvedeným trvale běžícím režimům je spouštěné (triggered) zachytávání, kde senzor vyšle snímek pouze tehdy, když o něj snapshot() požádá. Kamera mezi snímky zahálí a pokaždé, když se aplikace ozve, zahájí novou expozici.
Cenou je propustnost: spouštěné zachycení se nemůže překrývat s předchozím, takže maximální dosažitelná snímková frekvence je poloviční oproti běžné frekvenci senzoru. Přínosem je časování expozice. Snapshot přesně řídí, kdy expozice začne, což je to, co aplikace chce, když expozice musí být sladěna s externí událostí – zábleskem stroboskopu, senzorem polohy dopravníku, pulzem na lince GPIO – namísto aby přistála kdekoli, kde se zrovna nachází plynulý snímek volně běžícího senzoru ve chvíli, kdy je aplikace připravena jej přečíst.
Spouštěný režim je specifický pro daný senzor. Na podporovaných senzorech se povoluje voláním csi0.ioctl(csi.IOCTL_SET_TRIGGERED_MODE, True) a zakazuje předáním False.