From: Sangchul Lee Date: Mon, 18 Mar 2024 08:36:29 +0000 (+0900) Subject: webrtc_internal: Add functions to set/get drop receiving data X-Git-Tag: accepted/tizen/8.0/unified/20240320.143624~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b7686cd3ed6228aa6d7783e7d63f58b81cd3c438;p=platform%2Fcore%2Fapi%2Fwebrtc.git webrtc_internal: Add functions to set/get drop receiving data 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 --- diff --git a/include/webrtc_internal.h b/include/webrtc_internal.h index 40c1772c..3543e258 100644 --- a/include/webrtc_internal.h +++ b/include/webrtc_internal.h @@ -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 diff --git a/include/webrtc_private.h b/include/webrtc_private.h index 2afdf1fe..232844ae 100644 --- a/include/webrtc_private.h +++ b/include/webrtc_private.h @@ -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 */ diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index 9a260a06..e01d5e1a 100644 --- a/packaging/capi-media-webrtc.spec +++ b/packaging/capi-media-webrtc.spec @@ -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 diff --git a/src/webrtc_internal.c b/src/webrtc_internal.c index d23234bd..97c38711 100644 --- a/src/webrtc_internal.c +++ b/src/webrtc_internal.c @@ -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(); diff --git a/src/webrtc_private.c b/src/webrtc_private.c index c6df867c..8cb80386 100644 --- a/src/webrtc_private.c +++ b/src/webrtc_private.c @@ -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; diff --git a/src/webrtc_sink.c b/src/webrtc_sink.c index 64c892e7..b3103496 100644 --- a/src/webrtc_sink.c +++ b/src/webrtc_sink.c @@ -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; } diff --git a/src/webrtc_source.c b/src/webrtc_source.c index 8718ba4c..06055da8 100644 --- a/src/webrtc_source.c +++ b/src/webrtc_source.c @@ -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); diff --git a/src/webrtc_source_private.c b/src/webrtc_source_private.c index 9971f68b..5df60b4b 100644 --- a/src/webrtc_source_private.c +++ b/src/webrtc_source_private.c @@ -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); diff --git a/src/webrtc_transceiver.c b/src/webrtc_transceiver.c index 94366001..70745e01 100644 --- a/src/webrtc_transceiver.c +++ b/src/webrtc_transceiver.c @@ -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; +}