Конференция "Media" » Вопрос про раскодирование потока с IP камеры Axis (MJPEG) [D1, D2, D3, D4, D5, D6, D7, WinXP]
 
  • axwork © (25.11.08 14:20) [0]
    Есть камера IP Axis 205
    Получаю с нее поток при помощи запроса:
    'GET /axis-cgi/mjpg/video.cgi HTTP/1'+#$0d#$0a или
    'GET /axis-cgi/jpg/image.cgi HTTP/1'+#$0d#$0a - отдельный кадр
    выделяю блок JPG но никак не получается загрузить его в TJpegImage и конвертить в TBitmap для обработки.
    TJpegImage говорит что ошибка заголовка Jpeg.

    S:=TMemoryStream.Create;
    S.WriteBuffer(St[1],Length(St)); //Переброска в stream буфера картинки из St(строка)
    S.Seek(0,0);
    Jpg:=TJpegImage.Create;
    Jpg.LoadFromStream(S); //Ошибка происходит здесь
    Jpg.SaveToFile('C:\1.jpg');
    Jpg.Free;
    Info.Source.Assign(Jpg); //Конвертация в TBitmap
    S.Free;

    Похоже что передаётся некорректный Jpeg...
    Помогите разобраться с этим форматом... мож там что дописать нужно в блок или подменить...
  • Сергей М. © (25.11.08 14:24) [1]

    > St[1]


    St - это что, строка ?
  • Сергей М. © (25.11.08 14:26) [2]
    Как у тебя в строковой переменной оказались данные заведомо ожидаемого нестрокового формата ?
  • axwork © (25.11.08 14:41) [3]
    Помоему строки позволяют хранить массив байт... так что St: String с буфером полученных байт из камеры по HTTP запросу...

    var
      error :     integer;
      buf   :     array [0..1023] of Char;
      str   :      string;

    ...

      str:='GET /axis-cgi/jpg/image.cgi HTTP/1.0'#13#10#13#10;

      send(sock, str[1], Length(str), 0);
      ZeroMemory(@Buf,1024);

      error:=recv(sock,Buf,1024,0);St:='';
      while (error>0) and (CamProperty[Info.CamNum].EnabledCam) and (Info.State<>thsFree) do
       begin
        St:=St+Copy(buf,0,error);
        error:=recv(sock,buf,1024,0);
       end;
  • Сергей М. © (25.11.08 14:47) [4]

    > St:=St+Copy(buf,0,error);


    ты справку к ф-ции Copy вообще читал ?
  • axwork © (25.11.08 14:56) [5]
    Спасибо за наводку ... похоже дело действительно в этом.
  • Сергей М. © (25.11.08 14:57) [6]

    > похоже дело действительно в этом


    И не только в этом.
  • DVM © (25.11.08 22:25) [7]

    > axwork ©   (25.11.08 14:56) [5]

    Дарю класс. Принимай данные в этот буфер.


    {******************************************************************************}
    {*                                                                            *}
    {*  CamBuff                                                                   *}
    {*  (с) 2005-2008 Дмитрий Муратов (dvmuratov@yandex.ru)                       *}
    {*  Версия 2.1  8/10/2008                                                     *}
    {*                                                                            *}
    {******************************************************************************}

    unit CamBuff;

    interface

    type

     TBuffer = class(TObject)
     private
       FStorage: PAnsiChar;
       FAllocation: integer;
       FHead: PAnsiChar;
       FTail: PAnsiChar;
       FSize: integer;
       function GetSize: integer;
       procedure SetSize(ASize: integer);
       function GetHead: PAnsiChar;
       function GetStorage: PAnsiChar;
       function GetTail: PAnsiChar;
     public
       constructor Create; overload;
       constructor Create(ASize: integer); overload;
       constructor Create(AStorage: PAnsiChar; ASize: integer); overload;
       constructor Create(ABuffer: TBuffer); overload;
       destructor Destroy; override;
       function AppendBuff(ABuffer: TBuffer): integer;
       function Append(AStorage: PAnsiChar; ASize: integer): integer;
       function Assign(AStorage: PAnsiChar; ASize: integer): integer;
       function AssignBuff(ABuffer: TBuffer): integer;
       function Consume(ACount: integer): integer;
       procedure Emply;
       function IsEmpty: boolean;
       function Expand(ACount: integer): integer;
       function Extract(ASize: integer): PAnsiChar;
       function Shrink(ACount: integer): integer;
       property Head: PAnsiChar read GetHead;
       property Size: integer read GetSize write SetSize;
       property Storage: PAnsiChar read GetStorage;
       property Tail: PAnsiChar read GetTail;
     end;


  • DVM © (25.11.08 22:25) [8]

    implementation

    //------------------------------------------------------------------------------

    constructor TBuffer.Create;
    begin
     FAllocation := 0;
     FSize := 0;
     GetMem(FStorage, FAllocation);
     FHead := FStorage;
     FTail := FHead;
    end;

    //------------------------------------------------------------------------------

    constructor TBuffer.Create(ASize: integer);
    begin
     FAllocation := ASize;
     FSize := ASize;
     GetMem(FStorage, FAllocation);
     FHead := FStorage;
     FTail := FHead;
    end;

    //------------------------------------------------------------------------------

    constructor TBuffer.Create(AStorage: PAnsiChar; ASize: integer);
    begin
     FAllocation := ASize;
     FSize := ASize;
     GetMem(FStorage, FAllocation);
     FHead := FStorage;
     Move(AStorage^, FStorage^, ASize);
     FTail := FHead + FSize;
    end;

    //------------------------------------------------------------------------------

    constructor TBuffer.Create(ABuffer: TBuffer);
    begin
     FAllocation := ABuffer.Size;
     FSize := ABuffer.Size;
     GetMem(FStorage, FAllocation);
     FHead := FStorage;
     Move(ABuffer.Storage^, FStorage^, ABuffer.Size);
     FTail := FHead + FSize;
    end;

    //------------------------------------------------------------------------------

    function TBuffer.GetSize: integer;
    begin
     result := FSize;
    end;

    //------------------------------------------------------------------------------

    procedure TBuffer.SetSize(ASize: integer);
    begin
     if FSize < ASize then Expand(ASize) else FSize := ASize;
    end;

    // Отсекает первые ACount символов ----------------------------------------------

    function TBuffer.Consume(ACount: integer): integer;
    begin
     if ACount > FSize then ACount := FSize;
     FHead := FHead + ACount;
     FSize := FSize - ACount;
     Result := ACount;
    end;

    // Отсекает последние ACount символов -------------------------------------------

    function TBuffer.Shrink(ACount: integer): integer;
    begin
     if ACount > FSize then ACount := FSize;
     FSize := FSize - ACount;
     if FTail > FHead + FSize then FTail := FHead + FSize;
     Result := ACount;
    end;

    // Расширение буфера -----------------------------------------------------------

    function TBuffer.Expand(ACount: integer): integer;
    var
     Spare, HeadSpace, TailSpace, Width, OldAllocation: integer;
     NewStorage: PAnsiChar;
    begin
     // Находим свободный (незанятый) объем буфера
     Spare := FAllocation - FSize;
     // Вычисляем свободное место в начале буфера
     HeadSpace := FHead - FStorage;
     // Вычисляем свободное место в конце буфера
     TailSpace := Spare - HeadSpace;
     // Вычисляем размер (ширину) занятой части буфера
     Width := Tail - Head;
     // Если в буфере есть достаточно свободного места для добавления count символов
     if Spare > ACount then
       begin
         // Если в конце бефера свободного места меньше чем надо добавить
         if TailSpace < ACount then
           begin
             // Двигаем полезные данные в начало буфера
            Move(FHead^, FStorage^, FSize);
             // Теперь начало полезных данных совпадает с началом буфера
            FHead := FStorage;
             // Корректируем указатель на свободное место в конце буфера
             FTail := FHead + Width;
           end;
       end
     else
       // Если в буфере недостаточно места для добавления count символов
       begin
         OldAllocation := FAllocation;
         // Общий объем буфера увеличиваем на count
         FAllocation := FAllocation + ACount;
         // Создаем временный буфер нужного размера
         GetMem(NewStorage, FAllocation);
         FillChar(NewStorage^, FAllocation, 0);
         if FStorage <> nil then
           begin
             // Копируем в него данные из старого буфера
             Move(FHead^, NewStorage^, FSize);
             // Старый буфер удаляем
             FreeMem(FStorage, OldAllocation);
           end;
         // Новый буфер заменяет старый
         FStorage := NewStorage;
         // Данные в начале буфера
         FHead := FStorage;
         // Хвоcт на расстоянии width от головы буфера
         FTail := FHead + Width;
       end;
     // Устанавливаем новый размер буфера
     FSize := FSize + ACount;
     // Возвращаем новый размер
     result := FSize;
    end;

    // Добавление данных в конец буфера --------------------------------------------

    function TBuffer.Append(AStorage: PAnsiChar; ASize: integer): integer;
    begin
     Expand(ASize);
     Move(AStorage^, FTail^, ASize);
     FTail := FTail + ASize;
     result := FSize;
    end;

    // Добавление данных в конец буфера --------------------------------------------

    function TBuffer.AppendBuff(ABuffer: TBuffer): integer;
    begin
     result := Append(ABuffer.Storage, ABuffer.Size);
    end;

    // Извлечение первых ASize символов с их удалением из буфера ------------------

    function TBuffer.Extract(ASize: integer): PAnsiChar;
    var
     OldHead: PAnsiChar;
    begin
     if ASize > FSize then ASize := FSize;
     OldHead := FHead;
     FHead := FHead + ASize;
     FSize := FSize - ASize;
     result := OldHead;
    end;

    //------------------------------------------------------------------------------

    function TBuffer.GetHead: PAnsiChar;
    begin
     result := FHead;
    end;

    //------------------------------------------------------------------------------

    function TBuffer.GetStorage: PAnsiChar;
    begin
     result := FStorage;
    end;

    //------------------------------------------------------------------------------

    function TBuffer.GetTail: PAnsiChar;
    begin
     result := FTail;
    end;

    //------------------------------------------------------------------------------

    procedure TBuffer.Emply;
    begin
     FSize := 0;
     FHead := FStorage;
     FTail := FHead;
    end;

    //------------------------------------------------------------------------------

    function TBuffer.Assign(AStorage: PAnsiChar; ASize: integer): integer;
    begin
     FreeMem(FStorage, FAllocation);
     FSize := ASize;
     FAllocation := FSize;
     GetMem(FStorage, FAllocation);
     FHead := FStorage;
     Move(AStorage^, FStorage^, FSize);
     FTail := FHead + FSize;
     result := FSize;
    end;

    //------------------------------------------------------------------------------

    function TBuffer.AssignBuff(ABuffer: TBuffer): integer;
    begin
     result := Assign(ABuffer.Storage, ABuffer.Size);
    end;

    //------------------------------------------------------------------------------

    function TBuffer.IsEmpty: boolean;
    begin
     result := FSize = 0;
    end;

    //------------------------------------------------------------------------------

    destructor TBuffer.Destroy;
    begin
     FreeMem(FStorage, FAllocation);
     inherited Destroy;
    end;

    //------------------------------------------------------------------------------

    end.

  • DVM © (25.11.08 23:14) [9]

    > axwork ©   (25.11.08 14:20)  


    > выделяю блок JPG

    Кстати, как выделяешь то? Сдается мне, что строковыми функциями пользуешься?
 
Конференция "Media" » Вопрос про раскодирование потока с IP камеры Axis (MJPEG) [D1, D2, D3, D4, D5, D6, D7, WinXP]
Есть новые Нет новых   [134431   +10][b:0][p:0.011]