Разбор MPEG4-фреймов из rtp-пакетов - PullRequest
3 голосов
/ 03 ноября 2010

Я пытаюсь проанализировать различные кадры mpeg4 из потока rtp, поступающего с осевой камеры, и передать пакеты в библиотеку ffmpeg с помощью функции avcodec_decode_video.Вот шаги, которые я делаю 1. Поток rtsp инициализируется 2. Поток rtp начинает поступать 3. Первый пакет, который я получаю, начинается с 000001b0 ... и данные конфигурации следуют, а после этого кадра начинается с 000001b6 .. Вторая полезная нагрузка rtpбудет другим, пока я не получу пакет rtp, где установлен бит маркера.после чего я снова получаю пакет, начинающийся с 000001b6 и продолжающий около 5-10 пакетов rtp .. этот шаблон повторяет

, что я делаю, если я обнаружив 000001b0 / b6 - я соберу все пакеты, пришедшие послеи передать больший буфер в функцию avcodec_decode_video libavcodec, после правильной инициализации контекста декодера.

Но я получаю дрянное изображение здесь, с самой верхней частью, горизонтальной полосой - кристально чистое изображение и остальныедерьмовыйЯ не уверен, почему он ведет себя так.Пожалуйста, помогите мне

Данные, которые я получаю в rtp-пакете, являются динамическими-96.

Обратите внимание: когда я передаю фреймы и p-кадры, которые включены в пропреитарный протокол некоторыхffmpeg способен анализировать и давать очень хорошие изображения.

Любая помощь приветствуется

1 Ответ

9 голосов
/ 26 января 2011

Попробуйте поиграть с настройками потока MPEG4 на IP-камере AXIS.Обратите внимание на видео и изображения / расширенную часть, где вы должны установить это:

  1. Тип видео объекта: SIMPLE
  2. [x] ISMA-совместимый
  3. GOV Структура: IP

Также попробуйте изменить настройку «Приоритет» или «Оптимизировать видеопоток для» (у вас должна быть частота кадров, качество изображения, пропускная способность, нет).

Если ничего из этогоработает, тогда читайте дальше ...

Я надеюсь, что вы понимаете, как поток MPEG4 передается по RTP.Вкратце (если вы не уверены, как):

  1. «Фрейм конфигурации» (запуск последовательности визуальных объектов) начинается с целого числа 000001B0 (шестнадцатеричное).Он содержит данные, необходимые для декодирования видео.Вам нужно отправить его в декодер только в первый раз, когда вы пытаетесь декодировать поток, и он используется для декодирования всех VOP, следующих за ним.Обратите внимание, что AXIS отправляет этот пакет в SDP (ответ на DESCRIBE в RTSP), например: a=fmtp:96 profile-level-id=245; config=000001B0F5000001B5891300000100000001200086C40FA28A021E0A21.Так что, если поток никогда не меняется, и вы получаете это в SDP, вам не нужно передавать VOS декодеру ... но если вы это сделаете, это не повредит.

  2. ВидеоПлоскость объекта (I-VOP, P-VOP, B-VOP) начинается с целого числа 000001B6.Если вы установите длину GOV равной 10, а структуру потока - «IP», вы получите 1 I-кадр (I-VOP) и 9 P-VOP, но у всех будет начальный код 000001B6.Хитрость для различения между ними заключается в проверке следующих двух битов в пятом байте.Проверьте таблицу, чтобы определить тип VOP, который вы получаете:

    VOP_CODING_TYPE (binary)  Coding method
                          00  intra-coded (I)
                          01  predictive-coded (P)
                          10  bidirectionally-predictive-coded (B)
                          11  sprite (S)
    

Теперь, чтобы декодировать видео, вам необходимо отправить VOS в декодер, после чего сразу же следует I-VOP.Но, во-первых, ваш способ извлечения этих кадров из потока RTP неудобен ... Если I-VOP имеет размер 10000B, а сетевой MTU равен 1400B, вы не можете отправить его как есть и не иметь перегрузки сети.Таким образом, камера AXIS разделяет I-VOP и все другие БОЛЬШИЕ кадры на ФРАГМЕНТЫ, которые она отправляет по RTP в виде пакетов RTP, размер которых не превышает MTU.Основная идея заключается в следующем (пример):

  1. Разделить 10000B на фрагменты размером MTU (для 1400B MTU вы получите примерно 8x [1400B] и 1x [200B] фрагментов)
  2. Отправьте каждый из нихс RTP MARKER BIT, установленным на 0
  3. Отправить последний фрагмент с RTP MARKER BIT, установленным в 1, чтобы отметить последний фрагмент

Теперь, когда вы получаете это, вы как бы получаете идею, но вам нужно восстановить исходный 10KB FRAME, чтобы декодер смог его декодировать.Как вы делаете, вы только декодируете первые байты MTU гораздо большего кадра, а все остальные фрагменты, которые вы отправляете в декодер, отбрасываются.Вот почему вы можете получить дерьмовую картинку ...

Чтобы восстановить исходный кадр:

  1. Получить пакет с начальным кодом 000001B6 или 000001B0 и установленным битом RTP MARKERв 0. Если MARKER установлен в 1, то это весь кадр, и вы можете декодировать его как есть!Если оно равно 0, следуют другие части ...
  2. Поместите первый фрагмент все последующие фрагменты в буфер, пока не получите один фрагмент с MARKER BIT, установленным в 1. Когда вы получите последний фрагмент, поместите егов буфер.
  3. Ваш буфер теперь содержит один целый кадр, который вы можете отправить в декодер!

Там, надеюсь, я помог ...:)

...