webrtc_internal: Add functions to set/get drop receiving data 32/308132/2
authorSangchul Lee <sc11.lee@samsung.com>
Mon, 18 Mar 2024 08:36:29 +0000 (17:36 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Tue, 19 Mar 2024 01:52:13 +0000 (10:52 +0900)
Funtions are added as below.
 : webrtc_media_source_set_transceiver_recv_drop()
 : webrtc_media_source_get_transceiver_recv_drop()

Receiving packets from a remote peer are related to a specific transceiver
which was created by media source in this API.
To drop receiving packets without decoding, these new functions are
added.

[Version] 0.4.54
[Issue Type] Internal API

Change-Id: I414bea2fda91a08170928452ecc457f5d29b3962
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
include/webrtc_internal.h
include/webrtc_private.h
packaging/capi-media-webrtc.spec
src/webrtc_internal.c
src/webrtc_private.c
src/webrtc_sink.c
src/webrtc_source.c
src/webrtc_source_private.c
src/webrtc_transceiver.c

index 40c1772cf62e9906b04efd2b9801925f152d15dd..3543e258739c558e4842a795935535812b09ce3f 100644 (file)
@@ -403,6 +403,42 @@ int webrtc_media_source_active_transceiver_encoding(webrtc_h webrtc, unsigned in
  */
 int webrtc_media_source_get_transceiver_mid(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, char **mid);
 
+/**
+ * @internal
+ * @brief Sets drop of the receiving packets from the transceiver of the media source.
+ * @since_tizen 8.0
+ * @remarks If @a drop is set to @c true, playback of media received from a remote peer will be dropped without decoding.\n
+ *          If the transceiver of @a source_id has the #WEBRTC_TRANSCEIVER_DIRECTION_SENDONLY direction, #WEBRTC_ERROR_INVALID_OPERATION will be returned.
+ * @param[in] webrtc      WebRTC handle
+ * @param[in] source_id   The source id
+ * @param[in] media_type  The media type
+ * @param[in] drop        Drop or not (@c true = drop, @c false = not drop)
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #WEBRTC_ERROR_NONE    Successful
+ * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation
+ * @see webrtc_media_source_get_transceiver_recv_drop()
+ */
+int webrtc_media_source_set_transceiver_recv_drop(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, bool drop);
+
+/**
+ * @internal
+ * @brief Gets the drop state of the receiving packets from the transceiver of the media source.
+ * @since_tizen 8.0
+ * @remarks The default value is @c false.
+ * @param[in] webrtc      WebRTC handle
+ * @param[in] source_id   The track id
+ * @param[in] media_type  The media type
+ * @param[out] dropped    Dropped or not (@c true = dropped, @c false = not dropped)
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #WEBRTC_ERROR_NONE    Successful
+ * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see webrtc_media_source_set_transceiver_recv_drop()
+ */
+int webrtc_media_source_get_transceiver_recv_drop(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, bool *dropped);
+
 /**
  * @internal
  * @brief Gets the media type of the media source.
@@ -548,7 +584,7 @@ int webrtc_util_strip_description(const char *origin_description, char **descrip
  * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation
  * @see webrtc_util_strip_description()
  */
-int webrtc_util_create_description(bool is_offer, const char *sdp, char **description);
+int webrtc_util_create_description(bool offer, const char *sdp, char **description);
 
 /**
  * @internal
index 2afdf1feafae804fc484cd4966fb7657e0b67b63..232844ae2cc64662fa7e3fb251c7d8622c283709 100644 (file)
@@ -536,6 +536,7 @@ typedef struct _webrtc_s {
 
        GHashTable *data_channels;
        GHashTable *track_build_contexts;
+       GHashTable *sources;
 
 #ifdef TIZEN_FEATURE_SNAPSHOT
        struct {
@@ -611,6 +612,7 @@ typedef struct _webrtc_gst_slot_s {
                        GstElement *appsrc;
                        GstCaps *appsrc_caps;
                        bool hw_decoder_used;
+                       bool drop;
                } render;
        } av[AV_IDX_MAX];
        struct {
@@ -757,6 +759,8 @@ int _add_transceiver_encoding(webrtc_s *webrtc, unsigned int source_id, webrtc_m
 int _remove_transceiver_encoding(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, const char *rid);
 int _active_transceiver_encoding(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, const char *rid, bool active);
 int _get_transceiver_mid(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, char **mid);
+int _set_transceiver_recv_drop(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, bool drop);
+int _get_transceiver_recv_drop(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, bool *dropped);
 GstCaps *_make_rtp_caps_with_encoding(webrtc_gst_slot_s *source, bool is_audio);
 
 /* file source */
index 9a260a06965fa0e6cb48c746731bf980606890bd..e01d5e1ada05cb05471b6b01fafecb1e5732ca7e 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.4.53
+Version:    0.4.54
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index d23234bd224f0da8871db58628c5fde75c1af4fe..97c3871174e489f543ad743122ba70320bacb6e0 100644 (file)
@@ -286,6 +286,33 @@ int webrtc_media_source_get_transceiver_mid(webrtc_h webrtc, unsigned int source
        return _get_transceiver_mid(webrtc, source_id, media_type, mid);
 }
 
+int webrtc_media_source_set_transceiver_recv_drop(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, bool drop)
+{
+       g_autoptr(GMutexLocker) locker = NULL;
+       webrtc_s *_webrtc = (webrtc_s *)webrtc;
+
+       RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF(source_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "source_id is 0");
+
+       locker = g_mutex_locker_new(&_webrtc->mutex);
+
+       return _set_transceiver_recv_drop(_webrtc, source_id, media_type, drop);
+}
+
+int webrtc_media_source_get_transceiver_recv_drop(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, bool *dropped)
+{
+       g_autoptr(GMutexLocker) locker = NULL;
+       webrtc_s *_webrtc = (webrtc_s *)webrtc;
+
+       RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF(source_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "source_id is 0");
+       RET_VAL_IF(dropped == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "dropped is NULL");
+
+       locker = g_mutex_locker_new(&_webrtc->mutex);
+
+       return _get_transceiver_recv_drop(_webrtc, source_id, media_type, dropped);
+}
+
 int webrtc_media_source_get_type(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e *media_type)
 {
        webrtc_s *_webrtc = (webrtc_s *)webrtc;
@@ -405,7 +432,7 @@ int webrtc_util_strip_description(const char *origin_description, char **descrip
        return WEBRTC_ERROR_NONE;
 }
 
-int webrtc_util_create_description(bool is_offer, const char *sdp, char **description)
+int webrtc_util_create_description(bool offer, const char *sdp, char **description)
 {
        JsonObject *desc, *sdp_desc;
        gchar *result;
@@ -414,7 +441,7 @@ int webrtc_util_create_description(bool is_offer, const char *sdp, char **descri
        RET_VAL_IF(description == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "description is NULL");
 
        sdp_desc = json_object_new();
-       json_object_set_string_member(sdp_desc, "type", is_offer ? "offer": "answer");
+       json_object_set_string_member(sdp_desc, "type", offer ? "offer": "answer");
        json_object_set_string_member(sdp_desc, "sdp", sdp);
 
        desc = json_object_new();
index c6df867ccb65c9b729d8075528ff9003cb09ef30..8cb80386d9e02c8ef449c870bbd1bcfd3ccaf5c3 100644 (file)
@@ -1621,6 +1621,7 @@ int _gst_build_pipeline(webrtc_s *webrtc)
        webrtc->gst.source_slots = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _source_slot_destroy_cb);
        webrtc->gst.sink_slots = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _sink_slot_destroy_cb);
        webrtc->track_build_contexts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _track_build_context_destroy_cb);
+       webrtc->sources = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
 
        return WEBRTC_ERROR_NONE;
 
@@ -1659,6 +1660,10 @@ void _gst_destroy_pipeline(webrtc_s *webrtc)
        }
        __destroy_sink_pipeline(webrtc);
        __destroy_source_pipeline(webrtc);
+       if (webrtc->sources) {
+               g_hash_table_destroy(webrtc->sources);
+               webrtc->sources = NULL;
+       }
        if (webrtc->gst.bus_watcher > 0) {
                gst_bus_remove_watch(webrtc->gst.bus);
                webrtc->gst.bus_watcher = 0;
index 64c892e7a32698f7adbcd6a4c0a2a75ad53f072d..b3103496b24e5b86db2239b1778e895e600087c4 100644 (file)
@@ -1042,14 +1042,37 @@ static GstCaps* __make_caps_if_h264_or_h265(GstPad *pad)
 GstPadProbeReturn _webrtcbin_payloaded_data_probe_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
 {
        probe_userdata_s *probe_data = (probe_userdata_s *)user_data;
-       g_autofree gchar *media_type = _get_mime_type_from_pad(pad);
        webrtc_gst_slot_s *sink;
+       webrtc_gst_slot_s *source;
+       webrtc_s *webrtc;
+       g_autofree gchar *msid = NULL;
+       GstWebRTCRTPTransceiver *transceiver;
 
        ASSERT(probe_data);
 
        sink = probe_data->slot;
-       LOG_VERBOSE("pad[%p] media_type[%s] av_idx[%d] sink[%p, id:%u]",
-               pad, media_type, probe_data->av_idx, sink, sink->id);
+       ASSERT(sink);
+
+       webrtc = sink->webrtc;
+
+       g_object_get(pad,
+               "msid", &msid,
+               "transceiver", &transceiver,
+               NULL);
+
+       LOG_VERBOSE("pad[%p, remote msid:%s, transceiver:%p] av_idx[%d] sink[%p, id:%u]",
+               pad, msid, transceiver, probe_data->av_idx, sink, sink->id);
+
+       source = g_hash_table_lookup(webrtc->sources, transceiver);
+       if (!source) {
+               LOG_WARNING("could not find source by transceiver[%p]", transceiver);
+               return GST_PAD_PROBE_OK;
+       }
+
+       if (source->av[probe_data->av_idx].render.drop) {
+               LOG_DEBUG("data for this transceiver of source->id[%u], drop it,", source->id);
+               return GST_PAD_PROBE_DROP;
+       }
 
        return GST_PAD_PROBE_OK;
 }
index 8718ba4cfa88493f474cba1a23fdf598cb1baf3a..06055da8eb21b188eafb3acb1382ba8adc384909 100644 (file)
@@ -592,8 +592,10 @@ void _source_slot_destroy_cb(gpointer data)
 
                _destroy_looopback_render_pipeline(source, i);
 
-               if (source->av[i].transceiver)
+               if (source->av[i].transceiver) {
                        gst_object_unref(source->av[i].transceiver);
+                       g_hash_table_remove(source->webrtc->sources, source->av[i].transceiver);
+               }
                g_free(source->av[i].mid);
 
                g_hash_table_destroy(source->av[i].encodings);
index 9971f68bf7b9e9dea39a292f3f0482213ad613f9..5df60b4b79da952a9229bb82ff728cf3d12e4f93 100644 (file)
@@ -367,6 +367,8 @@ int _link_source_with_webrtcbin(webrtc_gst_slot_s *source, GstElement *webrtcbin
        GstPad *sinkpad;
        gchar *sinkpad_name = NULL;
        gchar *srcpad_name = NULL;
+       g_autofree gchar *msid = NULL;
+       GstWebRTCRTPTransceiver *transceiver;
 
        RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
        RET_VAL_IF(webrtcbin == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtcbin is NULL");
@@ -381,6 +383,13 @@ int _link_source_with_webrtcbin(webrtc_gst_slot_s *source, GstElement *webrtcbin
                goto exit;
        }
 
+       g_object_get(sinkpad,
+               "msid", &msid,
+               "transceiver", &transceiver,
+               NULL);
+
+       LOG_DEBUG("sinkpad_name[%s] local msid[%s] transceiver[%p]", sinkpad_name, msid, transceiver);
+
        if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_FILE) {
                if ((source->media_types & MEDIA_TYPE_AUDIO) && !__is_linked_pad(source, "audio"))
                        srcpad_name = g_strdup_printf("audio_src_%u", source->id);
index 94366001d2fdb74de602325f0b616f21f09e24ed..70745e01301a43a71238b78335117ccfb8de95ac 100644 (file)
@@ -133,6 +133,8 @@ void _webrtcbin_on_new_transceiver_cb(GstElement *webrtcbin, GstWebRTCRTPTransce
                        LOG_INFO("source->id[%u] source->av[%s][transceiver:%p, direction:%s, mid:%s]",
                                source->id, j == AV_IDX_AUDIO ? "AUDIO" : "VIDEO", source->av[j].transceiver,
                                __convert_transceiver_direction(source->av[j].direction)->str, source->av[j].mid);
+
+                       ASSERT(g_hash_table_insert(webrtc->sources, transceiver, source));
                        return;
                }
        }
@@ -891,3 +893,35 @@ int _get_transceiver_mid(webrtc_s *webrtc, unsigned int source_id, webrtc_media_
 
        return WEBRTC_ERROR_NONE;
 }
+
+int _set_transceiver_recv_drop(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, bool drop)
+{
+       webrtc_gst_slot_s *source;
+       int av_idx = (media_type == WEBRTC_MEDIA_TYPE_AUDIO) ? AV_IDX_AUDIO : AV_IDX_VIDEO;
+
+       RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF((source = _get_slot_by_id(webrtc->gst.source_slots, source_id)) == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
+       RET_VAL_IF(source->av[av_idx].direction == WEBRTC_TRANSCEIVER_DIRECTION_SENDONLY, WEBRTC_ERROR_INVALID_OPERATION, "direction is SENDONLY");
+
+       source->av[av_idx].render.drop = drop;
+
+       LOG_INFO("webrtc[%p] source_id[%u] media_type[%d] drop[%d]", webrtc, source_id, media_type, drop);
+
+       return WEBRTC_ERROR_NONE;
+}
+
+int _get_transceiver_recv_drop(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, bool *dropped)
+{
+       webrtc_gst_slot_s *source;
+       int av_idx = (media_type == WEBRTC_MEDIA_TYPE_AUDIO) ? AV_IDX_AUDIO : AV_IDX_VIDEO;
+
+       RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF((source = _get_slot_by_id(webrtc->gst.source_slots, source_id)) == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
+       RET_VAL_IF(dropped == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "dropped is NULL");
+
+       *dropped = source->av[av_idx].render.drop;
+
+       LOG_INFO("webrtc[%p] source_id[%u] media_type[%d] dropped[%d]", webrtc, source_id, media_type, *dropped);
+
+       return WEBRTC_ERROR_NONE;
+}