Как транслировать MPEG-TS по UDP?

Как транслировать MPEG-TS по UDP?

Я использую gstreamer для потоковой передачи через пользовательский AppSink, который имитирует UdpSink. Мы делаем это таким образом, чтобы можно было включить прослушивание других портов для некоторых метаданных. Плюс, стандартный UdpSink сломан. В любом случае, я успешно транслировал видео, но пакеты UDP, похоже, не были правильно упакованы. Мне интересно, не пропустил ли я какой-то шаг.

Вот мой конвейер отправки:

filesrc (mpeg TS file) ! displayQueue ! streamTee ! tsdemux ! decoder ! videosink

streamTee ! sendQueue ! udpSink (our custom one)

принимающая сторона:

UdpSrc (custom) ! queue ! mpegtsdemux ! queue ! (mpegdecode || h264decode) ! ... ! videosink

Стриминг работает. Но кажется очень хрупким. Иногда просто останавливается. Много артефактов.

Итак, я попробовал VLC. Я настроил его на потоковую передачу по UDP unicast. Он отлично работает. Я заметил, что VLC отправляет видео не так, как мой конвейер. Я использовал Wireshark для анализа пакетов:

Используемые протоколы: VLC: IP:UDP:MP2T(а также PETпакеты PMTи все остальное, что связано с TS)

Мой:IP:UDP:Data

Похоже, что используемый мной конвейер просто отправляет сырое видео по UDP без какой-либо коррекции ошибок. Что я упускаю? Используемые видео — это .mpgфайлы в кодировке h264 или mpeg.

Я использую gstreamer-java для программирования пользовательских элементов UdpSink и UdpSrc, но не могу использовать gstreamer в консоли для тестирования, так как стандартныйПлагин UdpSink сломанЯ попробовал простой конвейер в виртуальной машине Linux и получил такой же набор пакетов, как и VLC:

gst-launch-0.10 -v videotestsrc ! mpeg2enc ! mpegtsmux ! udpsink host=192.168.2.100 port=1234

решение1

Это просто мысль, я не очень хорошо знаком с gstreamer, поэтому не знаю, как он filesrcработает, но предполагаю, что он не понимает MPEG-TS. MPEG-TS требует, чтобы пакеты приходили на определенных границах (обычно 188 байт). Я бы попробовал поместить ваш tee после demux, а затем добавить mpegtsmux перед вашим udpSink.

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

решение2

Вы близки. Плагин filesrc ничего не знает о содержимом файла, который он считывает. GStreamer должен знать, что данные являются транспортным потоком, чтобы правильно транслировать их. Хотя демультиплексирование и мультиплексирование потока выполняют эту работу, есть способ получше:

Source: gst-launch -v filesrc location=myvideo.ts ! tsparse set-timestamps=true ! udpsink host=192.168.2.100 port=1234

Dest:   gst-launch udpsrc caps="video/mpegts, systemstream=(boolean)true, packetsize=(int)188" port=1234 ! tsdemux ! (video decoder) ! autovideosink

Плагин tsparse считывает поток и анализирует информацию о потоке. Он также идентифицирует свой вывод как транспортный поток. Этого самого по себе может быть достаточно для ваших потребностей в потоковой передаче, поскольку позволяет udpsink знать, что данные находятся в пакетах по 188 байт. На принимающей стороне tsdemux необходим для анализа фактического видеопотока. Элемент "set-timestamps" сообщает tsparse о необходимости устанавливать временные метки на исходящих пакетах, чтобы udpsink отправлял каждый кадр вовремя, а не так быстро, как может.

Вы также можете использовать rtpmp2tpay и rptmp2depay, которые пакетируют данные для отправки udpsink. Он также устанавливает имя кодировки на MP2T. Вы можете попробовать оба способа.

Source: gst-launch -v filesrc location=myvideo.ts ! tsparse set-timestamps=true ! rtpmp2tpay ! udpsink host=192.168.2.100 port=1234

Dest:   gst-launch udpsrc caps="application/x-rtp, systemstream=(boolean)true, packetsize=(int)188" port=1234 ! rtpmp2tdepay ! tsdemux ! (video decoder) ! autovideosink

Связанный контент