#include "media_streamer_gst_webrtc.h"
#include "media_streamer_node.h"
+static gchar *__make_ice_candidate_message(guint mlineindex, gchar *candidate)
+{
+ JsonObject *ice, *msg;
+ gchar *text;
+
+ ms_retvm_if(candidate == NULL, NULL, "candidate is NULL");
+
+ ice = json_object_new();
+ json_object_set_string_member(ice, "candidate", candidate);
+ json_object_set_int_member(ice, "sdpMLineIndex", mlineindex);
+
+ msg = json_object_new();
+ json_object_set_object_member(msg, "ice", ice);
+
+ text = ms_get_string_from_json_object(msg);
+
+ json_object_unref(msg);
+
+ return text;
+}
+
static gchar* __make_sdp_message(GstWebRTCSessionDescription *desc)
{
gchar *text;
}
}
-static void __on_answer_created_cb(GstPromise *promise, gpointer user_data)
+static void __ms_webrtcbin_set_session_description(GstElement *webrtcbin, GstWebRTCSessionDescription *session_description, gboolean is_remote)
{
- GstWebRTCSessionDescription *answer = NULL;
+ GstPromise *promise;
+ ms_retm_if(session_description == NULL, "session_description is NULL");
+ ms_retm_if(webrtcbin == NULL, "webrtcbin is NULL");
+
+ ms_debug_fenter();
+
+ promise = gst_promise_new();
+ g_signal_emit_by_name(webrtcbin, is_remote? "set-remote-description" : "set-local-description", session_description, promise);
+ gst_promise_interrupt(promise);
+ gst_promise_unref(promise);
+
+ ms_debug_fleave();
+}
+
+static void __on_offer_created_cb(GstPromise *promise, gpointer user_data)
+{
+ GstWebRTCSessionDescription *offer = NULL;
const GstStructure *reply;
media_streamer_node_s *webrtc_node = (media_streamer_node_s *)user_data;
node_info_s *node_klass_type = NULL;
}
reply = gst_promise_get_reply(promise);
- gst_structure_get(reply, "answer",
- GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &answer, NULL);
- gst_promise_unref(promise);
-
- promise = gst_promise_new();
- g_signal_emit_by_name(G_OBJECT(webrtcbin), "set-local-description", answer, promise);
- gst_promise_interrupt(promise);
+ gst_structure_get(reply, "offer",
+ GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &offer, NULL);
gst_promise_unref(promise);
- sdp_msg = __make_sdp_message(answer);
+ __ms_webrtcbin_set_session_description(webrtcbin, offer, FALSE);
- /* TODO: need to add to send this message to signalling server */
- ms_debug("SDP message is sent: %s", sdp_msg);
+ sdp_msg = __make_sdp_message(offer);
+ gst_webrtc_session_description_free(offer);
+ /* Send local description to peer */
+ __trigger_message_callback(webrtc_node, sdp_msg);
g_free(sdp_msg);
- gst_webrtc_session_description_free(answer);
-
ms_debug_fleave();
}
-static void __on_offer_created_cb(GstPromise *promise, gpointer user_data)
+static void __on_answer_created_cb(GstPromise * promise, gpointer user_data)
{
- GstWebRTCSessionDescription *offer = NULL;
+ GstWebRTCSessionDescription *answer = NULL;
const GstStructure *reply;
- media_streamer_node_s *webrtc_node = (media_streamer_node_s *)user_data;
+ media_streamer_node_s *node = (media_streamer_node_s *)user_data;
node_info_s *node_klass_type = NULL;
- GstElement *webrtcbin = NULL;
gchar *sdp_msg;
+ GstElement *webrtcbin;
ms_retm_if(promise == NULL, "promise is NULL");
- ms_retm_if(webrtc_node == NULL, "webrtc_node is NULL");
+ ms_retm_if(node == NULL, "node is NULL");
+ ms_retm_if(node->gst_element == NULL, "webrtc_container is NULL");
ms_retm_if(gst_promise_wait(promise) != GST_PROMISE_RESULT_REPLIED, "promise is not for replied result");
ms_debug_fenter();
node_klass_type = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_WEBRTC);
- if (!(webrtcbin = ms_find_element_in_bin_by_type(webrtc_node->gst_element, node_klass_type))) {
+ if (!(webrtcbin = ms_find_element_in_bin_by_type(node->gst_element, node_klass_type))) {
ms_error("Could not find webrtcbin by type[%s, %s]", node_klass_type->klass_name, node_klass_type->default_name);
return;
}
reply = gst_promise_get_reply(promise);
- gst_structure_get(reply, "offer",
- GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &offer, NULL);
- gst_promise_unref(promise);
-
- promise = gst_promise_new();
- g_signal_emit_by_name(G_OBJECT(webrtcbin), "set-local-description", offer, promise);
- gst_promise_interrupt(promise);
+ gst_structure_get(reply, "answer", GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &answer, NULL);
gst_promise_unref(promise);
- sdp_msg = __make_sdp_message(offer);
+ __ms_webrtcbin_set_session_description(webrtcbin, answer, FALSE);
- __trigger_message_callback(webrtc_node, sdp_msg);
+ sdp_msg = __make_sdp_message(answer);
+ gst_webrtc_session_description_free(answer);
+ /* Send local description to peer */
+ __trigger_message_callback(node, sdp_msg);
g_free(sdp_msg);
- gst_webrtc_session_description_free(offer);
ms_debug_fleave();
}
+int ms_webrtcbin_set_remote_session_description(media_streamer_node_s *node, const char *sdp_msg)
+{
+ GstSDPMessage *gst_sdp;
+ gchar *sdp;
+ gchar *type;
+ GstWebRTCSessionDescription *answer, *offer;
+ node_info_s *node_klass_type;
+ GstElement *webrtcbin;
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ ms_retvm_if(node == NULL || node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: empty webrtcbin");
+ ms_retvm_if(sdp_msg == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "sdp_msg is NULL");
+
+ ms_debug_fenter();
+
+
+ node_klass_type = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_WEBRTC);
+ if (!(webrtcbin = ms_find_element_in_bin_by_type(node->gst_element, node_klass_type))) {
+ ms_error("Could not find webrtcbin by type[%s, %s]", node_klass_type->klass_name, node_klass_type->default_name);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ ret = ms_webrtc_get_sdp_from_message(sdp_msg, &sdp, &type);
+ if (ret != MEDIA_STREAMER_ERROR_NONE)
+ goto end;
+
+ ret = gst_sdp_message_new(&gst_sdp);
+ if (ret != GST_SDP_OK) {
+ ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ goto end;
+ }
+
+ ret = gst_sdp_message_parse_buffer((guint8 *)sdp, strlen(sdp), gst_sdp);
+ if (ret != GST_SDP_OK) {
+ ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ goto end;
+ }
+
+ if (g_str_equal(type, "answer")) {
+ answer = gst_webrtc_session_description_new(GST_WEBRTC_SDP_TYPE_ANSWER, gst_sdp);
+ g_assert_nonnull(answer);
+
+ __ms_webrtcbin_set_session_description(webrtcbin, answer, TRUE);
+ gst_webrtc_session_description_free(answer);
+ } else if (g_str_equal(type, "offer")) {
+ offer = gst_webrtc_session_description_new(GST_WEBRTC_SDP_TYPE_OFFER, gst_sdp);
+ g_assert_nonnull(offer);
+
+ __ms_webrtcbin_set_session_description(webrtcbin, offer, TRUE);
+ gst_webrtc_session_description_free(offer);
+
+ ms_webrtcbin_on_negotiation_process_answer(webrtcbin, node);
+ } else {
+ ms_error("type is %s, it is not a answer or offer", type);
+ }
+
+end:
+ MS_SAFE_GFREE(sdp);
+ MS_SAFE_GFREE(type);
+
+ ms_debug_fleave();
+
+ return ret;
+}
+
+int ms_webrtcbin_add_ice_candidate(media_streamer_node_s *node, const char *ice_msg)
+{
+ gchar *candidate;
+ gint sdpmlineindex;
+ node_info_s *node_klass_type;
+ GstElement *webrtcbin;
+ int ret;
+
+ ms_retvm_if(node == NULL || node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: empty webrtcbin");
+ ms_retvm_if(ice_msg == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ice_msg is NULL");
+
+ ms_debug_fenter();
+
+ node_klass_type = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_WEBRTC);
+ if (!(webrtcbin = ms_find_element_in_bin_by_type(node->gst_element, node_klass_type))) {
+ ms_error("Could not find webrtcbin by type[%s, %s]", node_klass_type->klass_name, node_klass_type->default_name);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ ret = ms_webrtc_get_ice_candidate_from_message(ice_msg, &candidate, &sdpmlineindex);
+ if (ret != MEDIA_STREAMER_ERROR_NONE)
+ return ret;
+
+ /*Add ice candidate sent by remote peer */
+ g_signal_emit_by_name(webrtcbin, "add-ice-candidate", sdpmlineindex, candidate);
+
+ g_free(candidate);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
void ms_webrtcbin_on_negotiation_process_answer(GstElement *webrtcbin, media_streamer_node_s *webrtc_node)
{
GstPromise *promise;
ms_retm_if(webrtcbin == NULL, "webrtcbin is NULL");
- ms_retm_if(webrtc_node == NULL, "webrtc_node is NULL");
ms_debug_fenter();
ms_debug_fleave();
}
-static gchar *__make_ice_candidate_message(guint mlineindex, gchar *candidate)
-{
- JsonObject *ice, *msg;
- gchar *text;
-
- ms_retvm_if(candidate == NULL, NULL, "candidate is NULL");
-
- ice = json_object_new();
- json_object_set_string_member(ice, "candidate", candidate);
- json_object_set_int_member(ice, "sdpMLineIndex", mlineindex);
-
- msg = json_object_new();
- json_object_set_object_member(msg, "ice", ice);
-
- text = ms_get_string_from_json_object(msg);
-
- json_object_unref(msg);
-
- return text;
-}
-
void ms_webrtcbin_on_ice_candidate_cb(GstElement *webrtcbin, guint mlineindex, gchar *candidate, gpointer user_data)
{
gchar *ice_candidate_msg = NULL;
ms_add_no_target_ghostpad(webrtc_container, MS_RTP_PAD_VIDEO_IN, GST_PAD_SINK);
MS_SET_INT_STATIC_STRING_PARAM(webrtc_container, MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE, DEFAULT_WEBRTC_PEER);
+ MS_SET_INT_STATIC_STRING_PARAM(webrtc_container, MEDIA_STREAMER_PARAM_WEBRTC_REMOTE_SESSION_DESCRIPTION, NULL);
+ MS_SET_INT_STATIC_STRING_PARAM(webrtc_container, MEDIA_STREAMER_PARAM_WEBRTC_ADD_ICE_CANDIDATE, NULL);
if (!(webrtcbin = ms_element_create("webrtcbin", NULL))) {
ms_error("Failed to create webrtcbin element");