Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Bild von IP-Webcam auslesen (https://www.delphipraxis.net/176863-bild-von-ip-webcam-auslesen.html)

himitsu 1. Okt 2013 11:03

Bild von IP-Webcam auslesen
 
Moin ihr.


Ein Kunde hat bei sich einige TP-Link SC3230N von seinem IT-Dienstleister installieren lassen und ich versuche nun ein bild davon in unsere Software zu bekommen.
http://www.tp-link.com.de/products/d...del=TL-SC3230N
http://www.tp-link.com.de/support/do...rsion=V1#tbl_b

Am Besten/Einfachten wäre ja der direkte Zugriff auf ein JPEG, PNG oder BMP.

Unter Netzwerk > Protokolle ist zwar Allerhand aufgelistet, aber ich fand keinen anderen Zugriff, außer über HTTP/HTTPS.
Ein FTP-, Samba- oder sonstige Server scheinen wohl nicht implementitert zu sein. Außer daß die Kamera selber darauf zugreifen und z.B. Logs abspeichern kann.

Der Zugriff auf die Videos-Streams, welche ausreichend zur Vergügung gestellt werden, ist ja "nativ" mit Delphi nicht möglich.

Ich fand zwar das http://192.168.0.236/image.jpg , aber jenes ist nicht erreichbar.
Zitat:

Can not service right now, please try later.
Und da Dieses ist erstens nicht dokumentiert und via Google und Co. war auch nichts zu finden.
(eine Anfrage an TP-Link ist aber schon raus)

Das Webinterface dieser Kamera zeigt im Browser zwar nur die VideoStreams an,
aber von irgendwo bekommt der Bild-Speichern-Knopf auf der Webseite ein JPEG im angegeben Pfad abgespeichert.
(aber das JavaScript ist sowas von verwirrend ... ich fand nichtmal raus wie und wo der Code für's Speichern versteckt ist, bzw. wo das Bild dann herkommt)


Vielleicht kennt sich ja schon jemand mit dieser oder solchen IP-Webcams aus und kann helfen?
(die ein zwei anderen vorhandenen Threads, in der DP und im restlichen Netz, waren jedenfalls nicht hilfreich, bzw. befassten sich mit anderen Problemen)



Und was Fremdkomponenten angeht:
Ich bin noch am Suchen und Rumprobieren, allerdings muß Dieses auch in XE funktionieren.
(Neueres wäre vorhanden, aber Fremdkomponenten und eventuelle Codeanpassungen lassen ein Upgrade des gesamten Projekts nicht so leicht zu)

GoogleCode - IPCamViewer
Hab ich mir noch nicht angesehn, aber die Installation/Registrierung von ActiveX-Komponenten bereitet manchmal einige Probleme (wie wir mit einer Anderen DLL schon leidlich bemerkt haben).

Torry - BasicVideo (bzw. VideoLab und VisionLab) probier ich grade aus,
aber das ist erst ab XE2, in den Demos ist nichts zu finden, und ich hab noch nicht rausgefunden, wie man damit überhaupt auf eine IP-Webcam zugreifen kann.
Dokumentation vorhanden, aber ich finde nichts.
Falls sich hier jemand mit diesen Komponenten auskennt, dann wäre ich über Hilfe sehr Dankbar.
TVLDSCapture+TVLDSImageDisplay oder TVLCapture+TVLImageDisplay auf die Form und versuchen da irgendwie die Quelle anzugeben, geht nicht.
Delphi-Quellcode:
VLCapture1.ShowVideoSourceDialog
VLDSCapture1.ShowVideoDialog(...)
VLDSCapture1.Start
VLDSCapture1.Open

---------------------------
Project5
---------------------------
Can't open video driver. - 0 - 0.
---------------------------
OK  
---------------------------
Torry - VisioForge Video Capture
Noch nicht angesehn. (vorher schau ich mir IPCamViewer an)

Morphie 1. Okt 2013 11:20

AW: Bild von IP-Webcam auslesen
 
Ich habe gerade zufällig vor 2 Tagen eine entsprechende Klasse programmiert... Allerdings nicht für TP-Link sondern für Tenvis-Kameras.

Meine Klasse setzt voraus, dass die Kamera einen MJPEG-Stream sendet...
Das scheinen wohl viele Kameras von TP-Link zu können, aber wohl nicht alle (oder die Datenbank ist unvollständig)
http://www.ispyconnect.com/man.aspx?n=TP-Link

Gibt es für deine Kamera ein MJPEG-Stream? (bitte mal ausprobieren)


edit: gerade gesehen: http://www.tp-link.com/en/products/d...L-SC3230N#spec
Video Compression: H.264, MJPEG


Sollte also gehen...

Mavarik 1. Okt 2013 11:45

AW: Bild von IP-Webcam auslesen
 
Zitat:

Zitat von Morphie (Beitrag 1230453)
Ich habe gerade zufällig vor 2 Tagen eine entsprechende Klasse programmiert... Allerdings nicht für TP-Link sondern für Tenvis-Kameras..

emm kannst Du uns die Klasse zur Verfügung stellen?

Mavarik

Morphie 1. Okt 2013 12:03

AW: Bild von IP-Webcam auslesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Klar, ein Beispielprojekt findest du im Anhang...
Dazu sei aber gesagt, dass
1. der Code noch keinen Praxistest durchlaufen hat und
2. der Code sicherlich noch einige Fehler hat

Aber um sich generell mal das MJPEG-Protokoll anzusehen, reicht er wohl :-)

Falls ihr Verbesserungsvorschläge habt, dann dürft ihr die ruhig äußern, es ist meine 1. Klasse, die von TThread ableitet

himitsu 1. Okt 2013 12:31

AW: Bild von IP-Webcam auslesen
 
MJPEG und irgendwas von RealMedia liefert die Kamera via HTTP/HTTPS.

Und dann ist noch so Zeug wie eingebaut.
RTSP (Real-Time Streaming Protocol) - Port 554
Remote Playback - Port 8866 (?)


So, dann schau ich besser erstmal ob der Kunde die Kameras auch aktiviert hat.
So ging ja erstmal eine Woche drauf, nur um die IPs zu bekommen und daß die Kameras auch aktiv sind.
und vorher erstmal zu erfahren was das nun genau für Kameras sind.
Mir sagte man ja nicht, daß es IP-Webcams sind und so hab ich mich erstmal auf CAPI und Co. gestürzt und als dann alles fertig war und es beim Kunden getestet werden sollte ...... nja.

Morphie 1. Okt 2013 12:37

AW: Bild von IP-Webcam auslesen
 
Das Problem kenne ich... Egal wie detailliert man ein Lasten/Pflichtenheft (oder etwas vergleichbares) schreibt, es fehlen immer irgendwelche Details, die dazu führen, dass man nachbessern muss... :-(

himitsu 1. Okt 2013 12:59

AW: Bild von IP-Webcam auslesen
 
Lasten- und Pflichtenheft ist gut ... "bau ma was ein, damit wir auch von einer webcam das bild in DMS bekommen"

Nja, da mach ich mal 3 Wochen Urlaub und schon schaltet wer die Kameras aus.


Aber zur Komponente.
Wenn du z.B. von TComponent erbst und den TThread nur als Unterkomponente laufen läßt, dann kann man diese Komponente auch nett auf der Form oder einem DatenModul ablegen und gemütlich über den OI die Events anhängen.
Bzw. das TThread.Execute ganz einfach über
Delphi-Quellcode:
TThread.CreateAnonymousThread(...)
startet, die Synchronisierung über TThread.Synchronize(nil, ...) schiebt und sich somit die komplette TThread-Instanz erspart.
(im Notfall kann ich's dir auch mal in wenigen Minütchen entsprechend umstellen)



PS: Den Mist mit dem TfrmMain.JPEGReceived hab ich auch schon erlebt. :kotz:
grad erst vor paar Wochen, als ich meine Webcam schnell mal via CAPI reingebaut hatte.

Wusstest du, daß es theoretisch sowas gibt?
Delphi-Quellcode:
procedure TfrmMain.JPEGReceived(Sender: TObject; Data: TMemoryStream);
begin
  Image1.Picture.ForceType(TJPEGImage);
  Image1.Picture.Graphic.LoadFromStream(Data);
end;
Aber weil irgendein besch* Arsch diese Prozedur unbedingt als Private deklarieren mußte, sieht der Ersatz-Code praktisch so aus
Delphi-Quellcode:
procedure TfrmMain.JPEGReceived(Sender: TObject; Data: TMemoryStream);
var
  JPEG: TJPEGImage;
begin
  if not (Image1.Picture.Graphic is TJPEGImage) then begin
    JPEG := TJPEGImage.Create;
    try
      Image1.Picture.Assign(JPEG); // bzw. Image1.Picture.Graphic := JPEG;
    finally
      JPEG.Free;
    end;
  end;
  Image1.Picture.Graphic.LoadFromStream(Data);
end;
Oder eben so, wie bei dir.

Morphie 1. Okt 2013 13:08

AW: Bild von IP-Webcam auslesen
 
Zitat:

Zitat von himitsu (Beitrag 1230488)
(im Notfall kann ich's dir auch mal in wenigen Minütchen entsprechend umstellen)

Das wäre nett, würde mich schon interessieren, was man noch so alles verbessern kann

himitsu 1. Okt 2013 14:04

AW: Bild von IP-Webcam auslesen
 
Ohhh, der MJPEG-Stream das sind einfach nur viele HTTP-Anfragen in einer Connection?
Im Prinzip müsste es dann doch auch gehn, wenn ich auf den Stream einfach vie TIdHttp zugreife, welches schon eingebaut ist.
Dann könnte ich es so erstmal so beim Kunden schnell zum Laufen bringen.

Ich probiere es so dann erstmal aus und schau dann, was ich mit deiner Komponente machen kann.
Wäre auf jeden Fall einfacher, als jetzt einen ActiveX-Server zu installieren oder andere extrem große Fremdkoponenten reinzubekommen.



Für die Schnittstellen noch ein Hinweis:

Verwende besser kein TMemoryStream für die Parameter in öffentlichen Schnittstellen, sondern lieber einen passenden gemeinsamen Vorfahren.
Du kannst intern gern den TMemoryStream verwenden, aber als Parameter/Schnittstelle macht sich der Basistyp TStream besser.

z.B. kann man bei
Delphi-Quellcode:
procedure Test(Data: TStream);
alles übergen, was einen Stream darstellt, auch TMemoryStream und TFileStream.
Aber wurde es direkt als TMemoryStream deklariert, dann kann man keinen TFileStream mehr übergeben.
(Ausnahmen sind natürlich, wenn intern direkt auf spezielle)

In deinem Fall kommt der Stream da zwar raus und wird nicht reingegeben, aber insgesammt sind Komponenten/Codes einfacher wiederverwendbar, wenn sie sich auf gemeinsame Basistypen beziehen.

Morphie 1. Okt 2013 14:10

AW: Bild von IP-Webcam auslesen
 
Zitat:

Zitat von himitsu (Beitrag 1230498)
Ohhh, der MJPEG-Stream das sind einfach nur viele HTTP-Anfragen in einer Connection?

Es gibt eigentlich nur eine einzige Anfrage an den Server. Der sendet daraufhin quasi eine "unendliche" Antwort zurück.
Die "unendliche" Antwort besteht im Prinzip aus unendlich vielen JPEGs + Größenangabe usw.

Zitat:

Zitat von himitsu (Beitrag 1230498)
Im Prinzip müsste es dann doch auch gehn, wenn ich auf den Stream einfach vie TIdHttp zugreife, welches schon eingebaut ist.
Dann könnte ich es so erstmal so beim Kunden schnell zum Laufen bringen.

Ob man mit idHTTP darauf zugreifen kann, weiß ich nicht, da der Stream ja nie komplett heruntergeladen werden kann...

Zitat:

Zitat von himitsu (Beitrag 1230498)
Für die Schnittstellen noch ein Hinweis:

Danke, werde ich berücksichtigen :-)

Wenn das so weitergeht, kann womöglich noch eine ordentliche Komponente entstehen (vielleicht was für die CodeLib?)

jensw_2000 1. Okt 2013 14:24

AW: Bild von IP-Webcam auslesen
 
Oder Du nimmst das VLC ActiveX Control.
Das kann RTSP und Screenshots aus dem Videostream IMHO auch.

himitsu 1. Okt 2013 14:30

AW: Bild von IP-Webcam auslesen
 
Dann muß aber vermutlichauf dem Zielkomputer der VLC-player installiert sein?
Ist vielleicht etwas übertrieben, wo die dort auf dem arbeitsrechner eh keine Videos gucken dürfen. :angel:


HTTP ging leider nicht :(
(wäre auch zu Einfach gewesen :lol:)

Ist jetzt kein Problem an deiner Komponente, sondern mehr ein kleiner Fehler bei der Verwaltung.
Delphi-Quellcode:
procedure TfrmMain.Button1Click(Sender: TObject);
begin
  FreeAndNil(Client); // Schließen, wenn schon offen

  Client := TMJPEGClient.Create('192.168.1.10', 80, '/videostream.cgi'); // die URL ist bei vielen Kameras anders, also anpassen!
  Client.OnJPEGReceived := JPEGReceived;
  ...
  Client.Start;
end;

procedure TfrmMain.Button2Click(Sender: TObject);
begin
  FreeAndNil(Client);
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  FreeAndNil(Client); // auch wenn du zwar den Thread über das Terminated abbrichst, bleibt die Komponente bestehen und könnte womöglich auch noch nach dem freigeben des Fensters nochmal versuchen drauf zuzugreifen.
end;
Drück einfach mal mehrmals auf Starten (ok, da passiert hier nicht viel, außer daß jetzt mehrere Threads arbeiten),
aber mehrmals auf Stoppen geklickt, wird vermutlich schön knallen (aber mindestens einmal mußte vorher der thread gestartet wurden sein).

Morphie 1. Okt 2013 14:34

AW: Bild von IP-Webcam auslesen
 
Ja, das ist mir auch aufgefallen... Da das aber ein Beispiel ist, war mir das egal, es ging ja um die Klasse TMJPEGClient ;-)

edit: wenn man die Klasse dann noch in eine Komponente gießt, kann man die Verwaltung dort ja sauberer gestalten...

himitsu 1. Okt 2013 17:34

AW: Bild von IP-Webcam auslesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Das Demoprogramm funktionierte soweit erstmal.
Ich hatte mir nur in die GUI noch ein paar Edits reingemacht, um leichter Testen zu können.
(EXE im Anhang, falls noch wer bei seiner Webcam testen möchte)

Nach einer Weile blieb allerdings das Bild einfach hängen und veränderte sich nicht mehr.
Es gab keine Fehlermeldung und die Form-Caption stand auf Verbunden.
Bei Klick auf Stoppen kam dann aber manchmal die Meldung "Verbindung wurde vom Host getrennt."
(wobei es bei mir zwei verschachtelte RDP-Sitzungen gab, da der Kundenrechner nur von unserem Server aus erreichbar ist, was hier und da einige Problemchen verursacht)

Und Stretch macht sich mit Proportional zusammen auch nicht schlecht.


Der TThread ist jetzt noch nicht raus, aber so sieht man erstmal die Unterschiede direkter.
- die winzigen zu synchronisierenden Prozeduren als anonyme Methoden angelegt (aus 2-3 Funktioen wurde jeweils nur noch Eine)
- die globelan Klassenvariablen entfernt, welche eh nur für die Synchronisierung verwendet wurden
- FormatMessage+FORMAT_MESSAGE_FROM_SYSTEM durch SysErrorMessage ersetzt
- Klassenintern auch auf die internen Variablen gegangen, anstatt über die öffentlichen Property
(da wo es intern nur an der einen Stelle Zugriffe gibt ... so könnte man später auch Getter und Setter verbauen, um externe Zugriffe zu verarbeiten)

Morphie 2. Okt 2013 06:42

AW: Bild von IP-Webcam auslesen
 
Hmmm irgendwie flackert das Bild jetzt aber... Ist das bei dir nicht so?

btw: Das mit den anonymen Methoden kannte ich noch nicht, das finde ich echt nett :)

edit: das Flackern liegt am "proportional = true"
außerdem:
Delphi-Quellcode:
procedure TMJPEGClient.Execute;
...
          JPEGStream := TStream.Create;
...
              JPEGStream.Position := 0;
...
end;
Das erzeugt unter XE4 einen Fehler.
Der setter von Position ruft intern Seek auf. Und dort steht:
Zitat:

No existing TStream classes should call this method, since it was originally abstract.
Daher:
Delphi-Quellcode:
procedure TMJPEGClient.Execute;
...
          JPEGStream := TMemoryStream.Create;
...
end;

himitsu 2. Okt 2013 09:55

AW: Bild von IP-Webcam auslesen
 
OK, das Flackern hatte ich bemerkt, aber ich dachte das liegt am RDP.
Evntuell könnte man hier mit DouleBuffered was machen, aber so unproportional verzerrt sieht das Bild schon etwas komisch aus.
Wie gesagt, geh ich hier über zwei verschachtelte RDP-Sessions (Schlepptop > Firmenserver > Kundenrechner) und RDP ist in manchen Belangen doch etwas "eigenartig".

Ja, beim Erstellen sollte natürlich TMemoryStream drinstehn. :oops:
(eventuell hatte ich zum Testen die falsche Datei übertragen)

Morphie 2. Okt 2013 10:01

AW: Bild von IP-Webcam auslesen
 
Nachdem ich das jetzt in eine Komponente gegossen habe, bin ich nun eigentlich ziemlich zufrieden =) Habe den Stream jetzt schon seit über einer Stunde an und keinerlei Unterbrechungen... Auch die interne Verwaltung ist mit einer Komponente entsprechend eleganter geworden...

Danke für deine Tipps :)

himitsu 2. Okt 2013 12:02

AW: Bild von IP-Webcam auslesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Wobei deine Streamauswertung eher als "böse" anzusehn ist.

Bei TP sieht der MJPEG-Stream so aus:
boundary gibt den Code an, für da, wo ein neues Bild anfängt .... das ist praktisch genauso, wie bei bei den Multipart-eMails (HTML/Text/Anhänge).
Code:
HTTP/1.1 200 OK
Server: httpd
Cache-Control: no-store
Pragma: no-cache
Connection: close
Content-Type: multipart/x-mixed-replace;boundary===AMTKSTILLIMAGEBOUNDARY==

--==AMTKSTILLIMAGEBOUNDARY==
Content-Type: image/jpeg
Content-Length: 5495

{5495 Bytes ohne Zeilenumbruch am Ende, bzw. mit, wenn man die nachfolgende Zeile dazu nimmt}

--==AMTKSTILLIMAGEBOUNDARY==
Content-Type: image/jpeg
Content-Length: 5507

{5507 Bytes}

--==AMTKSTILLIMAGEBOUNDARY==
Content-Type: image/jpeg
...
Mal so aus Interesse, was steht denn bei dir im Log-Memo?
> starten und nach ein paar Bildern wieder stoppen

Morphie 2. Okt 2013 12:06

AW: Bild von IP-Webcam auslesen
 
Mit der Exe bekomme ich gar kein Bild:
Zitat:

Verbindung wird hergestellt...

Verbunden
HTTP/1.1 400 Bad Request
Server: Netwave IP Camera
Date: Wed, 02 Oct 2013 11:03:54 GMT
Content-Type: text/html
Content-Length: 135
Connection: close

Fehler -13: Unbekannt - "<HTML><HEAD><TITLE>400 Bad Request</TITLE></HEAD>
<BODY BGCOLOR="#cc9999"><H4>400 Bad Request</H4>
Can't parse request.
</BODY></HTML>"

Fehler -13: read image 0 ""
edit: es stimmt aber, dass das Protokoll eigentlich anders gedacht ist, aber da es bei mir ohne Weiteres funktioniert, reicht mir das so :)

himitsu 2. Okt 2013 12:15

AW: Bild von IP-Webcam auslesen
 
Bei der EXE ist Post 80 eingestellt. Das hattest du auch auf deine 81 geändert?

Im Anhang ist die selbe EXE, nur halt mit deinen Werten in den Edits.
OK, auch wenn kein Bild, so kommt dennoch ordnungsgemäß eine schöne HTML-Seite zurück. :D

Morphie 2. Okt 2013 12:22

AW: Bild von IP-Webcam auslesen
 
Ja, ich hatte alles korrekt eingetragen.
Bekomme aber immer noch 400 Bad Request... Hast du etwas an dem GET geändert?

Ich habe den Traffic mal mit meinem Programm geloggt:
Code:
'HTTP/1.1 200 OK'
'Server: Netwave IP Camera'
'Date: Wed, 02 Oct 2013 11:14:47 GMT'
'Accept-Ranges: bytes'
'Connection: close'
'Content-Type: multipart/x-mixed-replace;boundary=ipcamera'
''
'--ipcamera'
'content-type: image/jpeg'
'content-length: 36352'
''
Binärdaten
''
'--ipcamera'
'content-type: image/jpeg'
'content-length: 36352'
''
Binärdaten
''

himitsu 2. Okt 2013 12:48

AW: Bild von IP-Webcam auslesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
OK, dann ist das StreamFormat zumindestens gleich. :)


Etwas geändert ja (im OnConnect kann man für den RequestHeader weitere Zeilen mit übergeben), aber da dort nichts gemacht wird, sollte der Header eigentlich gleich bleiben. :gruebel:

Ich geb den Haeder mal mit ans Log aus.

[edit]
Und über eine CheckBox kann man angeben, ob die Header einzeilig (so wie es vorhin noch war) oder zusammenhängend versendet wird.

Morphie 2. Okt 2013 13:00

AW: Bild von IP-Webcam auslesen
 
Ich habe dir mal eine PN mit den Zugangsdaten zu meiner Cam geschickt, vielleicht kannst du damit besser testen?

himitsu 2. Okt 2013 13:15

AW: Bild von IP-Webcam auslesen
 
Du wirst es bestimmt nicht glauben, aber deine Kamera versteht auschließlich nur den Windowszeilenumbruch (#13#10).
Die ist einfach nicht mit der Linux-Variante (#10) klargekommen und auch den Mac (#13) mag sie nicht. :roll:

Und ich dachte mir so "läßt'e mal die #13 besser weg, nicht daß eine Kamera mal mit Windows nicht klar kommt" :lol:

himitsu 2. Okt 2013 15:31

AW: Bild von IP-Webcam auslesen
 
Liste der Anhänge anzeigen (Anzahl: 2)
Sooo,

noch ein bissl Fehlerbehandlung mit rein und versucht die Header mit auszuwerten, dazu vorher jeweils erstmal den kompletten Header einlesen.
Die Header werden auch an die Events mit übergeben, damit dort notfalls drauf reagiert werden könnte.


Wie sieht dein Code denn nun aus?

Ach ja, content-length muß natürlich nicht immer der letzte Headereintrag sein, kurz vor dem DataStream.
Der DataStream fängt aber nach der Leerzeile an, bzw. es fängt abwechselnd, nach der Leerzeile, der Header an.
(da du ja nach dem content-length versuchst das Bild zu laden)


Für dich eventuell besser, wenn du die Events nicht via Synchronize im Hauptthread ausführst.
So könntest du mehrere Threads (je Kamera Einen) parallel laufen lassen, in deinem Service, ohne daß die sich gegenseitig ausbremsen.



Ach ja, das Flackern kommt vom TImage, welches da wohl irgendwelche Problemchen hat.
Im Code zeichne ich daher aktuell das Jpeg auf eine TPaintBox.

Je größer das TImage, um so eher und stärker flackert es.
Mit Self.DoubleBuffered läßt es sich etwas eindämmen.
Das TImage selber hat kein DoubleBuffered, da es sich auf dem Canvas seines Owners zeichnet. Und mit einem TPanel+DoubleBuffered dazwischen war auch nichts zu machen.

himitsu 10. Okt 2013 12:16

AW: Bild von IP-Webcam auslesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, bisher gab es noch keine Antwort von TP.
(die Frage nach einem direkt auslesbaren JPEG war wohl zu schwer)

Die letzten Tage hab ich vorallem den Arbeits-Thread nochmal komplett überarbeitet.
- genauer das Übertragungsprotokoll direkt auf die grundsätzliche Motion JPEG-Definition angepaßt
- die Fehlerbehandlung überarbeitet
- ein Logging für den Thread und die übertragenen Daten eingebaut, um die Funktion zu testen und die Daten-/Fehleranalyse bissl zu vereinfachen
- die Error-Events entsprechend angepaßt
- versucht einen FrameLimiter einzubauen, bzw. die FPS mitzuzählen
- und vorallem wurde das ReceiveEvent erweitert
- im Testprogramm wird die Komponente immernoch manuell erstellt, damit die Unit installiert werden muß

Wäre nett, wenn nochjemand das Programm und den Code prüfen könnte, auch mit anderen Webcams.

Nette Test-Webcams hab ich auf www.mjpeg.net entdeckt und aktuell sind ein paar knuffige Vögelchen voreingestellt.

Morphie 10. Okt 2013 12:27

AW: Bild von IP-Webcam auslesen
 
Zitat:

Zitat von himitsu (Beitrag 1231581)
So, bisher gab es noch keine Antwort von TP.

Sorry, ich habe das Projekt erst mal eingefroren, da ich mich zur Zeit beruflich neu orientiere... Sobald ich wieder viel Freizeit habe, führe ich die Sache aber weiter...

Zitat:

Zitat von himitsu (Beitrag 1231581)
(die Frage nach einem direkt auslesbaren JPEG war wohl zu schwer)

??? Habe ich da etwas übersehen? Was meinst du?

Zitat:

Zitat von himitsu (Beitrag 1231581)
Wäre nett, wenn nochjemand das Programm und den Code prüfen könnte, auch mit anderen Webcams.

Mit meinen Webcams läuft das Testprogramm ohne Probleme.
Der Framerate-Limiter funktioniert auch.

himitsu 10. Okt 2013 12:29

AW: Bild von IP-Webcam auslesen
 
Zitat:

Zitat von Morphie (Beitrag 1231588)
Zitat:

Zitat von himitsu (Beitrag 1231581)
So, bisher gab es noch keine Antwort von TP.

Sorry, ich habe das Projekt erst mal eingefroren, da ich mich zur Zeit beruflich neu orientiere...

Keine Sorge, ich meinte TP-Link, den Hersteller der Webcam, von Welchem bisher noch keine Antwort eingetroffen ist.

himitsu 14. Okt 2013 13:07

AW: Bild von IP-Webcam auslesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, ich denk das war's jetzt erstmal.
Bis au eine Kleinigkeit (der Canvas) läuft es jetzt stabil.



Erstmal wurde eine kleine Version abgesplittet, welche einen Minimalcode enthält.

Die große Version enthält mehr Events und Einstellungsmöglichkeiten.
- diese kann aber über Compilerschalter eingeschränkt werden, z.B. indem man die VCL-Zugriffe entfernt
- es kann auf die Übertragenen Daten zugeriffen werden, z.B. zum Loggen oder für die Implementation einer Verschlüsselung
- der gesendete Anfrage-Header kann angepasst werden, z.B. für die Verschlüsselung und wenn es dort Probleme gibt
- man kann einen Canvas direkt anhängen, wo die Komponente das Bild draufzeichnet

Es sollte eigentlich für jedes Bedürfnis ein passendes Event/Property bereitstehen.
Ob und wie ich da aber noch Proxy reinbekomm, muß ich mal sehn. (sobald das direkt mit dem TTCPClient läßt es sich leicht nachrüsten)

Sehr unpraktisch ist, daß der TTCPClient in den Schleifen kein Timeout hat.
Mir war aufgefallen, daß eine Kamera manchmal einfach hängen blieb. (Connection blieb offen, aber es sind keine Daten mehr reingekommen)
So blieb meine Datenleseschleife hängen, bei "0 byte gelesen" im ReceiveBuf und landete in einer Endlosschleife. (das hab ich erstmal nicht über ein Timeout gelöst, aber dafür wird dort nun auf das "Stop" gehört)
[edit] in der MJpegClientSmall.pas fehlt dieser Bugfix noch (ist dann im nächsten Upload drin)
Aber im TTCPClient.ReceiveLn ist diese Endlosschleife dennoch drin.

Die Testprogramme sollte ich wohl auch langsam mal in Demo umbenennen.



Nun aber nochmal zum Canvas.
Die "Selbstzeichenfunktion", siehe MJpegTest_Canvas.dproj, gefällt mir noch nicht so richtig.
Vielleicht hat da jemand einen guten Vorschlag?

Ich hätte dort TGraphic als Property nehmen können, dann würde man ganz leicht auf TImage/TPicture/TJPEGImage zugreigen können.
Aber die TPaintBox hat ja kein TGraphic-Property.
So kann zwar überall draufgezeichnet werden, aber die Komponente kann die Bildgröße von den TImage/TPicture/TJPEGImage nicht automtisch anpassen.

Es kann aber auch nicht die Bildausgabe automatisch an die Zeichenfläsche angepasst werten => stretch
Und sowas http://www.delphipraxis.net/18336-gr...ermitteln.html geht ja leider nicht.

Nja, via OnDataReceived oder OnImageReceived kann man die Bilder immernoch manuell an alles übergeben.



In Punkto FrameLimiter hatte ich auch noch keine schöne Lösung.
Man kann zwar die Anzahl der angezeigten Bilder (FPS) begrenzen, indem man ein Sleep einbaut und somit die ausgabe verzögert.
Einige Cameras brechen die Verbindung ab, wenn der Sendepuffer voll ist und Andere legen nur eine Pause ein.
- nur sind dann dabei die Bilder verzögert => z.B. bei 0.1 FPS sind die Bilder um mindestens 10-20 Sekunden verzögert, wenn die Kamera ein Bild pro Sekunde ausliefert.

Die andere Lösung war, wenn man zwar alles schnell runterläd, aber z.B. via OnPreReceived die "unnötigen" Bilder überspringt.

ramboni 14. Nov 2013 22:06

AW: Bild von IP-Webcam auslesen
 
Hallo,

ist es möglich im Falle eines falschen Request, statt den Fehlercode "-9" den
jeweiligen Fehlercode zurück zu bekommen? Sprich z.B.: 401, 404 oder 400?

Oder geht das schon und ich bin nur zu doof?

LG

himitsu 14. Nov 2013 23:26

AW: Bild von IP-Webcam auslesen
 
Du bekommst im OnError (ErrorMessage) und vorher auch nochmal im OnConnected (ReceivedHeader) den HTTP-Header geliefert, wo du diesen Statuscode auslesen kannst.

Falls ich mich jetzt nicht vertan hab, sähe 'ne Billigvariante für OnError mit ErrorCode=TMJpegClient.eFAILURE so aus:
Delphi-Quellcode:
i := Pos(sLineBreak, ErrorMessage); // bzw. 'HTTP/' statt sLineBreak
i := PosEx(' ', ErrorMessage, i);
StatusCode := Copy(ErrorMessage, i + 1, 3);

StatusCode := Copy(ErrorMessage, PosEx(' ', ErrorMessage, Pos(sLineBreak, ErrorMessage)) + 1, 3);
Ab der zweiten Zeile fängt der Header an und da steht immer in der 1. Zeile der Statuscode.
Delphi-Quellcode:
HTTP/1.1 200 OK
(HTTP-Version Leerzeichen StatusCode Leerzeichen StatusTextBisZeilenende)



Bestimmt wäre es möglich diese Fehlernachrichten direkt als TStrings anstatt String an diese Events zu übergeben, dann wäre Auswerten etwas einfacher.
[edit]
Als TStrings hätte es denn Vorteil, daß der RequestHeader immer an der selben Stelle (Index) anfangen könnte, da einzeilne Zeilen Strings auch Zeilenumbrüche enthalten können.

ramboni 15. Nov 2013 00:12

AW: Bild von IP-Webcam auslesen
 
Bei
.Connected(Sender: TObject; ReceivedHeader: TStrings);

bekomme ich mit ReceivedHeader.Text in der ersten Zeile: HTTP/1.1 401 Unauthorized
Was super ist.

Allerdings bekomme ich bei
.Error(Sender: TObject; ErrorCode: HRESULT; ErrorMessage: string);

<HTML><HEAD><TITLE>401 Unauthorized</TITLE></HEAD>
<BODY BGCOLOR="#cc9999"><H4>401 Unauthorized</H4>
Authorization required.
</BODY></HTML>


Das sieht irgendwie nicht nach einem Header aus, oder?
Hier wäre "HTTP/1.1 401 Unauthorized" cool
Oder muss da was von HTML stehen?

LG

himitsu 15. Nov 2013 02:00

AW: Bild von IP-Webcam auslesen
 
Liste der Anhänge anzeigen (Anzahl: 2)
Joar, gerade bei der einen ErrorMessage war kein Header dabei, obwohl es Einen gibt. :angle2:

NWar nur der Fehlertext, den der Server ausgibt, der natürlich sonstwie aussehen kann ... angefangen bei einem einfachen Text, wo "401 Unauthorized" steht, bis zu einer mehr oder weniger aufwändigen HTML-Seite.
(der Witz ist, jetzt wenn ich drüber nachdenke, dann hatte ich an der Stelle den Header auch noch absichtlich weggelassen :lol:)

Delphi-Quellcode:
if ErrorMessage.Length > 2 then
  StatusCode := StrToInt(Copy(ErrorMessage[2], Pos(' ', ErrorMessage[2]) + 1, 3));
[edit]
Anhang nochmal ausgetauscht (09:30 17:22)

himitsu 15. Nov 2013 08:30

AW: Bild von IP-Webcam auslesen
 
Ich kopiere das mal für Alle hier mit rein.

Zitat:

Zitat von ramboni
Gibt es ein Event wenn der Benutzername/Passwort falsch sind
bzw. wie kann ich soetwas feststellen?

Ein direktes Event dafür gibt es nicht,
aber da die Kamera in diesem Fall die Verbindung verweigern sollte, kommt natürlich bei OnError eine entsprechende Meldung an,
jenachdem wie der Server in der Kamera darauf reagiert und was/ob er dann zurückgibt.

Zitat:

Zitat von ramboni
Ich habe eine relativ hohe CPU-Auslastung wenn ich beide Kameras aktiviert habe
bzw. den Stream ca. 5x gleichzeitig öffne. Mach ich da was falsch? Ich habe die Ausgabe
auf einem Image.

Das Dekodieren und Anzeigen der Bilder braucht halt ein bissl Rechenleistung.

Man könnte die Streamverarbeitung ausbremsen, indem man z.B. ein Sleep nach jedem Bild einfügt.
z.B. siehe Max FPS in MJpegTest_OnImage, MJpegTest_OnData

Aber einige Kameras scheinen das nicht ganz zu mögen und trennen irgendwann die Verbindung (womöglich Überlauf des Sendepuffers).
Bzw. dabei könnte das Video mehr oder weniger verzögert sein.

Man kann auch versuchen die Bearbeitung der Bilder anders zu lösen.
- Also bei OnDataReceived einsteigen und den Stream in eine andere/schnellere JPEG-Komponente einlesen.
- Und/oder die Ausgabe/Darstellung anders lösen?

Oder man könnte über OnPreReceived dafür sorgen, das garnicht erst alle empfangenen Bilder verarbeitet werden.
Delphi-Quellcode:
Result := (GetTickCount - ReceiveStart) >= 1000;
= überspringe das Bild, wenn das letzte Bild vor weniger als einer Sekunde angezeigt wurde.
Damit würde der Datenstrom zur Kamera nicht beeinflusst.
Man kann ja gern versuchen da auch nochmal ein kleines Sleep reinzumachen, um zusätzlich nochmal den Traffic zu beschränken.

Zitat:

Zitat von ramboni
Du schreibst in deinem Text: " gesendete Anfrage-Header kann angepasst werden"
Kannst du mir sagen wie das geht? Verschlüsselung hört sich interessant an :)

Die einfachste Verschlüsselung ginge via HTTPS. (in wie weit und ob das jetzt schon möglich ist, weiß ich aber noch nicht)

In OnConnecting kannst du den RequestHeader bearbeiten, bevor er zur Kamera gesendet wird.
Da könnte man z.B. eine Komprimierung oder eben Verschlüsselung aktivieren, indem man die passenden Werte im Header übergibt.

Es kommt aber alles darauf an, was die Kamera für Funktionen anbietet, denn die muß da ja mitmachen.

Und über OnReceiveDebug kommt man an TTCPClient.OnReceive und TTCPClient.OnSend ran, wo man dann die empfangenen/gesendeten Daten komprimieren/dekomprimieren/verschlüsseln/entschlüsseln.

ramboni 15. Nov 2013 15:27

AW: Bild von IP-Webcam auslesen
 
Moin,

bei mir funktioniert:

Delphi-Quellcode:
if ErrorMessage.Length > 2 then
  StatusCode := StrToInt(Copy(ErrorMessage.ValueFromIndex[2], Pos(' ', ErrorMessage.ValueFromIndex[2]) + 1, 3));
leider nicht. Zum einen kennt er ErrorMessage.Length nicht und ValueFromIndex[2] ist leer.

Mit:
Delphi-Quellcode:
Copy(ErrorMessage[2], Pos(' ', ErrorMessage[2]) + 1, 3))
bekomme ich jedoch 401 als String zurück...

Also Danke Danke Danke :)

himitsu 15. Nov 2013 15:40

AW: Bild von IP-Webcam auslesen
 
Was steht denn insgesamt in ErrorMessage / ErrorMessage.Text drin?

Wenn ich mich nirgendwo verzählt hab, dann sollte in [0] ein Text passend zum ErrorCode stehen,
in [1] eine Zusatzinfo, wie z.B. das übersetzte GetLastError
und ab [2], falls vorhanden, der empfangene HTTP-Header.


[edit]
Stimmt, die erste Zeile vom HTTP-Header ist noch anders formatiert.
Dein zweiter Code ist also richtig.

Bei den 3xx-StatusCodes könnte man sich mit
Delphi-Quellcode:
URL := Trim(ErrorMessage.Value['Location']);
die neue URL besorgen.

Thomasl 15. Nov 2013 23:20

AW: Bild von IP-Webcam auslesen
 
Ich habe schon ein paar Kameras mit diesem ActiveX eingebunden.
http://www.axis.com/techsup/software/amc/software.php

Hier ist auch ein Video.
http://www.axis.com/de/techsup/cam_s...ev/activex.htm

ramboni 26. Feb 2014 19:57

AW: Bild von IP-Webcam auslesen
 
Moin Moin,

ist ja schon einige Zeit her als ich was geschrieben hatte.

"Damals" mit meiner alten Cam hat auch alles wunderbar funktioniert.
Ich habe die Daten einfach so übergeben:

IP_Adresse/videostream.cgi?user=USERNAME&pwd=PASSWORT
Hat super funktioniert. Nun habe ich eine neue IP-Kamera und siehe da,
nüscht geht mehr :(

Es ist eine DCS-5222L und laut: http://www.zoneminder.com/wiki/index...Link#DCS-5222L

Muss die Auth so aussehen:

HTTP
Source Type: Remote
Remote Host Name: user:pass@<IP Address of Camera>
Remote Host Port: 80 (Default)
Remote Host Path: /video/mjpg.cgi (for mjpeg stream)
Remote Host Path: /image/jpeg.cgi (for jpeg stream)

Was im Browser wunderbar funktioniert.

Ich habe also den Path geändert, aber mit dem Benutzernamen & Psw VOR der IP
kommt die Komponente irgendwie nicht klar.
Ich bekomme immer Benutzername Passwort falsch zurück :(

Oder habe ich, was sehr viel wahrscheinlicher ist, einen Fehler gemacht?


BTW: Bei den vielen Pathangaben die es so gibt, besteht da nicht die möglichkeit die
Kamera zu fragen wo ihre URL zum Video ist?
So das ich nicht für jede Cam testen muss?

ContaCam z.B. macht das auch irgendwie alles automatisch.


LG

himitsu 27. Feb 2014 02:07

AW: Bild von IP-Webcam auslesen
 
Womit hat du es denn probiert?

Bei der MJpegClient.pas (aktuellster Download im Post #33) könntest du es mal so probieren:

Als Host dein
Delphi-Quellcode:
'user:pass@ip'
angeben und ins
Delphi-Quellcode:
{TMJpegClient}.OnConnecting
dann noch Folgendes rein
Delphi-Quellcode:
with (Sender as TMJpegClient).Header do
  if Pos('@', Values['Host']) > 0 then
    Values['Host'] := Copy(Values['Host'], Pos('@', Values['Host']) + 1);

ramboni 27. Feb 2014 11:21

AW: Bild von IP-Webcam auslesen
 
Vielen Dank, ich werde es heute Abend versuchen.

Gibt es einen Standard der sagt das jede Cam auf eine bestimmte Weise
reagieren muss? Ich möchte nur ungern den Code für jede Cam anpassen müssen.

Bis jetzt suche ich mir die Daten zum Videopath noch per Hand raus, und der
ist schon bei dem Cams recht unterschiedlich. Steht da nicht in irgendeiner
Datei drin wo das Video her kommt, so das ich das automatisieren kann?

LG


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:05 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz