Socket disconnecting when capturing screen with old managed DX

Locked Socket disconnecting when capturing screen with old managed DX

  • Saturday, February 04, 2012 9:13 AM
     
      Has Code

    The old managed DX is the only solution I could find with half decent performance so dont go telling me its old and all that...

    No not even slimdx...

    After a few seconds the size of the image that's sent before the image arrives gets corrupted and ends up as a ridiculously huge number as if the size of the last frame was too small and the remaining data ends up in the size of the next frame.

            private void Work(Object state){
                using (_vSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)){
                    try{
                        _vSock.SendBufferSize = 10485760;
                        _vSock.ReceiveBufferSize = 10485760;
                        _vSock.Connect(_address, 48624);
                        var name = Encoding.ASCII.GetBytes(textBox1.Text);
                        _vSock.Send(BitConverter.GetBytes(name.Length));
                        _vSock.Send(name);
                        Invoke(new ConnectedDelegate(ConnectEvent), false);
                        var bounds = Screen.PrimaryScreen.Bounds;
                        _vSock.Send(BitConverter.GetBytes(bounds.Width));
                        _vSock.Send(BitConverter.GetBytes(bounds.Height));
                        var pp = new PresentParameters{BackBufferFormat = Format.A8R8G8B8, BackBufferWidth = bounds.Width, BackBufferHeight = bounds.Height, Windowed = true, DeviceWindowHandle = (IntPtr)state, SwapEffect = SwapEffect.Discard, PresentationInterval = PresentInterval.Default};
                        var direct3D9 = new Direct3D();
                        using (var gpu = new Device(direct3D9, 0, DeviceType.Hardware, (IntPtr)state, CreateFlags.HardwareVertexProcessing, pp))
                        using (var surf0 = Surface.CreateOffscreenPlain(gpu, bounds.Width, bounds.Height, Format.A8R8G8B8, Pool.SystemMemory))
                        using (var surf1 = Surface.CreateOffscreenPlain(gpu, bounds.Width, bounds.Height, Format.A1R5G5B5, Pool.SystemMemory))
                        {
                            while (_go){
                                using (var stream = new MemoryStream()){
                                    _sw.Start();
                                    gpu.GetFrontBufferData(0, surf0);
                                    Surface.FromSurface(surf1, surf0, Filter.None, 0);
                                    Surface.ToStream(surf1, ImageFileFormat.Png, bounds).CopyTo(stream);
                                    _ok.WaitOne();
                                    ThreadPool.QueueUserWorkItem(SendImage, stream.ToArray());
                                }
                            }
                        }
                    } catch (SocketException){} catch (ObjectDisposedException){} catch (Exception e){
                        MessageBox.Show(e.ToString());
                    }
                    if (_go) Invoke(new ConnectedDelegate(ConnectEvent), true);
                }
            }
    

    and heres the receiving end...

            private void GetSnapshots(object state){
                try{
                    using (_vSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)){
                        _vSock.Bind(new IPEndPoint(IPAddress.Any, 48624));
                        _vSock.Listen(1);
                        using (_vclient = _vSock.Accept()){
                            Invoke(new ConnectedDelegate(ConnectEvent), false);
                            _vclient.SendBufferSize = 10485760;
                            _vclient.ReceiveBufferSize = 10485760;
                            var namel = new byte[4];
                            _vclient.Receive(namel, 4, SocketFlags.None);
                            var name = new byte[BitConverter.ToInt32(namel, 0)];
                            _vclient.Receive(name, name.Length, SocketFlags.None);
                            _info = Encoding.ASCII.GetString(name);
                            var sizew = new byte[4];
                            var sizeh = new byte[4];
                            _vclient.Receive(sizew, 4, SocketFlags.None);
                            _vclient.Receive(sizeh, 4, SocketFlags.None);
                            var bounds = new Rectangle(0, 0, BitConverter.ToInt32(sizew, 0), BitConverter.ToInt32(sizeh, 0));
                            Invoke(new SetSizeDelegate(SetSize), bounds);
                            while (_go){
                                _sw1.Start();
                                var sizeb = new byte[4];
                                _vclient.Receive(sizeb, sizeb.Length, SocketFlags.None);
                                int size = BitConverter.ToInt32(sizeb, 0);
                                if (size <= 0 || size > 10485760) break;
                                var image = new byte[size];
                                for (int got = 0; got < size;){
                                    int i = _vclient.Receive(image, image.Length, SocketFlags.None);
                                    got += i;
                                }
                                _sw1.Stop();
                                _sw1Time = _sw1.Elapsed.TotalMilliseconds;
                                _sw1.Reset();
                                _sw0.Start();
                                try{
                                    using (var ms = new MemoryStream(image)) _bmpbuf = new Bitmap(ms);
                                } catch{}
                                Invoke(new ImageCompleteDelegate(ImageComplete));
                            }
                        }
                    }
                } catch (SocketException){
                    MessageBox.Show("Listener tcp port 48624 fail!");
                }
                Invoke(new ConnectedDelegate(ConnectEvent), true);
            }
    

    They are run in threadpool threads.


All Replies

  • Sunday, February 05, 2012 9:44 PM
     
     
    I hate to bump but I need this solved.
  • Monday, February 06, 2012 6:26 AM
     
     
    Hi,

    I am moving your thread into the Network Class Library (System.Net) Forum for dedicated support.
    Have a nice day, 

    Leo Liu [MSFT]
    MSDN Community Support | Feedback to us
  • Monday, February 06, 2012 6:03 PM
     
      Has Code

    Changed it slightly and still cant figure out why its happening read op again for info.

    If I change the ImageFileFormat from Png to Bmp it goes WAY faster but that raises 2 different issues, 1. it only captures about 80% of the top left of the screen then magnifies it but I cant have it as a bmp because its FAR to big for our ripoff upload speeds and 2. It throws a Direct3DXException after several seconds because there's a memory leak at

    SurfaceLoader.SaveToStream(ImageFileFormat.Png, surf).CopyTo(stream);
    
  • Wednesday, February 08, 2012 9:26 AM
     
     
    This is the most useless forum ever!!!!!
  • Thursday, February 09, 2012 8:54 PM
     
     

    So if you look at the documentation of Receive if will receive a less than or equal of the specified bytes. Since you are sending an image it could become fragmented and not receive all the bytes. You should continue to loop to receive into the buffer until the maximum amount is hit. Your image length could be 1 million bytes but your NIC buffer is smaller then that. This means you receive parts of the bytes at once and saving it will cause the visual problem you described.

    Thanks,

    Brad

  • Saturday, February 18, 2012 3:39 AM
     
     
    I have put it in a loop and it gets every last byte of every single frame but some get corrupted and i have to catch the exceptions it causes so thay dont get thrown.
  • Saturday, February 18, 2012 3:55 AM
     
     

    What are the exact exceptions that are thrown?

  • Wednesday, February 22, 2012 12:18 AM
     
     
    This thread is redundant.