Add new APIs to set/unset webrtc message callback 74/235274/10
authorSangchul Lee <sc11.lee@samsung.com>
Wed, 3 Jun 2020 08:59:00 +0000 (17:59 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Mon, 8 Jun 2020 07:09:07 +0000 (16:09 +0900)
- int media_streamer_webrtc_node_set_message_cb(media_streamer_node_h webrtc,
                                                media_streamer_webrtc_message_cb callback,
                                                void *user_data)
- int media_streamer_webrtc_node_unset_message_cb(media_streamer_node_h webrtc)
- typedef void (*media_streamer_webrtc_message_cb)(media_streamer_node_h webrtc,
                                                   const char *message,
                                                   void *user_data);

[Version] 0.1.52
[Issue Type] New feature

Change-Id: I452d7c88ff6e6e80cb41388a7d5c6d05d308527e
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
include/media_streamer.h
include/media_streamer_priv.h
packaging/capi-media-streamer.spec
src/media_streamer.c
src/media_streamer_gst_webrtc.c
src/media_streamer_node.c

index 0d2c397..f686645 100644 (file)
@@ -514,6 +514,21 @@ typedef void (*media_streamer_position_changed_cb)(void *user_data);
 typedef void (*media_streamer_interrupted_cb)(media_streamer_interrupted_code_e code, void *user_data);
 
 /**
+ * @brief Called when the media streamer WebRTC node needs to send the message to the remote peer of WebRTC connection.
+ * @since_tizen 6.0
+ * @remarks Two types will be delivered with @ message which is JSON string.
+ *          One is for the remote session description and the other is for a new ICE candidate.
+ *          For the remote session description, @ message will be {"sdp":{"type":"offer or answer","sdp":"..."}}.
+ *          For the new ICE candidate, @ message will be {"ice":{"candidate":"..."}}.
+ * @param[in] webrtc     Media streamer WebRTC node handle
+ * @param[in] message    The message to be passed to the remote peer over the signaling channel
+ * @param[in] user_data  The user data passed from the callback registration function
+ * @see media_streamer_webrtc_node_set_message_cb()
+ * @see media_streamer_webrtc_node_unset_message_cb()
+ */
+typedef void (*media_streamer_webrtc_message_cb)(media_streamer_node_h webrtc, const char *message, void *user_data);
+
+/**
  * @brief Sets a error callback function to be invoked when an error occurs.
  * @details Following error codes can be delivered by error callback.
  *          #MEDIA_STREAMER_ERROR_INVALID_OPERATION,
@@ -1245,7 +1260,6 @@ int media_streamer_node_get_params(media_streamer_node_h node, bundle **param_li
 int media_streamer_node_set_param(media_streamer_node_h node,
                                        const char *param_name, const char *param_value);
 
-
 /**
  * @brief Gets value of parameter.
  * @details Gets parameter one by one without creating param bundle.
@@ -1271,6 +1285,36 @@ int media_streamer_node_get_param(media_streamer_node_h node,
                                        const char *param_name, char **param_value);
 
 /**
+ * @brief Sets a callback function to be invoked when WebRTC node needs to send the message to the remote peer of WebRTC connection.
+ * @details This function can be called only for #MEDIA_STREAMER_NODE_TYPE_WEBRTC type.
+ * @since_tizen 6.0
+ * @param[in] webrtc    Media streamer WebRTC node handle
+ * @param[in] callback  The WebRTC message callback function to register
+ * @param[in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Create a media streamer WebRTC node handle by calling media_streamer_node_create().
+ * @post media_streamer_webrtc_message_cb() will be invoked.
+ * @see media_streamer_webrtc_node_unset_message_cb()
+ * @see media_streamer_webrtc_message_cb()
+ */
+int media_streamer_webrtc_node_set_message_cb(media_streamer_node_h webrtc, media_streamer_webrtc_message_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the webrtc message callback function.
+ * @since_tizen 6.0
+ * @param[in] src    Media streamer WebRTC node handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #MEDIA_STREAMER_ERROR_NONE Successful
+ * @retval #MEDIA_STREAMER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see media_streamer_webrtc_node_set_message_cb()
+ */
+int media_streamer_webrtc_node_unset_message_cb(media_streamer_node_h webrtc);
+
+/**
  * @}
  */
 
index cb2355c..15fe4fc 100644 (file)
@@ -128,6 +128,8 @@ typedef struct {
        mm_resource_manager_res_h resource;
        device_policy_manager_h dpm_handle;
        int policy_changed_cb_id;
+
+       media_streamer_callback_s user_cb;
 } media_streamer_node_s;
 
 /**
index 4def19b..d3a9a81 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-streamer
 Summary:    A Media Streamer API
-Version:    0.1.51
+Version:    0.1.52
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index b255ac8..dbb28cb 100644 (file)
@@ -937,3 +937,37 @@ int media_streamer_unset_interrupted_cb(media_streamer_h streamer)
 
        return MEDIA_STREAMER_ERROR_NONE;
 }
+
+int media_streamer_webrtc_node_set_message_cb(media_streamer_node_h webrtc, media_streamer_webrtc_message_cb callback, void *user_data)
+{
+       media_streamer_node_s *ms_node = (media_streamer_node_s *) webrtc;
+
+       ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
+       ms_retvm_if(ms_node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is not for WebRTC");
+
+       ms_debug_fenter();
+
+       ms_node->user_cb.callback = callback;
+       ms_node->user_cb.user_data = user_data;
+
+       ms_debug_fleave();
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
+
+int media_streamer_webrtc_node_unset_message_cb(media_streamer_node_h webrtc)
+{
+       media_streamer_node_s *ms_node = (media_streamer_node_s *) webrtc;
+
+       ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
+       ms_retvm_if(ms_node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is not for WebRTC");
+
+       ms_debug_fenter();
+
+       ms_node->user_cb.callback = NULL;
+       ms_node->user_cb.user_data = NULL;
+
+       ms_debug_fleave();
+
+       return MEDIA_STREAMER_ERROR_NONE;
+}
\ No newline at end of file
index 669be14..371ec64 100644 (file)
@@ -56,6 +56,21 @@ static gchar* __make_sdp_message(GstWebRTCSessionDescription *desc)
        return text;
 }
 
+static void __trigger_message_callback(media_streamer_node_s *webrtc_node, gchar *message)
+{
+       ms_retm_if(webrtc_node == NULL, "webrtc_node is NULL");
+
+       ms_debug("message is : \n%s", message);
+
+       if (webrtc_node->user_cb.callback) {
+               ms_debug("=====> Now trigger user callback(%p)", webrtc_node->user_cb.callback);
+               ((media_streamer_webrtc_message_cb)(webrtc_node->user_cb.callback))(webrtc_node, message, webrtc_node->user_cb.user_data);
+               ms_debug("<===== End of the callback");
+       } else {
+               ms_warning("message callback is NULL");
+       }
+}
+
 static void __on_answer_created_cb(GstPromise *promise, gpointer user_data)
 {
        GstWebRTCSessionDescription *answer = NULL;
@@ -103,15 +118,23 @@ static void __on_offer_created_cb(GstPromise *promise, gpointer user_data)
 {
        GstWebRTCSessionDescription *offer = NULL;
        const GstStructure *reply;
-       GstElement *webrtcbin = (GstElement *)user_data;
+       media_streamer_node_s *webrtc_node = (media_streamer_node_s *)user_data;
+       node_info_s *node_klass_type = NULL;
+       GstElement *webrtcbin = NULL;
        gchar *sdp_msg;
 
        ms_retm_if(promise == NULL, "promise is NULL");
-       ms_retm_if(webrtcbin == NULL, "webrtcbin is NULL");
+       ms_retm_if(webrtc_node == NULL, "webrtc_node 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))) {
+               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);
@@ -124,11 +147,9 @@ static void __on_offer_created_cb(GstPromise *promise, gpointer user_data)
 
        sdp_msg = __make_sdp_message(offer);
 
-       /* TODO: need to add to send this message to signalling server */
-       ms_debug("SDP message is sent: %s", sdp_msg);
+       __trigger_message_callback(webrtc_node, sdp_msg);
 
        g_free(sdp_msg);
-
        gst_webrtc_session_description_free(offer);
 
        ms_debug_fleave();
@@ -154,10 +175,11 @@ void ms_webrtcbin_on_negotiation_needed_cb(GstElement *webrtcbin, gpointer user_
        GstPromise *promise;
 
        ms_retm_if(webrtcbin == NULL, "webrtcbin is NULL");
+       ms_retm_if(user_data == NULL, "user_data is NULL");
 
        ms_debug_fenter();
 
-       promise = gst_promise_new_with_change_func(__on_offer_created_cb, webrtcbin, NULL);
+       promise = gst_promise_new_with_change_func(__on_offer_created_cb, user_data, NULL);
        g_signal_emit_by_name(G_OBJECT(webrtcbin), "create-offer", NULL, promise);
 
        ms_debug_fleave();
@@ -187,14 +209,15 @@ static gchar *__make_ice_candidate_message(guint mlineindex, gchar *candidate)
 void ms_webrtcbin_on_ice_candidate_cb(GstElement *webrtcbin, guint mlineindex, gchar *candidate, gpointer user_data)
 {
        gchar *ice_candidate_msg = NULL;
+       media_streamer_node_s *webrtc_node = (media_streamer_node_s *)user_data;
 
        ms_retm_if(webrtcbin == NULL, "webrtcbin is NULL");
        ms_retm_if(candidate == NULL, "candidate is NULL");
+       ms_retm_if(webrtc_node == NULL, "webrtc_node is NULL");
 
        ice_candidate_msg = __make_ice_candidate_message(mlineindex, candidate);
 
-       /* TODO: need to add to send this message to signalling server */
-       ms_debug("ICE candidate message is sent: %s", ice_candidate_msg);
+       __trigger_message_callback(webrtc_node, ice_candidate_msg);
 
        g_free(ice_candidate_msg);
 }
index 41536cc..01ced4b 100644 (file)
@@ -1445,7 +1445,8 @@ int ms_webrtc_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s
        ms_debug_fenter();
 
        ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
-       ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "node is NULL");
+       ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
+       ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is not WebRTC");
 
        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))) {
@@ -1453,15 +1454,20 @@ int ms_webrtc_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s
                return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
        }
 
+       if (!node->user_cb.callback) {
+               ms_error("message callback should be set before preparing");
+               return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+       }
+
        if (__ms_webrtc_node_is_offerer(node, &is_offerer)) {
                ms_error("Failed to get peer type");
                return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
        }
 
        if (is_offerer)
-               ms_signal_create(&node->sig_list, webrtcbin, "on-negotiation-needed", G_CALLBACK(ms_webrtcbin_on_negotiation_needed_cb), NULL);
+               ms_signal_create(&node->sig_list, webrtcbin, "on-negotiation-needed", G_CALLBACK(ms_webrtcbin_on_negotiation_needed_cb), node);
 
-       ms_signal_create(&node->sig_list, webrtcbin, "on-ice-candidate", G_CALLBACK(ms_webrtcbin_on_ice_candidate_cb), NULL);
+       ms_signal_create(&node->sig_list, webrtcbin, "on-ice-candidate", G_CALLBACK(ms_webrtcbin_on_ice_candidate_cb), node);
        ms_signal_create(&node->sig_list, webrtcbin, "notify::ice-gathering-state", G_CALLBACK(ms_webrtcbin_notify_ice_gathering_state_cb), NULL);
 
        if (ms_element_set_state(webrtcbin, GST_STATE_READY)) {