![]() |
selbstgebastelter webcam stream
Hallo,
ich programmiere gerade einen ferngesteuerten webcam client mit Delphi 7 Enterprise. Dazu nutze ich Directx für die Webcam und IdTCPClient und Server für die Verbindung. das ding ist eine dreieckstruktur. ich habe ein client-server-system und dazu einen webserver. der server sendet die configuration an den webserver. der client liest die config vom webserver und arbeitet dem entsprechend alles ab. und sendet zumbeispiel den webcam stream an den server. den webserver schalte ich zwischen aufgrund der hohen erreichbarkeit. so kann ich indirekt den client abschalten etc. ohne dass eine direkte verbindung besteht. die webcam greife ich über directx ab. siehe ![]() per timer grabbe ich einzelne frames und übertrage die per indy an den server. hier die prozedur des clients zum senden.
Delphi-Quellcode:
procedure TForm1.sendStream(pic:TBitmap);
var MStream:TMemoryStream; begin MStream:=TMemoryStream.Create; try pic.SaveToStream(MStream); MStream.Position:=0; try IdTCPClient1.Socket.Write(MStream,0,true); except end; finally MStream.Free; end; end; das gebe ich dann einfach beim server aus. Es funktioniert alles wunderbar. Mein Problem: ich will natürlich keine Bitmaps versenden, aufgrund der dateigröße. deshalb habe ich bereits jpg und png genutzt. das funktioniert auch. allerdings ist dementsprechend die cpu auslastung beim client dauerhaft bei über 15% und springt auch mal auf 40%, (bei Bitmap logischerweise 0-1%) ich suche deshalb eine praktikable kompression zum übertragen der frames. Hoffe da hat jemand was parat :roll: |
Re: selbstgebastelter webcam stream
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Delphi-Quellcode:
lg. Astatuses ZLibEx; procedure CompressBitmap_Slow(bmp: TBitmap; var Data: string); var ms : TMemoryStream; buf : pointer; size : integer; begin ms := TMemoryStream.Create; bmp.SaveToStream(ms); ZCompress(ms.Memory, ms.Size, buf, size); SetLength(Data, size); Move(buf^, Data[1], size); FreeMem(buf); ms.Free; end; procedure CompressBitmap(bmp: TBitmap; var Data: string); var cs: TZCompressionStream; ms: TMemoryStream; begin ms := TMemoryStream.Create; cs := TZCompressionStream.Create(ms,zcDefault); // clDefault ist schneller als clMax bmp.SaveToStream(cs); cs.Free; SetLength(Data, ms.Size); Move(ms.Memory^, Data[1], ms.Size); ms.Free; end; procedure UnCompressBitmap(const Data: string; bmp: TBitmap); var ms : TMemoryStream; buf : pointer; size : integer; outsize:integer; begin try size:=0; outsize:=Length(Data) * 3; ZDecompress(@Data[1], Length(Data), buf,outsize, size); except on E: Exception do begin E.Message := Format('Error Decompressing Buffer (Len = %d):'#13#10'%s', [Length(Data), e.Message]); raise; end; end; ms := TMemoryStream.Create; ms.Write(buf^, outSize); FreeMem(buf); ms.Position := 0; Assert(bmp <> nil); bmp.LoadFromStream(ms); ms.Free; end; |
Re: selbstgebastelter webcam stream
hab mir deinen code angeschaut, versteh ihn aber nicht ganz.
wozu ist der parameter Data da ? kannste den quelltext bitte en bischen erläutern ? Edit: ich habs jetz so verstanden: die komprimierte bmp liegt im ms und wird dann in data geschrieben. da kann ich ja gleich den ms per indy verschicken oder nicht ? |
Re: selbstgebastelter webcam stream
So ich habs ma probiert umzusetzen:
hier der client:
Delphi-Quellcode:
procedure TForm1.sendStream(pic:TBitmap);
var MStream:TMemoryStream; data:string; begin MStream:=TMemoryStream.Create; CompressBitmap(pic,data); try MStream.WriteBuffer(data,Length(Data)); MStream.Position:=0; try IdTCPClient1.Socket.Write(MStream,0,true); except end; finally MStream.Free; end; end; hier der server:
Delphi-Quellcode:
procedure TForm2.IdTCPServer1Execute(AContext: TIdContext);
var data:string; FStream:TMemoryStream; bmp:TBitmap; begin FStream:=TMemoryStream.Create; try AContext.Connection.Socket.ReadStream(FStream); FStream.Position:=0; finally try FStream.Read(data,1000000); finally //bmp.LoadFromStream(FStream); FStream.Free; end; end; UnCompressBitmap(data,bmp); end; sooo der client schickt anscheinend was, zumindest ist data gefüllt beim server kommt Connection closed Gracefully. |
Re: selbstgebastelter webcam stream
Zitat:
Delphi-Quellcode:
ZCompress(ms.Memory, ms.Size, buf, size); send(ASocket, buf^, size) Da die komprimierten Daten in buf liegen. lg. Astat |
Re: selbstgebastelter webcam stream
ähm ich arbeite mit CompressBitmap, nicht mit CompressBitmap_slow ;)
|
Re: selbstgebastelter webcam stream
Hallo!
Da existiert noch eine andere Möglichkeit, allerdings ist mein WebCam Code noch nicht 100%ig darauf vorbereitet: Unter Umständen sind Deine Bilder von der Kamera eh schon komprimiert: YUY2, MJPG etc. Wenn Du im aktuellen Beispielcode der Unit VFrames.pas nachsiehst, findest Du dort die Routine, welche Dir die Bitmaps liefert: TVideoImage.GetBitmap(BMP: TBitmap). Diese Routine wiederum ruft UnpackFrame(..) auf. Das heißt, falls Deine Kamera beispielsweise MJPG Daten liefert (was unterm Strich schon fertige JPG Bilder sind), dann packt diese Routine das Ding aus in ein Bitmap, und Du machst es dann wieder klein, um es zu verschicken. Es könnte sich also lohnen, die Originaldaten zu holen (Also Pointer fImagePtr[fImagePtrIndex], welcher auf fImagePtrSize[fImagePtrIndex] Bytes zeigt), diese zu verschicken, und das Auspacken auf Empfänger-Seite zu erledigen. Da mußt Du allerdings noch ein bissl was einbauen ;) Allerding: Das hilft natürlich nur, wenn Deine Kamera schon eine solche Datenkompression anbietet. Ist es von vorneherein entpackt, dann hilft mein Vorschlag hier nicht weiter... Gruß Michael |
Re: selbstgebastelter webcam stream
du hast recht, ich mach das so :D
ich gehe über getBitmap(); allerdings habe ich mit dem hintergrund noch nicht beschäftigt ^^ muss mir dat erstma anschaun oder du hast noch paar anhaltspunkte |
Re: selbstgebastelter webcam stream
Zitat:
Delphi-Quellcode:
lg. Astatprocedure TForm1.sendStream(pic: TBitmap); var MStream:TMemoryStream; pOutBuf : pointer; cbOutSize:integer; begin pOutBuf := nil; cbOutSize := 0; MStream := TMemoryStream.Create; try pic.SaveToStream(MStream); ZCompress(MStream.memory, MStream.size, pOutBuf, cbOutSize, zcMax); finally MStream.Free; end; if (pOutBuf <> nil) and (cbOutSize > 0) then begin IdTCPClient1.Socket.Write(pOutBuf, cbOutSize, 0); FreeMem(pOutBuf); end else raise exception.Create('u should never see this.'); end; |
Re: selbstgebastelter webcam stream
ich schaue mir beide ansätze an, da erster flexibler ist.
ich bin gespannt wie nacher die unterschiede bei cpu last und speicherverbrauch sind. aber schreibt ruhig mehr :D |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:26 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz