4.15. Képkocka-pufferek¶
Miután a kamera érzékelője inicializálva lett, folyamatosan, a képkockasebességének megfelelően bocsát ki képkockákat – minden képkockaperiódusban egy új képkockát, függetlenül attól, hogy az alkalmazás készen áll-e rá. Minden képkockának szüksége van egy helyre a RAM-ban, ahová leérkezhet, különben elvész. A képkocka-puffer halmaz az a hely, ahol ezek a képkockák a DMA-ból való kilépés és a felhasználói kód általi feldolgozás között tartózkodnak, és az, hogy a kamera hány képkocka-puffert tart ebben a halmazban, határozza meg, hogyan osztozik rajtuk a DMA és az alkalmazás. A választás a framebuffers() metóduson keresztül érhető el, és négy mód áll rendelkezésre, amelyeket a pufferek száma választ ki.
4.15.1. Egyetlen puffer (count = 1)¶
Egyetlen képkocka-puffer a RAM-ban. A DMA feltölti; az alkalmazás kiolvassa belőle; a snapshot() következő hívása nem indulhat el addig, amíg az alkalmazás fel nem szabadította a puffert, mivel ugyanarra a pufferre van szükség mindkettőhöz.
A kamera és az alkalmazás lépésről lépésre, szinkronban fut. A DMA-nak meg kell várnia, hogy az alkalmazás befejezze, az alkalmazásnak pedig meg kell várnia, hogy a DMA befejezze, ami azt jelenti, hogy az elérhető képkockasebesség a legjobb esetben is az érzékelő képkockasebességének a fele – az érzékelő által kibocsátott minden második képkocka akkor érkezik, amikor a puffer foglalt, és elvész.
Ez a mód a legkisebb RAM-igényű és a leglassabb átviteli teljesítményű. Csak akkor használja, ha a RAM túl szűkös ahhoz, hogy második puffert lehessen lefoglalni.
4.15.2. Dupla puffer (count = 2)¶
Két képkocka-puffer a RAM-ban: egy hátsó puffer, amelyet a DMA tölt fel, és egy elülső puffer, amelyből az alkalmazás kiolvas. Amikor az alkalmazás befejezi az elülső puffert, a két szerep felcserélődik, és a DMA elkezdi feltölteni az imént felszabadított puffert, miközben az alkalmazás az éppen feltöltöttből olvas.
Amíg az alkalmazás minden képkockát egy kamera-képkockaperiódusnál rövidebb idő alatt dolgoz fel, az alkalmazás az érzékelő teljes képkockasebességét látja – a DMA következő képkockája már a hátsó pufferben várakozik, amikor az alkalmazás ismét meghívja a snapshot() metódust. Abban a pillanatban azonban, amikor a feldolgozási idő meghaladja az egy képkockaperiódust, a sebesség megfeleződik: a kamera két képkockát állít elő abban az időben, amíg az alkalmazás egyet feldolgoz, és a kettő közül csak a második kerül átadásra.
Ezen a ponton túl a sebesség egyenletesen romlik a feldolgozási idővel. Valahányszor a DMA befejez egy új hátsópuffer-képkockát, miközben az alkalmazás még az elülső pufferen dolgozik, az új képkocka helyben felülírja az előző felvételt, ahelyett, hogy eldobná. Az alkalmazás a következő snapshot() híváskor mindig a kamera által előállított legfrissebb képkockát kapja meg, és az elérhető alkalmazássebesség a feldolgozási idejének az inverze lesz.
4.15.3. Tripla puffer (count = 3)¶
Három képkocka-puffer a RAM-ban: két hátsó puffer, amelyeken a DMA körbejár, és egy elülső puffer, amelyen az alkalmazás éppen dolgozik. Ez az alapértelmezett mód, amelyet az OpenMV Cam választ, ha elegendő RAM áll rendelkezésre, automatikus visszalépéssel a dupla vagy egyetlen pufferre, ha nincs elég.
A harmadik puffer teljesen leválasztja a kamera képkockasebességét az alkalmazás képkockasebességéről. A DMA-nak mindig van puffere, amelybe írhat; az alkalmazásnak mindig van puffere, amelyből olvashat; minden snapshot() híváskor a legfrissebb kész hátsó puffer lesz az új elülső puffer, az előző elülső puffer pedig felszabadul a DMA számára. Az alkalmazás képkockasebessége megegyezik azzal az idővel, amennyi ténylegesen szükséges az egyes képkockák feldolgozásához – anélkül az 1/2 lépcső nélkül, amelybe a dupla puffer esik, amikor a feldolgozási idő éppen csak túllép egy képkockaperióduson.
4.15.4. Videó FIFO (count = 4 vagy több)¶
Négy vagy több képkocka-puffer a RAM-ban, egymás után rögzített képkockák gyűrűjeként elrendezve. A kamera által átadott minden képkocka bekerül a FIFO sorba, és a snapshot() a legrégebbi sorba állított képkockát adja vissza, nem a legfrissebbet. Az alkalmazás a rögzített képkockákon a rögzítés sorrendjében halad végig, abban az időben, amennyi ténylegesen rendelkezésére áll mindegyikre.
Ez a mód a megfelelő választás, amikor minden képkocka számít, és rövid feldolgozási megakadások várhatók: videó írása SD-kártyára, amelynek tárolórétege egy törlés során több tíz ezredmásodpercig blokkolhat, USB-n keresztüli adatfolyam küldése egy gazdagéphez, amely rövid időre abbahagyja az olvasást, vagy egy gyors esemény rövid sorozatának pufferelése a kódban való vizsgálathoz.
Két házirend kezeli azt az esetet, amikor a FIFO megtelik, mielőtt az alkalmazás kiürítette volna.
Régi képkockák eldobása (alapértelmezett). Amikor a FIFO megtelik, az aktív kivételével az összes sorba állított képkocka eldobásra kerül, így a következő
snapshot()egy friss képkockát ad vissza, nem egy elavultat. A DMA végig folyamatosan rögzít, így az alkalmazás egy megakadás után mindig friss adatokat lát. Ez a megfelelő házirend, amikor a cél a rögzített adatfolyam naprakészen tartása – videórögzítés, élő közvetítés.A rögzítés leállítása túlcsordulás esetén. Adja át az
fflush=Falseparamétert aCSIkonstruktornak, és a DMA leállítja a FIFO feltöltését, amikor az megtelik, érintetlenül hagyva a sorba állított képkockákat. Asnapshot()továbbra is a rögzítés sorrendjében adja vissza a képkockákat, amíg az alkalmazás ki nem üríti azokat, ezután a DMA folytatja. Ez a megfelelő házirend, amikor a cél egy rövid sorozat minden képkockájának megőrzése – gyors mozgás rögzítése, hogy utólag a kódban képkockáról képkockára meg lehessen vizsgálni.
A teljes API-t lásd a csi.CSI.framebuffers() metódusnál.
4.15.5. Triggerelt mód¶
A fenti, mindig futó módok alternatívája a triggerelt rögzítés, ahol az érzékelő csak akkor bocsát ki képkockát, amikor a snapshot() kér egyet. A kamera a pillanatképek között tétlen, és minden alkalommal friss expozíciót indít, amikor az alkalmazás jelentkezik.
Ennek ára az átviteli teljesítmény: egy triggerelt rögzítés nem fedhet át az előzővel, így a maximális elérhető képkockasebesség az érzékelő normál sebességének a fele. Az előnye az expozíció időzítése. A pillanatkép pontosan szabályozza, hogy mikor kezdődik az expozíció, ami az, amire egy alkalmazásnak szüksége van, amikor az expozíciónak egy külső eseményhez kell igazodnia – egy stroboszkópos villanáshoz, egy szállítószalag-pozíció érzékelőhöz, egy GPIO-vonalon érkező impulzushoz –, nem pedig oda érkeznie, ahol a szabadon futó érzékelő gördülő képkockája éppen tart, amikor az alkalmazás készen áll a kiolvasására.
A triggerelt mód érzékelőfüggő. A támogatott érzékelőkön a csi0.ioctl(csi.IOCTL_SET_TRIGGERED_MODE, True) hívásával engedélyezhető, és a False átadásával tiltható le.