Hi Leute,
ich bin's mal wieder mit einer
Indy-Frage, ich kämpfe jetzt schon sehr lange mit den
Indy-Komponenten, aber manchmal könnte ich das Blocking Sockets verfluchen. Warum haben die sich dafür entschieden ?
Aufgabe:
Bildübertragung eines Webcam-Bilds so gut und schnell wie möglich.
Problem:
Im Moment verwende ich produktiv gerade ein eigenes Protokoll das noch sehr viel Overhead hat.
Aber 4 Leute können problemlos mein Bild betrachten.
Jetzt habe ich mein Protokoll wirklich auf das wichtigste beschränkt die Bildübertragung.
Code Beispiel Server :
Code:
Var ms : TMemoryStream;
ImgWrapper : TImageWrapper;
sCmd : String;
begin
// Speicher zur Bildablage im Stream erzeugen
ms := TMemoryStream.Create;
// KLasse zum Abgreifen des Video-Bild erzeugen
imgWrapper := TImageWrapper.Create(AThread,frmMain.Video);
try
imgWrapper.FileSys := bFileSys;
imgWrapper.Kompression := Einstell.Compression; // Bildkompression setzen
// Solange eine Socket-Verbindung besteht jetzt das Bild zum Kunden übertragen
While (AThread.Connection.Connected) do begin
// MemoryStream leeren
ms.clear;
// aktuelles Bild jetzt laden/abgreifen
if imgWrapper.loadImage then begin
// Geladenes Bild in Strean schreiben
imgWrapper.WriteToStream(ms);
// Bildspeicherposition auf den Anfang setzen
ms.Position := 0;
// Bild einfach in den Buffer schreiben und abschicken
// durch die entsprechenden Parameter in WriteStream,
// steht in den ersten vier Bytes des Streams die Stream Grösse
try
AThread.Connection.OpenWriteBuffer;
AThread.Connection.WriteStream(ms,true,true);
AThread.Connection.CloseWriteBuffer;
except
logf.log('Versuche Write Buffer zu canceln',1);
//AThread.Connection.CancelWriteBuffer;
AThread.Connection.ClearWriteBuffer;
//AThread.Connection.DisconnectSocket;
end;
end
else begin
// es konnte kein Bild geladen werden, es wird jetzt der leere Stream zum Client geschickt
// der überprüft anhand der Streamgrösse ob er darauf reagiert, so wird der normale
// Befehlsablauf nicht unterbrochen
AThread.Connection.OpenWriteBuffer;
try
AThread.Connection.WriteStream(ms,true,true);
AThread.Connection.CloseWriteBuffer;
except
//AThread.Connection.CancelWriteBuffer;
AThread.Connection.ClearWriteBuffer;
end;
logf.log('Send empty stream size 0',1);
end;
end;
finally
// Speicher wieder freigeben
ms.Clear;
FreeAndNil(ms);
FreeAndNil(ImgWrapper);
end;
Code Bsp. Client :
Code:
// die Procedure StreamNow wird innerhalb des VideoStreamThread immer wieder aufgerufen
procedure TVideoStreamThread.StreamNow;
begin
// Speicher leeren
ms.Clear; //
try
if (TcpCon.Connected) and (not Terminated) then begin
try
TcpCon.ReadStream(ms);
except
ms.clear;
end;
if ms.Size > 0 then begin
// Stream Position auf null, damit vom Anfang gelesen wird
ms.Position := 0;
jpg.LoadFromStream(ms);
// Haben wir ein gültiges Jpg
if not jpg.Empty then begin
aktJpg := jpg;
// Jpg zeichnen
Synchronize(PaintImage);
end;
end;
end;
finally
// Memory-Stream leeren
ms.clear;
end;
end;
Wie Ihr seht beschränkte ich mich jetzt auf die reine Bildübertragung, das Problem dabei ist, das das Bild zwar super schnell und super flüssig wird, aber ab dem dritten User beim Server die CPU Last auf 100% steigt und ich nicht nachvollziehen kann warum.
In meinen Logfile steht kein einziger Fehler von irgenteinem Thread, kann es sein das diese intensiven Threads für Windows bzw.
Indy zuviel sind ?
Jeder Kommentar hilft vielleicht weiter, sitze schon etwas länger darüber und komme jetzt gerade nicht weiter.
Und das ist echt frustierend bin schon am überlegen, ob ich das ganze Projekt auf die ICS-Komponenten umschreibe, aber das würde etwas dauern und ich habe mit denen auch noch keinerlei Erfahrung.
Was sagt Ihr ?
Danke Data
Der Horizont vieler Menschen ist ein Kreis mit Radius Null, und das nennen sie ihren Standpunkt.