title: C# Screen streaming program
body: <p>Lately, I have been working on a simple screen-sharing program.</p>
  <p>Actually, the program works on a <code>TCP protocol</code> and uses the <strong>Desktop duplication API</strong>- a cool service that supports very fast screen capturing and also provides information about <code>MovedRegions</code>(areas that only changed their position on the screen but still exist) and <code>UpdatedRegions</code>(changed areas).</p>
  <p>The Desktop duplication has 2 important properties-<strong>2 byte arrays</strong> an array for the <code>previous-pixels</code> and a <code>NewPixels</code> array. Every 4 bytes represent a pixel in the <strong>RGBA</strong> form so for example if my screen is 1920 x 1080 the buffer size is 1920 x 1080 * 4.</p>
  <p>Below are the important highlights of my strategy</p>
  <ol>
  <li>In the initial state (the first time) I send the entire pixel buffer (in my case it's 1920 x 1080 * 3) - the alpha component is always 255 on screens :)</li>
  <li>From now on, I iterate over the UpdatedRegions (it's a rectangles array) and I send the regions bounds and Xo'r the pixels in it something like this:</li>
  </ol>
  <pre class="lang-cs prettyprint-override"><code>writer.Position = 0;
  var n = frame._newPixels;
  var w = 1920 * 4; //frame boundaries.
  var p = frame._previousPixels;
  
  foreach (var region in frame.UpdatedRegions)
  {
      writer.WriteInt(region.Top);
      writer.WriteInt(region.Height);
      writer.WriteInt(region.Left);
      writer.WriteInt(region.Width);
      
      for (int y = region.Top, yOffset = y * w; y &lt; region.Bottom; y++, yOffset += w)
      {
          for (int x = region.Left, xOffset = x * 4, i = yOffset + xOffset; x &lt; region.Right; x++, i += 4)
          {
              writer.WriteByte(n[i] ^ p[i]); //'n' is the newpixels buffer and 'p' is the previous.xoring for differences.
              writer.WriteByte(n[i+1] ^ p[i+1]);
              writer.WriteByte(n[i + 2] ^ p[i + 2]);
  
          }
      }
  }
  </code></pre>
  <ol>
  <li>I Compress the buffer using the lz4 wrapper written in c# (refer to <a href="https://github.com/IonKiwi/lz4.net" rel="nofollow noreferrer">lz4.NET</a>. Then, I write the data on a NetworkStream.</li>
  <li>I merge the areas on the receiver side to get the updated image - this is not our problem today :)</li>
  </ol>
  <p>'writer' is an instance of the 'QuickBinaryWriter' class I wrote (simply to reuse the same buffer again).</p>
  <pre class="lang-cs prettyprint-override"><code>public class QuickBinaryWriter
  {
      private readonly byte[] _buffer;
      private int _position;
  
      public QuickBinaryWriter(byte[] buffer)
      {
          _buffer = buffer;
      }
  
      public int Position
      {
          get { return _position; }
          set { _position = value; }
      }
  
      public void WriteByte(byte value)
      {
          _buffer[_position++] = value;
      }
  
  
      public void WriteInt(int value)
      {
          byte[] arr = BitConverter.GetBytes(value);
          
          for (int i = 0; i &lt; arr.Length; i++)
              WriteByte(arr[i]);
      }
     
  }
  </code></pre>
  <p>From many measures, I've seen that the data sent is really huge, and sometimes for a single frame update the data could get up to 200kb (after compression!).
  Let's be honest-200kb is really nothing, but if I want to stream the screen smoothly and watch at a high Fps rate I would have to work on this a little bit - to <strong>minimize the network traffic and bandwidth usage</strong>.</p>
  <p>I'm looking for suggestions and creative ideas to improve the efficiency of the program- mainly the data sent on the network part (by packing it in other ways or any other idea) I'll appreciate any help and ideas.
  Thanks!</p>