Как я уже сказал в вопросе, было две (ну, фактически три) причины, по которым MPlayer не смог воспроизвести мой поток UDP.
Первая причина связана с пакетированием. NVEnc заполняет свои выходные буферы блоками данных, называемыми NALU, которые он разделяет на «начальные коды», в основном предназначенные для синхронизации битового потока. (Перейдите к szatmary's отличным SO answer, если вы хотите узнать больше о Приложении B - и его конкуренте AVCC).
Проблема заключается в том, что NVEnc иногда обеспечивает более одного такого NALU в одном выходном буфере. Хотя большинство NALU содержат закодированные видеофрагменты, иногда необходимо (и обязательно в начале потока) отправлять некоторые метаданные, такие как разрешение, частота кадров и т. Д. NVEnc помогает в этом, генерируя эти специальные NALU (более на этом ниже).
Как оказалось, программное обеспечение проигрывателя не поддерживает получение более одного NALU в одном пакете UDP. Это означает, что вам нужно запрограммировать простой цикл, который ищет стартовые коды (два или три «0» байта, за которым следует «1» байт), чтобы вырезать выходной буфер и отправлять каждый NALU в свой собственный UDP-пакет. (Обратите внимание, однако, что UDP-пакеты все равно должны включать эти стартовые коды.)
Еще одна проблема с пакетизацией заключается в том, что IP-пакеты обычно не могут превышать определенный размер. Опять же, SO answer дает ценное представление о том, что эти ограничения находятся в разных контекстах. Важным здесь является то, что в то время как вы не должны справиться с этим самостоятельно, вы должны сказать NVEnc на «срез» свой выход, установив следующие параметры при создании объекта датчика:
m_stEncodeConfig.encodeCodecConfig.h264Config.sliceMode = 1;
m_stEncodeConfig.encodeCodecConfig.h264Config.sliceModeData = 1500 - 28;
(с m_stEncodeConfig
являющийся структурой параметров, которая будет передана в NvEncInitializeEncoder()
, 1500 - MTU Ethernet-пакетов, а 28 - добавленные размеры заголовка IP4 и UDP-заголовка).
Вторая причина, по которой MPlayer не может воспроизводить мой поток, связана с природой потокового видео, а не с хранением в файле. Когда проигрыватель начнет воспроизведение файла H.264, он найдет необходимые NALU метаданных, содержащие разрешение, частоту кадров и т. Д., Сохранит эту информацию и, следовательно, никогда не понадобится. Принимая во внимание, что, когда его попросят воспроизвести поток, он пропустит начало этого потока и не сможет начать играть до тех пор, пока отправитель не отправит метаданные.
И вот в чем проблема: если не сказано иначе, NVEnc будет генерировать только метаданные NALU в самом начале сеанса кодирования. Здесь параметр конфигурации датчика, который должен быть установлен:
m_stEncodeConfig.encodeCodecConfig.h264Config.repeatSPSPPS = 1;
Это говорит NVEnc повторно генерировать SPS/PPS на время элементы уровня сетевой абстракции от времени (я думаю, что по умолчанию, это означает, что с каждым кадром IDR).
И вуаля! С устранением этих препятствий вы сможете оценить мощность генерации сжатых видеопотоков, в то же время практически не облагая налогом процессор.
EDIT: Я понимаю, что такой ультрасовременный поток UDP обескуражен, так как он не соответствует ни одному стандарту. Mplayer будет играть такой поток, но VLC, который в противном случае способен играть практически во все, не будет. Основная причина заключается в том, что в потоке данных нет ничего, что даже указывает тип отправляемого носителя (в данном случае - видео). В настоящее время я занимаюсь исследованиями, чтобы найти самый простой способ, который удовлетворит принятые стандарты.
Если вы идете по стандарту IETF, вы смотрите на rfc3550 (RTP/UDP) + rfc6184 (формат полезной нагрузки H.264). Вероятно, вы захотите реализовать режим пакетирования = 0 (единичный режим NAL), поскольку вы уже настроили кодировщик в соответствии с сетевым MTU, хотя потребуется пакетный режим = 1 (без чередования), если вы хотите агрегировать/фрагментировать NAL-модули по нескольким RTP-пакетам. – Ralf
Спасибо @ Ralf. RFC6184 остается вариантом, но я решил, что пока что потоковая передача UDP прекрасна, поскольку поток будет генерироваться и потребляться пользовательским программным обеспечением. – JPNotADragon
@JpNotADragon - можете ли вы пинговать (email) мне вашу контактную информацию @ gmail.com, я хотел отбросить некоторые вопросы от вас по этому вопросу (спасибо!) –