Hallo, ich arbeite gerade daran, einen Windows-Screen zu "recorden", welches dann ein downscaling auf 320*240 (RGB 5:6:5) um es dann per UDP an einen uC zu streamen der das auf einem Display anzeigt. Ich habe das mal testweise in C# implementiert und funktioniert soweit, allerdings dauert ein FPS (snapshot+per UDP wegsenden) fast an die 100ms! Kennt ihr evtl. eine fertige Video-streamer Software die das machen kann? Gesendet wird das ganze dann unkomprimiert über Ethernet in 128 kleinen UDP Paketen zu je 1200 bytes. Damit kommt man dann auf die 320*240*2 bytes. Danke
VNC gibt es seit Jahrzehnten und ist quelloffen und plattformübergreifend. Das macht die Übertragung intelligenter und wahlweise auch komprimiert. Das Protokoll ist in RFC6143 beschrieben. fchk
Der Standard für Streaming ist RTP. https://de.wikipedia.org/wiki/Real-Time_Transport_Protocol
:
Bearbeitet durch User
Hast du mal mit einem Profiling-Tool geschaut, wo die meiste Zeit vertrödelt wird? Mal ins Blaue geraten: verwendest du zufällig die Bitmap-Klasse aus dem Framework, und davon die Methoden SetPixel(..)/.GetPixel(..)? Die sind gegenüber dem direkten Zugriff auf den Speicher einfacher zu verwenden, aber deutlich langsamer. Zum Lesen: https://docs.microsoft.com/en-us/dotnet/api/system.drawing.bitmap.lockbits
Ich share hier grad mal den code.. Mal gespannt ob es klappt. Das ist quasi die Routine die das alles einmal macht.
1 | |
2 | Bitmap printscreen2 = new Bitmap(1600, 1200); |
3 | |
4 | |
5 | Graphics graphics2 = Graphics.FromImage(printscreen2 as Image); |
6 | |
7 | |
8 | |
9 | graphics2.CopyFromScreen(0, 0, 0, 0, printscreen2.Size); |
10 | |
11 | using (MemoryStream s2 = new MemoryStream()) |
12 | { |
13 | printscreen2.Save(s2, System.Drawing.Imaging.ImageFormat.Bmp); |
14 | |
15 | |
16 | Image bmp2 = ResizeImage(Image.FromStream(s2), 320,240); |
17 | |
18 | pictureBox2.Image = bmp2; |
19 | |
20 | |
21 | bmp2.RotateFlip(RotateFlipType.Rotate180FlipX); |
22 | //Creat a 16 bit copy of it using the graphics class |
23 | Bitmap dest = new Bitmap(bmp2.Width, bmp2.Height, System.Drawing.Imaging.PixelFormat.Format16bppRgb565); |
24 | using (Graphics g = Graphics.FromImage(dest)) |
25 | { |
26 | g.DrawImageUnscaled(bmp2, 0, 0); |
27 | } |
28 | |
29 | Rectangle r = new Rectangle(0,0,dest.Width,dest.Height); |
30 | BitmapData bd = dest.LockBits(r, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format16bppRgb565); |
31 | byte[] TftData = new byte[dest.Width * dest.Height * 2]; |
32 | Marshal.Copy(bd.Scan0, TftData, 0, TftData.Length); |
33 | |
34 | dest.UnlockBits(bd); |
35 | byte[] txbuffer = new byte[1201]; |
36 | |
37 | try{ |
38 | for (int i=0; i<128; i++) { |
39 | Buffer.BlockCopy(TftData,0+i*1200,txbuffer,0,1200); |
40 | txbuffer[1200] = (byte) i; |
41 | udpClient.Send(txbuffer, 1201, "192.168.0.55", 5200); |
42 | } |
43 | |
44 | |
45 | |
46 | } |
47 | catch{ |
48 | |
49 | } |
UDP schrieb: > Ich share hier grad mal den code.. Mal gespannt ob es klappt. > Das ist quasi die Routine die das alles einmal macht. > > Bitmap printscreen2 = new Bitmap(1600, 1200); > for (int i=0; i<128; i++) { > Buffer.BlockCopy(TftData,0+i*1200,txbuffer,0,1200); > txbuffer[1200] = (byte) i; > udpClient.Send(txbuffer, 1201, "192.168.0.55", 5200); > } Wie willst du einen Bildschirm mit 1600x1200 in 128 Teile a 1201 Byte übertragen?
Na es wird ein downscaling auf 320*240 auf 16 Bit Farben gemacht.... Macht dann also 320 x 240 x 2bytes = 153600 bytes -> 128 pakete a 1200 bytes
Kenne die beteiltigten Libraries nicht, aber das Grabben und die Konvertierung sieht extrem ineffizient aus (insb die BMP-Konvertierung und der MemoryStream zwischendrin). Außerdem: UDP hat keine Bandbreitenverwaltung - wenn Pakete schneller ankommen als sie verarbeitet/weitergeleitet werden können, werden sie einfach weggeschmissen. Du schickst alles in einem Burst ...
einfach ffmpeg nutzen. FullHD via RDP mit 60 fps kein Problem. Alternativ gstreamer für geringste Latenz inkl. HW Enc + Dec
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.