На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Соблюдайте общие правила форума
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Указывайте точные версии Delphi и используемых сетевых библиотек.

Не приветствуется поднятие старых тем. Если ваш вопрос перекликается со старой темой, то для вопроса лучше создать новую тему, а старую указать в первом сообщении с описанием взаимосвязи.

Внимание:
попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...

Полезные ссылки:
user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


Выразить свое отношение к модераторам раздела можно здесь: user posted image Krid, user posted image Rouse_

Модераторы: Krid, Rouse_
  
> интерфейс RTSP(554)
    всем привет!

    надо сделать интерфейс общения с IP камерой, через RTSP
    уже нашёл описание данного стандарта (правда на английском, но это не проблема)

    на данный момент не получается правильно последовательно считать данные с камеры

    отправляю запрос:
    ExpandedWrap disabled
      'DESCRIBE rtsp://admin:admin@10.10.10.64:554/ RTSP/1.0' + #13#10 +
      'CSeq: 2' + #13#10 +
      'User-Agent: AppName' + #13#10 +
      'Accept: application/sdp' + #13#10;


    назад получаю не полные данные, что именно я должен получить я знаю, но вот приходят они частично обрезанные

    получилось считать целиком при помощи IdTCPClient
    но второй запрос уже обрабатываться не хочет, т.е. отсылаю его, а мне в ответ ошибка 10054

    подскажите как правильно отправить/получить данные

    P.S. разве в нет в дельфи аналогов функций SEND, RECV и обязательно надо использовать подключение заголовочного файла из "си"
    Сообщение отредактировано: woojin -
      Все есть, и recv, и классовые обертки. Но если уровень познаний в сокетах невелик, то легче использовать Indy.
      Обрезанные данные - скорее всего потому, что вычитываешь не полностью.
        да, уровень знаний равен НУЛЮ (((
        понятно что не полностью читается, но в "индях" первый пакет данных читается полностью, а вот при отправке запроса на второй пакет, вылетает ошибка - почему инди не правильно работает, если там всё "оптимизировано и настроено"?
          Цитата Fr0sT @
          Все есть, и recv, и классовые обертки.

          а где именно есть?
          и что за обёртка - win.sockets и TBaseSocket?
            Почему сервер рвет связь - это уж неизвестно. Возможно, ты ему что-то не то скармливаешь. Можешь попробовать отправлять запросы вручную через telnet - вот уж там точно влияние надстроек исключено. Ну а неполное вычитывание, не имея кода, точно никак не проверишь.
            Цитата woojin @
            а где именно есть?
            и что за обёртка - win.sockets и TBaseSocket?

            WinSock, TSocketClient
              ExpandedWrap disabled
                procedure TForm1.Button3Click(Sender: TObject);
                var
                  request: TRequest;
                  cmd, h, c: string;
                  szh, szc: integer;
                 
                begin
                  cmd := 'DESCRIBE rtsp://admin:admin@10.10.10.64:554/ RTSP/1.0' + #13#10 +
                         'CSeq: 2' + #13#10 +
                         'User-Agent: AppName' + #13#10 +
                         'Accept: application/sdp' + #13#10;
                 
                  TcpClient1.Open;
                  TcpClient1.Active:=True;
                  TcpClient1.Sendln(cmd);
                //  TcpClient1.Receiveln;
                end;
                 
                procedure TForm1.TcpClient1Receive(Sender: TObject; Buf: PAnsiChar;
                  var DataLen: Integer);
                begin
                  Memo1.Lines.Add('Receive(' + IntToStr(DataLen) + '): ' + Buf);
                end;


              вот таким кодом отправляю запрос, но в ответ ни чего не получаю без закомментированной строки
              если её раскоментировать, то в Memo сразу появляется текст
              ExpandedWrap disabled
                RTSP/1.0 200 OK
                CSeq: 2
                Content-Type: application/sdp
                Content-Base: rtsp://10.10.10.64:554/
                Content-Length: 545
                 
                v=0
                o=- 1480520940099739 1480520940099739 IN IP4 10.10.10.64
                s=Media Presentation
                e=NONE
                b=AS:5050
                t=0 0
                a=control:rtsp://10.10.10.64:554/
                m=video 0 RTP/AVP 96
                c=IN IP4 0.0.0.0
                b=AS:5000
                a=recvonly
                a=x-dimensions:1280,720
                a=control:rtsp://10.10.10.64:554/trackID=1
                a=rtpmap:96 H264/90000
                a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z0IAII2NQCgC3QgAADhAAAr8gCA=,aM44gA==
                a=Media_header:


              но он не полный!
              не хватает в конце (после двоеточия)
              ExpandedWrap disabled
                MEDIAINFO=494D4B48010100000400010000000000000000000000000000000000000000000000000000000000;
                a=appversion:1.0
              Сообщение отредактировано: woojin -
                Что такое TcpClient? Он синхронный или асинхронный? Что за партизаны, каждый кусок инфы клещами тянуть приходится...

                Не знаю, как там у RTSP, но у HTTP по стандарту запрос должен завершаться двумя \r\n
                  Цитата Fr0sT @
                  Что такое TcpClient?

                  у RAD STUDIO XE5 есть набор компонентов INTENET, это оттуда
                  Цитата Fr0sT @
                  запрос должен завершаться двумя \r\n

                  это \r\n\r\n?
                    Цитата woojin @
                    это \r\n\r\n?

                    Ага.
                      сделал на другом компоненте
                      вроде как получилось, с одним "НО" ни как не могу понять, как подцепится к видео потоку
                      ExpandedWrap disabled
                        var                  
                          session: string;   // глобальная переменная
                         
                        // получаю данные с камеры
                        procedure TForm1.ButtonDescrClick(Sender: TObject);
                        var
                          s: string;
                         
                        begin
                          s := 'DESCRIBE rtsp://admin:admin@10.10.10.64:554 RTSP/1.0'+#13#10+
                               'CSeq: 2'+#13#10+
                               'User-Agent: AppName'+#13#10+
                               'Accept: application/sdp'+#13#10;
                         
                          if ClientSocket1.Socket.Connected then
                            begin
                              ClientSocket1.Socket.Close;
                              ClientSocket1.Close;
                            end;
                          ClientSocket1.Port := 554;
                          ClientSocket1.Address := '10.10.10.64';
                          ClientSocket1.ClientType := TClientType(ComboBox1.ItemIndex); // ctNonBlocking или ctBlocking - без разницы работает одинаково
                          ClientSocket1.Open;
                        end;

                      ответ
                      ExpandedWrap disabled
                        RTSP/1.0 200 OK
                        CSeq: 2
                        Content-Type: application/sdp
                        Content-Base: rtsp://admin:admin@10.10.10.64:554/
                        Content-Length: 575
                         
                        v=0
                        o=- 1481815230001505 1481815230001505 IN IP4 10.10.10.64
                        s=Media Presentation
                        e=NONE
                        b=AS:5050
                        t=0 0
                        a=control:rtsp://admin:admin@10.10.10.64:554/
                        m=video 0 RTP/AVP 96
                        c=IN IP4 0.0.0.0
                        b=AS:5000
                        a=recvonly
                        a=x-dimensions:1280,720
                        a=control:rtsp://admin:admin@10.10.10.64:554/trackID=1
                        a=rtpmap:96 H264/90000
                        a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z0IAII2NQCgC3QgAADhAAAr8gCA=,aM44gA==
                        a=Media_header:MEDIAINFO=494D4B48010100000400010000000000000000000000000000000000000000000000000000000000;
                        a=appversion:1.0

                      ExpandedWrap disabled
                        // делаю настройки
                        procedure TForm1.ButtonSetupClick(Sender: TObject);
                        var
                          s: string;
                          start, finish: integer;
                         
                        begin
                          s := 'SETUP rtsp://admin:admin@10.10.10.64:554/trackID=1 RTSP/1.0'+#13#10+
                               'CSeq: 3'+#13#10+
                               'User-Agent: AppName'+#13#10+
                               'Transport: RTP/AVP;unicast;client_port=10024-10025'+#13#10+#13#10; // порты взяты на обум но они свободны
                         
                          ClientSocket1.Socket.SendText(s);
                          sleep(300);
                          s := ClientSocket1.Socket.ReceiveText;
                          start := pos('Session:', s)+Length('Session:');   // \
                          finish := pos(';', s, start);                     //  > получаю номер сессии в глобальную переменную session
                          session := trim(copy(s, start, finish-start));    // /
                          Memo1.Lines.Add(s);
                        end;

                      ответ
                      ExpandedWrap disabled
                        RTSP/1.0 200 OK
                        CSeq: 3
                        Session:       1471661481;timeout=60
                        Transport: RTP/AVP;unicast;client_port=10024-10025;server_port=8280-8281;ssrc=509cf2f0;mode="play"
                        Date:  Thu, Dec 15 2016 15:20:30 GMT

                      ExpandedWrap disabled
                        // отправляю запрос на проигрывание
                        procedure TForm1.ButtonPlayClick(Sender: TObject);
                        var
                          s: string;
                         
                        begin
                          s := 'PLAY rtsp://admin:admin@10.10.10.64:554/ RTSP/1.0'+#13#10+
                               'CSeq: 4'+#13#10+
                               'User-Agent: AppName'+#13#10+
                               'Session: '+ session +#13#10+
                               'Range: npt=0.000-'+#13#10+#13#10;
                         
                          ClientSocket1.Socket.SendText(s);
                          sleep(300);
                          s := ClientSocket1.Socket.ReceiveText;
                          Memo1.Lines.Add(s);
                        end;

                      ответ
                      ExpandedWrap disabled
                        RTSP/1.0 200 OK
                        CSeq: 4
                        Session:       1471661481
                        RTP-Info: url=rtsp://admin:admin@10.10.10.64:554/trackID=1;seq=49912;rtptime=665131904
                        Date:  Thu, Dec 15 2016 15:20:30 GMT

                      и далее как то надо начать читать поток... но вот как не могу разобраться, т.е. как назначить своему клиенту именно те порты которые я указал выше (10024-10025) и что именно надо писать после внесения данных в лог (Memo1.Lines.Add(s);) что бы началось чтение из указанных портов сервера?
                      надо ли создавать новы(й/е) компонент(ы) TClientSocket с разными портами сервера (опять же вопрос как назначить свои собственные порты)?

                      в логе програмки на С++ вот что отображается (часть с предыдущего ответа):
                      ExpandedWrap disabled
                        Date:  Thu, Dec 15 2016 15:20:30 GMT
                         
                         
                        [URL:"rtsp://admin:admin@10.10.10.64:554/"]: Started playing session...
                        Stream "rtsp://admin:admin@10.10.10.64:554/"; video/H264:    Received 20 bytes.      Presentation time: 1481797230.432135!
                        Stream "rtsp://admin:admin@10.10.10.64:554/"; video/H264:    Received 4 bytes.       Presentation time: 1481797230.432135!
                        Stream "rtsp://admin:admin@10.10.10.64:554/"; video/H264:    Received 25377 bytes.   Presentation time: 1481797230.432135!
                        Stream "rtsp://admin:admin@10.10.10.64:554/"; video/H264:    Received 3025 bytes.    Presentation time: 1481797230.472135!
                        Stream "rtsp://admin:admin@10.10.10.64:554/"; video/H264:    Received 3041 bytes.    Presentation time: 1481797230.512135!


                      если кто то занимался подобными вещами посоветуйте плиз
                        Если надо слушать порт на своей машине, чтобы сервер на него начал передавать поток, то это Bind на порт, Listen, Accept, получение принимающего сокета и затем чтение из него. Если же надо инициировать соединение самому, то это проще - просто еще один clientsocket.
                        А вообще советую почитать статью А. Григорьева про сокеты, чтобы иметь представление о предмете. Потому что "ctNonBlocking или ctBlocking - без разницы работает одинаково", "sleep(300);" - это тихий ужас. Кроме того, если ответ сервера не уместится в один пакет, то ReceiveText вернет только часть ответа. Надо собирать ответ в буфере, пока не встретится сигнатура завершения, и тогда уже его разбирать.
                          Цитата Fr0sT @
                          "ctNonBlocking или ctBlocking - без разницы работает одинаково"

                          по поводу этого, мне просто не понятно в каком случае применить блокировку
                          Цитата Fr0sT @
                          ReceiveText вернет только часть ответа

                          ползал я в System.Win.ScktComp эта функция (на сколько я понимаю, хотя могу и ошибаться) читает полностью весь пакет
                          ExpandedWrap disabled
                            function TCustomWinSocket.ReceiveText: AnsiString;
                            begin
                              SetLength(Result, ReceiveBuf(Pointer(nil)^, -1));                // выставляет длину получаемых данных
                              SetLength(Result, ReceiveBuf(Pointer(Result)^, Length(Result))); // и тут уже записывает их в Result
                            end;

                          а вот без этого
                          Цитата Fr0sT @
                          "sleep(300);"

                          вообще читать ни чего не хочет, кстати интересно что если поставить меньше 300 то тоже ни каких данных не приходит
                          если использовать OnRead снова ни чего нет, я так понял что надо самому инициализировать чтение потока, по этому сначала отправка сообщения, потом задержка и чтение

                          P.S. статейка эта Статья :: 2.2. Сокеты Windows : А Григорьев? правильно нашёл?
                          и ещё Bind, Listen, Accept - их можно задать у ClientSocket или придётся всё самому описывать с использованием WinApi.WinSock?
                            Цитата woojin @
                            по поводу этого, мне просто не понятно в каком случае применить блокировку

                            Блокировка блокирует выполнение, если в данный момент не получается выполнить функцию прямо сейчас. Т.е. вокруг неблокирующего сокета должна быть обвязка, тем или иным способом повторяющая вызов либо проверяющая результат. В твоем случае легче блокирующий.
                            Цитата woojin @
                            ползал я в System.Win.ScktComp эта функция (на сколько я понимаю, хотя могу и ошибаться) читает полностью весь пакет

                            Да, пакет читает. Но что если ответ сервера в него не влезет? Функция прочитает только часть. Т.ч. в идеале надо склеивать в накопитель, искать там \r\n\r\n (конец заголовка), разбирать его, вычленять content-length и считывать тело ответа, если он есть.
                            Цитата woojin @
                            вообще читать ни чего не хочет, кстати интересно что если поставить меньше 300 то тоже ни каких данных не приходит
                            если использовать OnRead снова ни чего нет, я так понял что надо самому инициализировать чтение потока, по этому сначала отправка сообщения, потом задержка и чтение

                            При блокирующем режиме должен читать без всяких слипов.
                            Цитата woojin @
                            P.S. статейка эта Статья :: 2.2. Сокеты Windows : А Григорьев? правильно нашёл?

                            Почти, только в WSA не стоит лезть, можно обойтись берклевскими функциями.
                            Цитата woojin @
                            и ещё Bind, Listen, Accept - их можно задать у ClientSocket или придётся всё самому описывать с использованием WinApi.WinSock?

                            Насколько я помню, нужен ServerSocket. Но я не знаю, как используется этот порт - клиент у себя открывает или сервер.
                              Цитата Fr0sT @
                              При блокирующем режиме должен читать без всяких слипов.

                              подцепляюсь с блокировкой (кнопка DESCR) - ни какого ответа пока не нажмёшь на кнопку SETUP - после приходит первый ответ :( (фигня какая то)
                              Цитата Fr0sT @
                              Функция прочитает только часть

                              там нет ограничений на количество прочитанного (о чём говорит параметр -1 SetLength(Result, ReceiveBuf(Pointer(nil)^, -1)))
                              Цитата Fr0sT @
                              можно обойтись берклевскими функциями.

                              примерчик можно?
                              Цитата Fr0sT @
                              Насколько я помню, нужен ServerSocket. Но я не знаю, как используется этот порт - клиент у себя открывает или сервер.

                              это получается сервер к серверу будет цепляться?
                              есть пример? (если не сложно)

                              P.S. могу дать С++ программу (она правда под FreeBSD) там (для меня) дикий сумбур, но хотелось бы сделать нечто подобное
                                Цитата woojin @
                                подцепляюсь с блокировкой (кнопка DESCR) - ни какого ответа пока не нажмёшь на кнопку SETUP - после приходит первый ответ

                                А какой может быть ответ, если в Descr ты ничего серверу не отсылаешь?
                                Цитата woojin @
                                там нет ограничений на количество прочитанного (о чём говорит параметр -1 SetLength(Result, ReceiveBuf(Pointer(nil)^, -1)))

                                там нет ограничений на количество прочитанного на момент вызова функции.
                                1. Пришел пакет с Response pt1
                                2. Socket.Read
                                3. Пришел пакет с Response pt2
                                4. ???
                                Цитата woojin @
                                примерчик можно?

                                Это обычные функции/методы без WSA. recv, send, connect и т.д. См. первую часть статьи Григорьева.
                                Цитата woojin @
                                это получается сервер к серверу будет цепляться?

                                Повторяю: я не знаю, как устроен протокол. Смотри в спеки, как там эти порты будут использоваться. Если смущает название "сервер" - окей, пусть это будет "слушающий сокет на клиенте". Но компонент все равно называется ServerSocket.
                                Цитата woojin @
                                могу дать С++ программу (она правда под FreeBSD) там (для меня) дикий сумбур, но хотелось бы сделать нечто подобное

                                Давай
                                  подумал... почитал... посмотрел...

                                  получилось сделать, на winsock отправку и приём текста для управления камерой
                                  после получения камерой команды PLAY, она начинает вещать/передавать уже по UDP, и в этом случае н придумал ничего лучшего как просто за биндить (BIND) рандомно выбранные порты
                                  выглядит это вот так:
                                  ExpandedWrap disabled
                                    procedure TRTSPSocket.SetError(error: Integer);
                                    begin
                                      Ferror := error;
                                    end;
                                     
                                    function TRTSPSocket.init (const ver: word; const socktype: integer; protocol: integer): boolean;
                                    var
                                      iResult: integer;
                                     
                                    begin
                                      Result := true;
                                      iResult := WSAStartup(Fver, vWSAData);
                                      if iResult<>0 then
                                        begin
                                          SetError(WSAGetLastError());
                                          exit(false);
                                        end;
                                     
                                      vSocket := socket(AF_INET, socktype, protocol);
                                      if vSocket = INVALID_SOCKET then
                                        begin
                                          SetError(WSAGetLastError());
                                          exit(false);
                                        end;
                                    end;
                                     
                                    function TRTSPSocket._GetLocalIP : string;
                                    var
                                      HostEnt : PHostEnt;
                                      Name : PAnsiChar;
                                      InAddr : PInAddr;
                                      h_addr_list : MarshaledAStringList;
                                     
                                    begin
                                      GetHostName( Name, $FF );
                                      HostEnt := GetHostByName( Name );
                                    //  Result := inet_ntoa( PInAddr( HostEnt.h_addr_list^ )^ );
                                      h_addr_list := HostEnt.h_addr_list;
                                      InAddr := PInAddr( h_addr_list^ );
                                      Result := inet_ntoa( InAddr^ );
                                    end;
                                     
                                    function TRTSPSocket.create(const AAddress: string; const APort: integer = 554; ASockType: integer = SOCK_STREAM; AProtocol: integer = IPPROTO_IP): boolean;
                                    var
                                      iResult, p : integer;
                                      a : string;
                                     
                                    begin
                                      if not init(Fver, ASockType, AProtocol) then
                                        begin
                                          SetError(WSAGetLastError());
                                          exit(false);
                                        end;
                                     
                                      a := _GetLocalIP;
                                      vSockAddrIn.sin_family := AF_INET;
                                      Randomize;
                                      p := Random( 65535 - 1024 ) + 1024;
                                      vSockAddrIn.sin_port := htons( p );
                                      vSockAddrIn.sin_addr.S_addr := inet_addr(PAnsiChar(AnsiString(a)));
                                    //  vSockAddrIn.sin_addr.S_addr := inet_addr(PAnsiChar(AnsiString('10.10.10.10')));
                                     
                                      vSockAddrOut.sin_family := AF_INET;
                                      vSockAddrOut.sin_port := htons(APort);
                                      vSockAddrOut.sin_addr.S_addr := inet_addr(PAnsiChar(AnsiString(AAddress)));
                                     
                                      iResult := bind(vSocket, vSockAddrIn, sizeof(vSockAddrIn));
                                      if iResult = SOCKET_ERROR then
                                        begin
                                          SetError(WSAGetLastError());
                                          exit(false);
                                        end;
                                    end;


                                  камера начинает передавать на нужн(ый/ые) порты данные, они иду кусками, сначала 31 байт, потом 15, потом валит несколько кусков по 1480 (примерно), далее, всё повторяется 31,15,... и так далее
                                  интересно то что если смотреть на лог liveMedia, то там сначала 20 байт, потом 4 и потом разные размеры без остановки
                                  я так понимаю у них читается только первый заголовок, а потом просто идёт складывание всех кусков (пакетов - ХЗ как эти части правильно назвать) и они пропускают следующие заголовки, но опять же не понятно почему такая разница в размерах: у меня 31 и 15 - у них 20 и 4

                                  по скольку с камеры прёт только видео h264 то значит получать его надо в структуру (или reord) описывающий данный стандарт (rfc6184), попытался отправить данные в такую структуру, но она как то не верно заполняется

                                  ExpandedWrap disabled
                                    /**
                                       Sequence Parameter Set
                                       @see 7.3.2.1 Sequence parameter set RBSP syntax
                                       @see read_seq_parameter_set_rbsp
                                       @see write_seq_parameter_set_rbsp
                                       @see debug_sps
                                    */
                                    typedef struct
                                    {
                                        int profile_idc;
                                        int constraint_set0_flag;
                                        int constraint_set1_flag;
                                        int constraint_set2_flag;
                                        int constraint_set3_flag;
                                        int constraint_set4_flag;
                                        int constraint_set5_flag;
                                        int reserved_zero_2bits;
                                        int level_idc;
                                        int seq_parameter_set_id;
                                        int chroma_format_idc;
                                        int residual_colour_transform_flag;
                                        int bit_depth_luma_minus8;
                                        int bit_depth_chroma_minus8;
                                        int qpprime_y_zero_transform_bypass_flag;
                                        int seq_scaling_matrix_present_flag;
                                          int seq_scaling_list_present_flag[8];
                                          int* ScalingList4x4[6];
                                          int UseDefaultScalingMatrix4x4Flag[6];
                                          int* ScalingList8x8[2];
                                          int UseDefaultScalingMatrix8x8Flag[2];
                                        int log2_max_frame_num_minus4;
                                        int pic_order_cnt_type;
                                          int log2_max_pic_order_cnt_lsb_minus4;
                                          int delta_pic_order_always_zero_flag;
                                          int offset_for_non_ref_pic;
                                          int offset_for_top_to_bottom_field;
                                          int num_ref_frames_in_pic_order_cnt_cycle;
                                          int offset_for_ref_frame[256];
                                        int num_ref_frames;
                                        int gaps_in_frame_num_value_allowed_flag;
                                        int pic_width_in_mbs_minus1;
                                        int pic_height_in_map_units_minus1;
                                        int frame_mbs_only_flag;
                                        int mb_adaptive_frame_field_flag;
                                        int direct_8x8_inference_flag;
                                        int frame_cropping_flag;
                                          int frame_crop_left_offset;
                                          int frame_crop_right_offset;
                                          int frame_crop_top_offset;
                                          int frame_crop_bottom_offset;
                                        int vui_parameters_present_flag;
                                        
                                        struct
                                        {
                                            int aspect_ratio_info_present_flag;
                                              int aspect_ratio_idc;
                                                int sar_width;
                                                int sar_height;
                                            int overscan_info_present_flag;
                                              int overscan_appropriate_flag;
                                            int video_signal_type_present_flag;
                                              int video_format;
                                              int video_full_range_flag;
                                              int colour_description_present_flag;
                                                int colour_primaries;
                                                int transfer_characteristics;
                                                int matrix_coefficients;
                                            int chroma_loc_info_present_flag;
                                              int chroma_sample_loc_type_top_field;
                                              int chroma_sample_loc_type_bottom_field;
                                            int timing_info_present_flag;
                                              int num_units_in_tick;
                                              int time_scale;
                                              int fixed_frame_rate_flag;
                                            int nal_hrd_parameters_present_flag;
                                            int vcl_hrd_parameters_present_flag;
                                              int low_delay_hrd_flag;
                                            int pic_struct_present_flag;
                                            int bitstream_restriction_flag;
                                              int motion_vectors_over_pic_boundaries_flag;
                                              int max_bytes_per_pic_denom;
                                              int max_bits_per_mb_denom;
                                              int log2_max_mv_length_horizontal;
                                              int log2_max_mv_length_vertical;
                                              int num_reorder_frames;
                                              int max_dec_frame_buffering;
                                        } vui;
                                     
                                        struct
                                        {
                                            int cpb_cnt_minus1;
                                            int bit_rate_scale;
                                            int cpb_size_scale;
                                              int bit_rate_value_minus1[32]; // up to cpb_cnt_minus1, which is <= 31
                                              int cpb_size_value_minus1[32];
                                              int cbr_flag[32];
                                            int initial_cpb_removal_delay_length_minus1;
                                            int cpb_removal_delay_length_minus1;
                                            int dpb_output_delay_length_minus1;
                                            int time_offset_length;
                                        } hrd;
                                     
                                    } sps_t;
                                     
                                     
                                    /**
                                       Picture Parameter Set
                                       @see 7.3.2.2 Picture parameter set RBSP syntax
                                       @see read_pic_parameter_set_rbsp
                                       @see write_pic_parameter_set_rbsp
                                       @see debug_pps
                                    */
                                    typedef struct
                                    {
                                        int pic_parameter_set_id;
                                        int seq_parameter_set_id;
                                        int entropy_coding_mode_flag;
                                        int pic_order_present_flag;
                                        int num_slice_groups_minus1;
                                        int slice_group_map_type;
                                          int run_length_minus1[8]; // up to num_slice_groups_minus1, which is <= 7 in Baseline and Extended, 0 otheriwse
                                          int top_left[8];
                                          int bottom_right[8];
                                          int slice_group_change_direction_flag;
                                          int slice_group_change_rate_minus1;
                                          int pic_size_in_map_units_minus1;
                                          int slice_group_id[256]; // FIXME what size?
                                        int num_ref_idx_l0_active_minus1;
                                        int num_ref_idx_l1_active_minus1;
                                        int weighted_pred_flag;
                                        int weighted_bipred_idc;
                                        int pic_init_qp_minus26;
                                        int pic_init_qs_minus26;
                                        int chroma_qp_index_offset;
                                        int deblocking_filter_control_present_flag;
                                        int constrained_intra_pred_flag;
                                        int redundant_pic_cnt_present_flag;
                                     
                                        // set iff we carry any of the optional headers
                                        int _more_rbsp_data_present;
                                     
                                        int transform_8x8_mode_flag;
                                        int pic_scaling_matrix_present_flag;
                                           int pic_scaling_list_present_flag[8];
                                           int* ScalingList4x4[6];
                                           int UseDefaultScalingMatrix4x4Flag[6];
                                           int* ScalingList8x8[2];
                                           int UseDefaultScalingMatrix8x8Flag[2];
                                        int second_chroma_qp_index_offset;
                                    } pps_t;
                                     
                                     
                                    /**
                                      Slice Header
                                      @see 7.3.3 Slice header syntax
                                      @see read_slice_header_rbsp
                                      @see write_slice_header_rbsp
                                      @see debug_slice_header_rbsp
                                    */
                                    typedef struct
                                    {
                                        int first_mb_in_slice;
                                        int slice_type;
                                        int pic_parameter_set_id;
                                        int frame_num;
                                        int field_pic_flag;
                                          int bottom_field_flag;
                                        int idr_pic_id;
                                        int pic_order_cnt_lsb;
                                        int delta_pic_order_cnt_bottom;
                                        int delta_pic_order_cnt[ 2 ];
                                        int redundant_pic_cnt;
                                        int direct_spatial_mv_pred_flag;
                                        int num_ref_idx_active_override_flag;
                                        int num_ref_idx_l0_active_minus1;
                                        int num_ref_idx_l1_active_minus1;
                                        int cabac_init_idc;
                                        int slice_qp_delta;
                                        int sp_for_switch_flag;
                                        int slice_qs_delta;
                                        int disable_deblocking_filter_idc;
                                        int slice_alpha_c0_offset_div2;
                                        int slice_beta_offset_div2;
                                        int slice_group_change_cycle;
                                     
                                     
                                        struct
                                        {
                                            int luma_log2_weight_denom;
                                            int chroma_log2_weight_denom;
                                            int luma_weight_l0_flag[64];
                                            int luma_weight_l0[64];
                                            int luma_offset_l0[64];
                                            int chroma_weight_l0_flag[64];
                                            int chroma_weight_l0[64][2];
                                            int chroma_offset_l0[64][2];
                                            int luma_weight_l1_flag[64];
                                            int luma_weight_l1[64];
                                            int luma_offset_l1[64];
                                            int chroma_weight_l1_flag[64];
                                            int chroma_weight_l1[64][2];
                                            int chroma_offset_l1[64][2];
                                        } pwt; // predictive weight table
                                     
                                        struct // FIXME stack or array
                                        {
                                            int ref_pic_list_reordering_flag_l0;
                                            int ref_pic_list_reordering_flag_l1;
                                            int reordering_of_pic_nums_idc;
                                            int abs_diff_pic_num_minus1;
                                            int long_term_pic_num;
                                        } rplr; // ref pic list reorder
                                     
                                        struct // FIXME stack or array
                                        {
                                            int no_output_of_prior_pics_flag;
                                            int long_term_reference_flag;
                                            int adaptive_ref_pic_marking_mode_flag;
                                            int memory_management_control_operation;
                                            int difference_of_pic_nums_minus1;
                                            int long_term_pic_num;
                                            int long_term_frame_idx;
                                            int max_long_term_frame_idx_plus1;
                                        } drpm; // decoded ref pic marking
                                     
                                    } slice_header_t;
                                     
                                     
                                    /**
                                       Access unit delimiter
                                       @see 7.3.1 NAL unit syntax
                                       @see read_nal_unit
                                       @see write_nal_unit
                                       @see debug_nal
                                    */
                                    typedef struct
                                    {
                                        int primary_pic_type;
                                    } aud_t;
                                     
                                    /**
                                       Network Abstraction Layer (NAL) unit
                                       @see 7.3.1 NAL unit syntax
                                       @see read_nal_unit
                                       @see write_nal_unit
                                       @see debug_nal
                                    */
                                    typedef struct
                                    {
                                        int forbidden_zero_bit;
                                        int nal_ref_idc;
                                        int nal_unit_type;
                                        void* parsed; // FIXME
                                        int sizeof_parsed;
                                     
                                        //uint8_t* rbsp_buf;
                                        //int rbsp_size;
                                    } nal_t;
                                     
                                    typedef struct
                                    {
                                        int _is_initialized;
                                        int sps_id;
                                        int initial_cpb_removal_delay;
                                        int initial_cpb_delay_offset;
                                    } sei_buffering_t;
                                     
                                    typedef struct
                                    {
                                        int clock_timestamp_flag;
                                            int ct_type;
                                            int nuit_field_based_flag;
                                            int counting_type;
                                            int full_timestamp_flag;
                                            int discontinuity_flag;
                                            int cnt_dropped_flag;
                                            int n_frames;
                                     
                                            int seconds_value;
                                            int minutes_value;
                                            int hours_value;
                                     
                                            int seconds_flag;
                                            int minutes_flag;
                                            int hours_flag;
                                     
                                            int time_offset;
                                    } picture_timestamp_t;
                                     
                                    typedef struct
                                    {
                                      int _is_initialized;
                                      int cpb_removal_delay;
                                      int dpb_output_delay;
                                      int pic_struct;
                                      picture_timestamp_t clock_timestamps[3]; // 3 is the maximum possible value
                                    } sei_picture_timing_t;
                                     
                                     
                                    typedef struct
                                    {
                                      int rbsp_size;
                                      uint8_t* rbsp_buf;
                                    } slice_data_rbsp_t;
                                     
                                    /**
                                       H264 stream
                                       Contains data structures for all NAL types that can be handled by this library.  
                                       When reading, data is read into those, and when writing it is written from those.  
                                       The reason why they are all contained in one place is that some of them depend on others, we need to
                                       have all of them available to read or write correctly.
                                     */
                                    typedef struct
                                    {
                                        nal_t* nal;
                                        sps_t* sps;
                                        pps_t* pps;
                                        aud_t* aud;
                                        sei_t* sei; //This is a TEMP pointer at whats in h->seis...    
                                        int num_seis;
                                        slice_header_t* sh;
                                        slice_data_rbsp_t* slice_data;
                                     
                                        sps_t* sps_table[32];
                                        pps_t* pps_table[256];
                                        sei_t** seis;
                                     
                                    } h264_stream_t;
                                     
                                    typedef struct
                                    {
                                        int payloadType;
                                        int payloadSize;
                                        uint8_t* payload;
                                    } sei_t;

                                  это СИшное описание, переделал под Паскалевское


                                  live555
                                  брал данную библиотеку/программу для контроля получаемых данных, хочу сделать нечто подобное (пока с минимальным функционалом) на дельфях

                                  P.S. и для неё нужна камера, к которой можно данной прогой (из каталога testProgs) подцепится
                                    Цитата woojin @
                                    н придумал ничего лучшего как просто за биндить (BIND) рандомно выбранные порты

                                    Если порт уже кем-то занят, конструктор вывалит исключение, зачем оно тебе, если порт неважен? Делай в цикле до первого успеха.
                                    Цитата woojin @
                                    по скольку с камеры прёт только видео h264 то значит получать его надо в структуру (или reord) описывающий данный стандарт (rfc6184), попытался отправить данные в такую структуру, но она как то не верно заполняется

                                    А ты собираешься еще и видео сам проигрывать (в смысле, разбирать свойства, декодировать кадры, отображать на канвасе)? Если нет, то зачем тебе заголовок, просто скорми поток классу-плееру на свой вкус
                                      ВСЕХ С НАСТУПИВШИМ! УДАЧИ, СЧАСТЬЯ, УСПЕХОВ :crazy:

                                      Цитата Fr0sT @
                                      А ты собираешься еще и видео сам проигрывать (в смысле, разбирать свойства, декодировать кадры, отображать на канвасе)? Если нет, то зачем тебе заголовок, просто скорми поток классу-плееру на свой вкус

                                      нет конечно, не собираюсь
                                      приложение будет консольным, ему надо сохранять данный поток в файл (но использовать библиотеки типа "ffmpeg" не хочется для таких дел)

                                      хочется переложить (или написать аналог) данную программу с С/С++ на Pascal


                                      p.s. начал перекладывать потихоньку (как переложу, конечно покажу) и возник вопрос
                                      файл .hh
                                      ExpandedWrap disabled
                                        extern DelayInterval const DELAY_ZERO;
                                        extern DelayInterval const DELAY_SECOND;
                                        extern DelayInterval const DELAY_MINUTE;
                                        extern DelayInterval const DELAY_HOUR;
                                        extern DelayInterval const DELAY_DAY;

                                      файл cpp;
                                      ExpandedWrap disabled
                                        #ifndef INT_MAX
                                        #define INT_MAX 0x7FFFFFFF
                                        #endif
                                        const DelayInterval DELAY_ZERO(0, 0);
                                        const DelayInterval DELAY_SECOND(1, 0);
                                        const DelayInterval DELAY_MINUTE = 60*DELAY_SECOND;
                                        const DelayInterval DELAY_HOUR = 60*DELAY_MINUTE;
                                        const DelayInterval DELAY_DAY = 24*DELAY_HOUR;
                                        const DelayInterval ETERNITY(INT_MAX, MILLION-1);

                                      можно ли такое же сделать на паскале, у меня получается ни как правильно описать данные константы

                                      это оба файла целиком (без вступительных коментов)
                                      *.hh
                                      ExpandedWrap disabled
                                        #ifndef _DELAY_QUEUE_HH
                                        #define _DELAY_QUEUE_HH
                                         
                                        #ifndef _NET_COMMON_H
                                        #include "NetCommon.h"
                                        #endif
                                         
                                        #ifdef TIME_BASE
                                        typedef TIME_BASE time_base_seconds;
                                        #else
                                        typedef long time_base_seconds;
                                        #endif
                                         
                                        ///// A "Timeval" can be either an absolute time, or a time interval /////
                                         
                                        class Timeval {
                                        public:
                                          time_base_seconds seconds() const {
                                            return fTv.tv_sec;
                                          }
                                          time_base_seconds seconds() {
                                            return fTv.tv_sec;
                                          }
                                          time_base_seconds useconds() const {
                                            return fTv.tv_usec;
                                          }
                                          time_base_seconds useconds() {
                                            return fTv.tv_usec;
                                          }
                                         
                                          int operator>=(Timeval const& arg2) const;
                                          int operator<=(Timeval const& arg2) const {
                                            return arg2 >= *this;
                                          }
                                          int operator<(Timeval const& arg2) const {
                                            return !(*this >= arg2);
                                          }
                                          int operator>(Timeval const& arg2) const {
                                            return arg2 < *this;
                                          }
                                          int operator==(Timeval const& arg2) const {
                                            return *this >= arg2 && arg2 >= *this;
                                          }
                                          int operator!=(Timeval const& arg2) const {
                                            return !(*this == arg2);
                                          }
                                         
                                          void operator+=(class DelayInterval const& arg2);
                                          void operator-=(class DelayInterval const& arg2);
                                          // returns ZERO iff arg2 >= arg1
                                         
                                        protected:
                                          Timeval(time_base_seconds seconds, time_base_seconds useconds) {
                                            fTv.tv_sec = seconds; fTv.tv_usec = useconds;
                                          }
                                         
                                        private:
                                          time_base_seconds& secs() {
                                            return (time_base_seconds&)fTv.tv_sec;
                                          }
                                          time_base_seconds& usecs() {
                                            return (time_base_seconds&)fTv.tv_usec;
                                          }
                                         
                                          struct timeval fTv;
                                        };
                                         
                                        #ifndef max
                                        inline Timeval max(Timeval const& arg1, Timeval const& arg2) {
                                          return arg1 >= arg2 ? arg1 : arg2;
                                        }
                                        #endif
                                        #ifndef min
                                        inline Timeval min(Timeval const& arg1, Timeval const& arg2) {
                                          return arg1 <= arg2 ? arg1 : arg2;
                                        }
                                        #endif
                                         
                                        class DelayInterval operator-(Timeval const& arg1, Timeval const& arg2);
                                        // returns ZERO iff arg2 >= arg1
                                         
                                         
                                        ///// DelayInterval /////
                                         
                                        class DelayInterval: public Timeval {
                                        public:
                                          DelayInterval(time_base_seconds seconds, time_base_seconds useconds)
                                            : Timeval(seconds, useconds) {}
                                        };
                                         
                                        DelayInterval operator*(short arg1, DelayInterval const& arg2);
                                         
                                        extern DelayInterval const DELAY_ZERO;
                                        extern DelayInterval const DELAY_SECOND;
                                        extern DelayInterval const DELAY_MINUTE;
                                        extern DelayInterval const DELAY_HOUR;
                                        extern DelayInterval const DELAY_DAY;
                                         
                                        ///// _EventTime /////
                                         
                                        class _EventTime: public Timeval {
                                        public:
                                          _EventTime(unsigned secondsSinceEpoch = 0,
                                                unsigned usecondsSinceEpoch = 0)
                                            // We use the Unix standard epoch: January 1, 1970
                                            : Timeval(secondsSinceEpoch, usecondsSinceEpoch) {}
                                        };
                                         
                                        _EventTime TimeNow();
                                         
                                        extern _EventTime const THE_END_OF_TIME;
                                         
                                         
                                        ///// DelayQueueEntry /////
                                         
                                        class DelayQueueEntry {
                                        public:
                                          virtual ~DelayQueueEntry();
                                         
                                          intptr_t token() {
                                            return fToken;
                                          }
                                         
                                        protected: // abstract base class
                                          DelayQueueEntry(DelayInterval delay);
                                         
                                          virtual void handleTimeout();
                                         
                                        private:
                                          friend class DelayQueue;
                                          DelayQueueEntry* fNext;
                                          DelayQueueEntry* fPrev;
                                          DelayInterval fDeltaTimeRemaining;
                                         
                                          intptr_t fToken;
                                          static intptr_t tokenCounter;
                                        };
                                         
                                        ///// DelayQueue /////
                                         
                                        class DelayQueue: public DelayQueueEntry {
                                        public:
                                          DelayQueue();
                                          virtual ~DelayQueue();
                                         
                                          void addEntry(DelayQueueEntry* newEntry); // returns a token for the entry
                                          void updateEntry(DelayQueueEntry* entry, DelayInterval newDelay);
                                          void updateEntry(intptr_t tokenToFind, DelayInterval newDelay);
                                          void removeEntry(DelayQueueEntry* entry); // but doesn't delete it
                                          DelayQueueEntry* removeEntry(intptr_t tokenToFind); // but doesn't delete it
                                         
                                          DelayInterval const& timeToNextAlarm();
                                          void handleAlarm();
                                         
                                        private:
                                          DelayQueueEntry* head() { return fNext; }
                                          DelayQueueEntry* findEntryByToken(intptr_t token);
                                          void synchronize(); // bring the 'time remaining' fields up-to-date
                                         
                                          _EventTime fLastSyncTime;
                                        };
                                         
                                        #endif

                                      .cpp
                                      ExpandedWrap disabled
                                        #include "DelayQueue.hh"
                                        #include "GroupsockHelper.hh"
                                         
                                        static const int MILLION = 1000000;
                                         
                                        ///// Timeval /////
                                         
                                        int Timeval::operator>=(const Timeval& arg2) const {
                                          return seconds() > arg2.seconds()
                                            || (seconds() == arg2.seconds()
                                            && useconds() >= arg2.useconds());
                                        }
                                         
                                        void Timeval::operator+=(const DelayInterval& arg2) {
                                          secs() += arg2.seconds(); usecs() += arg2.useconds();
                                          if (useconds() >= MILLION) {
                                            usecs() -= MILLION;
                                            ++secs();
                                          }
                                        }
                                         
                                        void Timeval::operator-=(const DelayInterval& arg2) {
                                          secs() -= arg2.seconds(); usecs() -= arg2.useconds();
                                          if ((int)useconds() < 0) {
                                            usecs() += MILLION;
                                            --secs();
                                          }
                                          if ((int)seconds() < 0)
                                            secs() = usecs() = 0;
                                         
                                        }
                                         
                                        DelayInterval operator-(const Timeval& arg1, const Timeval& arg2) {
                                          time_base_seconds secs = arg1.seconds() - arg2.seconds();
                                          time_base_seconds usecs = arg1.useconds() - arg2.useconds();
                                         
                                          if ((int)usecs < 0) {
                                            usecs += MILLION;
                                            --secs;
                                          }
                                          if ((int)secs < 0)
                                            return DELAY_ZERO;
                                          else
                                            return DelayInterval(secs, usecs);
                                        }
                                         
                                         
                                        ///// DelayInterval /////
                                         
                                        DelayInterval operator*(short arg1, const DelayInterval& arg2) {
                                          time_base_seconds result_seconds = arg1*arg2.seconds();
                                          time_base_seconds result_useconds = arg1*arg2.useconds();
                                         
                                          time_base_seconds carry = result_useconds/MILLION;
                                          result_useconds -= carry*MILLION;
                                          result_seconds += carry;
                                         
                                          return DelayInterval(result_seconds, result_useconds);
                                        }
                                         
                                        #ifndef INT_MAX
                                        #define INT_MAX 0x7FFFFFFF
                                        #endif
                                        const DelayInterval DELAY_ZERO(0, 0);
                                        const DelayInterval DELAY_SECOND(1, 0);
                                        const DelayInterval DELAY_MINUTE = 60*DELAY_SECOND;
                                        const DelayInterval DELAY_HOUR = 60*DELAY_MINUTE;
                                        const DelayInterval DELAY_DAY = 24*DELAY_HOUR;
                                        const DelayInterval ETERNITY(INT_MAX, MILLION-1);
                                        // used internally to make the implementation work
                                         
                                         
                                        ///// DelayQueueEntry /////
                                         
                                        intptr_t DelayQueueEntry::tokenCounter = 0;
                                         
                                        DelayQueueEntry::DelayQueueEntry(DelayInterval delay)
                                          : fDeltaTimeRemaining(delay) {
                                          fNext = fPrev = this;
                                          fToken = ++tokenCounter;
                                        }
                                         
                                        DelayQueueEntry::~DelayQueueEntry() {
                                        }
                                         
                                        void DelayQueueEntry::handleTimeout() {
                                          delete this;
                                        }
                                         
                                         
                                        ///// DelayQueue /////
                                         
                                        DelayQueue::DelayQueue()
                                          : DelayQueueEntry(ETERNITY) {
                                          fLastSyncTime = TimeNow();
                                        }
                                         
                                        DelayQueue::~DelayQueue() {
                                          while (fNext != this) {
                                            DelayQueueEntry* entryToRemove = fNext;
                                            removeEntry(entryToRemove);
                                            delete entryToRemove;
                                          }
                                        }
                                         
                                        void DelayQueue::addEntry(DelayQueueEntry* newEntry) {
                                          synchronize();
                                         
                                          DelayQueueEntry* cur = head();
                                          while (newEntry->fDeltaTimeRemaining >= cur->fDeltaTimeRemaining) {
                                            newEntry->fDeltaTimeRemaining -= cur->fDeltaTimeRemaining;
                                            cur = cur->fNext;
                                          }
                                         
                                          cur->fDeltaTimeRemaining -= newEntry->fDeltaTimeRemaining;
                                         
                                          // Add "newEntry" to the queue, just before "cur":
                                          newEntry->fNext = cur;
                                          newEntry->fPrev = cur->fPrev;
                                          cur->fPrev = newEntry->fPrev->fNext = newEntry;
                                        }
                                         
                                        void DelayQueue::updateEntry(DelayQueueEntry* entry, DelayInterval newDelay) {
                                          if (entry == NULL) return;
                                         
                                          removeEntry(entry);
                                          entry->fDeltaTimeRemaining = newDelay;
                                          addEntry(entry);
                                        }
                                         
                                        void DelayQueue::updateEntry(intptr_t tokenToFind, DelayInterval newDelay) {
                                          DelayQueueEntry* entry = findEntryByToken(tokenToFind);
                                          updateEntry(entry, newDelay);
                                        }
                                         
                                        void DelayQueue::removeEntry(DelayQueueEntry* entry) {
                                          if (entry == NULL || entry->fNext == NULL) return;
                                         
                                          entry->fNext->fDeltaTimeRemaining += entry->fDeltaTimeRemaining;
                                          entry->fPrev->fNext = entry->fNext;
                                          entry->fNext->fPrev = entry->fPrev;
                                          entry->fNext = entry->fPrev = NULL;
                                          // in case we should try to remove it again
                                        }
                                         
                                        DelayQueueEntry* DelayQueue::removeEntry(intptr_t tokenToFind) {
                                          DelayQueueEntry* entry = findEntryByToken(tokenToFind);
                                          removeEntry(entry);
                                          return entry;
                                        }
                                         
                                        DelayInterval const& DelayQueue::timeToNextAlarm() {
                                          if (head()->fDeltaTimeRemaining == DELAY_ZERO) return DELAY_ZERO; // a common case
                                         
                                          synchronize();
                                          return head()->fDeltaTimeRemaining;
                                        }
                                         
                                        void DelayQueue::handleAlarm() {
                                          if (head()->fDeltaTimeRemaining != DELAY_ZERO) synchronize();
                                         
                                          if (head()->fDeltaTimeRemaining == DELAY_ZERO) {
                                            // This event is due to be handled:
                                            DelayQueueEntry* toRemove = head();
                                            removeEntry(toRemove); // do this first, in case handler accesses queue
                                         
                                            toRemove->handleTimeout();
                                          }
                                        }
                                         
                                        DelayQueueEntry* DelayQueue::findEntryByToken(intptr_t tokenToFind) {
                                          DelayQueueEntry* cur = head();
                                          while (cur != this) {
                                            if (cur->token() == tokenToFind) return cur;
                                            cur = cur->fNext;
                                          }
                                         
                                          return NULL;
                                        }
                                         
                                        void DelayQueue::synchronize() {
                                          // First, figure out how much time has elapsed since the last sync:
                                          _EventTime timeNow = TimeNow();
                                          if (timeNow < fLastSyncTime) {
                                            // The system clock has apparently gone back in time; reset our sync time and return:
                                            fLastSyncTime  = timeNow;
                                            return;
                                          }
                                          DelayInterval timeSinceLastSync = timeNow - fLastSyncTime;
                                          fLastSyncTime = timeNow;
                                         
                                          // Then, adjust the delay queue for any entries whose time is up:
                                          DelayQueueEntry* curEntry = head();
                                          while (timeSinceLastSync >= curEntry->fDeltaTimeRemaining) {
                                            timeSinceLastSync -= curEntry->fDeltaTimeRemaining;
                                            curEntry->fDeltaTimeRemaining = DELAY_ZERO;
                                            curEntry = curEntry->fNext;
                                          }
                                          curEntry->fDeltaTimeRemaining -= timeSinceLastSync;
                                        }
                                         
                                         
                                        ///// _EventTime /////
                                         
                                        _EventTime TimeNow() {
                                          struct timeval tvNow;
                                         
                                          gettimeofday(&tvNow, NULL);
                                         
                                          return _EventTime(tvNow.tv_sec, tvNow.tv_usec);
                                        }
                                         
                                        const _EventTime THE_END_OF_TIME(INT_MAX);
                                      Сообщение отредактировано: woojin -
                                        Тут какая-то очередь, неясно зачем. Если надо только сохранять принятое (да еще и в консольном приложении), то никаких сложностей не вижу - блокирующие сокеты, простейший вариант. Коннектимся, пишем в сокет запрос, читаем ответ, откусываем заголовок, поток пишем в файл. Для отзывчивости перед каждым блокирующим вызовом (recv, send, connect) вызывать select с таймаутом. Всё.
                                          Цитата Fr0sT @
                                          Тут какая-то очередь, неясно зачем.

                                          вот и я не понял, а вообще такого же типа константу в delphi можно описать?
                                          Цитата Fr0sT @
                                          откусываем заголовок

                                          вот! именно!
                                          как откусить ХЗ сколько, по RFC там то ли 12 байт, то ли 12 бит, то ли все 32 байта
                                            Цитата woojin @
                                            вот и я не понял, а вообще такого же типа константу в delphi можно описать?

                                            const DELAY_SECOND: DelayInterval = (sec: 1, usec: 0);
                                            Но еще раз, с очередью какая-то странная муть, скорее всего, для твоих целей оно и не нужно.
                                            Цитата woojin @
                                            как откусить ХЗ сколько, по RFC там то ли 12 байт, то ли 12 бит, то ли все 32 байта

                                            Ну я имел в виду заголовок http ответа, весь заголовок бинарного потока по идее должен сохраниться.
                                              В аттаче к посту программа, в ней реализовано общение с трансляцией VLC-плеера. На молчаливый вопрос «почему не камера», ответ таков - пока нет ни одной камеры в офисе, к которой мне можно подключиться, жду закупки.
                                              Запускаем трансляцию в VLC, после этого запускаем прогу.

                                              Чтобы пошла трансляция, необходимо произвести такие шаги:
                                              - Жмём кнопку «Подключиться», после этого появится список команд
                                              - Жмём двойной клик на команде DESCRIBE – это отправит запрос на наличие потоков, к которым можно подключиться. Далее в списке появятся ссылки на доступные потоки. Все, которые начинаются там с «2=», это потоки видео. В этот же момент запоминается тип данных (96 – это видео в формате h264).
                                              - выбираем в списке ниже ту ссылку, которая начинается с 2= и жмём двойной клик на команде SETUP. От этого действия мы получаем идентификатор сессии, с помощью которого можно начинать получать видео.
                                              - жмём двойной клик на PLAY, после этого начинается передача видео на UDP-порт 54000.

                                              Теперь видео-кадры приходят. Отлично приходят, получаю их, нахожу смещение Payload, получаю RTP (обкурил RFC и эти материалы - https://habr.com/ru/post/117735/, https://habr.com/ru/post/233237/).
                                              Надеюсь, всё вышеперечисленное сможет кому-то помочь, включая проблему, оставшуюся без ответа в этом топике. В приложенном коде кроме описанного также присутствует:
                                              - отправка «логического» пинга, чтобы связь не обрывалась, по таймеру, который нужен источнику.
                                              - запоминание SPS и PPS кадров, потому что от VLC и многих камер, они просто не приходят

                                              И вот тут начинаются проблемы… Вроде всё сделано по инструкции, но внезапно оказалось, что тип кадра 5 (опорный) не приходит в пакетах с маркером конца пакета. Иногда он может быть у одного из «серединных» пакетов кадра. Тип кадра беру как последние 5 бит второго байта RTP-пакета если пакет – часть кадра или как последние 5 бит первого байта RTP-пакета, если кадр целиком уместился в пакет. При этом, по итогу сохранения данных, я вполне наблюдаю определённую периодичность бОльших, чем другие кадров.
                                              Помогите, пожалуйста, разобраться, где я промахнулся с получением типа кадра.

                                              Прошу прощения за некропост, но мне кажется, что тут в топике есть некоторая недосказанность, которая у меня уже решена. И в то же самое время, наступил тупик через несколько шагов. Если вы поможете мне из него выбраться, буду очень благодарен.

                                              Если будете запускать прогу до ознакомления с содержимым, то на этот случай предупреждаю - засирает папку файлами, в которые сохраняются RTP-пакеты, для отладочных целей.

                                              Прикреплённый файлПрикреплённый файлRTSPProtocol.rar (8,94 Кбайт, скачиваний: 976)
                                                Не очень активная тема, к сожалению ...

                                                В общем, решил я свой вопрос. Не разбирался непосредственно в проблеме, скорей всего неправильные сдвиги при распарсивании пакета. Просто сделал такие переделки:
                                                - WinSock вместо Indy
                                                - interleaved вместо non-interleaved
                                                - ну и камеру подвезли, вместо эмулятора VLC

                                                Получаемые кадры отлично скармливаются декодеру, картинка есть. В прилагаемом примере нет работы с авторизацией и логического пинга. Однако, работа непосредственно с RTP налажена. Забирайте кому надо :).
                                                Прикреплённый файлПрикреплённый файлRTSPProtocol.rar (36,29 Кбайт, скачиваний: 957)
                                                  Скачал исходник, при компиляции ругается на отсутствующий модуль cBaseThread_TH

                                                  Добавлено
                                                  Lem0nti не думал реализовать трансляцию RTSP потока?
                                                    Там есть dcu для тех модулей, исходники которых включать неуместно. Не удаляйте их и всё срастётся.

                                                    Нет, не думал.
                                                    Но с трансляцией как есть всё просто - берём кадры как есть в h264 и пересылаем их куда надо. Собственно, у меня так работает. Конечно, если надо раздавать обязательно в соответствии с RFC и потребители видео условно неизвестны, то это может не помочь.
                                                      Lem0nti Есть коммерческое предложение, нужно сделать RTSP клиент который способен получить аудио-видео поток от видеокамеры/видеорегистратора кроме того, нужно писать этот поток на HDD, и после этого еще раздавать нуждающмся клиентам, их адреса заранее не известны

                                                      Добавлено
                                                      Lem0nti ни в какую не компилирует без этих юнитов, на DCUхи он и не смотрит

                                                      Добавлено
                                                      Lem0nti пока курил эту тему узнал что DCU годится при одинаковых версиях компилятора
                                                        По dcu - сделано в 10.2. Если она недосутпна, то вы можете попробовать адаптировать парсинг пакета из его текущей обёртки. TBaseThread это наследник от потока, ожидающий элементы очереди, а TThreadSignalledQueue это просто потокозащищённый наследник от TQueue.
                                                          Lem0ntiБоюсь что у меня нет таких знаний, проверьте лс
                                                            Добрый день.
                                                            У меня та же беда, старался поймать поток с камеры, но не получилось.
                                                            Что я делал:
                                                            1. Есть камеры ДАХУА -с них поток поймало по HTTP и скриншот сделало из потока .
                                                            Ну в VLC плеере работает так: rtsp://admin:admin@172.16.42.12:554/cam/realmonitor?channel=1&subtype=0
                                                            ExpandedWrap disabled
                                                              var
                                                                Form1: TForm1;
                                                                memorystream: TMemoryStream;
                                                                Jpeg:  TJpegImage;
                                                                aaa:string;
                                                                Error:string;
                                                               
                                                              implementation
                                                               
                                                              {$R *.dfm}
                                                               
                                                              procedure TForm1.BitBtn1Click(Sender: TObject);
                                                              begin
                                                                    memorystream.Clear;
                                                                    // edit1.Text  ---->  http://admin:admin@172.16.42.12:8080/cgi-bin/snapshot.cgi?channel1
                                                                    try
                                                                        NetHTTPClient1.Get (edit1.Text, memorystream);
                                                                        memorystream.SaveToFile('A_Teste.jpeg');
                                                                    except
                                                                            on E: Exception do
                                                                            begin
                                                                                    Error:=e.ToString();
                                                                                    showmessage(' Ошибка= '+Error);
                                                                            end;
                                                                    end;
                                                              end;



                                                            2. Есть иная камера , "HeroSpeed" ,location="Guangzhou", 172.16.42.11
                                                            Через VLC плеер пашет = rtsp://admin:admin@172.16.42.11:554/cam/realmonitor?channel=1&subtype=0
                                                            и так пашет = rtsp://admin:admin@172.16.42.11:554/cam/realmonitor
                                                            и так пашет = rtsp://admin:admin@172.16.42.11:8080/0
                                                            и так пашет = rtsp://admin:admin@172.16.42.11:554/0
                                                            но через DELPHI - не хочет по HTTP.
                                                            НЕ пашет = http://admin:admin@172.16.42.11:8080/cgi-b...ot.cgi?channel1

                                                            Может кто-то подсказать по этой камере, как ее заставить работать ?
                                                              Потому что это не HTTP-протокол. Если вы скачаете пример выше, то там есть как организовать общение с камерой по RTSP.
                                                                Написал на ПАЙТОНЕ, тоже не работает именно с этой камерой.
                                                                172.16.42.12:554 - пашет
                                                                172.16.42.11:554 - не пашет

                                                                ExpandedWrap disabled
                                                                  import cv2
                                                                  from tkinter import *
                                                                  from tkinter import messagebox
                                                                   
                                                                  cap = cv2.VideoCapture('rtsp://admin:admin@172.16.42.12:554/cam/realmonitor?channel=1&subtype=0')
                                                                   
                                                                  while True:
                                                                      ret, img = cap.read()
                                                                      gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                                                                      img=cv2.resize(img,(800,600))
                                                                      cv2.imshow('IP Camera stream', img)
                                                                   
                                                                   
                                                                      if cv2.waitKey(1) & 0xFF == ord('s'):
                                                                          cv2.imwrite('c:\Python\images.jpg', img)
                                                                          
                                                                      if cv2.waitKey(1) & 0xFF == ord('q'):
                                                                          break
                                                                   
                                                                   
                                                                  cv2.destroyAllWindows()


                                                                Добавлено
                                                                есть прогресс.......
                                                                В пайтоне заработал первый поток, нулевой НЕ ХОЧЕТ
                                                                ПАШЕТ = cap = cv2.VideoCapture('rtsp://admin:admin@172.16.42.11:554/1')
                                                                НЕ ПАШЕТ = cap = cv2.VideoCapture('rtsp://admin:admin@172.16.42.11:554/0')
                                                                (прошу прощения за НЕ ДЕЛФИ язык, но приходиться извращаться для достижения цели)
                                                                Подсказку нашел на этом сайте: https://www.ispyconnect.com/camera/herospeed
                                                                  Ураааааааааааааааааа, нулевой поток ожил.
                                                                  Нужно было в настройках камеры указать в разделе:
                                                                  Конфигурация-Видео-Видео-Видеокодирование
                                                                  стоял параметр: MJPEG
                                                                  нужно было поставить: H.264 и разрешение поставил максимальное
                                                                  ЗАРАБОТАЛО !
                                                                  (Но в Пайтоне)
                                                                    DELPHI - заработало:
                                                                    edit1.Text:='http://admin:admin@172.16.42.11:8080/snap.jpg%27;


                                                                    ExpandedWrap disabled
                                                                      procedure TForm1.BitBtn1Click(Sender: TObject);
                                                                      begin
                                                                            memorystream.Clear;
                                                                            try
                                                                                NetHTTPClient1.Get (edit1.Text, memorystream);
                                                                                memorystream.SaveToFile('A_Teste.jpeg');
                                                                            except
                                                                                    on E: Exception do
                                                                                    begin
                                                                                            Error:=e.ToString();
                                                                                            showmessage(' Ошибка= '+Error);
                                                                                    end;
                                                                            end;
                                                                      end;
                                                                       
                                                                       
                                                                       
                                                                      procedure TForm1.FormCreate(Sender: TObject);
                                                                      begin
                                                                          memorystream:=TMemoryStream.Create;
                                                                          Jpeg:=TJpegImage.create;
                                                                          edit1.Text:='http://admin:admin@172.16.42.11:8080/snap.jpg';
                                                                      end;
                                                                      Судя по всему, скачать пример из темы оказалось сложнее чем яндексить варианты на питоне.
                                                                      Ваш путь - это одноразовый путь.
                                                                      Если вы не разберётесь с RTSP, то плата за подход "как бы сделать так, чтобы ничего не делать" - это открытки и высокий траффик
                                                                      Сообщение отредактировано: Lem0nti -
                                                                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                      0 пользователей:


                                                                      Рейтинг@Mail.ru
                                                                      [ Script execution time: 0,1114 ]   [ 21 queries used ]   [ Generated: 28.03.24, 19:20 GMT ]