Megjegyzések

A csomagokban a félkövérrel szedett részek változó tartalmú részt jelölnek. Az ilyen blokkokat szögletes zárójellel kezdtem illetve zártam. Ezek a zárójelek nem lesznek benne a csomagokban, csak az elválasztást szimbolizálják.

Mi is az az MJPG?

Igen már a rövidítés felvet bizonyos problémákat, ugyanis MJPG szabvány, mint hivatalos, dokumentált formátum nem létezik. Esetünkben olyan HTTP protokollon keresztültörténő mozgókép továbbítási eljárást értek alatta, amikor egy lekérésünk után a szerver folyamatosan küldi a JPG képeket egy bizonyos elválasztóval. Az előnye az a szimpla JPG fájlok folyamatos letöltögetésével szemben, hogy nem kell minden egyes képkockánál újracsatlakozni. Az FPS növekedése nem szignifikáns, azonban az egyes képek késése a fizikai valósághoz képest redukálható, így javaslom mindenkinek, akinek lehetősége van rá, hogy próbálja ezt a módot használni a kép letöltésére.

WebcamXP mjpg formátuma:

A webcamXP formátuma nem felel meg semmilyen webes standardnak, csak a programhoz adott JAVA/flashes kliens segítségével lehet lejátszani.

Miután elküldtük a GET lekérést a cam_1.mjpg url-re, siker esetén a következőhöz hasonló fejléc érkezik meg (természetesen a dátumok eltérőek). Érdemes megfigyelni, hogy a lejárat dátuma 23 perccel korábbra van állítva.

HTTP/1.1 200 OK\r\n

Connection: keep-alive\r\n

Content-Type: multipart/x-mixed-replace; boundary=--myboundary\r\n

Content-Length: 9999999\r\n

Cache-control: no-cache, must revalidate\r\n

Date: Sat, 08 Jan 2011 18:27:41 GMT\r\n

Expires: Sat, 08 Jan 2011 18:04:41 GMT\r\n

Pragma: no-cache\r\n

Server: webcamXP\r\n

\r\n


Ezt követi egy 50 bájt hosszúságú fejléc, amely a következő stringgel kezdődik, majd 0-kkal van feltöltve:


mjpeg [valami szám ascii karaktertekkel (időbélyeg valószínűleg) 12 karakter hosszan]


Ezt követi a maga a JPG kép. A JPG képet könnyű felismerni mivel van két markere: SOI és EOI (Start Of Image, End Of Image). Ez két byte pár: SOI: 0xFF 0xD8, EOI: 0xFF 0xD9.

Mivel a timestamp formátuma nem ismert ezért az mjpg-streamer egy random számsorozatot ír ide.

A javas klienst visszafejtve ki lehetne okoskodni, hogy mi is ez pontosan.
Java forrás itt, a readimage metódust kell mazsolázni.  Ha valaki rájön valamire akkor kérem értesítsen.

Ezzel a formátummal az a baj, hogy a kliens nem tudja pontosan hol a kép a bejövő bufferben, addig amíg meg nem érkezik a következő mjpeg tag.

Erre a következő megoldások nyílnak:

A) a socketen beérkező adatot bájtonként dolgozzuk fel, és figyeljük, hogy az előző 5 bájt nem mjpeg volt e véletlenül.
Lassú, agyalni kell sokat, nem jó.

B) Figyeljük a JPG SOI és EOI markereit. Minden JPG kép első két bájtja FF D8 és az utolsó két bájt FF D9
Kókány megoldás nem ajánlott.

C) Az mjpg streamer a képet több csomagban küldi. A header minden esetben külön csomagban jön. Tehát elegendő a csomag beestekor megnézni az első 5 bájtot, és ha az mjpeg akkor feldolgozni az eddig bejött adatokat a fejléc nélkül.


Mjpg-streamer mjpg formátuma:

Az mjpg-streamer által előállított streamet a legtöbb böngésző minden kodek, plugin, beépülő médialejátszó nélkül képes megjeleníteni, és hellyel közzel megfelelően lejátszani. Egyes böngészők hanyag memóriakezelésének köszönhetően egy idő után a stream belassulhat, illetve időnként érdekes félképek jelenhetnek meg. Bővebb infó itt.

Miután elküldtük a GET lekérést az ?action=stream vagy a cam_1.mjpg url-re, siker esetén a következő fejléc érkezik meg:

HTTP/1.0 200 OK\r\n

Connection: close\r\n

Server: MJPG-Streamer/0.2\r\n

Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n

Pragma: no-cache\r\n

Expires: Mon, 3 Jan 2000 12:34:56 GMT\r\n

Content-Type: multipart/x-mixed-replace;boundary=boundarydonotcross\r\n


Ezt követően a képek fognak érkezni a következő keretben:

\r\n

--boundarydonotcross\r\n

Content-Type: image/jpeg\r\n

Content-Length: [JPG kép mérete ascii számként]\r\n

X-Timestamp: [időpont mp].[időpont ms 6 tizedesjegy hosszan]\r\n

\r\n

[Majd itt jön a JPG kép annyi bájt hosszan mint amit a Content-length sorban megadtunk.]

A JPG képet könnyű felismerni mivel van két markere: SOI és EOI (Start Of Image, End Of Image). Ez két byte pár: SOI: 0xFF 0xD8, EOI: 0xFF 0xD9.


Az időpont taggal kapcsolatban:

Az időérték a V4L API-ból származik, a képek kinyeréséhez használt v4l2_buffer adattag rendelkezik egy timestamp mezővel, ami így kerül közvetítésre. Az API szerint ez azt az időpontot jelöli amikor az első bájt megérkezett a kép lekérésére. (Ez a hardver szinten értendő tehát amikor a kamera az első bájtot elkezdte küldeni a képből.) Az időbélyeg a gép bekapcsolása óta eltelt másodperceket illetve mikroszekundumokat tartalmazza. Főleg FPS mérésre lehet felhasználni, illetve segítségével kiszűrhetők az időben nagyon megcsúszott képek.

További infó:

http://v4l2spec.bytesex.org/spec/x5953.htm