Selbstgebastelte Desktopübertragung - optimieren



  • Meine Übertragung hat einige Probleme:

    1. Ich speichere die Bilder erst auf der Festplatte, bevor ich sie per ftp versende (2x)
    2. Die Bilder sind im Bitmap Format werden zu JPG konvertiert und dann versendet !
    (Ich dachte, so sende ich schneller, doch sind die mir immer noch zu groß)

    Ich brauche hier etwas Hilfe, denn ich erhalte bei einem lokalen Netzwerk nur 1.5 Bilder in der Sekunde, ich wollte mindestens auf 3 pro Sekunde. Über Internet spreche ich erst gar nicht, da ist das senden des gesammten Bildschirms als Bild einfach nicht geeignet, da müsste es schon eine direkter Videostream sein, aber sowas liegt über meinen Möglichkeiten.

    Hier mein Code, der gut funktioniert ( aber Banane is(s)t )

    Server:

    HDC hdc;
    			HWND hWnd;
    			hWnd = GetDesktopWindow();
    			hdc = GetDC(hWnd);
    			String SaveLocation = sReadValue;
    			int width = Screen->Width;
    			int height = Screen->Height;
    			dc2bitmap(hdc, width, height, "C:\\Windows\\Buffer.bmp"); // ERHALTE nur BMP und muss auf Festplatte speichern
    // Ich brauche eine bessere Funktion um den Desktop zu lesen (Komplett) !!!
    
    			ImageCompressor->Picture->LoadFromFile("C:\\Windows\\Buffer.bmp");
    
    			TJPEGImage *jpg = new TJPEGImage();
    
    			jpg->Assign(ImageCompressor->Picture->Bitmap);
    			jpg->SaveToFile(SaveLocation); 
    // lade, komprimiere und speicher nochmal. Das geht GAR NICHT ! Am besten wäre ein Stream, den hab ich aber nicht (siehe funktion oben)
    
    			std::remove("C:\\Windows\\Buffer.bmp"); // lösche altes Bild... dauert auch !
    
    			delete jpg;
    

    Client:

    bool TRemoteAdminXP::GetScreenShot()
    {
    
    	try
    	{
    		// Create Screenshot
    
    		String Location = "";
    		//	FunOMat->IdTCPClient1->Host = Remote->FileTransfer->Host;
    		//	FunOMat->IdTCPClient1->Port = (Remote->FileTransfer->Port - 11);
    // entfernt da vorher gelesen
    		FunOMat->IdTCPClient1->Connect();
    		IdTCPClient1->Socket->WriteLn("GET WINDOWS DIR"); // erhält C:\\
    		Location +=  FunOMat->IdTCPClient1->Socket->ReadLn();
    		if (Location == "unknown command")
    		{
    			ShowMessage("Die Serverversion ist zu alt");
    		}
    		else
    		{
    			IdTCPClient1->Socket->WriteLn("0"); // letzten Befehl abschließen
    			Location += "WINDOWS\\Picture.jpg";
    
    			FunOMat->IdTCPClient1->Socket->WriteLn("SCREENSHOT");
    			Remote->Errormsg->Caption = FunOMat->IdTCPClient1->Socket->ReadLn();
    			FunOMat->IdTCPClient1->Socket->WriteLn(Location); // SavePicTo
    			FunOMat->IdTCPClient1->Disconnect();
    
    			// Construct PictureFile Location
    
    			String Loca2;
    			Loca2 = ModuleInformation("Appi",1).c_str(); // Gibt Programm Ort
    			Loca2 += "Screenshot.jpg"; // und NOCHMAL auf ein HDD
    			TMemoryStream* Stream = new TMemoryStream;
    
    			// Connect to FTP-Server and Get File
    
    			Remote->FileTransfer->Connect();
    			Remote->FileTransfer->Get(Location,Loca2,true); //Speichern auf HDD
    			Remote->FileTransfer->Disconnect();
    			Remote->Screencapture->Picture->LoadFromFile(Loca2); // und nochmal in stream lesen :O
    			return true;
    		}
    	}
    	catch(Exception &exc)
    	{
    		Remote->GetNewSreencapture->Enabled = false;
    		Log->Lines->Add("ERROR: " + exc.Message);
    	}
    }
    

    Wie umgehe ich diese ganzen Speicher und Ladevorgänge besser.
    So kann das auf jeden Fall nicht bleiben.



  • Hallo

    - Speichere nicht deine Bilddaten als Datei auf der Festplatte, sondern schicke sie direkt als binären Datenstrom (ich weiß nicht welcher Datentyp hinter Remote genau steckt, aber diese Möglichkeit bieten eigentlich alle FTP-Komponenten)
    - Baue nicht für jedes einzelne Bild eine neue Verbindung auf, sondern halte die Verbindung aufrecht
    - Reduziere Farbtiefe der zu schickenden Bild-Daten
    - Verwende nicht FTP, sondern direkt TCP-Socket oder gar UDP-Socket.

    bis bald
    akari



  • sondern direkt TCP-Socket oder gar UDP-Socket.

    😮
    soll ich die Bytes einzeln senden ? Das dauert doch Jahre ???

    Reduziere Farbtiefe der zu schickenden Bild-Daten

    Einfacher gesagt als Umgesetzt

    Und ich brauche eine Möglichkeit den Bildschirm Zeilenweise zu lesen, oder Komplett, und das in einen Stream. Die Funktion die ich benutze, ist pure WinApi und speichert gleich auf die Festplatte, das würde ich gern ändern.
    Ich kann Pixelweise lesen, aber das dauert noch länger.



  • Tim06TR schrieb:

    😮
    soll ich die Bytes einzeln senden ? Das dauert doch Jahre ???

    Nein. Lies dir mal was zu TCP und UDP durch. Und FTP -- denn das setzt auf TCP auf. Bei einer Echtzeitanwendung wie dieser wäre es aber wahrscheinlich besser, auf UDP zu setzen, so wie es auch bei Internet-Telefonie üblich ist. TCP garantiert dir nämlich, dass alle deine Daten fehlerfrei und in der richtigen Reihenfolge übertragen werden, sodass ggf. bei Fehlern die Daten erneut gesendet werden, was zum Stocken im Bildstrom führen kann. Außerdem macht es keinen Sinn, das vergangene Bild eines Videos (oder eines Desktops) nochmal zu übertragen, wenn bereits ein aktuelleres zur Verfügung steht. Das ein oder andere fehlende oder fehlerhafte Bild ist in deinem Fall aber eher zu verschmerzen, als Verzögerungen in der Anzeige. UDP überträgt Daten ohne Bestätigungen der Gegenseite. Dadurch weiß man zwar nicht, ob die Daten angekommen sind, werden aber auch nicht verzögert.



  • Hallo

    Tim06TR schrieb:

    soll ich die Bytes einzeln senden ? Das dauert doch Jahre ???

    Nein. Sondern über eine Komponente verwenden, die gleich z.B. einen TMemoryStream als Datenquelle akzeptiert, und nicht erst auf Dateien ausweicht. Und dann ein Protokoll verwenden das möglichst wenig Overhead braucht, bzw. gleich selbst eins definieren indem du direkt Socket-Komponenten verwendest.

    Tim06TR schrieb:

    Und ich brauche eine Möglichkeit den Bildschirm Zeilenweise zu lesen, oder Komplett, und das in einen Stream. Die Funktion die ich benutze, ist pure WinApi und speichert gleich auf die Festplatte, das würde ich gern ändern.
    Ich kann Pixelweise lesen, aber das dauert noch länger.

    Siehe Thema Screenshot in der FAQ hier im Forum.

    bis bald
    akari



  • Bei der zweiten Version aus dem FAQ
    wird mein Bild nur 105 * 105 groß.
    Wie kann das sein ?

    EDTI: muss ich vorher ein weißen bereich in die TBitmap legen (per Canvas)?
    (1680*1050)



  • Ich habe es so gemacht, dass jedes Bild in 8x8-Blöcke aufgeteilt wird und nur seit dem letzten Bild veränderte Blöcke übertragen werden, die dann komprimiert werden (dafür ist LZO gut geeignet, da extrem schnell). Damit konnte man auch über eine DSL-Leitung mit 3xx kbps Upload recht gut arbeiten, über LAN natürlich erst recht.

    An den Bildschirminhalt kommst du mit BitBlt auf ein compatible bitmap + GetDIBits.


Anmelden zum Antworten