Toon posts:

[DELPHI] jpeg van network webcam -> delphi proggie

Pagina: 1
Acties:

Verwijderd

Topicstarter
Beste Tweakers,

Ik probeer in Delphi een programma te schrijven dat een plaatje ophaalt van en netwerk camera en deze weergeeft in een Timage component (of wegschrijft in een bestand, dat is me om het even). Ik werk met een Edimax IC-1000, deze levert plaatjes in JPEG formaat.

Als eerste heb ik gekeken of ik kon achterhalen welk bericht van de webbrowser wordt gestuurt om een plaatje terug te krijgen. Vervolgens de data uit het TCP pakketje gevist en deze weggestuurd d.m.v. een TClientSocket.

Delphi:
1
2
3
4
procedure TForm1.TTButton2Click(Sender: TObject);
begin
  ClientSocket1.socket.SendText(#48#49#49#48#13#10);
end;


En waarempel, ik krijg een hele zooi TCP pakketjes teruggestuurd. Zie einde post voor hoe dat er in tekst uitziet. Maargoed, nu moet ik op de een of andere manier deze stroom data in een Timage gieten. Je kan natuurlijk geen string in een Timage gieten, en het lijkt erop dat je alleen tekst uit een TClientWinSocket kan lezen... Heeft iemand enig idee hoe je dit op zou kunnen lossen?





Œô¥´¹Åac½.)4HgÿÐênð6ñN^”ÛÂ>Zzr+XœVÔZJZ
?ÿÑêé
8ÓMjq
4Úq¦Õ"OÿÒéj)”dT¦ ›!‡¥txƒ•¹SsšByâ‹ùŽÞGÿÓÛi2h k¢ÞGÌBy¦šv)†˜XÿÔÖ–)Eulpoæ(ŜLZÿÕ×i˜æŸQçÔy㈦“ÇRM3ž”\,ÿÖÑúÒu=iØûSz×Qç Ôê[õTÃÜ(ëO°ÿ
Ô„ô GÿÓí°
ë…i
ñA¤<Ö§(™¢“¥€?ÿÕÚ&£'šq¦Ôå3u&#143;õ5ƒ[ºÏúªÂ§ˆ]OÿÖÅ­&#143;ÿ
¨¢–ºLD¢Ŝ(ÿÑ稢Ŝê0Ŝ(¤ÿÒçh¢Ŝé1ãô±ñ"Ÿzm÷‡Ö&#144;ÿÓèù¦K÷
MšG
FÚ¶"ö£Êö©öˆ,Ïÿ×ÄÅZ¹äûRùU§´1å(í£iô«ÞWµ/”)û@±ÿÐʵ\\!÷®Î/õcé\¼1&#129;*ýk¨ˆ~í~•´g}ídÇ7JˆÔ‡8¨ÏZOÿÑÙ<
m8ô¤íZœ£©\¶N*äœÖsœ±4¤ÿÒCLj&#144;Ó
3„±fBqLòzUÆ_›4ݵ%+ÿÓËòG¥]YÛFÊ.Ìô+ùtyuggµ)ÏÿÔÍÙK²§ÛíFÚFW ÙFÊŸe)…ÏÿÕÎÛK¶§ÙFÊ®A²&#141;•>Ê6P+ŸÿÖ¡²&#141;•6Ú6ÐbC¶&#141;µ.ÚM´
çÿ×ÚÍQ]!çŜ¯S\u¨*XÖçÿйFi)kSœ\ÒƒM¢&#129;ŸÿÑ¿š3M¢µ0šZe.iÿÒÒ´ÀiwV¦©i ÒƒHÿÓÕ©­Î$IÃŜÔÀÔ)ÀžÔÄ9ANVÅ&6&#127;ÿÔé¯N#ÉíX²¹c[Z‡6äÖUÏq¦šiÆši&#127;ÿÕq¦šq¦Ó23ï´¼T"Z.&#129;›¥7`ô¦¥a[SÿÖÊšÛÐc½SòÇ¥iiµÚ¯&#157;™ÅYšÆ&#129;Aé@¦D·?ÿ×艤 õ Ö‡8‡¥6”ÒPÿÐÞ¦·ž:U{‡Ââ´9È'“qÀéUÍ8ÓMAHÿјÓ
<ÓZƒ"'Ojœõ£m ?ÿÒ‡a£eXÙFʈ6Q²§Ø)vR¸ÏÿÓ‹e*}¢&#141;´®fA²—eK¶&#141;´\ÿÔj/Î>µÐEþ©~•†£æ·ú¥úSƒÔÍì<ô¨ÏZyéL<
ÐÄÿÕÚ4ÃO¦šÔå+ܾ¨š±pÙ|zUsQ"‘ÿÖ
0ÓÍ4Ðb7nhÙO)iÿ×fÊ6Ó詹&#157;†mmê(ÿÐfÚM´úJ“!1IŜuÿÑ&#143;b–ƒRd6ŒRÑLGÿÒ†&#144;Ó©
#)
-! GÿÓÚ¥è)(í])ZsóTTé~ñ¦T±ÄÿÔ·KIEls‹Ŝ(¥¤3ÿÕº(¢–µ0–Ŝ(ÿÖ½KIŜ\V¦
Ðd9zRÒ'Ju&3ÿ×ZJZJƒ0¢ŜJ
ªÌÑÿÕ&#144;ÓM8Óƒ!¦šiM!¤3ÿÖŒÓM)¤5&b§Z’£N´ú
y=94õÿ

[ Voor 11% gewijzigd door Verwijderd op 26-07-2005 10:44 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Volgens mij moet je gewoon een HTTP request doen (en dus niet "ranzig" pakketjes gaan sniffen en die maar weer "copy-en" en opnieuw sturen). Het ziet er naar uit (gezien aan de #13#10) dat je een "gewoon" request moet doen (met een CR = 13 en LF = 10). Ik neem aan dat je poort 80 gebruikt? Sterker: Je stuurt nu dus HIIHCRLF als ik het als Hex ASCII codes interpreteer.

Verder zie ik aan die "zooi" niks terug of dat een JPG is (die bevatten doorgaans in de eerste zoveel bytes de tekst JFIF ofzo; zie daarvoor ook deze site, effe zoeken op "JPEG"). Dus kijk even of je wel de juiste data terug krijgt (denk aan Unicode en dat soort dingen die nog wel eens problemen willen opleveren) en schrijf desnoods die string even binair weg in een bestand.jpg en kijk of je dat bestand wel kunt openen. Helaas ben ik geen Delphi guru, dus ik weet niet hoe je die string in die Timage gaat krijgen, hoewel je met wat API calls misschien m.b.v. de handle van dat ding je image erin zou kunnen krijgen...

[ Voor 36% gewijzigd door RobIII op 05-07-2005 17:38 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

En een TClientSocket kan weldegelijk ook binaire pakketjes aan. Hier vind je kant en klare Delphi source voor een webcam progje.

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Topicstarter
Bedankt voor jullie reply,

@LordLarry
Hier heb ik inderdaad uit kunnen afleiden hoe je een plaatje kan oversturen. Das natuurlijk zeer fijn, maar degene die het plaatje serveert is de netwerk/IP camera/webcam en niet een server die ik zelf heb geschreven. maargoed, wel weer een stapje dichterbij :)

@RobIII
Ik heb geprobeert om het met een http request te doen, maar als ik een GET zou doen... welk bestandje zou ik dan willen GET-en? die #48#49#49#48#13#10 stuur ik naar poort 4321, en niet naar poort 80, dus die webcam zal waarschijnlijk geen http request op poort 4321 verwachten. poort 80 wordt gebruikt om de browser interface aan te roepen. Het applet wat dan vervolgens in de browser draait vraagt het plaatjes aan de webcam via poort 4321.

En dan de "ranzig" gesnifte pakketjes. Die "#48#49#49#48#13#10" heb ik verkregen door te kijken wat voor pakketje gestuurd wordt door het applet wat in de browser runned om een nieuw plaatje te verkrijgen. Ik werdt toch wel benieuwd hoe de viewer die op de CD meegeleverd was dit deed. Deze stuurd ook een pakketje naar poort 4321, maar deze heeft als data #48#49#49#48, zonder de #13#10 dus.... vergeleken wat voor bestand ik terug krijg en het bestand bevat precies dezelfde header dan het bestand verkregen met de oude request string.

Nadat ik het een paar keer geprobeert had te openen in paintshop viel me op dat de bestanden die ik probeerte te openen maar 14 KB groot waren. Maar gelukkig hield de bijgeleverde viewer ook wat stats bij: Video Received(KB) 159567 Numerber of Frames: 11779. Dat zit dus wel goed.

Toen kwam ik op het lumineuze idee om het bestandje maar eens in een hex editor te bekijken. Ik zal onder aan de post alleen de header posten (hetgeen wat ik denk dat de header is omdat dit gedeelte in alle gedownloade bestanden hetzelfde is). Mischien niet de meest handige manier om dit te posten... maar uhm, het belangrijkste is dat de combinatie "4A 46 49 46" in de eerste regel staat voor JFIF. Jippie!, toch?

Toen maar eens gekeken hoe het eruit ziet als je een plaatje met een http GET over het lijntje trekt (gewoon eenr andom plaatje van Inet opgevraagt). Deze pakketjes maar eens in de hex viewer van ethereal bekeken en er waren twee dingen die me opvielen. Punt 1: er was geen JFIF te bekeken, Punt 2: bepaalde strings komen overeen met strings die in de header van de stream bytes die van de IPcam komen. Je vindt deze bij een http Get op het volgende punt:
Nadat je een http GET op een bepaald bestand doet krijg je als reply (als het bestand bestaat) een OK (code 200). In dit geval was het: "HTTP/1.0 200 OK (JPEG JFIF image)" In dit pakketje zit ook een beschijving van het "JPEG File Interchange Format" (waarschijnlijk hoe de parameters zijn ingesteld voor het JFIF bestandje?). Eén van deze stukjes informatie bevat informatie over het "Define Huffman Tables". Ik weet niet precies wat dat is, maar wel dat het iets is wat je optioneel kan meesturen in de header. En deze definities komen overeen met gedeeltes uit de header van de bestandjes uit de IPcam.

Oh ja, nog belangrijk te vermelden is dat ik geprobeert heb om een jpg template over het ontvangen bestandje te leggen in een hex editor. Dit lukte (as in, hij gaf geen error), maar er waren veel ontbrekende delen en hij kon bijvoorbeeld maar 1 sigment vinden (bij "werkende" jpeg plaatjes die ik op deze manier bekeken heb waren er altijd 8 sigmenten).

Dus ja... Mijn vraag is eigenlijk, wat is dit bestandje? moet het op de één of andere manier gedecodeerd worden door http? of is het een bestandje dat een frame is uit een video (maar dan zou je die JFIF niet verwachten...)? Kan ik het bestandje op de een of andere manier leesbaar krijgen? Ik weet het ff niet meer... Hopelijk weet iemand anders hier wat zinnigs over te zeggen. Als je behoefte hebt aan het bestandje kan ik dat mailen, ik kan het helaas niet ff snel ergens uploaden. Ik zal in de tussentijd het gedrag van een andere network webcam (de Sitecom ln-400) gaan bestuderen :)

35 E0 01 00 FF D8 FF E0 00 10 4A 46 49 46 00 01
01 00 00 01 00 01 00 00 FF DB 00 43 00 10 0B 0C
0E 0C 0A 10 0E 0D 0E 12 11 10 13 18 28 1A 18 16
16 18 31 23 25 1D 28 3A 33 3D 3C 39 33 38 37 40
48 5C 4E 40 44 57 45 37 38 50 6D 51 57 5F 62 67
68 67 3E 4D 71 79 70 64 78 5C 65 67 63 FF DB 00
43 01 11 12 12 18 15 18 2F 1A 1A 2F 63 42 38 42
63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63
63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63
63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63
63 63 FF C4 00 1F 00 00 01 05 01 01 01 01 01 01
00 00 00 00 00 00 00 00 01 02 03 04 05 06 07 08
09 0A 0B FF C4 00 B5 10 00 02 01 03 03 02 04 03
05 05 04 04 00 00 01 7D 01 02 03 00 04 11 05 12
21 31 41 06 13 51 61 07 22 71 14 32 81 91 A1 08
23 42 B1 C1 15 52 D1 F0 24 33 62 72 82 09 0A 16
17 18 19 1A 25 26 27 28 29 2A 34 35 36 37 38 39
3A 43 44 45 46 47 48 49 4A 53 54 55 56 57 58 59
5A 63 64 65 66 67 68 69 6A 73 74 75 76 77 78 79
7A 83 84 85 86 87 88 89 8A 92 93 94 95 96 97 98
99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 B4 B5 B6
B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA D2 D3 D4
D5 D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 E8 E9 EA
F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FF C4 00 1F 01 00
03 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00
01 02 03 04 05 06 07 08 09 0A 0B FF C4 00 B5 11
00 02 01 02 04 04 03 04 07 05 04 04 00 01 02 77
00 01 02 03 11 04 05 21 31 06 12 41 51 07 61 71
13 22 32 81 08 14 42 91 A1 B1 C1 09 23 33 52 F0
15 62 72 D1 0A 16 24 34 E1 25 F1 17 18 19 1A 26
27 28 29 2A 35 36 37 38 39 3A 43 44 45 46 47 48
49 4A 53 54 55 56 57 58 59 5A 63 64 65 66 67 68
69 6A 73 74 75 76 77 78 79 7A 82 83 84 85 86 87
88 89 8A 92 93 94 95 96 97 98 99 9A A2 A3 A4 A5
A6 A7 A8 A9 AA B2 B3 B4 B5 B6 B7 B8 B9 BA C2 C3
C4 C5 C6 C7 C8 C9 CA D2 D3 D4 D5 D6 D7 D8 D9 DA
E2 E3 E4 E5 E6 E7 E8 E9 EA F2 F3 F4 F5 F6 F7 F8
F9 FA FF C0 00 11 08 01 E0 02 80 03 01 22 00 02
11 01 03 11 01 FF DD 00 04 00 02 FF DA 00 0C 03
01 00 02 11 03 11 00 3F 00

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Omdat het geen poort 80 betreft wil het nog niet zeggen dat het geen HTTP is ;)
En misschien wordt er wel http compressie gebruikt?

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

Topicstarter
Dat zou idd kunnen, dat betekent dat de informatie die de network webcam verstuurd bij een http client moet aankomen. Enig idee hoe ik een http client zover krijg om hem een 4 bytes aan data (#48#49#48#49) te versturen ipv een GET?

Verwijderd

Topicstarter
Inmiddels heb ik het gehele verhaal met de sitecom ln-400 wel aan de praat gekregen, naar een beetje rondsnuffellen blijkt dat je daar alleen een GET op "/IMAGE.JPG" hoeft te doen, etc voila.

Mischien niet iets wat mij helpt bij die andere camera, maar ik kon het nergens op inet vinden, dus bij deze ;)

Verwijderd

Verwijderd schreef op donderdag 07 juli 2005 @ 14:48:
Mischien niet iets wat mij helpt bij die andere camera, maar ik kon het nergens op inet vinden, dus bij deze ;)
Als je TCL kan (laten) ontcijferen...
http://gem.win.co.nz/mb/misc/edicam/

Verwijderd

Topicstarter
Ik had idd die site ook gevonden en de maker in een mailtje zeer beleeft gevraagt of hij mischien kon vertellen wat voor info je terug gestuurd kreeg. Dat mailtje had ik gestuurd voordat ik dit topic poste, maar ik heb inmiddels antwoord terug :)

"The camera puts a header in front of the actual image data. I forget the
details off-hand, but I think it's 4 bytes, 2 of which are the size, and
the other 2 are always the same.

Also, with this camera you have to send the string 0110 followed by CRLF
(from memory) to make it capture an image. And there is another
subtlety--sometimes when you send 0110 it will return a 0-size image.
This means the camera is busy. You have to wait approximately 50ms and
try again in this case."

Dus is het nu een kwestie van die eerste paar bytes eraf snoepen. En even kijken of mijn manier van een file ontvangen ook goed werkt. Omdat het geen JFIF plaatje is kan ik helaas niet de code uit dat mooie webcam proggie copieren die LordLarry gelinked heeft. Wat ik nu heb staan kan je onder aan deze post bewonderen, maar het blijft hangen bij hetbinnenhalen van het einde van de opgevraagde file. Ik ga er weer mee verder, maar kwou even dit posten zodat mensen die behulpzaam willen zijn geen onnodig denkwerk hoeven te verrichten ;)
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
procedure TForm1.TTButton3Click(Sender: TObject);
var
  intReturnCode: Integer;
  s, strLocalFileName: string;
  szBuffer: array[0..128] of Char;
  FileOut: TFileStream;
begin
  strLocalFileName := 'C:\download\incomming.jpg';
  FileOut := TFileStream.Create(strLocalFileName, fmCreate);
  try
    with ClientSocket1 do
    begin
      ClientType := ctBlocking;
      try
        Open;
        {send query}
        s := #48#49#49#48#13#10;
        intReturnCode := Socket.SendBuf(Pointer(s)^, Length(s));
        if intReturnCode > 0 then
        begin
          {receive the answer}
          { iterate until no more data }
          while (intReturnCode > 0) do
          begin
            { clear buffer before each iteration }
            FillChar(szBuffer, SizeOf(szBuffer), 0);
            { try to receive some data }
            intReturnCode := Socket.ReceiveBuf(szBuffer, SizeOf(szBuffer));
            { if received a some data, then add this data to the result string }
            if intReturnCode > 0 then
              FileOut.Write(szBuffer, intReturnCode);
          end
        end
        else
          MessageDlg('No answer from server', mtError, [mbOk], 0);
        Close;
      except
        MessageDlg('No connection', mtError, [mbOk], 0);
      end;
    end;
  finally
    FileOut.Free
  end;
end;

Verwijderd

Topicstarter
Twerkt :) kheb hem wat gealgemeniseert en in een class gezet die onder andere een clientsocket heeft, een reqstr (in het geval van de edimax #48#49#49#48#13#10) en skipbytes (hoeveel hij van de eerste bytes moet wegeten, in geval van de edimax zijn het er 4). Het is nog niet erg netjes, maar het werkt (bijv, het byte voor byte wegschrijven van de eerst readout heb ik erin gezet omdat de regel die er twee regels onder uitcomentariseerd is niet hetgeen doet wat ik wil).
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
procedure TSMRemoteImage.GetRAWImage(filenm: string);
var
  intReturnCode,i: Integer;
  s, LocalFileName: string;
  szBuffer: array[0..128] of Char;
  fpBuffer: array of Char;
  FileOut: TFileStream;
  firstpass: Boolean;
begin
  LocalFileName := fotopad+filenm+'.jpg';
  firstpass := true;
//  if strRemoteFileName[1] <> '/' then
//    strRemoteFileName := '/' + strRemoteFileName;
  FileOut := TFileStream.Create(LocalFileName, fmCreate);
  try
  begin
    FClientSocket.Host := Host;
    FClientSocket.ClientType := ctBlocking;
    FClientSocket.Port := Port;
    try
      FClientSocket.Open;
      {send query}
      s := reqstr;
//      s := 'GET ' + strRemoteFileName + '   HTTP/1.0'#13#10 +
//           'Host: ' + strHost + #13#10#13#10;
      intReturnCode := FClientSocket.Socket.SendBuf(Pointer(s)^, Length(s));
      if intReturnCode > 0 then
      begin
        {receive the answer}
        { iterate until no more data }
        while (intReturnCode > 0) do
        begin
          { clear buffer before each iteration }
          FillChar(szBuffer, SizeOf(szBuffer), 0);
          { try to receive some data and make sure that there is any data to receive}
          if FClientSocket.Socket.ReceiveLength > 0 then
            intReturnCode := FClientSocket.Socket.ReceiveBuf(szBuffer, SizeOf(szBuffer))
          else
            intReturnCode := 0;
          if not firstpass then
          begin
          { if data received, then add this data to the result string }
            if intReturnCode > 0 then
              FileOut.Write(szBuffer, intReturnCode);
          end
          else
          begin
            firstpass := False;
            SetLength(fpBuffer, (intReturnCode-skipbytes));
            for i := skipbytes to intReturnCode-1 do
            begin
              fpBuffer[i-skipbytes] := szBuffer[i];
              FileOut.Write(fpBuffer[i-skipbytes], 1)
            end;
//            FileOut.Write(fpBuffer, (intReturnCode-skipbytes))
          end
        end
      end
      else
        MessageDlg('No answer from server', mtError, [mbOk], 0);
      FClientSocket.Close;
    except
      MessageDlg('No connection', mtError, [mbOk], 0);
    end;
  end;
  finally
    FileOut.Free
  end;
end;

[ Voor 3% gewijzigd door Verwijderd op 26-07-2005 10:42 ]


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Zou je misschien [code=delphi][/code]-tags om je code heen willen zetten? Dat leest wat makkelijker. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.

Pagina: 1