Сохранение файла JPEG, поступающего из потока RTP сетевой камеры

У меня был сокет RTP Stream, принимающий поток JPEG от сетевой камеры Samsung.

Я мало знаю о том, как работает формат JPEG, но я знаю, что этот входящий поток JFIF или JPEG выдает мне заголовок JPEG

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | 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                    |
   |                              ...                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Я думаю, что я правильно их проанализировал, и это фрагмент кода, как я СОХРАНИТЕ один пакет JPEG Stream.

    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) & 0x3FF);
            if (width == 0) /** elphel 333 full image size more than just one byte less that < 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 < 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) & 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 < size; )
                buffer_ptr[_offset++] = data[i++];
            size -= 24+extraOff;
            next_fragment_offset += size;
            sync = true;
            return ((data[1] >> 7) == 1);
        }
        else
        {
            _initialized = false;
            _offset = qtable.Length;
            next_fragment_offset = 0;
            sync = false;
            return false;
        }
    }

Проблема заключается в том, что файл JPEG, который я успешно сохранил на жестком диске в результате объединения потоков JPEG, не отображает весь поток должным образом, все средства предварительного просмотра изображений показывают ПЕРВЫЕ ДВУХ входящие пакетные данные, а остальные оставляют СЕРЫМ, Я считаю, что это означает, что данные от третьего до последнего пакета RTP не анализируются и не сохраняются должным образом.

это фрейм, который я отредактировал http://rectsoft.net/ideerge/zzz.jpg

: так я вызвал функцию записи

            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] >> 7) == 1)
            {
                sync = true;
            }

rawBuffer заполненный моей функцией приема UDP, он ведет себя точно так же, как я обрабатываю свой поток h264, и выглядит на 100% как то, что я захватил из WIRESHARK на VLC.

18
задан Sameera Thilakasiri 4 December 2011 в 17:10
поделиться