Как извлечь SPS и PPS из потока RTMP (закодированный avc1)? - PullRequest
0 голосов
/ 11 декабря 2018

Я работаю над расширением Node Media Server , чтобы сохранить входящие потоки на диск в формате MP4.Для этого преобразования в MP4 я в значительной степени опираюсь на спецификацию Apple QuickTime Movie , в спецификации ISO / IEC 14496-14 (которую я обнаружил в репозитории Rust-MP4 GitHub бесплатно) и Исходный код HLS.js

В данный момент я тестирую одно видео.Как только это сработает, я начну экспериментировать с другими видео.Для моего случая использования мне нужно только поддерживать видео H.264 и аудио AAC.

В настоящее время, когда установлено соединение RTMP, первые 3 пакета, которые я получаю, последовательно:

  • 1AMF metadata пакет (RTMP cid = 6), содержащий такую ​​информацию, как ширина видео, высота видео, битрейт, частота дискретизации аудио и т. Д.
  • 1 audio пакет (RMTP cid = 4), содержащий 7 байтов данных.Я предполагаю, что это пакет конфигурации AAC
  • 1 video (RTMP cid = 5), содержащий 46 байтов данных.Я предполагаю, что это пакет конфигурации AVC

При записи атома MP4 moov, есть два места, где мне нужно использовать дополнительную информацию, которая не находится в метаданных AMF (и предположительно расположена в этих двухпакеты конфигурации):

  • В атоме esds, Источник HLS.js добавляет данные "config".Я предполагаю, что я просто добавляю всю 7-байтовую полезную нагрузку из пакета аудиоконфигурации здесь
  • В avcC атоме, Источник HLS.js добавляет "sps" и "pps"данные.Это корень моей проблемы

Что касается анализа этих 46 байтов, я нашел код в Узел Медиа-сервер и HLS.js , который, кажется,разбирать те же данные.Разница между этими двумя частями кода заключается в том, что Node Media Server ожидает дополнительные 13 байтов данных в начале пакета.Кажется, что пакет, который я получаю, содержит эти дополнительные 13 байтов, поэтому я просто следую их примеру в извлечении width, height, profile, compat и level информации.В частности, 46 байтов:

[0x17, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0xc0, 0x1f, 0xff, 0xe1, 0x00, 0x19, 0x67, 0x42, 0xc0, 0x1f, 0xa6, 0x11, 0x02, 0x80, 0xbf, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xc2, 0x3c, 0x60, 0xc8, 0x46, 0x01, 0x00, 0x05, 0x68, 0xc8, 0x42, 0x32, 0xc8]

Разбить это на байты, которые я могу легко разобрать (до использования экспоненциального кодирования Голомба):

[
    0x17, // "frame type", specifies H.264 or HVEC
    0x00, 0x00, 0x00, 0x00, 0x01, // ignored. Reserved?
    0x42, // profile
    0xc0, // compat
    0x1f, // level
    0xff, // "info.nalu" (per Node Media Server source)
    0xe1, // "info.nb_sps" (per Node Media Server source)
    0x00, 0x19, // "nal size"
    // Above here are the bits exclusively seen by Node Media Server (specific to RTMP?)
    // Below here are the bits passed to HLS.js as "unit.data" (common to all AVC1 streams?):
    0x67, // "nal type"
    0x42, // profile (again?)
    0xc0, // compat (again?)
    0x1f, // level (again?)
    // Below here, data is not necessarily byte-aligned as Exponential Golomb encoding is used
    // ...
]

Теперь проблема, с которой я сталкиваюсь, заключается в том, что при создании атома moov (и атома avcC, в частности) мне нужно знать как sps, так и ppsбайт. Из источника HLS.js похоже, что sps может быть просто этим видео-конфигурационным пакетом минус первые 13 байтов.Однако, как мне найти pps?Является ли pps последними байтами этого пакета, и я должен его где-то разделить?Будет ли это доставлено в другом пакете?Если нужно ожидать два видеопакета, есть ли какой-то способ, которым я должен их дифференцировать, чтобы я знал, какой из них sps, а какой pps?

Если я смогу выяснить этот последний маленький кусочек,тогда я должен полностью закончить написание пакета moov (после чего мне просто нужно выяснить правильный формат для пакета mdat и у меня должен быть рабочий код)

Обновление: Для записи, я только что проверил четвертый пакет, который был доставлен, чтобы увидеть, может ли он содержать pps данных.После повторного подключения к потоку ~ 20 раз четвертый пакет был последовательно video пакетом (RTMP cid = 5), но размер пакета варьировался от 16000 байтов до 21000 байтов.Я подозреваю, что это допустимые видеоданные.

Второе обновление: Я только что проверил, какое смещение было в пакете конфигурации видео, когда я закончил анализ SPS, и я был на байте 23 (0x84).Поэтому вполне вероятно, что PPS на самом деле равен в конце этого байтового массива, но я не уверен, сколько байтов являются разделителями / заголовками (тип NAL, длина NAL и т. Д.) И сколько байтовфактический PPS.

...