From 4110eea4568926dc18642a544718c87118629253 Mon Sep 17 00:00:00 2001 From: Lorenzo Miniero Date: Fri, 11 Feb 2022 10:01:53 +0100 Subject: [PATCH] Support for multistream PeerConnections (replaces #1459) (#2211) --- Makefile.am | 4 +- README.md | 2 + bower.json | 2 +- conf/janus.plugin.streaming.jcfg.sample.in | 50 + configure.ac | 6 +- docs/header.html | 1 + docs/janus-doxygen.cfg | 6 +- dtls-bio.c | 21 +- dtls.c | 138 +- dtls.h | 8 +- html/admin.html | 2 +- html/audiobridgetest.html | 2 +- html/audiobridgetest.js | 39 +- html/canvas.html | 2 +- html/canvas.js | 141 +- html/citeus.html | 2 +- html/demos.html | 6 +- html/devicetest.html | 2 +- html/devicetest.js | 255 +- html/e2etest.html | 2 +- html/e2etest.js | 234 +- html/echotest.html | 2 +- html/echotest.js | 234 +- html/index.html | 8 +- html/janus.js | 358 +- html/multiopus.html | 2 +- html/multiopus.js | 167 +- html/mvideoroomtest.html | 159 + html/mvideoroomtest.js | 1046 +++ html/navbar.html | 4 +- html/nosiptest.html | 2 +- html/nosiptest.js | 252 +- html/recordplaytest.html | 2 +- html/recordplaytest.js | 206 +- html/screensharingtest.html | 2 +- html/screensharingtest.js | 191 +- html/siptest.html | 2 +- html/siptest.js | 420 +- html/streamingtest.html | 14 +- html/streamingtest.js | 625 +- html/support.html | 2 +- html/textroomtest.html | 2 +- html/videocalltest.html | 2 +- html/videocalltest.js | 246 +- html/videoroomtest.html | 8 +- html/videoroomtest.js | 357 +- html/voicemailtest.html | 2 +- html/voicemailtest.js | 4 +- html/vp9svctest.html | 2 +- html/vp9svctest.js | 348 +- ice.c | 2234 +++--- ice.h | 304 +- janus.c | 964 +-- janus.ggo | 2 +- mainpage.dox | 44 +- plugins/janus_audiobridge.c | 47 +- plugins/janus_duktape.c | 34 +- plugins/janus_duktape_data.h | 1 + plugins/janus_echotest.c | 75 +- plugins/janus_lua.c | 34 +- plugins/janus_lua_data.h | 2 +- plugins/janus_nosip.c | 41 +- plugins/janus_recordplay.c | 158 +- plugins/janus_sip.c | 60 +- plugins/janus_streaming.c | 4670 +++++++----- plugins/janus_textroom.c | 4 +- plugins/janus_videocall.c | 28 +- plugins/janus_videoroom.c | 6549 +++++++++++------ plugins/plugin.c | 5 +- plugins/plugin.h | 34 +- ...test_gstreamer_1.sh => test_gstreamer1.sh} | 0 .../streams/test_gstreamer1_multistream.sh | 16 + plugins/streams/test_gstreamer_multistream.sh | 28 + postprocessing/janus-pp-rec.ggo | 2 +- postprocessing/pcap2mjr.ggo | 2 +- record.c | 12 +- rtp.c | 373 +- rtp.h | 19 +- sdp-utils.c | 1109 +-- sdp-utils.h | 220 +- sdp.c | 1021 ++- sdp.h | 28 +- utils.h | 1 + 83 files changed, 14626 insertions(+), 9089 deletions(-) create mode 100644 html/mvideoroomtest.html create mode 100644 html/mvideoroomtest.js rename plugins/streams/{test_gstreamer_1.sh => test_gstreamer1.sh} (100%) create mode 100755 plugins/streams/test_gstreamer1_multistream.sh create mode 100755 plugins/streams/test_gstreamer_multistream.sh diff --git a/Makefile.am b/Makefile.am index 9cef085d51..98d4cbb1a9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -482,7 +482,9 @@ stream_DATA += \ plugins/streams/music.mulaw \ plugins/streams/radio.alaw \ plugins/streams/test_gstreamer.sh \ - plugins/streams/test_gstreamer_1.sh + plugins/streams/test_gstreamer1.sh \ + plugins/streams/test_gstreamer_multistream.sh \ + plugins/streams/test_gstreamer1_multistream.sh EXTRA_DIST += \ conf/janus.plugin.streaming.jcfg.sample.in \ $(stream_DATA) diff --git a/README.md b/README.md index 54dd37b615..083a31028c 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Janus is an open source, general purpose, WebRTC server designed and developed b For some online demos and documentations, make sure you pay the [project website](https://janus.conf.meetecho.com/) a visit! +> **Note well:** this is the main branch for the `multistream` version of Janus, which is the new version. If you want to check the legacy version of Janus instead (i.e., `0.x`, a.k.a. "master") click [here](https://github.com/meetecho/janus-gateway/tree/0.x) instead. + If you have questions on Janus, or wish to discuss Janus with us and other users, please join our [meetecho-janus](https://groups.google.com/forum/#!forum/meetecho-janus) Google Group. If you encounter bugs, please submit an issue on [GitHub](https://github.com/meetecho/janus-gateway/issues): make sure you read the [guidelines](.github/ISSUE_TEMPLATE.md) before opening an issue, though. diff --git a/bower.json b/bower.json index d1fbabd47b..6f26f82a60 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "janus-gateway", - "version": "0.11.8", + "version": "1.0.0", "homepage": "https://github.com/meetecho/janus-gateway", "authors": [ "Lorenzo Miniero ", diff --git a/conf/janus.plugin.streaming.jcfg.sample.in b/conf/janus.plugin.streaming.jcfg.sample.in index 1a3fff8bb1..62818a1624 100644 --- a/conf/janus.plugin.streaming.jcfg.sample.in +++ b/conf/janus.plugin.streaming.jcfg.sample.in @@ -138,6 +138,56 @@ rtp-sample: { secret = "adminpwd" } +# +# This is a better example that uses the new settings to configure a live +# mountpoint to send multiple streams of the same type at the same time: +# that is, not simulcasting, but different streams (e.g., two audio +# streams and two video streams). To do so, you don't set the audio, +# video and data properties inline, but use an array of properties instead, +# each identifying a single stream to add, that will then translate to +# a dedicated m-line in the SDP. For each stream, you specify the type, +# a unique ID (mid), and can provide a short description (label) so that +# the client side can know what's what when rendering the streams. Notice +# how the port/pt/rtpmap/fmtp/etc. stuff is called just like that, without +# any audio/video/data prefix: in fact, each media stream can be configured +# the same way, and it's the type that allows us to differentiate them. +# As such, you can use the same approach for creating regular mountpoints +# as well (e.g., 1 audio and 1 video) in a much clearer, and cleaner, way. +# +multistream-test: { + type = "rtp" + id = 123 + description = "Multistream test (1 audio, 2 video)" + metadata = "This is an example of a multistream mountpoint: you'll get an audio stream and two video feeds" + media = ( + { + type = "audio" + mid = "a" + label = "Audio stream" + port = 5102 + pt = 111 + rtpmap = "opus/48000/2" + }, + { + type = "video" + mid = "v1" + label = "Video stream #1" + port = 5104 + pt = 100 + rtpmap = "VP8/90000" + }, + { + type = "video" + mid = "v2" + label = "Video stream #2" + port = 5106 + pt = 100 + rtpmap = "VP8/90000" + } + ) + secret = "adminpwd" +} + # # This is a sample of the file-based streaming support. Specifically, # this simulates a radio broadcast by streaming (in a loop) raw a-Law diff --git a/configure.ac b/configure.ac index d0c0a593bd..4f7bdaf6f0 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([Janus WebRTC Server],[0.11.8],[https://github.com/meetecho/janus-gateway],[janus-gateway],[https://janus.conf.meetecho.com]) +AC_INIT([Janus WebRTC Server],[1.0.0],[https://github.com/meetecho/janus-gateway],[janus-gateway],[https://janus.conf.meetecho.com]) AC_LANG(C) AC_CONFIG_AUX_DIR([.]) AC_CONFIG_MACRO_DIR([m4]) @@ -75,9 +75,9 @@ cc*) -Wunused-but-set-variable" esac -JANUS_VERSION=118 +JANUS_VERSION=1000 AC_SUBST(JANUS_VERSION) -JANUS_VERSION_STRING="0.11.8" +JANUS_VERSION_STRING="1.0.0" AC_SUBST(JANUS_VERSION_STRING) case "$host_os" in diff --git a/docs/header.html b/docs/header.html index 3c4c91d6b8..cef89e29c3 100644 --- a/docs/header.html +++ b/docs/header.html @@ -40,6 +40,7 @@
  • Documentation
  • Papers
  • Need help?
  • +
  • Janus (0.x)
  • JanusCon!
  • diff --git a/html/streamingtest.js b/html/streamingtest.js index 3f9937f11c..2c87bc80d0 100644 --- a/html/streamingtest.js +++ b/html/streamingtest.js @@ -52,11 +52,13 @@ var janus = null; var streaming = null; var opaqueId = "streamingtest-"+Janus.randomString(12); -var bitrateTimer = null; -var spinner = null; +var remoteTracks = {}, remoteVideos = 0, dataMid = null; +var bitrateTimer = {}; +var spinner = {}; -var simulcastStarted = false, svcStarted = false; +var simulcastStarted = {}, svcStarted = {}; +var streamsList = {}; var selectedStream = null; @@ -91,7 +93,9 @@ $(document).ready(function() { $('#start').removeAttr('disabled').html("Stop") .click(function() { $(this).attr('disabled', true); - clearInterval(bitrateTimer); + for(var i in bitrateTimer) + clearInterval(bitrateTimer[i]); + bitrateTimer = {}; janus.destroy(); $('#streamslist').attr('disabled', true); $('#watch').attr('disabled', true).unbind('click'); @@ -108,6 +112,10 @@ $(document).ready(function() { webrtcState: function(on) { Janus.log("Janus says our WebRTC PeerConnection is " + (on ? "up" : "down") + " now"); }, + slowLink: function(uplink, lost, mid) { + Janus.warn("Janus reports problems " + (uplink ? "sending" : "receiving") + + " packets on mid " + mid + " (" + lost + " lost packets)"); + }, onmessage: function(msg, jsep) { Janus.debug(" ::: Got a message :::", msg); var result = msg["result"]; @@ -121,27 +129,29 @@ $(document).ready(function() { else if(status === 'stopped') stopStream(); } else if(msg["streaming"] === "event") { + // Does this event refer to a mid in particular? + var mid = result["mid"] ? result["mid"] : "0"; // Is simulcast in place? var substream = result["substream"]; var temporal = result["temporal"]; if((substream !== null && substream !== undefined) || (temporal !== null && temporal !== undefined)) { - if(!simulcastStarted) { - simulcastStarted = true; - addSimulcastButtons(); + if(!simulcastStarted[mid]) { + simulcastStarted[mid] = true; + addSimulcastButtons(mid); } // We just received notice that there's been a switch, update the buttons - updateSimulcastButtons(substream, temporal); + updateSimulcastButtons(mid, substream, temporal); } // Is VP9/SVC in place? var spatial = result["spatial_layer"]; temporal = result["temporal_layer"]; if((spatial !== null && spatial !== undefined) || (temporal !== null && temporal !== undefined)) { - if(!svcStarted) { - svcStarted = true; - addSvcButtons(); + if(!svcStarted[mid]) { + svcStarted[mid] = true; + addSvcButtons(mid); } // We just received notice that there's been a switch, update the buttons - updateSvcButtons(spatial, temporal); + updateSvcButtons(mid, spatial, temporal); } } } else if(msg["error"]) { @@ -168,7 +178,7 @@ $(document).ready(function() { Janus.debug("Got SDP!", jsep); var body = { request: "start" }; streaming.send({ message: body, jsep: jsep }); - $('#watch').html("Stop").removeAttr('disabled').click(stopStream); + $('#watch').html("Stop").removeAttr('disabled').unbind('click').click(stopStream); }, error: function(error) { Janus.error("WebRTC error:", error); @@ -177,83 +187,124 @@ $(document).ready(function() { }); } }, - onremotestream: function(stream) { - Janus.debug(" ::: Got a remote stream :::", stream); - var addButtons = false; - if($('#remotevideo').length === 0) { - addButtons = true; - $('#stream').append('