From 7b7f28981aeeab024ef20bcdd2906a063dfaeb3f Mon Sep 17 00:00:00 2001 From: Colin Edwards Date: Fri, 26 Aug 2022 12:25:37 -0500 Subject: [PATCH] obs-webrtc: prototype / playground --- .github/workflows/main.yml | 3 + CI/macos/02_build_obs.sh | 7 + UI/window-basic-settings-stream.cpp | 8 +- plugins/CMakeLists.txt | 1 + plugins/obs-webrtc/CMakeLists.txt | 51 + plugins/obs-webrtc/data/.keepme | 0 plugins/obs-webrtc/webrtc-call.c | 147 ++ plugins/obs-webrtc/webrtc-call.h | 9 + plugins/obs-webrtc/webrtc-services-main.c | 42 + plugins/obs-webrtc/webrtc-source.c | 81 + plugins/obs-webrtc/webrtc-source.h | 0 plugins/obs-webrtc/webrtc-stream.c | 120 + plugins/obs-webrtc/webrtc-stream.h | 11 + plugins/obs-webrtc/webrtc.c | 32 + plugins/obs-webrtc/webrtc/Cargo.lock | 2631 +++++++++++++++++++++ plugins/obs-webrtc/webrtc/Cargo.toml | 25 + plugins/obs-webrtc/webrtc/bindings.h | 29 + plugins/obs-webrtc/webrtc/build.rs | 18 + plugins/obs-webrtc/webrtc/cbindgen.toml | 1 + plugins/obs-webrtc/webrtc/src/call.rs | 305 +++ plugins/obs-webrtc/webrtc/src/lib.rs | 3 + plugins/obs-webrtc/webrtc/src/stream.rs | 274 +++ plugins/obs-webrtc/webrtc/src/whip.rs | 33 + plugins/obs-webrtc/whip.c | 83 + 24 files changed, 3912 insertions(+), 2 deletions(-) create mode 100644 plugins/obs-webrtc/CMakeLists.txt create mode 100644 plugins/obs-webrtc/data/.keepme create mode 100644 plugins/obs-webrtc/webrtc-call.c create mode 100644 plugins/obs-webrtc/webrtc-call.h create mode 100644 plugins/obs-webrtc/webrtc-services-main.c create mode 100644 plugins/obs-webrtc/webrtc-source.c create mode 100644 plugins/obs-webrtc/webrtc-source.h create mode 100644 plugins/obs-webrtc/webrtc-stream.c create mode 100644 plugins/obs-webrtc/webrtc-stream.h create mode 100644 plugins/obs-webrtc/webrtc.c create mode 100644 plugins/obs-webrtc/webrtc/Cargo.lock create mode 100644 plugins/obs-webrtc/webrtc/Cargo.toml create mode 100644 plugins/obs-webrtc/webrtc/bindings.h create mode 100644 plugins/obs-webrtc/webrtc/build.rs create mode 100644 plugins/obs-webrtc/webrtc/cbindgen.toml create mode 100644 plugins/obs-webrtc/webrtc/src/call.rs create mode 100644 plugins/obs-webrtc/webrtc/src/lib.rs create mode 100644 plugins/obs-webrtc/webrtc/src/stream.rs create mode 100644 plugins/obs-webrtc/webrtc/src/whip.rs create mode 100644 plugins/obs-webrtc/whip.c diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f5343ffa2fdae0..9729d960204eec 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -158,6 +158,9 @@ jobs: - name: 'Switch to Xcode 14 Beta' run: sudo xcode-select -switch /Applications/Xcode_14.0.app + - name: 'aarch64-apple-darwin' + run: rustup target add aarch64-apple-darwin + - name: 'Install dependencies' env: RESTORED_VLC: ${{ steps.vlc-cache.outputs.cache-hit }} diff --git a/CI/macos/02_build_obs.sh b/CI/macos/02_build_obs.sh index 073faa3322378c..9b850cad4b4bca 100755 --- a/CI/macos/02_build_obs.sh +++ b/CI/macos/02_build_obs.sh @@ -69,6 +69,12 @@ _configure_obs() { UNITTEST_OPTIONS="-DENABLE_UNIT_TESTS=ON" fi + if [ "${CI}" -a "${ARCH}" = "x86_64" ]; then + Rust_CARGO_TARGET="x86_64-apple-darwin" + else + Rust_CARGO_TARGET="aarch64-apple-darwin" + fi + cmake -S . -B ${BUILD_DIR} -G ${GENERATOR} \ -DCEF_ROOT_DIR="${DEPS_BUILD_DIR}/cef_binary_${MACOS_CEF_BUILD_VERSION:-${CI_MACOS_CEF_VERSION}}_macos_${ARCH:-x86_64}" \ -DENABLE_BROWSER=ON \ @@ -82,6 +88,7 @@ _configure_obs() { -DCMAKE_INSTALL_PREFIX=${BUILD_DIR}/install \ -DCMAKE_BUILD_TYPE=${BUILD_CONFIG} \ -DOBS_BUNDLE_CODESIGN_IDENTITY="${CODESIGN_IDENT:--}" \ + -DRust_CARGO_TARGET="${Rust_CARGO_TARGET}" \ ${YOUTUBE_OPTIONS} \ ${TWITCH_OPTIONS} \ ${RESTREAM_OPTIONS} \ diff --git a/UI/window-basic-settings-stream.cpp b/UI/window-basic-settings-stream.cpp index 12ca1db24dc352..774168bf4656b0 100644 --- a/UI/window-basic-settings-stream.cpp +++ b/UI/window-basic-settings-stream.cpp @@ -29,6 +29,7 @@ extern QCefCookieManager *panel_cookies; enum class ListOpt : int { ShowAll = 1, Custom, + WHIP, }; enum class Section : int { @@ -38,7 +39,8 @@ enum class Section : int { inline bool OBSBasicSettings::IsCustomService() const { - return ui->service->currentData().toInt() == (int)ListOpt::Custom; + return ui->service->currentData().toInt() == (int)ListOpt::Custom || + ui->service->currentData().toInt() == (int)ListOpt::WHIP; } void OBSBasicSettings::InitStreamPage() @@ -235,7 +237,7 @@ void OBSBasicSettings::SaveStream1Settings() obs_data_set_string(settings, "key", QT_TO_UTF8(ui->key->text())); OBSServiceAutoRelease newService = obs_service_create( - service_id, "default_service", settings, hotkeyData); + "whip", "default_service", settings, hotkeyData); if (!newService) return; @@ -349,6 +351,8 @@ void OBSBasicSettings::LoadServices(bool showAll) for (QString &name : names) ui->service->addItem(name); + ui->service->insertItem(0, QTStr("WHIP"), QVariant((int)ListOpt::WHIP)); + if (!showAll) { ui->service->addItem( QTStr("Basic.AutoConfig.StreamPage.Service.ShowAll"), diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index d20bce142fe43f..04a6a6baba1521 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -98,3 +98,4 @@ add_subdirectory(obs-transitions) add_subdirectory(rtmp-services) add_subdirectory(text-freetype2) add_subdirectory(aja) +add_subdirectory(obs-webrtc) diff --git a/plugins/obs-webrtc/CMakeLists.txt b/plugins/obs-webrtc/CMakeLists.txt new file mode 100644 index 00000000000000..e34dc9c8355e32 --- /dev/null +++ b/plugins/obs-webrtc/CMakeLists.txt @@ -0,0 +1,51 @@ +project(obs-webrtc) + +include(FetchContent) + +FetchContent_Declare( + Corrosion + GIT_REPOSITORY https://github.com/AndrewGaspar/corrosion.git + GIT_TAG origin/master # Optionally specify a version tag or branch here +) + +FetchContent_MakeAvailable(Corrosion) + +# find_package(Libcurl REQUIRED) + +include_directories(${LIBCURL_INCLUDE_DIRS}) + +include_directories(${OBS_JANSSON_INCLUDE_DIRS}) + +option(ENABLE_FFMPEG_LOGGING "Enables obs-ffmpeg logging" OFF) + +find_package( + FFmpeg REQUIRED + COMPONENTS avcodec + avfilter + avdevice + avutil + swscale + avformat + swresample) +include_directories(${FFMPEG_INCLUDE_DIRS}) + +set(obs-webrtc_HEADERS webrtc-stream.h webrtc-source.h webrtc-call.h) +set(obs-webrtc_SOURCES whip.c webrtc-stream.c webrtc-source.c webrtc.c + webrtc-call.c) + +if(WIN32) + set(MODULE_DESCRIPTION "OBS webrtc module") + configure_file(${CMAKE_SOURCE_DIR}/cmake/bundle/windows/obs-module.rc.in + obs-webrtc.rc) + list(APPEND obs-webrtc_SOURCES obs-webrtc.rc) +endif() + +add_library(obs-webrtc MODULE ${obs-webrtc_SOURCES} ${obs-webrtc_HEADERS}) + +corrosion_import_crate(MANIFEST_PATH webrtc/Cargo.toml) + +target_link_libraries(obs-webrtc libobs webrtc-rs-lib ${OBS_JANSSON_IMPORT} + ${LIBCURL_LIBRARIES} ${FFMPEG_LIBRARIES}) +set_target_properties(obs-webrtc PROPERTIES FOLDER "plugins") + +setup_plugin_target(obs-webrtc data) diff --git a/plugins/obs-webrtc/data/.keepme b/plugins/obs-webrtc/data/.keepme new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/plugins/obs-webrtc/webrtc-call.c b/plugins/obs-webrtc/webrtc-call.c new file mode 100644 index 00000000000000..06c76770aebc1c --- /dev/null +++ b/plugins/obs-webrtc/webrtc-call.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "webrtc-call.h" +#include "./webrtc/bindings.h" + +OBSWebRTCCall *call; + +pthread_t thread; + +AVFrame *frame; +AVFrame *audioFrame; +AVFrame *dst; + +struct OBSCallParticipant { + AVCodecContext *videoContext; + AVCodecContext *audioContext; +}; + +void packet_callback(const void *user_data, const uint8_t *packet_data, + unsigned int length, unsigned int video) +{ + + //blog(LOG_INFO, "%d", length); + struct OBSCallParticipant *participant = + (struct OBSCallParticipant *)user_data; + + AVCodecContext *context = NULL; + if (video) { + context = participant->videoContext; + } else { + context = participant->audioContext; + } + + uint8_t *unowned_packet = bzalloc(sizeof(uint8_t) * length); + memcpy(unowned_packet, packet_data, length); + + AVPacket *packet = av_packet_alloc(); + av_packet_from_data(packet, unowned_packet, length); + avcodec_send_packet(context, packet); + + if (video) { + int res = avcodec_receive_frame(context, frame); + + if (res == 0) { + + /*blog(LOG_INFO, "Width: %d, Height: %d, Format: %s", + frame->width, frame->height, + av_get_pix_fmt_name(frame->format));*/ + + dst->width = frame->width; + dst->height = frame->height; + dst->format = AV_PIX_FMT_BGRA; + av_image_alloc(dst->data, dst->linesize, frame->width, + frame->height, AV_PIX_FMT_BGRA, 1); + struct SwsContext *swsContext = sws_getContext( + frame->width, frame->height, frame->format, + frame->width, frame->height, AV_PIX_FMT_BGRA, + SWS_BILINEAR, NULL, NULL, NULL); + int out = sws_scale(swsContext, + (const uint8_t *const *)frame->data, + frame->linesize, 0, frame->height, + dst->data, dst->linesize); + sws_freeContext(swsContext); + + //blog(LOG_INFO, "out %d", out); + + //blog(LOG_INFO, "Width: %d, Height: %d, Format: %s", dst->width, dst->height, av_get_pix_fmt_name(dst->format)); + + obs_enter_graphics(); + + webrtcTexture = gs_texture_create( + dst->width, dst->height, GS_BGRA, 1, + (const uint8_t **)&dst->data, GS_DYNAMIC); + + //gs_texture_set_image(webrtcTexture, (const uint8_t **)&frame->data, frame->linesize[0], false); + + obs_leave_graphics(); + } + } else { + int res = avcodec_receive_frame(context, audioFrame); + + if (res == 0) { + //blog(LOG_INFO, "channels: %d", audioFrame->channels); + } + } +} + +void setup_call() +{ + obs_enter_graphics(); + webrtcTexture = + gs_texture_create(1920, 1080, GS_BGRA, 1, NULL, GS_DYNAMIC); + obs_leave_graphics(); + + const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264); + + AVDictionary *opts = NULL; + //av_dict_set(&opts, "b", "2.5M", 0); + if (!codec) + exit(1); + AVCodecContext *context = avcodec_alloc_context3(codec); + if (avcodec_open2(context, codec, &opts) < 0) + exit(1); + + /*AVCodecParameters* codecpar = avcodec_parameters_alloc(); + codecpar->codec_id = AV_CODEC_ID_H264; + codecpar->height = 720; + codecpar->width = 1280;*/ + + frame = av_frame_alloc(); + audioFrame = av_frame_alloc(); + dst = av_frame_alloc(); + + const AVCodec *opusCodec = avcodec_find_decoder(AV_CODEC_ID_OPUS); + AVCodecContext *audioContext = avcodec_alloc_context3(opusCodec); + if (avcodec_open2(audioContext, opusCodec, NULL) < 0) + exit(1); + + //codecpar-> + + //avcodec_parameters_to_context(context, codecpar); + + struct OBSCallParticipant *callParticipant = + malloc(sizeof(struct OBSCallParticipant)); + callParticipant->videoContext = context; + callParticipant->audioContext = audioContext; + + call = obs_webrtc_call_init(callParticipant, packet_callback); + + /*if (pthread_create(&thread, NULL, video_thread, NULL) != 0) { + blog(LOG_ERROR, "Failed to make render thread of webrtc call"); + }else { + blog(LOG_ERROR, "Thread running"); + }*/ +} + +void start_call() +{ + obs_webrtc_call_start(call); +} diff --git a/plugins/obs-webrtc/webrtc-call.h b/plugins/obs-webrtc/webrtc-call.h new file mode 100644 index 00000000000000..a85c5d229c9eac --- /dev/null +++ b/plugins/obs-webrtc/webrtc-call.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +extern struct gs_texture *webrtcTexture; + +void setup_call(); +void start_call(); +static void *video_thread(void *data); \ No newline at end of file diff --git a/plugins/obs-webrtc/webrtc-services-main.c b/plugins/obs-webrtc/webrtc-services-main.c new file mode 100644 index 00000000000000..7eaae82e4c797b --- /dev/null +++ b/plugins/obs-webrtc/webrtc-services-main.c @@ -0,0 +1,42 @@ +#include "util/text-lookup.h" +#include "util/threading.h" +#include "util/platform.h" +#include "util/dstr.h" +#include "obs-module.h" +#include "file-updater/file-updater.h" + +OBS_DECLARE_MODULE() +OBS_MODULE_USE_DEFAULT_LOCALE("obs-webrtc-services", "en-US") +MODULE_EXPORT const char *obs_module_description(void) +{ + return "OBS core WebRTC services"; +} + +#define RTMP_SERVICES_LOG_STR "[obs-webrtc-services plugin] " +#define RTMP_SERVICES_VER_STR \ + "obs-webrtc-services plugin (libobs " OBS_VERSION ")" + +extern struct obs_service_info whip_service; + +static update_info_t *update_info = NULL; +static struct dstr module_name = {0}; + +const char *get_module_name(void) +{ + return module_name.array; +} + +bool obs_module_load(void) +{ + dstr_copy(&module_name, "obs-webrtc-services plugin (libobs "); + dstr_cat(&module_name, obs_get_version_string()); + dstr_cat(&module_name, ")"); + + obs_register_service(&whip_service); + return true; +} + +void obs_module_unload(void) +{ + dstr_free(&module_name); +} diff --git a/plugins/obs-webrtc/webrtc-source.c b/plugins/obs-webrtc/webrtc-source.c new file mode 100644 index 00000000000000..56a378c27e8b02 --- /dev/null +++ b/plugins/obs-webrtc/webrtc-source.c @@ -0,0 +1,81 @@ +#include + +#include "webrtc-call.h" + +struct webrtc_source { + int tmp; +}; + +static const char *webrtc_source_getname(void *unused) +{ + UNUSED_PARAMETER(unused); + return obs_module_text("WebRTCSource"); +} + +static void *webrtc_source_create(obs_data_t *settings, obs_source_t *source) +{ + struct webrtc_source *webrtcSource = + bzalloc(sizeof(struct webrtc_source)); + return webrtcSource; +} + +static void webrtc_source_destroy(void *data) +{ + struct webrtc_source *webrtcSource = data; + + if (webrtcSource) { + bfree(webrtcSource); + } +} + +static obs_properties_t *webrtc_source_get_properties(void *data) +{ + return obs_properties_create(); +} + +static void webrtc_source_render(void *data, gs_effect_t *effect) +{ + + if (!webrtcTexture) + return; + + const bool previous = gs_framebuffer_srgb_enabled(); + gs_enable_framebuffer_srgb(true); + + gs_blend_state_push(); + gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA); + + gs_eparam_t *const param = gs_effect_get_param_by_name(effect, "image"); + gs_effect_set_texture_srgb(param, webrtcTexture); + + gs_draw_sprite(webrtcTexture, 0, 1920, 1080); + + gs_blend_state_pop(); + + gs_enable_framebuffer_srgb(previous); +} + +uint32_t webrtc_source_get_width(void *data) +{ + return 1920; +} + +uint32_t webrtc_source_get_height(void *data) +{ + return 1080; +} + +struct obs_source_info webrtc_source_info = { + .id = "webrtc_source", + .type = OBS_SOURCE_TYPE_INPUT, + .output_flags = OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO | + OBS_SOURCE_DO_NOT_DUPLICATE, + .get_name = webrtc_source_getname, + .create = webrtc_source_create, + .destroy = webrtc_source_destroy, + .get_properties = webrtc_source_get_properties, + .icon_type = OBS_ICON_TYPE_MEDIA, + .video_render = webrtc_source_render, + .get_width = webrtc_source_get_width, + .get_height = webrtc_source_get_height, +}; \ No newline at end of file diff --git a/plugins/obs-webrtc/webrtc-source.h b/plugins/obs-webrtc/webrtc-source.h new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/plugins/obs-webrtc/webrtc-stream.c b/plugins/obs-webrtc/webrtc-stream.c new file mode 100644 index 00000000000000..7bb300265d194e --- /dev/null +++ b/plugins/obs-webrtc/webrtc-stream.c @@ -0,0 +1,120 @@ +#include "webrtc-stream.h" + +static const char *webrtc_stream_getname(void *unused) +{ + UNUSED_PARAMETER(unused); + return obs_module_text("WebRTCStream"); +} + +static void *webrtc_stream_create(obs_data_t *settings, obs_output_t *output) +{ + struct webrtc_stream *stream = bzalloc(sizeof(struct webrtc_stream)); + + stream->output = output; + + stream->obsrtc = obs_webrtc_stream_init("test"); + + return stream; +} + +static void webrtc_stream_destroy(void *data) {} + +static bool webrtc_stream_start(void *data) +{ + struct webrtc_stream *stream = data; + + if (!obs_output_can_begin_data_capture(stream->output, 0)) { + return false; + } + if (!obs_output_initialize_encoders(stream->output, 0)) { + return false; + } + + obs_webrtc_stream_connect(stream->obsrtc); + + obs_output_begin_data_capture(stream->output, 0); + + return true; +} + +static void webrtc_stream_stop(void *data, uint64_t ts) +{ + struct webrtc_stream *stream = data; + + obs_output_end_data_capture(stream->output); +} + +static void webrtc_stream_data(void *data, struct encoder_packet *packet) +{ + struct webrtc_stream *stream = data; + + if (packet->type == OBS_ENCODER_VIDEO) { + int64_t duration = packet->dts_usec - stream->video_timestamp; + obs_webrtc_stream_data(stream->obsrtc, packet->data, + packet->size, duration); + stream->video_timestamp = packet->dts_usec; + } + + if (packet->type == OBS_ENCODER_AUDIO) { + int64_t duration = packet->dts_usec - stream->audio_timestamp; + obs_webrtc_stream_audio(stream->obsrtc, packet->data, + packet->size, duration); + stream->audio_timestamp = packet->dts_usec; + } +} + +static void webrtc_stream_defaults(obs_data_t *defaults) +{ + /*obs_data_set_default_int(defaults, OPT_DROP_THRESHOLD, 700); + obs_data_set_default_int(defaults, OPT_PFRAME_DROP_THRESHOLD, 900); + obs_data_set_default_int(defaults, OPT_MAX_SHUTDOWN_TIME_SEC, 30); + obs_data_set_default_string(defaults, OPT_BIND_IP, "default"); + obs_data_set_default_bool(defaults, OPT_NEWSOCKETLOOP_ENABLED, false); + obs_data_set_default_bool(defaults, OPT_LOWLATENCY_ENABLED, false);*/ +} + +static obs_properties_t *webrtc_stream_properties(void *unused) +{ + UNUSED_PARAMETER(unused); + + obs_properties_t *props = obs_properties_create(); + + return props; +} + +static uint64_t webrtc_stream_total_bytes_sent(void *data) +{ + //struct rtmp_stream *stream = data; + return 100; +} + +static int webrtc_stream_dropped_frames(void *data) +{ + //struct rtmp_stream *stream = data; + return 0; +} + +static int webrtc_stream_connect_time(void *data) +{ + //struct rtmp_stream *stream = data; + return 100; +} + +struct obs_output_info webrtc_output_info = { + .id = "webrtc_output", + .flags = OBS_OUTPUT_AV | OBS_OUTPUT_ENCODED | OBS_OUTPUT_SERVICE | + OBS_OUTPUT_MULTI_TRACK, + .encoded_video_codecs = "h264", + .encoded_audio_codecs = "opus", + .get_name = webrtc_stream_getname, + .create = webrtc_stream_create, + .destroy = webrtc_stream_destroy, + .start = webrtc_stream_start, + .stop = webrtc_stream_stop, + .encoded_packet = webrtc_stream_data, + .get_defaults = webrtc_stream_defaults, + .get_properties = webrtc_stream_properties, + .get_total_bytes = webrtc_stream_total_bytes_sent, + .get_connect_time_ms = webrtc_stream_connect_time, + .get_dropped_frames = webrtc_stream_dropped_frames, +}; \ No newline at end of file diff --git a/plugins/obs-webrtc/webrtc-stream.h b/plugins/obs-webrtc/webrtc-stream.h new file mode 100644 index 00000000000000..9a1e8b6a740b05 --- /dev/null +++ b/plugins/obs-webrtc/webrtc-stream.h @@ -0,0 +1,11 @@ +#include "obs-module.h" +#include "./webrtc/bindings.h" + +struct webrtc_stream { + obs_output_t *output; + + int64_t audio_timestamp; + int64_t video_timestamp; + + OBSWebRTCStream *obsrtc; +}; \ No newline at end of file diff --git a/plugins/obs-webrtc/webrtc.c b/plugins/obs-webrtc/webrtc.c new file mode 100644 index 00000000000000..0749f7849caaca --- /dev/null +++ b/plugins/obs-webrtc/webrtc.c @@ -0,0 +1,32 @@ +#include +#include "./webrtc/bindings.h" +#include "webrtc-call.h" + +OBS_DECLARE_MODULE() +OBS_MODULE_USE_DEFAULT_LOCALE("obs-webrtc", "en-US") +MODULE_EXPORT const char *obs_module_description(void) +{ + return "OBS webrtc module"; +} + +extern struct obs_output_info webrtc_output_info; +extern struct obs_service_info whip_service; +extern struct obs_source_info webrtc_source_info; + +struct gs_texture *webrtcTexture; + +bool obs_module_load(void) +{ + obs_register_output(&webrtc_output_info); + obs_register_service(&whip_service); + obs_register_source(&webrtc_source_info); + return true; +} + +void obs_module_post_load(void) +{ + setup_call(); + start_call(); +} + +void obs_module_unload(void) {} diff --git a/plugins/obs-webrtc/webrtc/Cargo.lock b/plugins/obs-webrtc/webrtc/Cargo.lock new file mode 100644 index 00000000000000..793b218ab807e4 --- /dev/null +++ b/plugins/obs-webrtc/webrtc/Cargo.lock @@ -0,0 +1,2631 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aead" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", + "rand_core 0.6.3", +] + +[[package]] +name = "aes" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" +dependencies = [ + "aes-soft", + "aesni", + "cipher 0.2.5", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher 0.3.0", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da" +dependencies = [ + "aead 0.3.2", + "aes 0.6.0", + "cipher 0.2.5", + "ctr 0.6.0", + "ghash 0.3.1", + "subtle", +] + +[[package]] +name = "aes-gcm" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +dependencies = [ + "aead 0.4.3", + "aes 0.7.5", + "cipher 0.3.0", + "ctr 0.8.0", + "ghash 0.4.4", + "subtle", +] + +[[package]] +name = "aes-soft" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" +dependencies = [ + "cipher 0.2.5", + "opaque-debug", +] + +[[package]] +name = "aesni" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" +dependencies = [ + "cipher 0.2.5", + "opaque-debug", +] + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "async-trait" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitvec" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98fcd36dda4e17b7d7abc64cb549bf0201f4ab71e00700c798ca7e62ed3761fa" +dependencies = [ + "funty", + "radium 0.3.0", + "wyz", +] + +[[package]] +name = "bitvec" +version = "0.19.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33" +dependencies = [ + "funty", + "radium 0.5.3", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-modes" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0" +dependencies = [ + "block-padding", + "cipher 0.2.5", +] + +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cbindgen" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e3973b165dc0f435831a9e426de67e894de532754ff7a3f307c03ee5dec7dc" +dependencies = [ + "clap", + "heck", + "indexmap", + "log", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn", + "tempfile", + "toml", +] + +[[package]] +name = "cc" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" + +[[package]] +name = "ccm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aca1a8fbc20b50ac9673ff014abfb2b5f4085ee1a850d408f14a159c5853ac7" +dependencies = [ + "aead 0.3.2", + "cipher 0.2.5", + "subtle", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "cipher" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim 0.8.0", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "const-oid" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f6b64db6932c7e49332728e3a6bd82c6b7e16016607d20923b537c3bc4c0d5f" + +[[package]] +name = "core-foundation" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + +[[package]] +name = "cpuid-bool" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" + +[[package]] +name = "crc" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" + +[[package]] +name = "crypto-common" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0" +dependencies = [ + "generic-array", +] + +[[package]] +name = "crypto-mac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" +dependencies = [ + "cipher 0.2.5", +] + +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher 0.3.0", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "darling" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "data-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" + +[[package]] +name = "der" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f59c66c30bb7445c8320a5f9233e437e3572368099f25532a59054328899b4" +dependencies = [ + "const-oid", +] + +[[package]] +name = "der-oid-macro" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4cccf60bb98c0fca115a581f894aed0e43fa55bf289fdac5599bec440bb4fd6" +dependencies = [ + "nom 6.1.2", + "num-bigint", + "num-traits", + "syn", +] + +[[package]] +name = "der-oid-macro" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c73af209b6a5dc8ca7cbaba720732304792cddc933cfea3d74509c2b1ef2f436" +dependencies = [ + "num-bigint", + "num-traits", + "syn", +] + +[[package]] +name = "der-parser" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7ededb7525bb4114bc209685ce7894edc2965f4914312a1ea578a645a237f0" +dependencies = [ + "der-oid-macro 0.4.0", + "nom 6.1.2", + "num-bigint", + "num-traits", + "rusticata-macros 3.2.0", +] + +[[package]] +name = "der-parser" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9807efb310ce4ea172924f3a69d82f9fd6c9c3a19336344591153e665b31c43e" +dependencies = [ + "der-oid-macro 0.5.0", + "nom 7.1.0", + "num-bigint", + "num-traits", + "rusticata-macros 4.0.0", +] + +[[package]] +name = "derive_builder" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d13202debe11181040ae9063d739fa32cfcaaebe2275fe387703460ae2365b30" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73" +dependencies = [ + "derive_builder_core", + "syn", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" +dependencies = [ + "block-buffer 0.10.0", + "crypto-common", + "generic-array", +] + +[[package]] +name = "displaydoc" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ecdsa" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fbdb4ff710acb4db8ca29f93b897529ea6d6a45626d5183b47e012aa6ae7e4" +dependencies = [ + "elliptic-curve", + "hmac 0.10.1", + "signature", +] + +[[package]] +name = "elliptic-curve" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2db227e61a43a34915680bdda462ec0e212095518020a88a1f91acd16092c39" +dependencies = [ + "bitvec 0.18.5", + "digest 0.9.0", + "ff", + "funty", + "generic-array", + "group", + "pkcs8", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "fastrand" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2" +dependencies = [ + "instant", +] + +[[package]] +name = "ff" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01646e077d4ebda82b73f1bca002ea1e91561a77df2431a9e79729bcc31950ef" +dependencies = [ + "bitvec 0.18.5", + "rand_core 0.5.1", + "subtle", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + +[[package]] +name = "futures-channel" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" + +[[package]] +name = "futures-sink" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" + +[[package]] +name = "futures-task" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" + +[[package]] +name = "futures-util" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "ghash" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375" +dependencies = [ + "opaque-debug", + "polyval 0.4.5", +] + +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug", + "polyval 0.5.3", +] + +[[package]] +name = "group" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc11f9f5fbf1943b48ae7c2bf6846e7d827a512d1be4f23af708f5ca5d01dde1" +dependencies = [ + "ff", + "rand_core 0.5.1", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9de88456263e249e241fcd211d3954e2c9b0ef7ccfc235a444eb367cae3689" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +dependencies = [ + "crypto-mac 0.10.1", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest 0.9.0", +] + +[[package]] +name = "http" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.1", +] + +[[package]] +name = "http-body" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa 0.4.8", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "interceptor" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f9c57d39048948d61191cdbe2d3900560cbe0adc626fa51677fe1fb43ddfc8a" +dependencies = [ + "async-trait", + "bytes", + "log", + "rand", + "rtcp", + "rtp", + "thiserror", + "tokio", + "waitgroup", + "webrtc-srtp", + "webrtc-util", +] + +[[package]] +name = "ipnet" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "js-sys" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lexical-core" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" +dependencies = [ + "arrayvec", + "bitflags", + "cfg-if", + "ryu", + "static_assertions", +] + +[[package]] +name = "libc" +version = "0.2.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "md-5" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6a38fc55c8bbc10058782919516f88826e70320db6d206aebc49611d24216ae" +dependencies = [ + "digest 0.10.1", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "mio" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "native-tls" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nix" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "nom" +version = "6.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" +dependencies = [ + "bitvec 0.19.6", + "funty", + "lexical-core", + "memchr", + "version_check", +] + +[[package]] +name = "nom" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" +dependencies = [ + "memchr", + "minimal-lexical", + "version_check", +] + +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "oid-registry" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6aae73e474f83beacd8ae2179e328e03d63d9223949d97e1b7c108059a34715" +dependencies = [ + "der-parser 5.1.2", +] + +[[package]] +name = "oid-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe554cb2393bc784fd678c82c84cc0599c31ceadc7f03a594911f822cb8d1815" +dependencies = [ + "der-parser 6.0.0", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "openssl" +version = "0.10.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "p256" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adcc06fe90ec8fb2d2ad46746d2cbd639b158d4240364aa832da7e263dbee91" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "pem" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9a3b09a20e374558580a4914d3b7d89bd61b954a5a5e1dcbea98753addb1947" +dependencies = [ + "base64", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4839a901843f3942576e65857f0ebf2e190ef7024d3c62a94099ba3f819ad1d" +dependencies = [ + "der", +] + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] +name = "polyval" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd" +dependencies = [ + "cpuid-bool", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" + +[[package]] +name = "radium" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core 0.6.3", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom 0.2.4", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core 0.6.3", +] + +[[package]] +name = "rcgen" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5911d1403f4143c9d56a702069d593e8d0f3fab880a85e103604d0893ea31ba7" +dependencies = [ + "chrono", + "pem", + "ring", + "x509-parser 0.12.0", + "yasna", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "reqwest" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "lazy_static", + "log", + "mime", + "native-tls", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rtcp" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d9625e47edb43aca711ec826ad12154d364ada9e60f4e6f8d40471b3e1e156" +dependencies = [ + "bytes", + "thiserror", + "webrtc-util", +] + +[[package]] +name = "rtp" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5110c12c9f7d1e76eba80076cce4ccb82ee085bd10a62472468de0663240f8b5" +dependencies = [ + "async-trait", + "bytes", + "rand", + "thiserror", + "webrtc-util", +] + +[[package]] +name = "rusticata-macros" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbbee512c633ecabd4481c40111b6ded03ddd9ab10ba6caa5a74e14c889921ad" +dependencies = [ + "nom 6.1.2", +] + +[[package]] +name = "rusticata-macros" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c52377bb2288aa522a0c8208947fada1e0c76397f108cc08f57efe6077b50d" +dependencies = [ + "nom 7.1.0", +] + +[[package]] +name = "rustls" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +dependencies = [ + "base64", + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sdp" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b079873978bd58399b80c17acf2a78d3cbba54254aa9b522a63996f29b5199d" +dependencies = [ + "rand", + "substring", + "thiserror", + "url", +] + +[[package]] +name = "security-framework" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d09d3c15d814eda1d6a836f2f2b56a6abc1446c8a34351cb3180d3db92ffe4ce" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e90dd10c41c6bfc633da6e0c659bd25d31e0791e5974ac42970267d59eba87f7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79" +dependencies = [ + "itoa 1.0.1", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.1", + "ryu", + "serde", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29f060a7d147e33490ec10da418795238fd7545bba241504d6b31a409f2e6210" +dependencies = [ + "digest 0.9.0", + "rand_core 0.5.1", +] + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "socket2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "stun" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c5e998a0b2bc5fe66e50dff28310f54210155f4d943a6c2b80bbb52fbaf3b0" +dependencies = [ + "base64", + "crc", + "lazy_static", + "md-5", + "rand", + "ring", + "subtle", + "thiserror", + "tokio", + "url", + "webrtc-util", +] + +[[package]] +name = "substring" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86" +dependencies = [ + "autocfg", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "turn" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4bdda1bbd859cb47d2a7299f83e1ab1f07468b7874985ec38974b535fe826a9" +dependencies = [ + "async-trait", + "base64", + "log", + "md-5", + "rand", + "ring", + "stun", + "thiserror", + "tokio", + "webrtc-util", +] + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "unicode-bidi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.4", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waitgroup" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1f50000a783467e6c0200f9d10642f4bc424e39efc1b770203e88b488f79292" +dependencies = [ + "atomic-waker", +] + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasm-bindgen" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" + +[[package]] +name = "web-sys" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webrtc" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5ba0c1cc8a2daa7bbf049e0785c06a0c4a144d466d6d0a7e1bb2f9cade4b759" +dependencies = [ + "async-trait", + "bytes", + "hex", + "interceptor", + "lazy_static", + "log", + "rand", + "rcgen", + "regex", + "ring", + "rtcp", + "rtp", + "rustls", + "sdp", + "serde", + "serde_json", + "sha2", + "stun", + "thiserror", + "tokio", + "turn", + "url", + "waitgroup", + "webrtc-data", + "webrtc-dtls", + "webrtc-ice", + "webrtc-mdns", + "webrtc-media", + "webrtc-sctp", + "webrtc-srtp", + "webrtc-util", +] + +[[package]] +name = "webrtc-data" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c6e77d7f15d517a85b1ac10921a91b541d2358174313719cbd1ed3ee1a439d" +dependencies = [ + "bytes", + "derive_builder", + "log", + "thiserror", + "tokio", + "webrtc-sctp", + "webrtc-util", +] + +[[package]] +name = "webrtc-dtls" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93acab591466d3fd09ce2e03e475e4009a1965af13e63d5973937e3df7f0c421" +dependencies = [ + "aes 0.6.0", + "aes-gcm 0.8.0", + "async-trait", + "bincode", + "block-modes", + "byteorder", + "ccm", + "der-parser 5.1.2", + "elliptic-curve", + "hmac 0.10.1", + "lazy_static", + "log", + "oid-registry 0.1.5", + "p256", + "rand", + "rand_core 0.5.1", + "rcgen", + "ring", + "rustls", + "serde", + "serde_derive", + "sha-1", + "sha2", + "signature", + "subtle", + "thiserror", + "tokio", + "webpki", + "webrtc-util", + "x25519-dalek", + "x509-parser 0.9.2", +] + +[[package]] +name = "webrtc-ice" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf8e7a68b512049291fd34df722d86205b47310469e012e5802b78b6bd180ba2" +dependencies = [ + "async-trait", + "crc", + "log", + "rand", + "stun", + "thiserror", + "tokio", + "turn", + "url", + "uuid", + "waitgroup", + "webrtc-mdns", + "webrtc-util", +] + +[[package]] +name = "webrtc-mdns" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59d92e5fe099cf7df43b06c2ee599ca327a319d1a8249033e53494926b426e2a" +dependencies = [ + "log", + "socket2", + "thiserror", + "tokio", + "webrtc-util", +] + +[[package]] +name = "webrtc-media" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fdf3e009c194ec4b8034d8dee81db45b146b7469928f1dfd40ba7be5faf52c1" +dependencies = [ + "byteorder", + "bytes", + "derive_builder", + "displaydoc", + "rand", + "rtp", + "thiserror", + "webrtc-util", +] + +[[package]] +name = "webrtc-rs-lib" +version = "0.1.0" +dependencies = [ + "anyhow", + "base64", + "bytes", + "cbindgen", + "reqwest", + "serde", + "serde_derive", + "serde_json", + "tokio", + "webrtc", +] + +[[package]] +name = "webrtc-sctp" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d48f4c8601507ef48712acdfd5019fc68c4f42d6cf934ec6937b9737339ba030" +dependencies = [ + "async-trait", + "bytes", + "crc", + "log", + "rand", + "thiserror", + "tokio", + "webrtc-util", +] + +[[package]] +name = "webrtc-srtp" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d21403708d58bf8532393d92be2c84d7ffee5b7847a2cc57147d88f4693227" +dependencies = [ + "aead 0.4.3", + "aes 0.7.5", + "aes-gcm 0.9.4", + "async-trait", + "byteorder", + "bytes", + "ctr 0.8.0", + "hmac 0.11.0", + "log", + "rtcp", + "rtp", + "sha-1", + "subtle", + "thiserror", + "tokio", + "webrtc-util", +] + +[[package]] +name = "webrtc-util" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b69bdea720881eddee50bd969be052ed95f04ccc5a6f684495131afb87e31c" +dependencies = [ + "async-trait", + "bitflags", + "bytes", + "cc", + "ipnet", + "lazy_static", + "libc", + "log", + "nix", + "parking_lot", + "rand", + "thiserror", + "tokio", + "winapi", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winreg" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +dependencies = [ + "winapi", +] + +[[package]] +name = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + +[[package]] +name = "x25519-dalek" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077" +dependencies = [ + "curve25519-dalek", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "x509-parser" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64abca276c58f8341ddc13fd4bd6ae75993cc669043f5b34813c90f7dff04771" +dependencies = [ + "base64", + "chrono", + "data-encoding", + "der-parser 5.1.2", + "lazy_static", + "nom 6.1.2", + "oid-registry 0.1.5", + "rusticata-macros 3.2.0", + "rustversion", + "thiserror", +] + +[[package]] +name = "x509-parser" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc90836a84cb72e6934137b1504d0cae304ef5d83904beb0c8d773bbfe256ed" +dependencies = [ + "base64", + "chrono", + "data-encoding", + "der-parser 6.0.0", + "lazy_static", + "nom 7.1.0", + "oid-registry 0.2.0", + "ring", + "rusticata-macros 4.0.0", + "thiserror", +] + +[[package]] +name = "yasna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e262a29d0e61ccf2b6190d7050d4b237535fc76ce4c1210d9caa316f71dffa75" +dependencies = [ + "chrono", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e8f13fef10b63c06356d65d416b070798ddabcadc10d3ece0c5be9b3c7eddb" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/plugins/obs-webrtc/webrtc/Cargo.toml b/plugins/obs-webrtc/webrtc/Cargo.toml new file mode 100644 index 00000000000000..e9af0341c679df --- /dev/null +++ b/plugins/obs-webrtc/webrtc/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "webrtc-rs-lib" +version = "0.1.0" +edition = "2018" +build = "build.rs" + +[dependencies] +webrtc = "0.3.3" +tokio = { version = "1.16.1", features = ["full"] } +anyhow = "1.0.45" +bytes = "1" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +serde_derive = "1.0" +base64 = "0.13.0" +reqwest = { version = "0.11.7", features = ["json"] } + +[lib] +crate-type=["cdylib"] + +[build-dependencies] +cbindgen = "0.20" + + + diff --git a/plugins/obs-webrtc/webrtc/bindings.h b/plugins/obs-webrtc/webrtc/bindings.h new file mode 100644 index 00000000000000..c5fceb5d1c43de --- /dev/null +++ b/plugins/obs-webrtc/webrtc/bindings.h @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +typedef struct CodecContext CodecContext; + +typedef struct OBSWebRTCCall OBSWebRTCCall; + +typedef struct OBSWebRTCStream OBSWebRTCStream; + +typedef void (*PacketCallback)(struct CodecContext, const uint8_t *, + unsigned int, unsigned int); + +struct OBSWebRTCCall *obs_webrtc_call_init(const void *context, + PacketCallback cb); + +void obs_webrtc_call_start(struct OBSWebRTCCall *obsrtc); + +struct OBSWebRTCStream *obs_webrtc_stream_init(const char *name); + +void obs_webrtc_stream_connect(struct OBSWebRTCStream *obsrtc); + +void obs_webrtc_stream_data(struct OBSWebRTCStream *obsrtc, const uint8_t *data, + uintptr_t size, uint64_t duration); + +void obs_webrtc_stream_audio(struct OBSWebRTCStream *obsrtc, + const uint8_t *data, uintptr_t size, + uint64_t duration); diff --git a/plugins/obs-webrtc/webrtc/build.rs b/plugins/obs-webrtc/webrtc/build.rs new file mode 100644 index 00000000000000..fef2f459a80267 --- /dev/null +++ b/plugins/obs-webrtc/webrtc/build.rs @@ -0,0 +1,18 @@ +extern crate cbindgen; + +use std::env; + +fn main() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + + let config = cbindgen::Config { + language: cbindgen::Language::C, + ..Default::default() + }; + + match cbindgen::generate_with_config(&crate_dir, config) { + Ok(bindings) => bindings.write_to_file("./bindings.h"), + Err(cbindgen::Error::ParseSyntaxError { .. }) => return, // ignore in favor of cargo's syntax check + Err(err) => panic!("{:?}", err) + }; +} \ No newline at end of file diff --git a/plugins/obs-webrtc/webrtc/cbindgen.toml b/plugins/obs-webrtc/webrtc/cbindgen.toml new file mode 100644 index 00000000000000..da0c7f74ad59cb --- /dev/null +++ b/plugins/obs-webrtc/webrtc/cbindgen.toml @@ -0,0 +1 @@ +language = "C" \ No newline at end of file diff --git a/plugins/obs-webrtc/webrtc/src/call.rs b/plugins/obs-webrtc/webrtc/src/call.rs new file mode 100644 index 00000000000000..8db81a6de52bdc --- /dev/null +++ b/plugins/obs-webrtc/webrtc/src/call.rs @@ -0,0 +1,305 @@ +use anyhow::Result; + +use std::sync::Mutex; +use std::{convert::TryInto, sync::Arc}; +use std::{ops::Add, os::raw::c_char}; + +use tokio::runtime::Runtime; +use tokio::time::Duration; + +use webrtc::api::interceptor_registry::register_default_interceptors; +use webrtc::api::media_engine::{MediaEngine, MIME_TYPE_H264, MIME_TYPE_OPUS}; +use webrtc::api::APIBuilder; +use webrtc::ice_transport::ice_server::RTCIceServer; +use webrtc::interceptor::registry::Registry; +use webrtc::peer_connection::configuration::RTCConfiguration; +use webrtc::peer_connection::peer_connection_state::RTCPeerConnectionState; +use webrtc::rtcp::payload_feedbacks::picture_loss_indication::PictureLossIndication; +use webrtc::rtp::codecs::h264::H264Packet; +use webrtc::rtp::codecs::opus::OpusPacket; +use webrtc::rtp::packetizer::Depacketizer; +use webrtc::rtp_transceiver::rtp_codec::{ + RTCRtpCodecCapability, RTCRtpCodecParameters, RTPCodecType, +}; +use webrtc::rtp_transceiver::rtp_receiver::RTCRtpReceiver; +use webrtc::track::track_remote::TrackRemote; + +use std::os::raw::{c_uint, c_void}; + +use crate::whip; + +pub type PacketCallback = unsafe extern "C" fn(CodecContext, *const u8, c_uint, c_uint); + +pub struct OBSWebRTCCall { + runtime: Runtime, + context: CodecContext, + cb: PacketCallback, +} +#[derive(Copy, Clone)] +pub struct CodecContext(*const c_void); + +unsafe impl Send for CodecContext {} +unsafe impl Sync for CodecContext {} + +impl OBSWebRTCCall { + fn callback(&self, data: bytes::Bytes, video: u32) { + let length = data.len().try_into().unwrap(); + unsafe { + (self.cb)(self.context, data.as_ptr(), length, video); + } + } +} + +#[no_mangle] +pub extern "C" fn obs_webrtc_call_init( + context: *const c_void, + cb: PacketCallback, +) -> *mut OBSWebRTCCall { + Box::into_raw(Box::new(OBSWebRTCCall { + runtime: tokio::runtime::Runtime::new().unwrap(), + context: CodecContext(context), + cb, + })) +} + +#[no_mangle] +pub extern "C" fn obs_webrtc_call_start(obsrtc: *mut OBSWebRTCCall) { + unsafe { + let obs = Box::from_raw(obsrtc); + (*obsrtc).runtime.spawn(async { + obs_webrtc_call_peer_connect(obs).await; + }); + } +} + +async fn obs_webrtc_call_peer_connect(obsrtc: Box) -> Result<()> { + // Create a MediaEngine object to configure the supported codec + let mut m = MediaEngine::default(); + + // Setup the codecs you want to use. + // We'll use a H264 and Opus but you can also define your own + m.register_codec( + RTCRtpCodecParameters { + capability: RTCRtpCodecCapability { + mime_type: MIME_TYPE_H264.to_owned(), + clock_rate: 90000, + channels: 0, + sdp_fmtp_line: + "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f" + .to_owned(), + rtcp_feedback: vec![], + }, + payload_type: 102, + ..Default::default() + }, + RTPCodecType::Video, + )?; + + m.register_codec( + RTCRtpCodecParameters { + capability: RTCRtpCodecCapability { + mime_type: MIME_TYPE_OPUS.to_owned(), + clock_rate: 48000, + channels: 2, + sdp_fmtp_line: "".to_owned(), + rtcp_feedback: vec![], + }, + payload_type: 111, + ..Default::default() + }, + RTPCodecType::Audio, + )?; + + // Create a InterceptorRegistry. This is the user configurable RTP/RTCP Pipeline. + // This provides NACKs, RTCP Reports and other features. If you use `webrtc.NewPeerConnection` + // this is enabled by default. If you are manually managing You MUST create a InterceptorRegistry + // for each PeerConnection. + let mut registry = Registry::new(); + + // Use the default set of Interceptors + registry = register_default_interceptors(registry, &mut m).await?; + + let api = APIBuilder::new() + .with_media_engine(m) + .with_interceptor_registry(registry) + .build(); + + let config = RTCConfiguration { + ice_servers: vec![RTCIceServer { + urls: vec!["stun:stun.l.google.com:19302".to_owned()], + ..Default::default() + }], + ..Default::default() + }; + + // Create a new RTCPeerConnection + let peer_connection = Arc::new(api.new_peer_connection(config).await?); + + // Allow us to receive 1 audio track, and 1 video track + peer_connection + .add_transceiver_from_kind(RTPCodecType::Audio, &[]) + .await?; + peer_connection + .add_transceiver_from_kind(RTPCodecType::Video, &[]) + .await?; + + let pc = Arc::downgrade(&peer_connection); + + let obsarc = Arc::new(obsrtc); + + peer_connection.on_track(Box::new(move |track: Option>, _receiver: Option>| { + if let Some(track) = track { + // Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval + let media_ssrc = track.ssrc(); + let pc2 = pc.clone(); + tokio::spawn(async move { + let mut result = Result::::Ok(0); + while result.is_ok() { + let timeout = tokio::time::sleep(Duration::from_secs(3)); + tokio::pin!(timeout); + + tokio::select! { + _ = timeout.as_mut() =>{ + if let Some(pc) = pc2.upgrade(){ + result = pc.write_rtcp(&[Box::new(PictureLossIndication{ + sender_ssrc: 0, + media_ssrc, + })]).await.map_err(Into::into); + }else { + break; + } + } + }; + } + }); + + + let obsclone = obsarc.clone(); + //let notify_rx2 = Arc::clone(¬ify_rx); + + Box::pin(async move { + let codec = track.codec().await; + let mime_type = codec.capability.mime_type.to_lowercase(); + if mime_type == MIME_TYPE_OPUS.to_lowercase() { + println!("Got Opus track, saving to disk as output.opus (48 kHz, 2 channels)"); + tokio::spawn(async move { + + while let Ok((rtp_packet, _)) = track.read_rtp().await { + + let mut opus_packet = OpusPacket::default(); + let payload = opus_packet.depacketize(&rtp_packet.payload); + + match payload { + Ok(tmp) => obsclone.callback(tmp, 0), + Err(e) => println!("packet ERROR: {}", e), + } + } + + }); + } else if mime_type == MIME_TYPE_H264.to_lowercase() { + println!("Got H264 track!"); + tokio::spawn(async move { + + let mut cached_packet = H264Packet::default(); + + let mut has_key_frame = false; + + while let Ok((rtp_packet, _)) = track.read_rtp().await { + if rtp_packet.payload.is_empty() { + continue; + } + + + if !has_key_frame { + has_key_frame = is_key_frame(&rtp_packet.payload); + if !has_key_frame { + continue; + } + } + + let payload = cached_packet.depacketize(&rtp_packet.payload); + match payload { + Ok(tmp) => obsclone.callback(tmp, 1), + Err(e) => println!("packet ERROR: {}", e), + } + } + }); + } + }) + }else { + Box::pin(async {}) + } + })).await; + + let (done_tx, mut done_rx) = tokio::sync::mpsc::channel::<()>(1); + + // Set the handler for Peer connection state + // This will notify you when the peer has connected/disconnected + peer_connection + .on_peer_connection_state_change(Box::new(move |s: RTCPeerConnectionState| { + println!("Peer Connection State has changed: {}", s); + + if s == RTCPeerConnectionState::Failed { + // Wait until PeerConnection has had no network activity for 30 seconds or another failure. It may be reconnected using an ICE Restart. + // Use webrtc.PeerConnectionStateDisconnected if you are interested in detecting faster timeout. + // Note that the PeerConnection may come back from PeerConnectionStateDisconnected. + println!("Peer Connection has gone to failed exiting"); + let _ = done_tx.try_send(()); + } + + Box::pin(async {}) + })) + .await; + + // Create an offer to send to the browser + let offer = peer_connection.create_offer(None).await?; + + // Create channel that is blocked until ICE Gathering is complete + let mut gather_complete = peer_connection.gathering_complete_promise().await; + + // Sets the LocalDescription, and starts our UDP listeners + peer_connection.set_local_description(offer).await?; + + // Block until ICE Gathering is complete, disabling trickle ICE + // we do this because we only can exchange one signaling message + // in a production application you should exchange ICE Candidates via OnICECandidate + let _ = gather_complete.recv().await; + + // Output the answer in base64 so we can paste it in browser + if let Some(local_desc) = peer_connection.local_description().await { + let sdp = whip::do_whip(local_desc).await?; + + peer_connection.set_remote_description(sdp).await?; + + println!("Press ctrl-c to stop"); + tokio::select! { + _ = done_rx.recv() => { + println!("received done signal!"); + } + _ = tokio::signal::ctrl_c() => { + println!(""); + } + }; + } else { + println!("generate local_description failed!"); + } + + peer_connection.close().await?; + + Ok(()) +} + +const NALU_TTYPE_STAP_A: u32 = 24; +const NALU_TTYPE_SPS: u32 = 7; +const NALU_TYPE_BITMASK: u32 = 0x1F; + +fn is_key_frame(data: &[u8]) -> bool { + if data.len() < 4 { + false + } else { + let word = u32::from_be_bytes([data[0], data[1], data[2], data[3]]); + let nalu_type = (word >> 24) & NALU_TYPE_BITMASK; + (nalu_type == NALU_TTYPE_STAP_A && (word & NALU_TYPE_BITMASK) == NALU_TTYPE_SPS) + || (nalu_type == NALU_TTYPE_SPS) + } +} diff --git a/plugins/obs-webrtc/webrtc/src/lib.rs b/plugins/obs-webrtc/webrtc/src/lib.rs new file mode 100644 index 00000000000000..d8c6ce04c18bf4 --- /dev/null +++ b/plugins/obs-webrtc/webrtc/src/lib.rs @@ -0,0 +1,3 @@ +mod call; +mod stream; +mod whip; diff --git a/plugins/obs-webrtc/webrtc/src/stream.rs b/plugins/obs-webrtc/webrtc/src/stream.rs new file mode 100644 index 00000000000000..14d53242b621d6 --- /dev/null +++ b/plugins/obs-webrtc/webrtc/src/stream.rs @@ -0,0 +1,274 @@ +use anyhow::Result; + +use std::boxed::Box; +use std::os::raw::c_char; +use std::slice; +use std::sync::Arc; + +use bytes::Bytes; + +use tokio::runtime::Runtime; +use tokio::sync::Notify; + +use webrtc::api::interceptor_registry::register_default_interceptors; +use webrtc::api::media_engine::{MediaEngine, MIME_TYPE_H264, MIME_TYPE_OPUS}; +use webrtc::api::APIBuilder; +use webrtc::ice_transport::ice_connection_state::RTCIceConnectionState; +use webrtc::ice_transport::ice_server::RTCIceServer; +use webrtc::interceptor::registry::Registry; +use webrtc::media::Sample; +use webrtc::peer_connection::configuration::RTCConfiguration; +use webrtc::peer_connection::peer_connection_state::RTCPeerConnectionState; +use webrtc::rtp_transceiver::rtp_codec::RTCRtpCodecCapability; +use webrtc::track::track_local::track_local_static_sample::TrackLocalStaticSample; +use webrtc::track::track_local::TrackLocal; +use webrtc::Error; + +use crate::whip; + +pub struct OBSWebRTCStream { + runtime: Runtime, + video_track: Arc, + audio_track: Arc, +} + +async fn connect( + video_track: Arc, + audio_track: Arc, +) -> Result<()> { + println!("Setting up webrtc!"); + + let mut m = MediaEngine::default(); + + m.register_default_codecs(); + + // Create a InterceptorRegistry. This is the user configurable RTP/RTCP Pipeline. + // This provides NACKs, RTCP Reports and other features. If you use `webrtc.NewPeerConnection` + // this is enabled by default. If you are manually managing You MUST create a InterceptorRegistry + // for each PeerConnection. + let mut registry = Registry::new(); + + // Use the default set of Interceptors + registry = register_default_interceptors(registry, &mut m).await?; + + // Create the API object with the MediaEngine + let api = APIBuilder::new() + .with_media_engine(m) + .with_interceptor_registry(registry) + .build(); + + // Prepare the configuration + let config = RTCConfiguration { + ice_servers: vec![RTCIceServer { + urls: vec!["stun:stun.l.google.com:19302".to_owned()], + ..Default::default() + }], + ..Default::default() + }; + + // Create a new RTCPeerConnection + let peer_connection = Arc::new(api.new_peer_connection(config).await?); + + let notify_tx = Arc::new(Notify::new()); + let notify_video = notify_tx.clone(); + let notify_audio = notify_tx.clone(); + + let (done_tx, mut done_rx) = tokio::sync::mpsc::channel::<()>(1); + let video_done_tx = done_tx.clone(); + let audio_done_tx = done_tx.clone(); + + // Add this newly created track to the PeerConnection + let rtp_sender = peer_connection + .add_track(Arc::clone(&video_track) as Arc) + .await?; + + // Read incoming RTCP packets + // Before these packets are returned they are processed by interceptors. For things + // like NACK this needs to be called. + tokio::spawn(async move { + let mut rtcp_buf = vec![0u8; 1500]; + while let Ok((_, _)) = rtp_sender.read(&mut rtcp_buf).await {} + Result::<()>::Ok(()) + }); + + // Add this newly created track to the PeerConnection + let rtp_sender = peer_connection + .add_track(Arc::clone(&audio_track) as Arc) + .await?; + + // Read incoming RTCP packets + // Before these packets are returned they are processed by interceptors. For things + // like NACK this needs to be called. + tokio::spawn(async move { + let mut rtcp_buf = vec![0u8; 1500]; + while let Ok((_, _)) = rtp_sender.read(&mut rtcp_buf).await {} + Result::<()>::Ok(()) + }); + + // Set the handler for ICE connection state + // This will notify you when the peer has connected/disconnected + peer_connection + .on_ice_connection_state_change(Box::new(move |connection_state: RTCIceConnectionState| { + println!("Connection State has changed {}", connection_state); + if connection_state == RTCIceConnectionState::Connected { + notify_tx.notify_waiters(); + } + Box::pin(async {}) + })) + .await; + + // Set the handler for Peer connection state + // This will notify you when the peer has connected/disconnected + peer_connection + .on_peer_connection_state_change(Box::new(move |s: RTCPeerConnectionState| { + println!("Peer Connection State has changed: {}", s); + + if s == RTCPeerConnectionState::Failed { + // Wait until PeerConnection has had no network activity for 30 seconds or another failure. It may be reconnected using an ICE Restart. + // Use webrtc.PeerConnectionStateDisconnected if you are interested in detecting faster timeout. + // Note that the PeerConnection may come back from PeerConnectionStateDisconnected. + println!("Peer Connection has gone to failed exiting"); + let _ = done_tx.try_send(()); + } + + Box::pin(async {}) + })) + .await; + + // Create an offer to send to the browser + let offer = peer_connection.create_offer(None).await?; + + // Create channel that is blocked until ICE Gathering is complete + let mut gather_complete = peer_connection.gathering_complete_promise().await; + + // Sets the LocalDescription, and starts our UDP listeners + peer_connection.set_local_description(offer).await?; + + // Block until ICE Gathering is complete, disabling trickle ICE + // we do this because we only can exchange one signaling message + // in a production application you should exchange ICE Candidates via OnICECandidate + let _ = gather_complete.recv().await; + + // Output the answer in base64 so we can paste it in browser + if let Some(local_desc) = peer_connection.local_description().await { + let sdp = whip::do_whip(local_desc).await?; + + peer_connection.set_remote_description(sdp).await?; + + println!("Press ctrl-c to stop"); + tokio::select! { + _ = done_rx.recv() => { + println!("received done signal!"); + } + _ = tokio::signal::ctrl_c() => { + println!(""); + } + }; + } else { + println!("generate local_description failed!"); + } + + peer_connection.close().await?; + + Ok(()) +} + +#[no_mangle] +pub extern "C" fn obs_webrtc_stream_init(name: *const c_char) -> *mut OBSWebRTCStream { + let name = unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() }; + println!("Hello, {}! I'm Rust!", name); + + let video_track = Arc::new(TrackLocalStaticSample::new( + RTCRtpCodecCapability { + mime_type: MIME_TYPE_H264.to_owned(), + clock_rate: 90000, + sdp_fmtp_line: "profile-level-id=428014; max-fs=3600; max-mbps=108000; max-br=1400" + .to_string(), + // "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f" + //.to_string(), + ..Default::default() + }, + "video".to_owned(), + "webrtc-rs".to_owned(), + )); + + // Create a audio track + let audio_track = Arc::new(TrackLocalStaticSample::new( + RTCRtpCodecCapability { + mime_type: MIME_TYPE_OPUS.to_owned(), + ..Default::default() + }, + "audio".to_owned(), + "webrtc-rs".to_owned(), + )); + + Box::into_raw(Box::new(OBSWebRTCStream { + runtime: tokio::runtime::Runtime::new().unwrap(), + video_track: video_track, + audio_track: audio_track, + })) +} + +#[no_mangle] +pub extern "C" fn obs_webrtc_stream_connect(obsrtc: *mut OBSWebRTCStream) { + let obs_webrtc = unsafe { &*obsrtc }; + let video_track = Arc::clone(&obs_webrtc.video_track) as Arc; + let audio_track = Arc::clone(&obs_webrtc.audio_track) as Arc; + unsafe { + (*obsrtc).runtime.spawn(async { + connect(video_track, audio_track).await; + }); + } +} + +#[no_mangle] +pub extern "C" fn obs_webrtc_stream_data( + obsrtc: *mut OBSWebRTCStream, + data: *const u8, + size: usize, + duration: u64, +) { + if obsrtc.is_null() { + return; + } + + let slice: &[u8] = unsafe { slice::from_raw_parts(data, size) }; + + let sample = Sample { + data: Bytes::from(slice), + duration: std::time::Duration::from_nanos(duration), + ..Default::default() + }; + + unsafe { + (*obsrtc).runtime.block_on(async { + (*obsrtc).video_track.write_sample(&sample).await; + }); + } +} + +#[no_mangle] +pub extern "C" fn obs_webrtc_stream_audio( + obsrtc: *mut OBSWebRTCStream, + data: *const u8, + size: usize, + duration: u64, +) { + if obsrtc.is_null() { + return; + } + + let slice: &[u8] = unsafe { slice::from_raw_parts(data, size) }; + + let sample = Sample { + data: Bytes::from(slice), + duration: std::time::Duration::from_micros(duration), + ..Default::default() + }; + + unsafe { + (*obsrtc).runtime.block_on(async { + (*obsrtc).audio_track.write_sample(&sample).await; + }); + } +} diff --git a/plugins/obs-webrtc/webrtc/src/whip.rs b/plugins/obs-webrtc/webrtc/src/whip.rs new file mode 100644 index 00000000000000..370d723c8f316f --- /dev/null +++ b/plugins/obs-webrtc/webrtc/src/whip.rs @@ -0,0 +1,33 @@ +use anyhow::Result; + +use std::collections::HashMap; + +use serde_derive::{Deserialize, Serialize}; + +use webrtc::peer_connection::sdp::session_description::RTCSessionDescription; + +#[derive(Deserialize, Serialize)] +struct WhipBody { + desc: String, +} + +pub async fn do_whip(local_desc: RTCSessionDescription) -> Result { + let json_str = serde_json::to_string(&local_desc)?; + let b64 = base64::encode(&json_str); + let mut map = HashMap::new(); + map.insert("desc", b64); + + let client = reqwest::Client::new(); + let res = client + .post("http://10.42.42.153:8000/whip") + .json(&map) + .send() + .await?; + + let body = res.json::().await?; + + let sdp = base64::decode(body.desc)?; + + let sdp: RTCSessionDescription = serde_json::from_slice(&sdp)?; + return Ok(sdp); +} diff --git a/plugins/obs-webrtc/whip.c b/plugins/obs-webrtc/whip.c new file mode 100644 index 00000000000000..d09007e330cdb6 --- /dev/null +++ b/plugins/obs-webrtc/whip.c @@ -0,0 +1,83 @@ +#include "obs-module.h" + +struct whip { + char *server, *key; +}; + +static const char *whip_name(void *unused) +{ + UNUSED_PARAMETER(unused); + return obs_module_text("WhipWebRTCStreaming"); +} + +static void whip_update(void *data, obs_data_t *settings) +{ + struct whip *service = data; + + bfree(service->server); + bfree(service->key); + + service->server = bstrdup(obs_data_get_string(settings, "server")); + service->key = bstrdup(obs_data_get_string(settings, "key")); +} + +static void whip_destroy(void *data) +{ + struct whip *service = data; + + bfree(service->server); + bfree(service->key); + bfree(service); +} + +static void *whip_create(obs_data_t *settings, obs_service_t *service) +{ + struct whip *data = bzalloc(sizeof(struct whip)); + whip_update(data, settings); + + UNUSED_PARAMETER(service); + return data; +} + +static const char *whip_url(void *data) +{ + struct whip *service = data; + return service->server; +} + +static const char *whip_key(void *data) +{ + struct whip *service = data; + return service->key; +} + +static obs_properties_t *whip_properties(void *unused) +{ + UNUSED_PARAMETER(unused); + + obs_properties_t *ppts = obs_properties_create(); + + obs_properties_add_text(ppts, "server", "URL", OBS_TEXT_DEFAULT); + obs_properties_add_text(ppts, "key", obs_module_text("StreamKey"), + OBS_TEXT_PASSWORD); + return ppts; +} + +static const char *whip_get_output_type(void *data) +{ + struct whip *service = data; + return "webrtc_output"; +} + +struct obs_service_info whip_service = { + .id = "whip", + .get_name = whip_name, + .create = whip_create, + .destroy = whip_destroy, + .update = whip_update, + .get_properties = whip_properties, + .get_url = whip_url, + .get_key = whip_key, + .get_output_type = whip_get_output_type, + //.apply_encoder_settings = rtmp_custom_apply_settings, +}; \ No newline at end of file