Netzwerkstream zerlegen - wie?



  • Hallo!

    Gegeben sein eine Netzwerk-Kamera, die einen jpeg-Bild zurück gibt.

    Das geht wunderbar z.B. hiermit:

    TMemoryStream *MyStream = new TMemoryStream();
            IdHTTP1->Get("http://cam/cgi-bin/nph-image",MyStream);
    
            MyStream->SaveToFile("bla.jpg");
    
            MyStream->Position = 0;
    
            TJPEGImage *pJPG = new TJPEGImage();
    
            if (MyStream)
            {
                    pJPG->LoadFromStream(MyStream);
                    Image1->Picture->Assign(pJPG);
            }
    
            delete pJPG;
            delete MyStream;
    

    Sie kann aber auch ein MJPEG-Stream liefern (das wäre dann /cgi-bin/nph-video).

    Wie kann ich jetzt diesen Stream zerpflücken, damich ich bei "Vollständigkeit eines Bildes" mein TImage aktualisieren kann?



  • Mit der Image-Komponente kann man nur ein Bild darstellen, keine Sequenz von Bildern (Video).
    Dafür bräuchtest du eine externe Komponente.
    Schau dich mal auf http://mjpeg.sourceforge.net/ um, ob dort ein Tool angeboten wird, daß dir aus dem MJPEG-Stream eine Sequenz von JPEGs erzeugt.



  • Es ist klar, daß TImage keine Videos anzeigen kann. Ich wollte daher den Stream zerlegen und jedes mal, wenn ein Bild komplett da ist, dieses in das TImage kopieren.



  • Hallo

    Dnn must du dir anschauen für das MJPEG-Format binär aufgebaut ist.

    bis bald
    akari



  • Ich habe das mal mit Wireshark mitgeschnibbelt:

    HTTP/1.0 200 OK
    Server: lumenera nph-cgi
    Cache-Control: no-cache
    Pragma: no-cache
    Content-Type: multipart/mixed; boundary="-lumenera"
    
    ---lumenera
    Content-type: image/jpeg
    Content-length: 120364
    
    ......Exif..MM.*.................>...........G.2.........N.i.........b....Lumenera.le375c.2007:10:12
    16:40:26...........0120.............|.....&..................................................G..Z..].220549.....C....................................................................C................................................................................................
    .3.......A.........
    ...P..O.........K....a..
    /.:..z.1...+.?.z..i.........9^....... .g....?...?..?.'.m..G.....%...1?..?g>.....}..exg...R...K....^............!..?.k.A...79...A...?.o.8......[.....4.....E...........?....gO./_.?..xg...Q.......5. .......................-......_.t.....c...W.................r.3.......A.........
    
    hier kommen jetzt viele binäre daten, das 120364 byte lange jpeg
    
    <.`*/...s..a.z}...EO.|W.9.~....F..o....1KV..IE/D.....6....m...\._/...
    
    ---lumenera
    Content-type: image/jpeg
    Content-length: 120198  
    
    ......Exif..MM.*.................>...........G.2.........N.i.........b....Lumenera.le375c.2007:10:12
    16:40:26...........0120.............|.....&..................................................G..Z..e|353660.....C....................................................................C................................................................................................
    ................................
    .....................}........!1A..Qa."q.2....#B...R..$3br..
    
    wieder viele daten
    
    x...v\..m....Yr...s..
    
    ---lumenera
    Content-type: image/jpeg
    Content-length: 120470  
    
    ......Exif..MM.*.................>...........G.2.........N.i.........b....Lumenera.le375c.2007:10:12
    16:40:26...........0120.............|.....&..................................................G..Z....501403.....C....................................................................C................................................................................................
    ................................
    

    Folgendes ist mir klar: Den http-header abgreifen, warten bis "--lunemera" kommt, dann content-type und -length abgreifen und entsprechend der Längen soundsoviel Bytes lesen.

    Irgendwie fehlt mir genau da der Ansatzpunkt.



  • Hat hier wirklich noch niemals jemand einen Stream dieser o.ä. Art zerlegt, der mir zumindest einen Anhaltspunkt geben könnte, wie ich da weiterkomme?



  • Im o.g Auszug wiederholt sich die Abkürzung EXIF, die jedem ersthaftem Digitalfotografen ein Begriff ist.

    Diesen EXIF-Block kannst du eigentlich schon rausfiltern/minimieren, da dort für dein Vorhaben
    unnötige Angaben enthalten sind.

    Beschäftige dich mal mit dem jpeg-Dateiformat, z.B. bei Wikipedia findest du eine gute Erklärung.

    MfG
    kpeter



  • Das EXIF etc. brauche ich nicht wirklich, die Lösung sieht anders aus:
    Zitat 3 Beiträge weiter oben:

    Folgendes ist mir klar: Den http-header abgreifen, warten bis "--lunemera" kommt, dann content-type und -length abgreifen und entsprechend der Längen soundsoviel Bytes lesen.

    Mir fehlt z.Zt. nur der Ansatz. 😞



  • Sicher kennst du die Daten deiner webcam wie

    Bilder/Sek. und Auflösung der gelieferten Bilder.

    Ich würde so herangehen:

    Mit einem Timer den Stream hacken (Bildfrequenz) und sicherstellen, dass ab Beginn --lunemera
    der Datenbock als Einzelbild on-the-fly dem Ausgabe-Image zugewiesen wird.

    Die EXIF-Daten kann man erst mal aussen vorlassen, denke ich.

    Aber sicher gibt es im Netz Lösungsansätze...

    MfG
    kpeter



  • Ich muß doch nur wissen, wie ich an die Zeile "Content-length:" ran komme. Dann kommt eine Leerzeile und ab dort dann x Bytes (von Content-length:) die Bilddaten.
    Und dann immer das ganze wieder von vorne...



  • Hier ein Beispiel für eine USB-Webcam. Ich weiß, du hast eine Netzwerk-Cam,

    aber sieh dir den Code trotzdem mal an. Basiert auf MS API und Macros.

    http://www.allanpetersen.com/index.php/contents/Main/Programming.html

    MfG
    kpeter


Anmelden zum Antworten