Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Мультимедиа в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме 85 тыс рублей в месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 25.10.2022, 10:36   #1
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию RTSP Поток видео от камеры

Добрый день форумчане!
Проблема с полученным видео потока.
Ситуация такая, получаю поток видео в H264 по RTP все хорошо работает, затем пытаюсь извлечь данные из этого потока в файл обрезая при этом RTP заголовок и вставляя NALU заголовки для проигрывания в плеере но плеер не распознает поток. Делаю все как описано здесь https://russianblogs.com/article/1754202088/ и здесь https://russianblogs.com/article/1291720039/ почитав при этом саму структуру здесь https://www.rfc-editor.org/rfc/rfc2326.

нашел на просторах интернета пример и переделал под свою задачу.

код получение потока и сохранение в файл.

Код:
const
  h264Marker: array [0..3] of byte = (0, 0, 0, 1); //00 00 00 01 - маркер начальной отметки NALU.

Len:= recvfrom(socket, Buff[0], SizeOf(Buff), 0, addr, @addrlen);
  if (Len > 12) and 
(Buff[0] = $80) and // проверка что это RTP заголовок обычно из 12 байт
(Buff[12] = $7C) then
  begin
    PayloadType:= Buff[1] AND $7F;  //01111111 - 7 бит
    if PayloadType = 96 then
    begin
     EndMarker:= (Buff[1] AND $80) = 128;  //10000000 - первый бит
    //расширенный заголовок
    if (Buff[0] AND $10) = 16 then         //00010000 - бит номер 3
      x:= 1
    else
      x:= 0;
    //количество CSRC
    CSRCCount:= Buff[0] AND $F;  //00001111 - 4 последних бита

    if x = 1 then
    begin
      //EHL
      EHLOffset:= 12 + (CSRCCount * 4) + 2; //96+CSRCCount*32+16 в битах
      move(Buff[EHLOffset], EHL, 2);
    end
    else
      EHL:= 0;
    //адрес равен 12+CSRCCount*4+x*4+x*EHL
    Payload:= 12 + (CSRCCount + x) * 4 + x * EHL;

    DataSize:= Len - Payload;
    //если в RTP первый бит 1, то это асерт, кодер понял что что-то не так и просигналил об этом
    AssertMarker:= (Buff[Payload] AND $80) = 128;  //10000000 - первый бит
      if not AssertMarker then
    begin
      //тип NAL
      PacketType:= Buff[Payload] AND $1F;  //00011111 - 5 последних бит
      //если тип 28, значит это частичная передача и первые 2 байта - служебные, иначе - только 1
      inc(Payload);
      if PacketType = 28 then
        inc(Payload);
      //если это первая порция, то для первого байта использовать первые три бита индикатора                                 }
      RTPType:= Buff[Payload - 1] AND $1F;  //00011111 - 5 последних бит

     SetLength(CurFrame, length(CurFrame) + DataSize);
      move(Buff[Payload], CurFrame[length(CurFrame) - DataSize], DataSize);
  if EndMarker then
   begin
      CurFrame[0]:= CurFrame[0] or (RTPType);  // Тип NAL
          MemoryStream:= TMemoryStream.Create;
          MemoryStream.Write(h264Marker[0], SizeOf(h264Marker));
          if RTPType = 5 then 
           begin
           MemoryStream.Write(Pointer(TCustomRTPClient(Param).SPS)^,
           Length(TCustomRTPClient(Param).SPS));
           MemoryStream.Write(h264Marker[0], SizeOf(h264Marker));
           MemoryStream.Write(Pointer(TCustomRTPClient(Param).PPS)^,
           Length(TCustomRTPClient(Param).PPS));
           MemoryStream.Write(h264Marker[0], SizeOf(h264Marker));
           end;
           MemoryStream.Write(CurFrame[0], length(CurFrame));
           MemoryStream.Position:= 0;
           MemoryStream.SaveToFile('D:\1111.mp4');
          MemoryStream.Free;
        SetLength(CurFrame, 0);
        exit;
      end;
    end;
   end;
кто нибудь работал с видео полученного по RTP ?

Последний раз редактировалось Aliens_wolfs; 25.10.2022 в 18:27.
Aliens_wolfs вне форума Ответить с цитированием
Старый 25.10.2022, 13:15   #2
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,217
По умолчанию

Код:
 h264Marker: array [0..2] of byte = (0, 0, 0, 1); //00 00 00 01 - маркер начальной отметки NALU.
Размерность 3, инициализаторов 4 и не ругается?
p51x вне форума Ответить с цитированием
Старый 25.10.2022, 14:35   #3
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,221
По умолчанию

Лишние - отбрасываются ?
digitalis на форуме Ответить с цитированием
Старый 25.10.2022, 18:07   #4
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Побывал по разному
Код:
h264Marker: array [0..3] of byte = (0, 0, 0, 1);
либо так
Код:
h264Marker: array [0..2] of byte = (0, 0, 1);
Опечатку сделал в показе кода поторопился.
Все исправил

Последний раз редактировалось Aliens_wolfs; 26.10.2022 в 11:38.
Aliens_wolfs вне форума Ответить с цитированием
Старый 25.10.2022, 18:16   #5
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

По сути должно быть так

00000001 + SPS + 00000001 + PPS + 00000001 + NAL + видеокадр как я понимаю

SPS и PPS я получил из запроса DESCRIBE

Код:
SPS:= parsing(fHead, 'sprop-parameter-sets=', ',');
if SPS <> '' then
fRTPClient.SPS:= TIByteArray(Base64ToStr(SPS));
PPS:= parsing(fHead, SPS + ',', #13#10);
if PPS <> '' then
fRTPClient.PPS:= TIByteArray(Base64ToStr(PPS));
Поток сохраняется в файл а вот плеер не читает.

Последний раз редактировалось Aliens_wolfs; 25.10.2022 в 18:32.
Aliens_wolfs вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме 85 тыс рублей в месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Масштабирование видео веб камеры demiancz Мультимедиа в Delphi 0 20.09.2020 09:18
улучшить видео/фото лица преступника с камеры видео наблюдения, срочно! Фандорин Помощь студентам 1 28.01.2014 10:28
Захват видео с веб камеры maks5 Общие вопросы Delphi 0 08.10.2011 15:22
Захват видео с веб-камеры alexprey Мультимедиа в Delphi 8 09.07.2010 15:28
Поток видео и аудио с камеры HarPy Мультимедиа в Delphi 0 04.03.2009 09:05