GStreamer mpegtsmux + udpsink, очень медленный перезапуск в случае отключения отправителя - PullRequest
0 голосов
/ 06 апреля 2020

Я передаю последовательность файлов mp4 H264 без перекодирования с использованием mpegtsmux по UDP. Раньше у меня были проблемы с потоковой передачей необработанного RTP H264 через UDP, поэтому я перешел на MPEGTS, который мне гораздо лучше удался.

Единственная проблема, с которой я столкнулся сейчас, заключается в том, что при наличии пропуска на стороне отправителя, приемникам иногда требуется очень много времени, чтобы наверстать упущенное (зависание на предыдущем кадре). Иногда это даже 20 секунд, иногда это почти мгновенно. Мне нужно, чтобы это было как можно быстрее. Вот как это работало при потоковой передаче h264 через RTP, но, к сожалению, это вызвало другие проблемы.

Это мой конвейер отправки (использующий gst-launch-1.0):

gst-launch-1.0 filesrc location=file.mp4 ! qtdemux ! h264parse config-interval=-1 ! video/x-h264,stream-type=byte-stream ! mpegtsmux alignment=7 ! rtpmp2tpay ! udpsink host=238.0.0.1 port=1234

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

udpsrc uri=udp://238.0.0.1:1234 buffer-size=65535 caps=\"application/x-rtp, clock-rate=90000, pt=33\" timeout=1000000000 ! rtpmp2tdepay ! tsparse ! tsdemux ! queue ! decodebin ! autovideosink"

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

Принимающая сторона - приложение C ++, использующее gst_parse_launch, что дает мне некоторые возможности манипулирования потоком.

Я зарегистрировал все сообщения, поступающие из конвейера, и вижу, что GST_MESSAGE_ELEMENT сообщение "pat" приходит от mpegtsparse, как только отправляющая сторона восстанавливается, но есть огромная задержка, пока приемники не начнут играть Поток (несколько секунд), иногда я даже вижу, что GST_MESSAGE_TAG сообщений принимаются из потока, но он все еще не воспроизводится. И когда он, наконец, начинает играть - это происходит в один и тот же момент на всех принимающих сторонах, как если бы было какое-то событие, вызывающее его, но я ничего не видел в логах.

Я пытался играть с отправителем mpegtsmux параметров, таких как pmt-interval et c, но ничего не изменилось, это не ошибка отправителя, потому что, когда получатель запускается в среднем потоке, он начинает играть почти мгновенно.

Так что я начал искать способ перезапустите принимающую сторону, когда она теряет данные, я добавил параметр timeout в udpsrc, и я могу успешно видеть сообщения о тайм-ауте, когда отправитель прекращает потоковую передачу, затем я попытался несколько раз перезапустить приемник, когда первый pat получено от mpegtsparse, но без везения. Вот методы, которые я попробовал:

  1. Отмена очистки конвейера и установка его состояния в NULL, а затем воссоздание его. Это сработало, но привело к некоторым утечкам памяти, и ссылки не были очищены (при каждом перезапуске номера увеличивались, т.е. udpsink1, udpsink2 и т. Д. 1055 *.)

  2. Перевод конвейера в состояние NULL & PLAYING при получении первых данных после тайм-аута, но это привело к ошибке о том, что udpsr c не был связан

  3. Перевод конвейера в PAUSED по тайм-ауту и следующий GST_MESSAGE_STATE_CHANGED положить его на ИГРА. Это сработало, но не дало никаких эффектов, поскольку задержка такая же. Я вижу сообщение pat, полученное, и состояние установлено на PLAYING, но конвейер фактически меняет состояние через несколько секунд, а затем начинает играть правильно (поэтому есть что-то, что препятствует воспроизведению конвейера, что вызывает эту задержку). Я также пытался искать 0 до воспроизведения, но все равно.

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

Есть ли способ, которым я может заставить конвейер перезапустить или сбросить всю предыдущую информацию о потоке и начать заново с данных fre sh?

...