Почему использование H264 в конвейерах отправителя / получателя приводит к ОГРОМНОЙ задержке? - PullRequest
1 голос
/ 24 мая 2010

Когда я пытаюсь создать конвейер, который использует H264 для передачи видео, я получаю огромную задержку, до 10 секунд, чтобы передать видео с моей машины на ... мою машину!Это неприемлемо для моих целей, и я хотел бы проконсультироваться со StackOverflow о том, что я (или кто-то еще) делаю неправильно.

Я взял конвейеры со страницы документации gstrtpbin и немного изменил их для использования Speex:

Это конвейер отправителя: #! / Bin / sh

gst-launch -v gstrtpbin name=rtpbin \
        v4l2src ! ffmpegcolorspace ! ffenc_h263 ! rtph263ppay ! rtpbin.send_rtp_sink_0 \
                  rtpbin.send_rtp_src_0 ! udpsink host=127.0.0.1 port=5000                            \
                  rtpbin.send_rtcp_src_0 ! udpsink host=127.0.0.1 port=5001 sync=false async=false    \
                  udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0                           \
        pulsesrc ! audioconvert ! audioresample  ! audio/x-raw-int,rate=16000 !    \
                  speexenc bitrate=16000 ! rtpspeexpay ! rtpbin.send_rtp_sink_1                   \
                  rtpbin.send_rtp_src_1 ! udpsink host=127.0.0.1 port=5002                            \
                  rtpbin.send_rtcp_src_1 ! udpsink host=127.0.0.1 port=5003 sync=false async=false    \
                  udpsrc port=5007 ! rtpbin.recv_rtcp_sink_1

Конвейер получателя:

! / Bin / sh

gst-launch -v\
    gstrtpbin name=rtpbin                                          \
    udpsrc caps="application/x-rtp,media=(string)video, clock-rate=(int)90000, encoding-name=(string)H263-1998" \
            port=5000 ! rtpbin.recv_rtp_sink_0                                \
        rtpbin. ! rtph263pdepay ! ffdec_h263 ! xvimagesink                    \
     udpsrc port=5001 ! rtpbin.recv_rtcp_sink_0                               \
     rtpbin.send_rtcp_src_0 ! udpsink port=5005 sync=false async=false        \
    udpsrc caps="application/x-rtp,media=(string)audio, clock-rate=(int)16000, encoding-name=(string)SPEEX, encoding-params=(string)1, payload=(int)110" \
            port=5002 ! rtpbin.recv_rtp_sink_1                                \
        rtpbin. ! rtpspeexdepay ! speexdec ! audioresample ! audioconvert ! alsasink \
     udpsrc port=5003 ! rtpbin.recv_rtcp_sink_1                               \
     rtpbin.send_rtcp_src_1 ! udpsink host=127.0.0.1 port=5007 sync=false async=false

Эти конвейеры, комбинацияH263 и Speex, работают достаточно хорошо.Я щелкаю пальцами возле камеры и микрофона, а затем одновременно вижу движение и слышу звук.

Затем я изменил конвейеры, чтобы использовать H264 вдоль пути видео.

Отправитель становится: #! / bin / sh

gst-launch -v gstrtpbin name=rtpbin \
        v4l2src ! ffmpegcolorspace ! x264enc bitrate=300 ! rtph264pay ! rtpbin.send_rtp_sink_0 \
                  rtpbin.send_rtp_src_0 ! udpsink host=127.0.0.1 port=5000                            \
                  rtpbin.send_rtcp_src_0 ! udpsink host=127.0.0.1 port=5001 sync=false async=false    \
                  udpsrc port=5005 ! rtpbin.recv_rtcp_sink_0                           \
        pulsesrc ! audioconvert ! audioresample  ! audio/x-raw-int,rate=16000 !    \
                  speexenc bitrate=16000 ! rtpspeexpay ! rtpbin.send_rtp_sink_1                   \
                  rtpbin.send_rtp_src_1 ! udpsink host=127.0.0.1 port=5002                            \
                  rtpbin.send_rtcp_src_1 ! udpsink host=127.0.0.1 port=5003 sync=false async=false    \
                  udpsrc port=5007 ! rtpbin.recv_rtcp_sink_1

И получатель становится: #! / bin / sh

gst-launch -v\
    gstrtpbin name=rtpbin                                          \
    udpsrc caps="application/x-rtp,media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264" \
            port=5000 ! rtpbin.recv_rtp_sink_0                                \
        rtpbin. ! rtph264depay ! ffdec_h264 ! xvimagesink                    \
     udpsrc port=5001 ! rtpbin.recv_rtcp_sink_0                               \
     rtpbin.send_rtcp_src_0 ! udpsink port=5005 sync=false async=false        \
    udpsrc caps="application/x-rtp,media=(string)audio, clock-rate=(int)16000, encoding-name=(string)SPEEX, encoding-params=(string)1, payload=(int)110" \
            port=5002 ! rtpbin.recv_rtp_sink_1                                \
        rtpbin. ! rtpspeexdepay ! speexdec ! audioresample ! audioconvert ! alsasink \
     udpsrc port=5003 ! rtpbin.recv_rtcp_sink_1                               \
     rtpbin.send_rtcp_src_1 ! udpsink host=127.0.0.1 port=5007 sync=false async=false

Это то, что происходит в Ubuntu 10.04.Я не заметил таких огромных задержек в Ubuntu 9.04 - задержки там были в диапазоне 2-3 секунды, AFAIR.

Ответы [ 3 ]

2 голосов
/ 30 августа 2010

С некоторой помощью из "Sharktooth" в # x264 на Freenode я обнаружил, что git-версия gst-plugins-ugly поддерживает предустановку "нулевой задержки".

Я настроил ваш пример для установки "x264enc pass = qual quantizer = 20 tune = zerolatency", и задержка, похоже, останется на уровне 0,7-0,9 секунды.Я не могу понять, как получить его ниже.

1 голос
/ 24 января 2012

x264 по умолчанию буферизует ввод, чтобы иметь больше данных для работы.Увеличение задержки в Ubuntu 10.04, скорее всего, связано с тем, что оно застряло в старой версии x264, до введения --mbtree и --rc-lookahead.

В На этой странице Mewiki вы можете увидеть, как рассчитать задержку, количество кадров и что вы должны сначала отключить, чтобы уменьшить задержку:

Уменьшение задержки x264 возможно, но снижает качество.Если вы не хотите задержки, установите --tune zerolatency.Если вы можете справиться с небольшой задержкой (т. Е. Менее 1 секунды), то стоит настроить параметры, чтобы разрешить это.Вот ряд шагов, которые вы можете выполнить, чтобы постепенно уменьшить задержку.Остановитесь, когда ваша задержка будет достаточно низкой:

  1. Начните с значений по умолчанию
  2. Kill sync-lookahead
  3. Сбросьте rc-lookahead не менее чем ~ 10
  4. Сбросить потоки до более низкого значения (например, 6 вместо 12)
  5. Использовать нарезанные потоки
  6. Отключить rc-lookahead
  7. Отключить b-кадры
  8. Теперь вы на --tune zerolatency

Итак, сначала вы должны попытаться добавить в вашу командную строку что-то вроде

sync-lookahead = 0, rc-lookahead = 10 (я не уверен в форматировании командной строки в вашем приложении)

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

Используйте tune = zerolatency согласно совету Sharktooth, если это все ещене достаточно.

Еще по теме: http://x264dev.multimedia.cx/archives/249

1 голос
/ 24 мая 2010

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

...