From 69df84bfd0d0e179777ae506835a2dce16e206e6 Mon Sep 17 00:00:00 2001 From: Kirill Date: Thu, 10 Jun 2021 18:56:19 +0500 Subject: [PATCH] Squashed commit of the following: commit 9c9d3354001b1de74bb5ff5839ceea86bf3d1c94 Author: Lionel Nicolas Date: Thu Jun 10 03:04:43 2021 -0400 Fix streaming plugin mutex unlock when disabling mountpoint (#2690) commit 2d83e9669d0c6509b82d3b9c1d0c0d247f0026d5 Author: Yurii Cherniavskyi Date: Mon Jun 7 16:02:41 2021 +0300 Fix SIP plugin unhold request docs typo (#2688) commit 2cd01182e44be6d7ff26635de216cb65703e9778 Author: August Black Date: Mon Jun 7 01:10:49 2021 -0700 minor adjustment to the audiobridge docs (#2687) commit de2117e9997f84c5cad583eff7fe82ee40d16526 Author: nicolasduteil Date: Tue Jun 1 11:26:29 2021 +0200 fix: [janus_sip] Fix "call_id" property in "missed_call" events (#2679) commit 9eeeb38c71098d7bed7cf951c2d1503d0c4872ec Author: Alessandro Toppi Date: Mon May 31 15:57:41 2021 +0200 Fix status vector parsing for incoming twcc feedbacks (resolves #2677). commit 8a25f6ef9d3cb3bb03497afb73e416d4eb382230 Merge: d3b39b9b 394fb48f Author: Alessandro Toppi Date: Fri May 28 13:29:54 2021 +0200 Merge pull request #2675 from kmeyerhofer/actions/fix GH Actions, fix variable name commit d3b39b9b96648a9f7ed0727a9723b05b44a4ccd2 Author: Lorenzo Miniero Date: Fri May 28 11:09:30 2021 +0200 Fixed race condition in VideoRoom commit 394fb48ffc81a67f6d2c93ec151c61b416d86bfc Author: Kurt Meyerhofer Date: Thu May 27 14:52:08 2021 -0600 Fixes variable name. commit b45cd37c04d4e95103550feddf97e32ec838173a Author: Lorenzo Miniero Date: Thu May 27 18:31:55 2021 +0200 Clarify that libnice 0.1.18 is recommended commit 5757a37d215a742203f977dd59bf98f66679223d Author: Lorenzo Miniero Date: Thu May 27 17:08:17 2021 +0200 Spatial audio support in AudioBridge via stereo mixing (#2446) commit 161fe7af130ace24ccd9ea40fcf28996a077c3d2 Author: Luca Barbato Date: Thu May 27 15:29:01 2021 +0200 Cleanup avformat-based preprocessors (#2665) commit 7b010cd265991132158541ea80afcaa14bf4eb42 Author: lucylu-star <78361868+lucylu-star@users.noreply.github.com> Date: Tue May 25 17:09:40 2021 +0800 Fixed broken simulcast support in VideoCall plugin (#2671) commit 4ae44a4baf4268b43d34c443515de87ab9c04d6e Author: nicolasduteil Date: Mon May 24 17:57:34 2021 +0200 feat: support for custom call-id in subscribe request + add 'call_id' property to subscribe & notify related events (#2664) commit 4294f20606050316209bb6d20d8bef1a66272e4d Author: Lorenzo Miniero Date: Mon May 24 11:02:48 2021 +0200 Fixed missing macro when using pthread mutexes (fixes #2666) commit f22ab0dc8c25d70296fe5add2c4c0a05dbc578c4 Author: Lorenzo Miniero Date: Wed May 19 12:03:32 2021 +0200 Fixed warning commit b3f3f1726175fce96fe1d239493a7ebffcd3b5c5 Author: Alessandro Toppi Date: Tue May 18 12:10:47 2021 +0200 Remove duplicated flag for fuzzing coverage. commit 4a7560c5078f8c8f980d4ff1fd5314545f451cd8 Author: nu774 Date: Fri May 14 00:26:36 2021 +0900 janus-pp-rec: support HEVC AP(aggregation packet) (#2662) commit 5db4be2fe4c7ac8f39cac345b469ff9dd7faa0d7 Author: Lorenzo Miniero Date: Wed May 12 17:43:43 2021 +0200 Fixed out of bounds array access commit 69f56f4dab1c9b7b76faf0d41a065ba22d0f1577 Author: nicolasduteil Date: Tue May 11 14:36:22 2021 +0200 feat: support for SUBSCRIBE expiry (Expires header) in sip plugin (#2661) commit b047ccff13d205604a81193d661588c1574ea96c Author: Lorenzo Miniero Date: Mon May 10 09:33:27 2021 +0200 Fixed types commit f8e8c5ebb3957aeefd797997df17ae00d21486a3 Author: Chris Wiggins Date: Mon May 10 19:26:45 2021 +1200 RabbitMQ Transport Reconnect Logic (#2651) commit 280e8e4159103f1d2a5faa22ca2c171f360fa318 Author: Lorenzo Miniero Date: Fri May 7 12:54:30 2021 +0200 Add per-participant recording options in AudioBridge to join API as well --- .github/workflows/janus-ci.yml | 2 +- Makefile.am | 2 + README.md | 2 +- ...janus.eventhandler.rabbitmqevh.jcfg.sample | 2 +- conf/janus.plugin.audiobridge.jcfg.sample | 1 + conf/janus.transport.rabbitmq.jcfg.sample | 1 + configure.ac | 1 + events/janus_rabbitmqevh.c | 68 +-- fuzzers/config.sh | 2 +- html/audiobridgetest.html | 5 +- html/audiobridgetest.js | 102 +++- mainpage.dox | 4 +- mutex.h | 8 +- plugins/janus_audiobridge.c | 269 +++++++-- plugins/janus_echotest.c | 6 +- plugins/janus_sip.c | 50 +- plugins/janus_streaming.c | 5 +- plugins/janus_videocall.c | 20 +- plugins/janus_videoroom.c | 19 +- postprocessing/pp-av1.c | 150 +---- postprocessing/pp-avformat.c | 92 +++ postprocessing/pp-avformat.h | 46 ++ postprocessing/pp-g722.c | 38 +- postprocessing/pp-h264.c | 63 +- postprocessing/pp-h265.c | 154 +++-- postprocessing/pp-opus.c | 259 ++------- postprocessing/pp-webm.c | 152 +---- rtcp.c | 6 +- transports/janus_mqtt.c | 2 +- transports/janus_rabbitmq.c | 540 ++++++++++-------- 30 files changed, 1112 insertions(+), 959 deletions(-) create mode 100644 postprocessing/pp-avformat.c create mode 100644 postprocessing/pp-avformat.h diff --git a/.github/workflows/janus-ci.yml b/.github/workflows/janus-ci.yml index 35b8a9561f..b54cddf66b 100644 --- a/.github/workflows/janus-ci.yml +++ b/.github/workflows/janus-ci.yml @@ -14,7 +14,7 @@ jobs: datachannels: ["yes", "no"] libcurl: ["yes", "no"] include: - - datachannel: "yes" + - datachannels: "yes" libcurl: "yes" deps_from_src: "yes" janus_config_opts: "" diff --git a/Makefile.am b/Makefile.am index 67b3b78035..576c2c17f4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -585,6 +585,8 @@ janus_pp_rec_SOURCES = \ postprocessing/pp-h264.h \ postprocessing/pp-av1.c \ postprocessing/pp-av1.h \ + postprocessing/pp-avformat.c \ + postprocessing/pp-avformat.h \ postprocessing/pp-h265.c \ postprocessing/pp-h265.h \ postprocessing/pp-opus.c \ diff --git a/README.md b/README.md index 3c86cac1a6..f2bfd40ff6 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ To install it, you'll need to satisfy the following dependencies: * [Jansson](http://www.digip.org/jansson/) * [libconfig](https://hyperrealm.github.io/libconfig/) -* [libnice](https://libnice.freedesktop.org/) (at least v0.1.16 suggested, master recommended) +* [libnice](https://libnice.freedesktop.org/) (at least v0.1.16 suggested, v0.1.18 recommended) * [OpenSSL](http://www.openssl.org/) (at least v1.0.1e) * [libsrtp](https://github.com/cisco/libsrtp) (at least v2.x suggested) * [usrsctp](https://github.com/sctplab/usrsctp) (only needed if you are interested in Data Channels) diff --git a/conf/janus.eventhandler.rabbitmqevh.jcfg.sample b/conf/janus.eventhandler.rabbitmqevh.jcfg.sample index a29ec4e3cb..c8635e2453 100644 --- a/conf/janus.eventhandler.rabbitmqevh.jcfg.sample +++ b/conf/janus.eventhandler.rabbitmqevh.jcfg.sample @@ -20,7 +20,7 @@ general: { #exchange = "janus-exchange" route_key = "janus-events" # Routing key to use when publishing messages #exchange_type = "fanout" # Rabbitmq exchange_type can be one of the available types: direct, topic, headers and fanout (fanout by defualt). - #heartbeat = 60 # Defines the seconds without communication that should pass before considering the TCP connection has unreachable. + #heartbeat = 60 # Defines the seconds without communication that should pass before considering the TCP connection unreachable. #declare_outgoing_queue = true # By default (for backwards compatibility), we declare an outgoing queue. Set this to false to disable that behavior #ssl_enable = false # Whether ssl support must be enabled diff --git a/conf/janus.plugin.audiobridge.jcfg.sample b/conf/janus.plugin.audiobridge.jcfg.sample index b4a7929187..e57a20f109 100644 --- a/conf/janus.plugin.audiobridge.jcfg.sample +++ b/conf/janus.plugin.audiobridge.jcfg.sample @@ -4,6 +4,7 @@ # secret = "" # pin = "" # sampling_rate = (e.g., 16000 for wideband mixing) +# spatial_audio = true|false (if true, the mix will be stereo to spatially place users, default=false) # audiolevel_ext = true|false (whether the ssrc-audio-level RTP extension must # be negotiated/used or not for new joins, default=true) # audiolevel_event = true|false (whether to emit event to other users or not, default=false) diff --git a/conf/janus.transport.rabbitmq.jcfg.sample b/conf/janus.transport.rabbitmq.jcfg.sample index 9aae80ef0a..27cfebd0a0 100644 --- a/conf/janus.transport.rabbitmq.jcfg.sample +++ b/conf/janus.transport.rabbitmq.jcfg.sample @@ -34,6 +34,7 @@ general: { #queue_durable = false # Whether or not incoming queue should remain after a RabbitMQ reboot #queue_autodelete = false # Whether or not incoming queue should autodelete after janus disconnects from RabbitMQ #queue_exclusive = false # Whether or not incoming queue should only allow one subscriber + #heartbeat = 60 # Defines the seconds without communication that should pass before considering the TCP connection unreachable. #ssl_enabled = false # Whether ssl support must be enabled #ssl_verify_peer = true # Whether peer verification must be enabled diff --git a/configure.ac b/configure.ac index 8315f2b6b8..69827ed9eb 100644 --- a/configure.ac +++ b/configure.ac @@ -605,6 +605,7 @@ AC_CHECK_LIB([rabbitmq], AC_DEFINE(HAVE_RABBITMQEVH) enable_rabbitmq_event_handler=yes ]) + AC_CHECK_HEADERS([rabbitmq-c/amqp.h]) ], [ AS_IF([test "x$enable_rabbitmq" = "xyes"], diff --git a/events/janus_rabbitmqevh.c b/events/janus_rabbitmqevh.c index 9fda6ddced..003ddf22be 100644 --- a/events/janus_rabbitmqevh.c +++ b/events/janus_rabbitmqevh.c @@ -12,10 +12,18 @@ #include +/* Latest RabbitMQ-C library changes the library paths from 0.12.0.0 onwards */ +#ifdef HAVE_RABBITMQ_C_AMQP_H +#include +#include +#include +#include +#else #include #include #include #include +#endif #include "../debug.h" #include "../config.h" @@ -177,7 +185,7 @@ int janus_rabbitmqevh_init(const char *config_path) { /* Compact, so no spaces between separators */ json_format = JSON_COMPACT | JSON_PRESERVE_ORDER; } else { - JANUS_LOG(LOG_WARN, "Unsupported JSON format option '%s', using default (indented)\n", item->value); + JANUS_LOG(LOG_WARN, "RabbitMQEventHandler: Unsupported JSON format option '%s', using default (indented)\n", item->value); json_format = JSON_INDENT(3) | JSON_PRESERVE_ORDER; } } @@ -224,7 +232,7 @@ int janus_rabbitmqevh_init(const char *config_path) { item = janus_config_get(config, config_general, janus_config_type_item, "heartbeat"); if(item && item->value && janus_string_to_uint16(item->value, &heartbeat) < 0) { - JANUS_LOG(LOG_ERR, "Invalid heartbeat timeout (%s), falling back to default\n", item->value); + JANUS_LOG(LOG_ERR, "RabbitMQEventHandler: Invalid heartbeat timeout (%s), falling back to default (0, disabling heartbeat)\n", item->value); heartbeat = 0; } @@ -279,9 +287,9 @@ int janus_rabbitmqevh_init(const char *config_path) { exchange = g_strdup(item->value); } if (exchange == NULL) { - JANUS_LOG(LOG_INFO, "RabbitMQ event handler enabled, %s:%d (%s) exchange_type:%s\n", rmqhost, rmqport, route_key,exchange_type); + JANUS_LOG(LOG_INFO, "RabbitMQEventHandler: enabled, %s:%d (%s) exchange_type:%s\n", rmqhost, rmqport, route_key,exchange_type); } else { - JANUS_LOG(LOG_INFO, "RabbitMQ event handler enabled, %s:%d (%s) exch: (%s) exchange_type:%s\n", rmqhost, rmqport, route_key, exchange,exchange_type); + JANUS_LOG(LOG_INFO, "RabbitMQEventHandler: enabled, %s:%d (%s) exch: (%s) exchange_type:%s\n", rmqhost, rmqport, route_key, exchange,exchange_type); } /* Connect */ @@ -300,7 +308,7 @@ int janus_rabbitmqevh_init(const char *config_path) { handler_thread = g_thread_try_new("janus rabbitmqevh handler", jns_rmqevh_hdlr, NULL, &error); if(error != NULL) { g_atomic_int_set(&initialized, 0); - JANUS_LOG(LOG_FATAL, "Got error %d (%s) trying to launch the RabbitMQEventHandler handler thread...\n", + JANUS_LOG(LOG_FATAL, "RabbitMQEventHandler: Got error %d (%s) trying to launch the RabbitMQEventHandler handler thread...\n", error->code, error->message ? error->message : "??"); g_error_free(error); goto error; @@ -309,7 +317,7 @@ int janus_rabbitmqevh_init(const char *config_path) { in_thread = g_thread_try_new("janus rabbitmqevh heartbeat handler", jns_rmqevh_hrtbt, NULL, &error); if(error != NULL) { g_atomic_int_set(&initialized, 0); - JANUS_LOG(LOG_FATAL, "Got error %d (%s) trying to launch the RabbitMQEventHandler heartbeat thread...\n", + JANUS_LOG(LOG_FATAL, "RabbitMQEventHandler: Got error %d (%s) trying to launch the RabbitMQEventHandler heartbeat thread...\n", error->code, error->message ? error->message : "??"); g_error_free(error); goto error; @@ -350,16 +358,10 @@ int janus_rabbitmqevh_connect(void) { JANUS_LOG(LOG_FATAL, "RabbitMQEventHandler: Can't connect to RabbitMQ server: error creating socket...\n"); return -1; } - if(ssl_verify_peer) { - amqp_ssl_socket_set_verify_peer(socket, 1); - } else { - amqp_ssl_socket_set_verify_peer(socket, 0); - } - if(ssl_verify_hostname) { - amqp_ssl_socket_set_verify_hostname(socket, 1); - } else { - amqp_ssl_socket_set_verify_hostname(socket, 0); - } + + amqp_ssl_socket_set_verify_peer(socket, ssl_verify_peer); + amqp_ssl_socket_set_verify_hostname(socket, ssl_verify_hostname); + if(ssl_cacert_file) { status = amqp_ssl_socket_set_cacert(socket, ssl_cacert_file); if(status != AMQP_STATUS_OK) { @@ -385,7 +387,7 @@ int janus_rabbitmqevh_connect(void) { JANUS_LOG(LOG_VERB, "RabbitMQEventHandler: Connecting to RabbitMQ server...\n"); status = amqp_socket_open(socket, rmqhost, rmqport); if(status != AMQP_STATUS_OK) { - JANUS_LOG(LOG_FATAL, "Can't connect to RabbitMQ server: error opening socket... (%s)\n", amqp_error_string2(status)); + JANUS_LOG(LOG_FATAL, "RabbitMQEventHandler: Can't connect to RabbitMQ server: error opening socket... (%s)\n", amqp_error_string2(status)); return -1; } JANUS_LOG(LOG_VERB, "RabbitMQEventHandler: Logging in...\n"); @@ -410,13 +412,13 @@ int janus_rabbitmqevh_connect(void) { amqp_exchange_declare(rmq_conn, rmq_channel, rmq_exchange, amqp_cstring_bytes(exchange_type), 0, 0, 0, 0, amqp_empty_table); result = amqp_get_rpc_reply(rmq_conn); if(result.reply_type != AMQP_RESPONSE_NORMAL) { - JANUS_LOG(LOG_FATAL, "RabbitMQEventHandler: Can't connect to RabbitMQ server: error diclaring exchange... %s, %s\n", amqp_error_string2(result.library_error), amqp_method_name(result.reply.id)); + JANUS_LOG(LOG_FATAL, "RabbitMQEventHandler: Can't connect to RabbitMQ server: error declaring exchange... %s, %s\n", amqp_error_string2(result.library_error), amqp_method_name(result.reply.id)); return -1; } } if (declare_outgoing_queue) { - JANUS_LOG(LOG_VERB, "Declaring outgoing queue... (%s)\n", route_key); + JANUS_LOG(LOG_VERB, "RabbitMQEventHandler: Declaring outgoing queue... (%s)\n", route_key); amqp_queue_declare(rmq_conn, rmq_channel, amqp_cstring_bytes(route_key), 0, 0, 0, 0, amqp_empty_table); result = amqp_get_rpc_reply(rmq_conn); if(result.reply_type != AMQP_RESPONSE_NORMAL) { @@ -425,6 +427,8 @@ int janus_rabbitmqevh_connect(void) { } } + JANUS_LOG(LOG_INFO, "RabbitMQEventHandler: Connected successfully"); + return 0; } @@ -446,9 +450,7 @@ void janus_rabbitmqevh_destroy(void) { g_async_queue_unref(events); events = NULL; - if(rmq_conn && rmq_channel) { - amqp_channel_close(rmq_conn, rmq_channel, AMQP_REPLY_SUCCESS); - amqp_connection_close(rmq_conn, AMQP_REPLY_SUCCESS); + if(rmq_conn) { amqp_destroy_connection(rmq_conn); } if(rmq_exchange.bytes) @@ -548,7 +550,7 @@ json_t *janus_rabbitmqevh_handle_request(json_t *request) { if(json_object_get(request, "grouping")) group_events = json_is_true(json_object_get(request, "grouping")); } else { - JANUS_LOG(LOG_VERB, "Unknown request '%s'\n", request_text); + JANUS_LOG(LOG_VERB, "RabbitMQEventHandler: Unknown request '%s'\n", request_text); error_code = JANUS_RABBITMQEVH_ERROR_INVALID_REQUEST; g_snprintf(error_cause, 512, "Unknown request '%s'", request_text); } @@ -570,7 +572,7 @@ json_t *janus_rabbitmqevh_handle_request(json_t *request) { /* Thread to handle incoming events */ static void *jns_rmqevh_hdlr(void *data) { - JANUS_LOG(LOG_VERB, "Joining RabbitMQEventHandler handler thread\n"); + JANUS_LOG(LOG_VERB, "RabbitMQEventHandler: joining handler thread\n"); json_t *event = NULL, *output = NULL; char *event_text = NULL; int count = 0, max = group_events ? 100 : 1; @@ -589,7 +591,7 @@ static void *jns_rmqevh_hdlr(void *data) { if(created && json_is_integer(created)) { gint64 then = json_integer_value(created); gint64 now = janus_get_monotonic_time(); - JANUS_LOG(LOG_DBG, "Handled event after %"SCNu64" us\n", now-then); + JANUS_LOG(LOG_DBG, "RabbitMQEventHandler: Handled event after %"SCNu64" us\n", now-then); } if(!group_events) { /* We're done here, we just need a single event */ @@ -613,7 +615,7 @@ static void *jns_rmqevh_hdlr(void *data) { /* Since this a simple plugin, it does the same for all events: so just convert to string... */ event_text = json_dumps(output, json_format); if(event_text == NULL) { - JANUS_LOG(LOG_WARN, "Failed to stringify event, event lost...\n"); + JANUS_LOG(LOG_WARN, "RabbitMQEventHandler: Failed to stringify event, event lost...\n"); /* Nothing we can do... get rid of the event */ json_decref(output); output = NULL; @@ -638,14 +640,14 @@ static void *jns_rmqevh_hdlr(void *data) { json_decref(output); output = NULL; } - JANUS_LOG(LOG_VERB, "Leaving RabbitMQEventHandler handler thread\n"); + JANUS_LOG(LOG_VERB, "RabbitMQEventHandler: leaving handler thread\n"); return NULL; } /* Thread to handle heartbeats */ static void *jns_rmqevh_hrtbt(void *data) { - JANUS_LOG(LOG_VERB, "Monitoring RabbitMQ HeartBeat\n"); + JANUS_LOG(LOG_VERB, "RabbitMQEventHandler: Monitoring RabbitMQ Heartbeat\n"); int waiting_usec = (heartbeat/2) * 1000000; struct timeval timeout; timeout.tv_sec = 0; @@ -666,15 +668,13 @@ static void *jns_rmqevh_hrtbt(void *data) { continue; } - JANUS_LOG(LOG_VERB, "Error on amqp_simple_wait_frame_noblock: %d (%s)\n", res, amqp_error_string2(res)); + JANUS_LOG(LOG_VERB, "RabbitMQEventHandler: Error on amqp_simple_wait_frame_noblock: %d (%s)\n", res, amqp_error_string2(res)); - if(rmq_conn && rmq_channel) { - amqp_channel_close(rmq_conn, rmq_channel, AMQP_REPLY_SUCCESS); - amqp_connection_close(rmq_conn, AMQP_REPLY_SUCCESS); + if(rmq_conn) { amqp_destroy_connection(rmq_conn); } if(!g_atomic_int_get(&stopping)) { - JANUS_LOG(LOG_VERB, "Trying to reconnect with RabbitMQ Server\n"); + JANUS_LOG(LOG_VERB, "RabbitMQEventHandler: Trying to reconnect\n"); int result = janus_rabbitmqevh_connect(); if(result < 0) { g_usleep(5000000); @@ -688,6 +688,6 @@ static void *jns_rmqevh_hrtbt(void *data) { } } - JANUS_LOG(LOG_VERB, "Leaving RabbitMQEventHandler HeartBeat thread\n"); + JANUS_LOG(LOG_VERB, "RabbitMQEventHandler: Leaving HeartBeat thread\n"); return NULL; } diff --git a/fuzzers/config.sh b/fuzzers/config.sh index de548eb78f..a362261956 100755 --- a/fuzzers/config.sh +++ b/fuzzers/config.sh @@ -16,7 +16,7 @@ DEFAULT_CC="clang" DEFAULT_CCLD=$DEFAULT_CC DEFAULT_CFLAGS="-O1 -fno-omit-frame-pointer -g -ggdb3 -fsanitize=address,undefined -fsanitize-address-use-after-scope -fno-sanitize-recover=undefined -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" DEFAULT_LDFLAGS="-O1 -fno-omit-frame-pointer -g -ggdb3 -fsanitize=address,undefined -fno-sanitize-recover=undefined -fsanitize-address-use-after-scope" -COVERAGE_CFLAGS="-O1 -fno-omit-frame-pointer -g -ggdb3 -fprofile-instr-generate -fcoverage-mapping -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" +COVERAGE_CFLAGS="-O1 -fno-omit-frame-pointer -g -ggdb3 -fprofile-instr-generate -fcoverage-mapping -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" COVERAGE_LDFLAGS="-O1 -fno-omit-frame-pointer -g -ggdb3 -fprofile-instr-generate -fcoverage-mapping -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" # Janus configure flags diff --git a/html/audiobridgetest.html b/html/audiobridgetest.html index 6621aca885..c30994b1c8 100644 --- a/html/audiobridgetest.html +++ b/html/audiobridgetest.html @@ -11,6 +11,7 @@ +