Какие настройки конвейера gstreamer необходимы для обработки потока rtp chrome?

Я транслирую потоковую передачу с веб-камеры из браузера с помощью webrtc на сервер, на котором работает следующая настройка:

  1. используя firefox и модифицированный html echo-test со шлюза janus, я отправляю поток веб-камеры на сервер janus
  2. сервер janus работает с использованием модифицированного подключаемого модуля echotest, который просто выполняет udp-потоки заданного char * buf в janus_videorecv_incoming_rtp () на порт 5060 только для целей тестирования (примерно так же)
  3. следующая командная строка gstreamer фактически открывает окно, показывающее потоковое видео

GST_DEBUG=p*:5 gst-launch-1.0 -vvv udpsrc caps="application/x-rtp,media=video,clock-rate=90000,payload=96" port=5060 ! rtpvp8depay ! vp8dec ! autovideosink

в модифицированном javascript эхо-теста я удаляю несколько строк из ответа sdp, который браузер получит следующим образом:

//jsep.sdp = jsep.sdp.replace(/a=rtcp-mux[^\s]*\s*/g, '');
jsep.sdp = jsep.sdp.replace(/a=rtpmap[^\s]*\s*red[^\s]*\s*/g, '');
jsep.sdp = jsep.sdp.replace(/a=rtpmap[^\s]*\s*ulpfec[^\s]*\s*/g, '');
jsep.sdp = jsep.sdp.replace(/a=fmtp[^\r\n]*\r*\n*/g, '');
jsep.sdp = jsep.sdp.replace(/a=rtcp-fb[^\s]*\s*goog-remb[^\s]*\s*/g, '');

ниже можно найти измененный ответ firefox sdp, который работает для указанной выше команды gstreamer, но таким же образом модифицированный ответ sdp не работает в случае хрома, я думал о настройке полезной нагрузки в крышках gstreamer, но 32,33,96,100,120 не сработало

Итак, вопрос: что нужно в случае хрома, чтобы это работало?

Я также попытался добавить запросы fir / pli, например, в videoroom.c от janus, как предложено здесь

вывод gstreamer в случае chrome is, где команда просто ждет в последней строке:

0:00:00.025791492 22279      0x1954b90 DEBUG               pipeline gstpipeline.c:219:gst_pipeline_init:<GstPipeline@0x1962180> set bus <bus2> on pipeline
Setting pipeline to PAUSED ...
0:00:00.029798090 22279      0x1954b90 DEBUG               pipeline gstpipeline.c:282:reset_start_time:<pipeline0> reset start_time to 0
Pipeline is live and does not need PREROLL ...
/GstPipeline:pipeline0/GstUDPSrc:udpsrc0.GstPad:src: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, payload=(int)96, encoding-name=(string)VP8-DRAFT-IETF-01
Setting pipeline to PLAYING ...
0:00:00.030045034 22279      0x1954b90 DEBUG               pipeline gstpipeline.c:377:gst_pipeline_change_state:<pipeline0> selecting clock and base_time
0:00:00.030053523 22279      0x1954b90 DEBUG               pipeline gstpipeline.c:398:gst_pipeline_change_state:<pipeline0> Need to update start_time
0:00:00.030058181 22279      0x1954b90 DEBUG               pipeline gstpipeline.c:403:gst_pipeline_change_state:<pipeline0> Need to update clock.
/GstPipeline:pipeline0/GstRtpVP8Depay:rtpvp8depay0.GstPad:src: caps = video/x-vp8, framerate=(fraction)0/1
/GstPipeline:pipeline0/GstVP8Dec:vp8dec0.GstPad:sink: caps = video/x-vp8, framerate=(fraction)0/1
0:00:00.030111345 22279      0x1954b90 DEBUG               pipeline gstpipeline.c:443:gst_pipeline_change_state:<pipeline0> start_time=0:00:00.000000000, now=33:52:04.529345754, base_time 33:52:04.529345754
/GstPipeline:pipeline0/GstRtpVP8Depay:rtpvp8depay0.GstPad:sink: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, payload=(int)96, encoding-name=(string)VP8-DRAFT-IETF-01
New clock: GstSystemClock

хром ответ:

v=0
o=- 8913399741269897639 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS janus
m=audio 1 RTP/SAVPF 111 103 104 0 8 106 105 13 126
a=mid:audio
c=IN IP4 192.168.0.1
a=sendrecv
a=rtcp-mux
a=ice-ufrag:l0n9
a=ice-pwd:r1elT1Ew8lP3TNlzwAHUsC
a=ice-options:trickle
a=fingerprint:sha-256 C5:5F:DA:7D:84:47:B1:BF:6B:55:16:62:48:31:3E:D3:F1:7B:25:89:92:4A:4B:4D:4D:D9:D5:AF:EA:D8:15:44
a=setup:active
a=connection:new
a=rtpmap:111 opus/48000/2
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:126 telephone-event/8000
a=maxptime:60
a=ssrc:600390024 cname:janusaudio
a=ssrc:600390024 msid:janus janusa0
a=ssrc:600390024 mslabel:janus
a=ssrc:600390024 label:janusa0
a=candidate:1 1 udp 2013266431 192.168.0.1 45728 typ host
m=video 1 RTP/SAVPF 100 116 117 96
a=mid:video
c=IN IP4 192.168.0.1
a=sendrecv
a=rtcp-mux
a=ice-ufrag:l0n9
a=ice-pwd:r1elT1Ew8lP3TNlzwAHUsC
a=ice-options:trickle
a=fingerprint:sha-256 C5:5F:DA:7D:84:47:B1:BF:6B:55:16:62:48:31:3E:D3:F1:7B:25:89:92:4A:4B:4D:4D:D9:D5:AF:EA:D8:15:44
a=setup:active
a=connection:new
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtpmap:96 rtx/90000
a=ssrc-group:FID 3188003624 3419969288
a=ssrc:677441062 cname:janusvideo
a=ssrc:677441062 msid:janus janusv0
a=ssrc:677441062 mslabel:janus
a=ssrc:677441062 label:janusv0
a=candidate:1 1 udp 2013266431 192.168.0.1 45728 typ host
m=application 0 DTLS/SCTP 0
c=IN IP4 192.168.0.1

Ответ Firefox:

v=0
o=Mozilla-SIPUA-32.0.3 11426 0 IN IP4 127.0.0.1
s=SIP Call
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS janus
m=audio 1 RTP/SAVPF 109 0 8 101
a=mid:audio
c=IN IP4 192.168.0.1
a=sendrecv
a=rtcp-mux
a=ice-ufrag:BRBU
a=ice-pwd:2W4fGNr//HejhiC4UIabW6
a=ice-options:trickle
a=fingerprint:sha-256 C5:5F:DA:7D:84:47:B1:BF:6B:55:16:62:48:31:3E:D3:F1:7B:25:89:92:4A:4B:4D:4D:D9:D5:AF:EA:D8:15:44
a=setup:active
a=connection:new
a=rtpmap:109 opus/48000/2
a=ptime:20
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=ssrc:3725983979 cname:janusaudio
a=ssrc:3725983979 msid:janus janusa0
a=ssrc:3725983979 mslabel:janus
a=ssrc:3725983979 label:janusa0
a=candidate:1 1 udp 2013266431 192.168.0.1 56574 typ host
m=video 1 RTP/SAVPF 120
a=mid:video
c=IN IP4 192.168.0.1
a=sendrecv
a=rtcp-mux
a=ice-ufrag:jZ5b
a=ice-pwd:dQQej9UIpPl5zuXBQNg3Nz
a=ice-options:trickle
a=fingerprint:sha-256 C5:5F:DA:7D:84:47:B1:BF:6B:55:16:62:48:31:3E:D3:F1:7B:25:89:92:4A:4B:4D:4D:D9:D5:AF:EA:D8:15:44
a=setup:active
a=connection:new
a=rtpmap:120 VP8/90000
a=rtcp-fb:120 nack
a=rtcp-fb:120 nack pli
a=rtcp-fb:120 ccm fir
a=ssrc:1425382999 cname:janusvideo
a=ssrc:1425382999 msid:janus janusv0
a=ssrc:1425382999 mslabel:janus
a=ssrc:1425382999 label:janusv0
a=candidate:2 1 udp 2013266431 192.168.0.1 39063 typ host
m=application 0 DTLS/SCTP 0
c=IN IP4 192.168.0.1

ОБНОВЛЕНИЕ: я изменил sdp-answer, так что и firefox, и chrome почти одинаковы, за исключением строк «o =» и «s =», которые я просто скопировал из sdp-offer v=0 o=- 7589782217972865757 2 IN IP4 127.0.0.1 s=- t=0 0 a=group:BUNDLE audio video a=msid-semantic: WMS janus m=audio 1 RTP/SAVPF 111 a=mid:audio c=IN IP4 192.168.0.1 a=sendrecv a=rtcp-mux a=ice-ufrag:g0kZ a=ice-pwd:d5oEody1jqIzDYUdf1fg6t a=ice-options:trickle a=fingerprint:sha-256 C5:5F:DA:7D:84:47:B1:BF:6B:55:16:62:48:31:3E:D3:F1:7B:25:89:92:4A:4B:4D:4D:D9:D5:AF:EA:D8:15:44 a=setup:active a=connection:new a=rtpmap:111 opus/48000/2 a=ssrc:1038736511 cname:janusaudio a=ssrc:1038736511 msid:janus janusa0 a=ssrc:1038736511 mslabel:janus a=ssrc:1038736511 label:janusa0 a=candidate:1 1 udp 2013266431 192.168.0.1 51232 typ host m=video 1 RTP/SAVPF 100 a=mid:video c=IN IP4 192.168.0.1 a=sendrecv a=rtcp-mux a=ice-ufrag:g0kZ a=ice-pwd:d5oEody1jqIzDYUdf1fg6t a=ice-options:trickle a=fingerprint:sha-256 C5:5F:DA:7D:84:47:B1:BF:6B:55:16:62:48:31:3E:D3:F1:7B:25:89:92:4A:4B:4D:4D:D9:D5:AF:EA:D8:15:44 a=setup:active a=connection:new a=rtpmap:100 VP8/90000 a=rtcp-fb:100 ccm fir a=rtcp-fb:100 nack a=rtcp-fb:100 nack pli a=rtcp-fb:100 goog-remb a=ssrc:2455978689 cname:janusvideo a=ssrc:2455978689 msid:janus janusv0 a=ssrc:2455978689 mslabel:janus a=ssrc:2455978689 label:janusv0 a=candidate:1 1 udp 2013266431 192.168.0.1 51232 typ host m=application 0 DTLS/SCTP 0 c=IN IP4 192.168.0.1


person John Doe    schedule 26.09.2014    source источник
comment
В chrome удаляются не все сопоставления. Почему вы удаляете a=rtcp-fb:100 goog-remb? Исправьте полезные данные rtp, отображаемые в строке мультимедиа видео, и удалите ненужное rtx сопоставление rtp. Это должно продвинуть вас дальше по дороге. Вы уверены, что Chrome даже присылает вам какие-нибудь медиафайлы? Я предполагаю, что он волнуется от ответа и ничего не отправляет. Если он отправляет мультимедиа, вы можете разбить заголовок rtp и увидеть полезную нагрузку, чтобы убедиться, что это VP8   -  person Benjamin Trent    schedule 26.09.2014
comment
Я действительно удалил goog-remb, потому что я пытался удалять строки за строкой, чтобы, возможно, что-то работало. на самом деле хром отправляет данные, и мой плагин janus также правильно пересылает, как я могу видеть через wirehark. Что касается правильной полезной нагрузки rtp в строке видео носителя, вы имеете в виду, что я должен установить m = video 1 RTP / SAVPF 120, как в firefox? что именно вы имеете в виду, говоря об разбиении заголовка rtp? как бы ты это сделал? Спасибо за ваше время   -  person John Doe    schedule 26.09.2014
comment
строка должна быть m=video 1 RTP/SAVPF 100, чтобы указывать только одно отображение (для VP8). Тогда должно существовать только отображение VP8. Некоторые указатели sdp webrtc. Вы можете преобразовать буфер как пакет rtp, а затем получить доступ к типу. rtp_header* packetheader = (rtp_header*) buf; packetheader->type; //payload   -  person Benjamin Trent    schedule 26.09.2014
comment
строка m теперь исправлена, я также скопировал sdp_template из плагина janus_videoroom.c с несколькими настройками. теперь у меня есть одинаковый ответ sdp для firefox и chrome. firefox работает с вышеуказанным gstreamer, хром - нет. Packageheader- ›type имеет значение 100 или 111 - как я понимаю, как и ожидалось для видео или аудио. также удалено отображение rtx   -  person John Doe    schedule 26.09.2014
comment
Что ж, если вы получаете видеопоток с полезной нагрузкой 100 для видео, это нормально VP8. Я предполагаю, что проблема с ключевым кадром с хромом происходит. Также попробуйте изменить получающий конвейер Gstreamer на udpsrc port=5060 caps="application/x-rtp, media=video, clock-rate=90000, encoding-name=VP8-DRAFT-IETF-01, payload=100" ! rtpvp8depay ! vp8dec ! ffmpegcolorspace ! autovideosink   -  person Benjamin Trent    schedule 26.09.2014
comment
Я заметил, что, похоже, существует огромная разница между gst-launch-0.10 и gst-launch-1.0 - если я использую вашу строку без ffmpegcolorspace в 0.10, все работает с FF, в 1.0 я вижу только первый проанализированный кадр, но без потока. используя 1.0 с хромом, ничего не происходит, как упоминалось в моем исходном вопросе. используя 0.10 с хромом, я получаю сообщение об ошибке corrupt frame   -  person John Doe    schedule 27.09.2014
comment
/GstPipeline:pipeline0/GstVP8Dec:vp8dec0.GstPad:sink: caps = video / x-vp8, framerate = (дробь) 0/1 /GstPipeline:pipeline0/GstVP8Dec:vp8dec0.GstPad:src: x-raws- video yuv, format = (fourcc) I420, width = (int) 1280, height = (int) 720, частота кадров = (дробь) 0/1, соотношение сторон пикселя = (дробь) 1/1, чересстрочное = (логическое) false ERROR: from element /GstPipeline:pipeline0/GstVP8Dec:vp8dec0: Не удалось декодировать кадр Дополнительная информация отладки: gstvp8dec.c (469): gst_vp8_dec_handle_frame (): / GstPipeline: pipeline0 / GstVP8Dec: vp8dec0: поврежденный кадр   -  person John Doe    schedule 27.09.2014
comment
Давайте продолжим это обсуждение в чате.   -  person John Doe    schedule 27.09.2014


Ответы (3)


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

Вот мои советы по изменениям вашего плагина

  1. убедитесь, что ваш конвейер gstreamer настроен на получение ДО того, как вы запросите ключевой кадр из Chrome
  2. Запросите ключевой кадр, когда носитель webrtc будет готов (подробности см. В функции janus_bidirectional_streaming_setup_media)
  3. Не используйте элемент rtpbin gstreamer для обработки входящего потока. По какой-то причине способ установки ограничений на самом деле не работает, и конвейер выйдет из строя. Если вы все же получаете пакеты rtp и можете отправлять их в порт, то следующий конвейер работает без проблем: gst-launch-1.0 udpsrc port=<your listener> caps="application/x-rtp, clock-rate=90000, payload=100" ! rtpvp8depay ! vp8dec ! autovideosink sync=false async=false

Теоретически, прямая отправка буферов в appsrc внутри плагина также должна работать.

person Benjamin Trent    schedule 29.09.2014

WebRTC имеет обязательное шифрование с помощью DTLS-SRTP (Chrome по-прежнему поддерживает нестандартный и явный ключ MUST-NOT-IMPLMENT SDES).

Вы не можете просто передать поток RTP в webrtc; это должен быть поток DTLS-SRTP с ключом начального соединения DTLS.

Люди подключили node.js к браузерам webrtc, поэтому я полагаю, что все необходимое оборудование уже есть.

person jesup    schedule 27.09.2014
comment
Я не уверен, что правильно вас понял. Вы имеете в виду, что не может просто передать поток rtp в webrtc ситуацию, когда я отправляю rtp с сервера в браузер? если да, то я не это пытаюсь делать. Я отправляю rtp из webrtc (браузер) на сервер и на сервере, пытаясь использовать gstreamer, чтобы показать мне поток в основном для целей отладки / тестирования. и относительно dtls, хотя я не знаю всех деталей, я читал, что janus (сервер) обрабатывает это - person John Doe; 27.09.2014
comment
Пакеты расшифровываются к тому моменту, когда они достигают конвейера gstreamer. Янус занимается расшифровкой и демультиплексированием каждого пакета. - person Benjamin Trent; 27.09.2014

Kurento Media Server (KMS) - это медиа-сервер WebRTC, полностью написанный поверх GStreamer. KMS предоставляет WebRtcEndpoint, реализующий все необходимые протоколы и алгоритмы для отправки / получения потоков WebRTC в / из веб-браузеров. KMS предоставляет API на основе элементов мультимедиа и конвейеров мультимедиа, которые переводятся в конвейеры мультимедиа GStreamer. В общем, все возможности GStreamer можно использовать и в KMS. Вы можете ознакомиться с KMS на странице http://www.kurento.org.

Отказ от ответственности: я являюсь частью команды разработчиков Kurento.

person lulop    schedule 27.09.2014
comment
Какой конвейер конкретно будет работать с расшифрованным, демультиплексированным потоком RTP из потока Chrome WebRTC? Пользователь уже использует janus, поэтому простое связывание другой технологии на самом деле не дает ответа на вопрос. - person Benjamin Trent; 27.09.2014