I'm making my first screen sharing application in VB.NET using sockets to establish the connections.
This is the client side receiving screen images from the server (they are both running in a thread):
Private Sub startscreen()
Using imgstream As NetworkStream = imgclient.GetStream()
Using ms As New MemoryStream
Dim read As Double
Do
If (imgstream.DataAvailable) Then
read = 0
ms.Seek(0, SeekOrigin.Begin)
While imgclient.Available
Dim buffer(imgclient.Available - 1) As Byte
imgstream.Read(buffer, 0, buffer.Length)
ms.Write(buffer, 0, buffer.Length)
read += buffer.Length
End While
Me.Text = "Frame bytes read: " & read
PictureBox1.Image = Image.FromStream(ms)
ms.Flush()
End If
Thread.Sleep(34) 'about 30 FPS
Loop
End Using
End Using
End Sub
And this is the server side:
Private Sub screen()
Using imgstream As NetworkStream = imgclient.GetStream()
Using ms As New MemoryStream
Do
Thread.Sleep(34) 'about 30 FPS
ms.Seek(0, SeekOrigin.Begin)
Using img = ScreenCap()
img.Save(ms, Imaging.ImageFormat.Jpeg)
End Using
ms.WriteTo(imgstream)
Loop
End Using
End Using
End Sub
Public Function ScreenCap() As Image
Dim screenSize As Size = New Size(My.Computer.Screen.Bounds.Width, My.Computer.Screen.Bounds.Height)
Dim screenGrab As New Bitmap(My.Computer.Screen.Bounds.Width, My.Computer.Screen.Bounds.Height) ', Imaging.PixelFormat.Format16bppRgb555)
Dim g As Graphics = Graphics.FromImage(screenGrab)
g.CopyFromScreen(New Point(0, 0), New Point(0, 0), screenSize)
g.Dispose()
Return screenGrab
End Function
The main problem is when I call the "Image.FromStream(ms)" function, it sometimes works and others doesn't depending on how many milliseconds I set the thread to wait. Tested on 2 different computers in my LAN, on around 1 second it seems OK but always with a high CPU-Network usage. If I set, as the example says around 34 milliseconds to get all more "LIVE", that function throw an exception because of the MemoryStream. How can I speed it up? Is there any smarter way I'm missing right now? I've also tried putting a delimiter byte (like a char = "*") at the and of the MemoryStream and then send it to the client who read one byte at a time until it found a char equal to the delimiter. But it turned out to be a bad solution because a single byte of the image could represent the delimiter if converted to char. Another question I have is: How can I change the image quality and the color depth? Is it a good approach using what the comment says: "Imaging.PixelFormat.Format16bppRgb555"
Thank you!