title: Saving JPEG file coming from Network Camera RTP Stream
body: <p>I had a RTP Stream socket, receiving a JPEG Stream, from a samsung network camera.</p>
  <p>I dont know much about how JPEG format works, but i do know that this incoming JFIF or JPEG stream is giving me the JPEG header</p>
  <pre><code>+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     | Type-specific |              Fragment Offset                  |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |      Type     |       Q       |     Width     |     Height    |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  
  and then 
  
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |       Restart Interval        |F|L|       Restart Count       |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  
  and then in the first packet, there is this header
  
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |      MBZ      |   Precision   |             Length            |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                    Quantization Table Data                    |
     |                              ...                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  </code></pre>
  <p>I think I parsed them properly, and this is a snippet of code, how i STORE one the JPEG Stream packet.</p>
  <pre><code>    int extraOff=0;
      public bool Decode(byte* data, int offset)
      {
          if (_initialized == false)
          {
              type_specific = data[offset + 0];
              _frag[0] = data[offset + 3];
              _frag[1] = data[offset + 2];
              _frag[2] = data[offset + 1];
              _frag[3] = 0x0;
              fragment_offset = System.BitConverter.ToInt32(_frag, 0);
              jpeg_type = data[offset + 4];
              q = data[offset + 5];
              width = data[offset + 6];
              height = data[offset + 7];
              _frag[0] = data[offset + 8];
              _frag[1] = data[offset + 9];
              restart_interval = (ushort)(System.BitConverter.ToUInt16(_frag, 0) &amp; 0x3FF);
              if (width == 0) /** elphel 333 full image size more than just one byte less that &lt; 256 **/
                  width = 256;
  
              byte jpegMBZ = (byte)(data[offset + 12]);
              byte jpegPrecision = (byte)(data[offset + 13]);
              int jpegLength = (int)((data[offset + 14]) * 256 + data[offset + 15]);
  
              byte[] tableData1 = new byte[64];
              byte[] tableData2 = new byte[64];
              for (int i = 0; i &lt; 64; ++i)
              {
                  tableData1[i] = data[offset + 16 + i];
                  tableData2[i] = data[offset + 16+64 + i];
              }
              byte[] tmp = new byte[1024];
              _offset = Utils.MakeHeaders(tmp,jpeg_type, width, height, tableData1, tableData2, 0);
              qtable = new byte[_offset];
  
              Array.Copy(tmp, 0, _buffer, 0, _offset);
  
  
              _initialized = true;
              tmp = null;
              GC.Collect();
              extraOff = jpegLength + 4 ;
          }
          else
          {
              _frag[0] = data[15]; //12 + 3
              _frag[1] = data[14]; //12 + 2
              _frag[2] = data[13]; //12 + 1]
              _frag[3] = 0x0;
              fragment_offset = System.BitConverter.ToInt32(_frag, 0);
              _frag[0] = data[offset + 8];
              _frag[1] = data[offset + 9];
              restart_interval = (ushort)(System.BitConverter.ToUInt16(_frag, 0) &amp; 0x3FF);
              extraOff = 0;
          }
  
          return (next_fragment_offset == fragment_offset);
      }
      public unsafe bool Write(byte* data, int size, out bool sync) //Write(ref byte[] data, int size,out bool sync)
      {
          if (Decode(data, 12))
          {
              for (int i = 24 + extraOff; i &lt; size; )
                  buffer_ptr[_offset++] = data[i++];
              size -= 24+extraOff;
              next_fragment_offset += size;
              sync = true;
              return ((data[1] &gt;&gt; 7) == 1);
          }
          else
          {
              _initialized = false;
              _offset = qtable.Length;
              next_fragment_offset = 0;
              sync = false;
              return false;
          }
      }
  </code></pre>
  <p>The problem i get is the JPEG File i successfully saved to my harddrive as a result of concatenating the JPEG streams is not showing the whole stream properly, all image previewers show the FIRST TWO incoming packet data, but leave the rest GRAY, i believe this means, the data from the third up to the last RTP packet are not parsed or saved properly.</p>
  <p>this is the frame that i got
  <a href="http://rectsoft.net/ideerge/zzz.jpg" rel="noreferrer">http://rectsoft.net/ideerge/zzz.jpg</a></p>
  <h1>edited : This is how i called the Write function</h1>
  <pre><code>            size = rawBuffer.Length;
              if (sync == true)
              {
                  unsafe
                  {
                      fixed (byte* p = rawBuffer)
                      {
                            if (_frame.Write(p, size, out sync)) //if (_frame.Write(ref _buffer, size, out sync))
                          {
                                  // i save my buffer to file here
                          }
                      }
                  }
              }
              else if ((rawBuffer[1] &gt;&gt; 7) == 1)
              {
                  sync = true;
              }
  </code></pre>
  <p>the rawBuffer is filled by my UDP Receive function, it behaves exactly like how I handle my h264 stream and looks 100% like what I captured from WIRESHARK on VLC.</p>