Преобразование H.264 с помощью FFmpeg (из потока RTP)

Окружающая среда:

У меня есть IP-камера, которая способна передавать свои данные через RTP в формате с кодировкой H.264. Этот необработанный поток записывается из сети Ethernet. С этими данными я должен работать.

Цель:

В конце концов, я хочу иметь файл *.mp4, который я могу воспроизводить с помощью обычных медиаплееров (, таких как VLC или Windows MP ).

Что я сделал до сих пор:

Я беру эти необработанные потоковые данные и анализирую их. Поскольку данные были переданы через RTP, мне нужно позаботиться о байтах NAL, SPS и PPS.

1. Запишите необработанный файл

Сначала я определяю тип каждого кадра, полученного через Ethernet. Для этого я анализирую первые два байта каждой полезной нагрузки RTP, чтобы получить 8 битов блока NAL, биты типа фрагмента и начальный, зарезервированный и конечный биты. В полезной нагрузке,они расположены вот так:

Byte 1: [          3 NAL Unit Bits          | 5 Fragment Type Bits]
Byte 2: [Start Bit | Reserved Bit | End Bit | 5 NAL Unit Bits]

Отсюда я могу определить:

  • Начало и конец a Видеокадр -> Стартовый бит и Конечный бит
  • Тип полезной нагрузки -> 5 бит типа фрагмента
  • Байт модуля NAL

Типы фрагментов, которые необходимы в моем случае, это:

Fragment Type  7 = SPS
Fragment Type  8 = PPS
Fragment Type 28 = Video Fragment

Байт NAL создается путем объединения битов блока NAL из байта 1 и 2.

Теперь в зависимости от типа фрагментации я делаю следующее:

СПС/ППС:

  1. Напишите префикс NAL(0x00 0x00 0x01)а затем данные SPS или PPS

Фрагментация с помощью стартового бита

  1. Запись префикса NAL
  2. Запись байта модуля NAL
  3. Записать оставшиеся необработанные данные

Фрагментация без стартового бита

  1. Запись необработанных данных

Это означает, что мой необработанный файл выглядит примерно так:

[NAL Prefix][SPS][NAL Prefix][PPS][NAL Prefix][NAL Unit Byte][Raw Video Data][Raw Video Data]....[NAL Prefix][NAL Unit Byte][Raw Video Data]...

Для каждого PPS и SPS, которые я нахожу в своих потоковых данных, я просто пишу префикс NAL (0x00 0x00 0x01 ), а затем сам SPS/PPS.

Теперь я не могу воспроизвести эти данные с помощью какого-то медиаплеера, что приводит меня к:

2. Конвертируйте файл

Поскольку я не хотел много работать с кодеками, я просто использовал существующее приложение -> FFmpeg. Это я звоню с такими параметрами:

ffmpeg.exe -f h264 -i <RawInputFile> -vcodec copy -r 25 <OutPutFilename>.mp4

-f h264:Это должно сообщить ffmpeg, что у меня есть закодированный поток h264

-vcodec copy:Цитата из справочной страницы:

Force video codec to codec. Use the "copy" special value to tell that the raw codec data must be copied as is.

-r 25:Устанавливает частоту кадров на 25 FPS.

Когда я вызываю ffmpeg с этими параметрами, я получаю файл.mp4, который я могу воспроизводить с помощью VLC и Windows MP, так что это действительно работает. Но теперь файл выглядит немного иначе, чем мой необработанный файл.

Это приводит меня к моему вопросу:

Что я на самом деле сделал?

Моя проблема не в том, что он не работает. Я просто хочу/нужно знать, что я на самом деле сделал с вызовом ffmpeg. У меня был необработанный файл H264, который я не мог воспроизвести. После использования FFmpeg я могу воспроизвести его.

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

  1. Заголовок :Файл FFmpeg имеет около 0x30 байт заголовка
  2. Нижний колонтитул :Файл FFmpeg также имеет нижний колонтитул
  3. Измененный префикс и 2 новых байта:

В то время как новый видеокадр из необработанного файла начинался как [NAL Prefix][NAL Unit Byte][Raw Video Data]в новом файле это выглядит так:

[0x00 0x00][2 "Random" Bytes][NAL Unit Byte][Raw Video Data].....[0x00 0x00[2 other "Random" Bytes][NAL Unit Byte][Raw Video Data]...

Я понимаю, что видеопотоку нужен формат контейнера (, поправьте меня, если я ошибаюсь, но я предполагаю, что за это отвечают новые верхний и нижний колонтитулы ). Но почему на самом деле это меняет несколько байтов в необработанных данных? Это не может быть какое-то декодирование, так как сам поток должен декодироваться плеером, а не ffmpeg.

Как видите, мне нужно не новое решение моей проблемы, а скорее объяснение (, чтобы я мог объяснить ее сам ). Что на самом деле делает ffmpeg? И почему он меняет некоторые байты в видеоданных?

17
задан Toby 18 July 2012 в 14:34
поделиться