From: Sangchul Lee Date: Wed, 17 Jan 2024 07:49:01 +0000 (+0900) Subject: webrtc_internal: Add API to active transceiver encoding option X-Git-Tag: accepted/tizen/unified/20240215.130027~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F74%2F305374%2F2;p=platform%2Fcore%2Fapi%2Fwebrtc.git webrtc_internal: Add API to active transceiver encoding option webrtc_media_source_active_transceiver_encoding() has been added. This function is to activate or deactivate each rid based stream. [Version] 0.4.41 [Issue Type] Internal API Change-Id: I65b4edcb7b171ad7c17b97153047888039a54e9f Signed-off-by: Sangchul Lee --- diff --git a/include/webrtc_internal.h b/include/webrtc_internal.h index f59fe525..2ea49a2f 100644 --- a/include/webrtc_internal.h +++ b/include/webrtc_internal.h @@ -364,6 +364,27 @@ int webrtc_media_source_add_transceiver_encoding(webrtc_h webrtc, unsigned int s */ int webrtc_media_source_remove_transceiver_encoding(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, const char *rid); +/** + * @internal + * @brief Actives the transceiver encoding option of the media source. + * @since_tizen 9.0 + * @remarks The default value is @c true. + * @param[in] webrtc WebRTC handle + * @param[in] source_id The media source id + * @param[in] media_type The media type + * @param[in] rid The RID (RTP Stream Identifier) + * @param[in] active Active or not (@c true = active, @c false = inactive) + * @return @c 0 on success, + * otherwise a negative error value + * @retval #WEBRTC_ERROR_NONE Successful + * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter + * @pre Add media source to @a webrtc to get @a source_id by calling webrtc_add_media_source(). + * @pre webrtc_media_source_add_transceiver_encoding() must be called before calling this function. + * @see webrtc_media_source_add_transceiver_encoding() + * @see webrtc_media_source_remove_transceiver_encoding() + */ +int webrtc_media_source_active_transceiver_encoding(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, const char *rid, bool active); + /** * @internal * @brief Sets the probability of RTP packet dropping. diff --git a/include/webrtc_private.h b/include/webrtc_private.h index 24434707..83ba7b50 100644 --- a/include/webrtc_private.h +++ b/include/webrtc_private.h @@ -667,6 +667,7 @@ typedef struct { int height; bool active; GstPad *src_pad; + gulong src_pad_probe_id; webrtc_gst_slot_s *source; } webrtc_transceiver_encoding_s; @@ -747,6 +748,7 @@ int _get_transceiver_codec(webrtc_s *webrtc, unsigned int source_id, webrtc_medi int _foreach_supported_transceiver_codec(webrtc_s *webrtc, webrtc_media_source_type_e source_type, webrtc_media_type_e media_type, webrtc_media_source_supported_transceiver_codec_cb callback, void *user_data); int _add_transceiver_encoding(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, const char *rid, int target_bitrate, int width, int height); 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); 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 d4dacc53..45fcf489 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.40 +Version: 0.4.41 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/webrtc_internal.c b/src/webrtc_internal.c index 0c2158d5..b3247ac6 100644 --- a/src/webrtc_internal.c +++ b/src/webrtc_internal.c @@ -259,6 +259,19 @@ int webrtc_media_source_remove_transceiver_encoding(webrtc_h webrtc, unsigned in return _remove_transceiver_encoding(webrtc, source_id, media_type, rid); } +int webrtc_media_source_active_transceiver_encoding(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, const char *rid, bool active) +{ + 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(rid == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "rid is NULL"); + + locker = g_mutex_locker_new(&_webrtc->mutex); + + return _active_transceiver_encoding(webrtc, source_id, media_type, rid, active); +} + int webrtc_set_rtp_packet_drop_probability(webrtc_h webrtc, bool sender, float probability) { webrtc_s *_webrtc = (webrtc_s *)webrtc; diff --git a/src/webrtc_source_simulcast.c b/src/webrtc_source_simulcast.c index 6591127a..cf690dbb 100644 --- a/src/webrtc_source_simulcast.c +++ b/src/webrtc_source_simulcast.c @@ -108,6 +108,53 @@ exit: return ret; } +static GstPadProbeReturn __encoding_stream_probe_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) +{ + webrtc_transceiver_encoding_s *encoding = (webrtc_transceiver_encoding_s *)user_data; + GstBuffer *buffer; + + ASSERT(info); + ASSERT(info->data); + ASSERT(encoding); + + buffer = gst_pad_probe_info_get_buffer(info); + + if (!encoding->active) { + LOG_DEBUG("inactive, drop buffer[%p] of encoding[ssrc:%d, pad:%p, probe_id:%lu]", + buffer, encoding->ssrc, encoding->src_pad, encoding->src_pad_probe_id); + return GST_PAD_PROBE_DROP; + } + + return GST_PAD_PROBE_OK; +} + +static void __add_probe_to_pad_for_active(webrtc_transceiver_encoding_s *encoding, void *probe_cb) +{ + ASSERT(encoding); + ASSERT(probe_cb); + + encoding->src_pad_probe_id = gst_pad_add_probe(encoding->src_pad, GST_PAD_PROBE_TYPE_BUFFER, + probe_cb, encoding, NULL); + + LOG_DEBUG("encoding[ssrc:%d, pad:%p, probe_id:%lu]", + encoding->ssrc, encoding->src_pad, encoding->src_pad_probe_id); +} + +static void __remove_probe_from_pad_for_active(webrtc_transceiver_encoding_s *encoding) +{ + ASSERT(encoding); + + if (encoding->src_pad_probe_id == 0) + return; + + LOG_DEBUG("encoding[ssrc:%d, pad:%p, probe_id:%lu]", + encoding->ssrc, encoding->src_pad, encoding->src_pad_probe_id); + + gst_pad_remove_probe(encoding->src_pad, encoding->src_pad_probe_id); + + encoding->src_pad_probe_id = 0; +} + static void __create_and_link_elements_foreach_cb(gpointer key, gpointer value, gpointer user_data) { webrtc_transceiver_encoding_s *encoding = (webrtc_transceiver_encoding_s *)value; @@ -128,7 +175,7 @@ static void __create_and_link_elements_foreach_cb(gpointer key, gpointer value, source = userdata->source; av_idx = userdata->is_audio ? AV_IDX_AUDIO : AV_IDX_VIDEO; - LOG_INFO("key[%s] encoding[%p, ssrc:%d, active:%d] userdata[is_audio:%d, source;%p]", + LOG_INFO("rid[%s] encoding[%p, ssrc:%d, active:%d] userdata[is_audio:%d, source:%p]", rid, encoding, encoding->ssrc, encoding->active, userdata->is_audio, userdata->source); if (!encoding->active) { @@ -194,6 +241,8 @@ static void __create_and_link_elements_foreach_cb(gpointer key, gpointer value, if (__link_encoding_bin_with_funnel(encoding, userdata->funnel) != WEBRTC_ERROR_NONE) goto exit_with_remove_from_bin; + __add_probe_to_pad_for_active(encoding, __encoding_stream_probe_cb); + SAFE_G_LIST_FREE(element_list); return; @@ -223,7 +272,7 @@ static void __add_rtp_header_extensions_foreach_cb(gpointer key, gpointer value, source = userdata->source; av_idx = userdata->is_audio ? AV_IDX_AUDIO : AV_IDX_VIDEO; - LOG_INFO("key[%s] encoding[%p, ssrc:%d, active:%d] userdata[is_audio:%d, source:%p]", + LOG_INFO("rid[%s] encoding[%p, ssrc:%d, active:%d] userdata[is_audio:%d, source:%p]", rid, encoding, encoding->ssrc, encoding->active, userdata->is_audio, userdata->source); if (!encoding->active) { @@ -257,6 +306,7 @@ int _add_no_target_ghostpad_to_encoding(webrtc_transceiver_encoding_s *encoding, void _encoding_slot_destroy_cb(gpointer data) { webrtc_transceiver_encoding_s *encoding = (webrtc_transceiver_encoding_s *)data; + GstElement *parent; ASSERT(encoding); ASSERT(encoding->source); @@ -264,8 +314,9 @@ void _encoding_slot_destroy_cb(gpointer data) LOG_DEBUG("encoding[%p, ssrc:%d, source:%s, soource_id:%u] is removed", encoding, encoding->ssrc, encoding->source->bin ? GST_ELEMENT_NAME(encoding->source->bin) : "null", encoding->source->id); - GstElement *parent = GST_ELEMENT(gst_element_get_parent(encoding->bin)); - if (parent) + __remove_probe_from_pad_for_active(encoding); + + if ((parent = GST_ELEMENT(gst_element_get_parent(encoding->bin)))) gst_bin_remove(GST_BIN(parent), GST_ELEMENT(encoding->bin)); g_free(encoding); @@ -419,6 +470,7 @@ GstCaps *_create_simulcast_caps(webrtc_gst_slot_s *source, bool is_send, bool is GHashTableIter iter; gpointer key, value; int count = 0; + webrtc_transceiver_encoding_s *encoding; RET_VAL_IF(source == NULL, NULL, "source is NULL"); @@ -437,6 +489,11 @@ GstCaps *_create_simulcast_caps(webrtc_gst_slot_s *source, bool is_send, bool is g_hash_table_iter_init(&iter, source->av[av_idx].encodings); while (g_hash_table_iter_next(&iter, &key, &value)) { + encoding = (webrtc_transceiver_encoding_s *)value; + if (!encoding->active) { + LOG_WARNING("skip this inactive encoding option"); + continue; + } rid_key = g_strdup_printf("rid-%s", (gchar *)key); gst_structure_set(s, rid_key, G_TYPE_STRING, is_send ? "send" : "recv", NULL); if (count++ > 0) diff --git a/src/webrtc_transceiver.c b/src/webrtc_transceiver.c index 40d49c7b..e30db3c5 100644 --- a/src/webrtc_transceiver.c +++ b/src/webrtc_transceiver.c @@ -838,3 +838,42 @@ int _remove_transceiver_encoding(webrtc_s *webrtc, unsigned int source_id, webrt return _remove_source_encoding(source, av_idx, rid); } + +static int __active_encoding(webrtc_gst_slot_s *source, int av_idx, const char *rid, bool active) +{ + webrtc_transceiver_encoding_s *encoding; + + ASSERT(source); + ASSERT(rid); + + if (!g_hash_table_contains(source->av[av_idx].encodings, rid)) { + LOG_ERROR("rid[%s] does not exist of the source[id:%u, av_idx:%d]", rid, source->id, av_idx); + return WEBRTC_ERROR_INVALID_PARAMETER; + } + + encoding = g_hash_table_lookup(source->av[av_idx].encodings, rid); + ASSERT(encoding); + + if (encoding->active == active) { + LOG_INFO("it is already the active[%d]", active); + return WEBRTC_ERROR_NONE; + } + + encoding->active = active; + LOG_INFO("source_id[%u], av_idx[%d], rid[%s], encoding[ssrc:%d, target_bitrate:%d, width:%d, height:%d, active:%d]", + source->id, av_idx, rid, encoding->ssrc, encoding->target_bitrate, encoding->width, encoding->height, encoding->active); + + return WEBRTC_ERROR_NONE; +} + +int _active_transceiver_encoding(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, const char *rid, bool active) +{ + 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(rid == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "rid is NULL"); + + return __active_encoding(source, av_idx, rid, active); +}