diff --git a/trunk/configure b/trunk/configure
index d233f66db..5efe7eb59 100755
--- a/trunk/configure
+++ b/trunk/configure
@@ -254,7 +254,7 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then
"srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_edge"
"srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" "srs_app_http_static"
"srs_app_recv_thread" "srs_app_security" "srs_app_statistic" "srs_app_hds"
- "srs_app_mpegts_udp" "srs_app_rtsp" "srs_app_listener" "srs_app_async_call"
+ "srs_app_mpegts_udp" "srs_app_rtc_udp" "srs_app_rtsp" "srs_app_listener" "srs_app_async_call"
"srs_app_caster_flv" "srs_app_process" "srs_app_ng_exec"
"srs_app_hourglass" "srs_app_dash" "srs_app_fragment" "srs_app_dvr"
"srs_app_coworkers" "srs_app_hybrid")
diff --git a/trunk/research/players/srs_rtc_player.html b/trunk/research/players/srs_rtc_player.html
new file mode 100644
index 000000000..bbb605ab5
--- /dev/null
+++ b/trunk/research/players/srs_rtc_player.html
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+rtc_media_player:
+
+
+
+
+
+
+
diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp
index 2a7b98bd3..315ec58f7 100644
--- a/trunk/src/app/srs_app_config.cpp
+++ b/trunk/src/app/srs_app_config.cpp
@@ -3486,7 +3486,7 @@ srs_error_t SrsConfig::check_normal_config()
&& n != "srs_log_tank" && n != "srs_log_level" && n != "srs_log_file"
&& n != "max_connections" && n != "daemon" && n != "heartbeat"
&& n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print_ms"
- && n != "http_server" && n != "stream_caster" && n != "srt_server"
+ && n != "http_server" && n != "stream_caster" && n != "rtc" && n != "srt_server"
&& n != "utc_time" && n != "work_dir" && n != "asprocess"
&& n != "ff_log_level" && n != "grace_final_wait" && n != "force_grace_quit"
&& n != "grace_start_wait"
@@ -4216,6 +4216,45 @@ int SrsConfig::get_stream_caster_rtp_port_max(SrsConfDirective* conf)
return ::atoi(conf->arg0().c_str());
}
+int SrsConfig::get_rtc_enabled()
+{
+ SrsConfDirective* conf = root->get("rtc");
+ return get_rtc_enabled(conf);
+}
+
+bool SrsConfig::get_rtc_enabled(SrsConfDirective* conf)
+{
+ static bool DEFAULT = false;
+
+ if (!conf) {
+ return DEFAULT;
+ }
+
+ conf = conf->get("enabled");
+ if (!conf || conf->arg0().empty()) {
+ return DEFAULT;
+ }
+
+ return SRS_CONF_PERFER_FALSE(conf->arg0());
+}
+
+int SrsConfig::get_rtc_listen()
+{
+ static int DEFAULT = 9527;
+
+ SrsConfDirective* conf = root->get("rtc");
+ if (!conf) {
+ return DEFAULT;
+ }
+
+ conf = conf->get("listen");
+ if (!conf || conf->arg0().empty()) {
+ return DEFAULT;
+ }
+
+ return ::atoi(conf->arg0().c_str());
+}
+
SrsConfDirective* SrsConfig::get_vhost(string vhost, bool try_default_vhost)
{
srs_assert(root);
diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp
index 6a58f2ef8..1f85550f7 100644
--- a/trunk/src/app/srs_app_config.hpp
+++ b/trunk/src/app/srs_app_config.hpp
@@ -490,6 +490,13 @@ public:
virtual int get_stream_caster_rtp_port_min(SrsConfDirective* conf);
// Get the max udp port for rtp of stream caster rtsp.
virtual int get_stream_caster_rtp_port_max(SrsConfDirective* conf);
+
+// rtc section
+public:
+ virtual int get_rtc_enabled();
+ virtual bool get_rtc_enabled(SrsConfDirective* conf);
+ virtual int get_rtc_listen();
+
// vhost specified section
public:
// Get the vhost directive by vhost name.
diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp
index 5355068eb..634ba647c 100644
--- a/trunk/src/app/srs_app_http_api.cpp
+++ b/trunk/src/app/srs_app_http_api.cpp
@@ -47,6 +47,73 @@ using namespace std;
#include
#include
+string test_sdp =
+"v=0\\r\\n"
+"o=- 0 0 IN IP4 127.0.0.1\\r\\n"
+"s=-\\r\\n"
+"t=0 0\\r\\n"
+"a=ice-lite\\r\\n"
+"a=group:BUNDLE 0 1\\r\\n"
+"a=msid-semantic: WMS 6VrfBKXrwK\\r\\n"
+"m=audio 9 UDP/TLS/RTP/SAVPF 111\\r\\n"
+"c=IN IP4 0.0.0.0\\r\\n"
+"a=candidate:10 1 udp 2115783679 192.168.170.129 9527 typ host generation 0\\r\\n"
+"a=rtcp:9 IN IP4 0.0.0.0\\r\\n"
+"a=ice-ufrag:xiaozhihongjohn\\r\\n"
+"a=ice-pwd:simple_rtmp_server__john\\r\\n"
+"a=ice-options:trickle\\r\\n"
+"a=fingerprint:sha-256 76:E8:6A:6D:48:F0:86:58:30:2E:69:56:0F:C6:A1:B8:69:98:5D:73:45:93:37:8E:C4:2B:C7:97:04:18:E4:24\\r\\n"
+"a=sendrecv\\r\\n"
+"a=mid:0\\r\\n"
+"a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\\r\\n"
+"a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\\r\\n"
+"a=rtcp-mux\\r\\n"
+"a=rtpmap:111 opus/48000/2\\r\\n"
+"a=fmtp:111 minptime=10;useinbandfec=1\\r\\n"
+"a=maxptime:60\\r\\n"
+"a=ssrc:3233846890 cname:o/i14u9pJrxRKAsu\\r\\n"
+"a=ssrc:3233846890 msid:6VrfBKXrwK a0\\r\\n"
+"a=ssrc:3233846890 mslabel:6VrfBKXrwK\\r\\n"
+"a=ssrc:3233846890 label:6VrfBKXrwKa0\\r\\n"
+"m=video 9 UDP/TLS/RTP/SAVPF 96 98 102\\r\\n"
+"c=IN IP4 0.0.0.0\\r\\n"
+"a=candidate:10 1 udp 2115783679 192.168.170.129 9527 typ host generation 0\\r\\n"
+"a=rtcp:9 IN IP4 0.0.0.0\\r\\n"
+"b=as:2000000\\r\\n"
+"a=ice-ufrag:xiaozhihongjohn\\r\\n"
+"a=ice-pwd:simple_rtmp_server__john\\r\\n"
+"a=ice-options:trickle\\r\\n"
+"a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\\r\\n"
+"a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\\r\\n"
+"a=extmap:4 urn:3gpp:video-orientation\\r\\n"
+"a=fingerprint:sha-256 76:E8:6A:6D:48:F0:86:58:30:2E:69:56:0F:C6:A1:B8:69:98:5D:73:45:93:37:8E:C4:2B:C7:97:04:18:E4:24\\r\\n"
+"a=sendrecv\\r\\n"
+"a=mid:1\\r\\n"
+"a=rtcp-mux\\r\\n"
+"a=rtpmap:96 VP8/90000\\r\\n"
+"a=rtcp-fb:96 ccm fir\\r\\n"
+"a=rtcp-fb:96 nack\\r\\n"
+"a=rtcp-fb:96 nack pli\\r\\n"
+"a=rtcp-fb:96 goog-remb\\r\\n"
+"a=rtcp-fb:96 transport-cc\\r\\n"
+"a=rtpmap:98 VP9/90000\\r\\n"
+"a=rtcp-fb:98 ccm fir\\r\\n"
+"a=rtcp-fb:98 nack\\r\\n"
+"a=rtcp-fb:98 nack pli\\r\\n"
+"a=rtcp-fb:98 goog-remb\\r\\n"
+"a=rtcp-fb:98 transport-cc\\r\\n"
+"a=rtpmap:102 H264/90000\\r\\n"
+"a=rtcp-fb:102 goog-remb\\r\\n"
+"a=rtcp-fb:102 transport-cc\\r\\n"
+"a=rtcp-fb:102 ccm fir \\r\\n"
+"a=rtcp-fb:102 nack\\r\\n"
+"a=rtcp-fb:102 nack pli \\r\\n"
+"a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f\\r\\n"
+"a=ssrc:3233846889 cname:o/i14u9pJrxRKAsu\\r\\n"
+"a=ssrc:3233846889 msid:6VrfBKXrwK v0\\r\\n"
+"a=ssrc:3233846889 mslabel:6VrfBKXrwK\\r\\n"
+"a=ssrc:3233846889 label:6VrfBKXrwKv0\\r\\n";
+
srs_error_t srs_api_response_jsonp(ISrsHttpResponseWriter* w, string callback, string data)
{
srs_error_t err = srs_success;
@@ -780,6 +847,44 @@ srs_error_t SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa
return srs_api_response(w, r, obj->dumps());
}
+SrsGoApiSdp::SrsGoApiSdp()
+{
+}
+
+SrsGoApiSdp::~SrsGoApiSdp()
+{
+}
+
+srs_error_t SrsGoApiSdp::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
+{
+ srs_error_t err = srs_success;
+
+ SrsStatistic* stat = SrsStatistic::instance();
+
+ // path: {pattern}{stream_id}
+ // e.g. /api/v1/streams/100 pattern= /api/v1/streams/, stream_id=100
+ int sid = r->parse_rest_id(entry->pattern);
+
+ SrsStatisticStream* stream = NULL;
+ if (sid >= 0 && (stream = stat->find_stream(sid)) == NULL) {
+ return srs_api_response_code(w, r, ERROR_RTMP_STREAM_NOT_FOUND);
+ }
+
+ SrsJsonObject* obj = SrsJsonAny::object();
+ SrsAutoFree(SrsJsonObject, obj);
+
+ obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
+ obj->set("server", SrsJsonAny::integer(stat->server_id()));
+
+ if (r->is_http_post()) {
+ obj->set("sdp", SrsJsonAny::str(test_sdp.c_str()));
+ } else {
+ return srs_go_http_error(w, SRS_CONSTS_HTTP_MethodNotAllowed);
+ }
+
+ return srs_api_response(w, r, obj->dumps());
+}
+
SrsGoApiClients::SrsGoApiClients()
{
}
diff --git a/trunk/src/app/srs_app_http_api.hpp b/trunk/src/app/srs_app_http_api.hpp
index 5957ff2f3..367edabab 100644
--- a/trunk/src/app/srs_app_http_api.hpp
+++ b/trunk/src/app/srs_app_http_api.hpp
@@ -164,6 +164,15 @@ public:
virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
};
+class SrsGoApiSdp : public ISrsHttpHandler
+{
+public:
+ SrsGoApiSdp();
+ virtual ~SrsGoApiSdp();
+public:
+ virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
+};
+
class SrsGoApiClients : public ISrsHttpHandler
{
public:
diff --git a/trunk/src/app/srs_app_rtc_udp.cpp b/trunk/src/app/srs_app_rtc_udp.cpp
new file mode 100644
index 000000000..4866c387a
--- /dev/null
+++ b/trunk/src/app/srs_app_rtc_udp.cpp
@@ -0,0 +1,89 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2020 Winlin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+using namespace std;
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+SrsRtcOverUdp::SrsRtcOverUdp()
+{
+}
+
+SrsRtcOverUdp::~SrsRtcOverUdp()
+{
+}
+
+srs_error_t SrsRtcOverUdp::on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf)
+{
+ char address_string[64];
+ char port_string[16];
+ if(getnameinfo(from, fromlen,
+ (char*)&address_string, sizeof(address_string),
+ (char*)&port_string, sizeof(port_string),
+ NI_NUMERICHOST|NI_NUMERICSERV)) {
+ return srs_error_new(ERROR_SYSTEM_IP_INVALID, "bad address");
+ }
+ std::string peer_ip = std::string(address_string);
+ int peer_port = atoi(port_string);
+
+ srs_error_t err = on_udp_bytes(peer_ip, peer_port, buf, nb_buf);
+ if (err != srs_success) {
+ return srs_error_wrap(err, "process udp");
+ }
+ return err;
+}
+
+srs_error_t SrsRtcOverUdp::on_udp_bytes(string host, int port, char* buf, int nb_buf)
+{
+ srs_error_t err = srs_success;
+
+ srs_trace("recv rtc udp packet from %s:%d, nb_buf=%d", host.c_str(), port, nb_buf);
+
+ return err;
+}
diff --git a/trunk/src/app/srs_app_rtc_udp.hpp b/trunk/src/app/srs_app_rtc_udp.hpp
new file mode 100644
index 000000000..707b6b830
--- /dev/null
+++ b/trunk/src/app/srs_app_rtc_udp.hpp
@@ -0,0 +1,52 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2020 Winlin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SRS_APP_RTC_UDP_HPP
+#define SRS_APP_RTC_UDP_HPP
+
+#include
+
+struct sockaddr;
+#include
+#include