From bdecfea19007b938a840f88553869e5459072fb2 Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Wed, 16 Mar 2016 21:39:51 +0900 Subject: [PATCH 01/16] fix build warning Change-Id: I4b569ee5e9649380d5d5d419c13cfbf204c8a355 Signed-off-by: Eunhae Choi --- CMakeLists.txt | 2 +- packaging/capi-media-streamer.spec | 2 +- src/media_streamer_gst.c | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) mode change 100755 => 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100755 new mode 100644 index 434752a..cf69184 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ FOREACH(flag ${${fw_name}_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror") SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") IF("${ARCH}" STREQUAL "arm") diff --git a/packaging/capi-media-streamer.spec b/packaging/capi-media-streamer.spec index 3d151f9..f94faeb 100755 --- a/packaging/capi-media-streamer.spec +++ b/packaging/capi-media-streamer.spec @@ -1,6 +1,6 @@ Name: capi-media-streamer Summary: A Media Streamer library in Tizen Native API -Version: 0.1.3 +Version: 0.1.4 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index cf92806..640441f 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -679,6 +679,7 @@ static gint __decodebin_autoplug_select_cb(GstElement * bin, GstPad * pad, GstCa gchar *factory_name = NULL; const gchar *klass = NULL; + GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY; factory_name = GST_OBJECT_NAME(factory); klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS); @@ -695,10 +696,10 @@ static gint __decodebin_autoplug_select_cb(GstElement * bin, GstPad * pad, GstCa return GST_AUTOPLUG_SELECT_SKIP; } } - } - return GST_AUTOPLUG_SELECT_TRY; +DONE: + return result; } static void __decodebin_newpad_streamer(GstElement * decodebin, GstPad * new_pad, const gchar * new_pad_type) -- 2.7.4 From 831e7713e8f713afee698f3066afce34386f6a6b Mon Sep 17 00:00:00 2001 From: Vyacheslav Valkovoy Date: Thu, 17 Mar 2016 17:33:34 +0200 Subject: [PATCH 02/16] Fixed distortion of audio, video at Client part while Streaming. Change-Id: I7edaf17ad9f222c768b5eecda283ff9e9b5e1a91 Signed-off-by: Vyacheslav Valkovoy --- include/media_streamer_util.h | 3 ++- src/media_streamer_gst.c | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/include/media_streamer_util.h b/include/media_streamer_util.h index 4e886e2..b3e898d 100644 --- a/include/media_streamer_util.h +++ b/include/media_streamer_util.h @@ -144,6 +144,7 @@ typedef struct { #define DEFAULT_EVAS_SINK "evaspixmapsink" #define DEFAULT_VIDEO_SCALE "videoscale" #define DEFAULT_VIDEO_CONVERT "videoconvert" +#define DEFAULT_VIDEO_RATE "videorate" #define DEFAULT_TEXT_OVERLAY "textoverlay" #define DEFAULT_AUDIO_CONVERT "audioconvert" #define DEFAULT_AUDIO_RESAMPLE "audioresample" @@ -178,6 +179,7 @@ typedef struct { #define MS_ELEMENT_IS_AUDIO(el) g_strrstr(el, "audio") #define MS_ELEMENT_IS_VIDEO(el) g_strrstr(el, "video") #define MS_ELEMENT_IS_IMAGE(el) g_strrstr(el, "image") +#define MS_ELEMENT_IS_TEXT(el) g_strrstr(el, "text") #define MS_RTP_PAD_VIDEO_IN "video_in" #define MS_RTP_PAD_AUDIO_IN "audio_in" @@ -187,7 +189,6 @@ typedef struct { #define MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT MS_RTP_PAD_AUDIO_IN"_format" #define MS_ELEMENT_IS_RTP(el) g_strrstr(el, "rtp_container") -#define MS_ELEMENT_IS_TEXT(el) g_strrstr(el, "text") #define MS_ELEMENT_IS_ENCODER(el) g_strrstr(el, "encoder") #define MS_ELEMENT_IS_DECODER(el) g_strrstr(el, "decoder") diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index 640441f..ba65bc6 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -984,6 +984,7 @@ GstElement *__ms_video_encoder_element_create(dictionary * dict, media_format_mi GstElement *video_scale = __ms_element_create(DEFAULT_VIDEO_SCALE, NULL); GstElement *video_convert = __ms_element_create(DEFAULT_VIDEO_CONVERT, NULL); + GstElement *video_rate = __ms_element_create(DEFAULT_VIDEO_RATE, NULL); format_prefix = g_strdup_printf("%s:encoder", __ms_convert_mime_to_string(mime)); plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_ENCODER); @@ -1000,17 +1001,16 @@ GstElement *__ms_video_encoder_element_create(dictionary * dict, media_format_mi gboolean gst_ret = FALSE; GstElement *encoder_bin = gst_bin_new("video_encoder"); GstElement *filter = __ms_element_create("capsfilter", NULL); - ms_retvm_if(!video_convert || !video_scale || !filter || !encoder_elem || !encoder_bin || !encoder_parser, (GstElement *) NULL, "Error: creating elements for video encoder bin"); + ms_retvm_if(!video_convert || !video_rate || !video_scale || !filter || !encoder_elem || !encoder_bin || !encoder_parser, (GstElement *) NULL, "Error: creating elements for video encoder bin"); format_prefix = g_strdup_printf(MEDIA_STREAMER_DEFAULT_ENCODER_FORMAT("%s"), __ms_convert_mime_to_string(mime)); GstCaps *videoCaps = gst_caps_from_string(format_prefix); g_object_set(G_OBJECT(filter), "caps", videoCaps, NULL); MS_SAFE_FREE(format_prefix); - gst_caps_unref(videoCaps); - gst_bin_add_many(GST_BIN(encoder_bin), video_convert, video_scale, encoder_elem, filter, encoder_parser, NULL); - gst_ret = gst_element_link_many(video_convert, video_scale, encoder_elem, filter, encoder_parser, NULL); + gst_bin_add_many(GST_BIN(encoder_bin), video_convert, video_scale, video_rate, encoder_elem, filter, encoder_parser, NULL); + gst_ret = gst_element_link_many(video_convert, video_scale, video_rate, encoder_elem, filter, encoder_parser, NULL); if (gst_ret != TRUE) { ms_error("Failed to link elements into encoder_bin"); MS_SAFE_UNREF(encoder_bin); @@ -1086,23 +1086,25 @@ GstElement *__ms_audio_encoder_element_create(void) { gboolean gst_ret = FALSE; GstElement *audio_convert = __ms_element_create("audioconvert", NULL); + GstElement *audio_resample = __ms_element_create("audioresample", NULL); GstElement *audio_filter = __ms_element_create("capsfilter", NULL); + GstElement *audio_postenc_convert = __ms_element_create("audioconvert", NULL); GstElement *audio_enc_bin = gst_bin_new("audio_encoder"); - ms_retvm_if(!audio_convert || !audio_filter || !audio_enc_bin, (GstElement *) NULL, "Error: creating elements for encoder bin"); + ms_retvm_if(!audio_convert || !audio_postenc_convert || !audio_filter || !audio_enc_bin, (GstElement *) NULL, "Error: creating elements for encoder bin"); GstCaps *audioCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT); g_object_set(G_OBJECT(audio_filter), "caps", audioCaps, NULL); gst_caps_unref(audioCaps); - gst_bin_add_many(GST_BIN(audio_enc_bin), audio_convert, audio_filter, NULL); - gst_ret = gst_element_link_many(audio_filter, audio_convert, NULL); + gst_bin_add_many(GST_BIN(audio_enc_bin), audio_convert, audio_postenc_convert, audio_filter, audio_resample, NULL); + gst_ret = gst_element_link_many(audio_convert, audio_resample, audio_filter, audio_postenc_convert, NULL); if (gst_ret != TRUE) { ms_error("Failed to link elements into decoder_bin"); MS_SAFE_UNREF(audio_enc_bin); } - __ms_add_ghostpad(audio_convert, "src", audio_enc_bin, "src"); - __ms_add_ghostpad(audio_filter, "sink", audio_enc_bin, "sink"); + __ms_add_ghostpad(audio_postenc_convert, "src", audio_enc_bin, "src"); + __ms_add_ghostpad(audio_convert, "sink", audio_enc_bin, "sink"); return audio_enc_bin; } -- 2.7.4 From 50be189144a825d65ffc5b5549025b9b8ce30164 Mon Sep 17 00:00:00 2001 From: Vyacheslav Valkovoy Date: Thu, 17 Mar 2016 17:39:42 +0200 Subject: [PATCH 03/16] Fixed File Streaming with inner subtitles Scenario. Change-Id: Ide44cb6f8dde6fcc90a3aeea80f7ac23a172ae42 Signed-off-by: Vyacheslav Valkovoy --- src/media_streamer_gst.c | 159 +++++++++++++++++++++++----------------------- src/media_streamer_node.c | 8 ++- 2 files changed, 84 insertions(+), 83 deletions(-) diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index ba65bc6..e71a4bc 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -698,31 +698,9 @@ static gint __decodebin_autoplug_select_cb(GstElement * bin, GstPad * pad, GstCa } } -DONE: return result; } -static void __decodebin_newpad_streamer(GstElement * decodebin, GstPad * new_pad, const gchar * new_pad_type) -{ - GstElement *found_element = NULL; - GstElement *bin_to_find_in = (GstElement *) gst_element_get_parent(decodebin); - - if (MS_ELEMENT_IS_VIDEO(new_pad_type)) { - found_element = __ms_combine_next_element(decodebin, new_pad, bin_to_find_in, NULL, NULL, DEFAULT_QUEUE); - found_element = __ms_combine_next_element(found_element, NULL, bin_to_find_in, MEDIA_STREAMER_BIN_KLASS, "video_encoder", DEFAULT_VIDEO_ENCODER); - found_element = __ms_combine_next_element(found_element, NULL, bin_to_find_in, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); - found_element = __ms_combine_next_element(found_element, NULL, bin_to_find_in, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); - } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) { - - found_element = __ms_combine_next_element(decodebin, new_pad, bin_to_find_in, NULL, NULL, DEFAULT_QUEUE); - found_element = __ms_combine_next_element(found_element, NULL, bin_to_find_in, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_AUDIO_CONVERT); - found_element = __ms_combine_next_element(found_element, NULL, bin_to_find_in, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); - found_element = __ms_combine_next_element(found_element, NULL, bin_to_find_in, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); - } else { - ms_error("Unsupported pad type [%s]!", new_pad_type); - } -} - static gint __pad_type_compare(gconstpointer a, gconstpointer b) { GstPad *a_pad = GST_PAD(a); @@ -746,36 +724,9 @@ static void __decodebin_newpad_cb(GstElement * decodebin, GstPad * new_pad, gpoi g_mutex_lock(&ms_streamer->mutex_lock); - const gchar *new_pad_type = __ms_get_pad_type(new_pad); - ms_info("Received new pad [%s] type [%s] from [%s]", GST_PAD_NAME(new_pad), new_pad_type, GST_ELEMENT_NAME(decodebin)); + g_object_ref(new_pad); + ms_streamer->pads_types_list = g_list_insert_sorted(ms_streamer->pads_types_list, new_pad, __pad_type_compare); - /* Looking for RTP node to find out if it is Playing or Streamer Scenario */ - GstElement *rtp = __ms_bin_find_element_by_klass(ms_streamer->topology_bin, - NULL, NULL, MEDIA_STREAMER_BIN_KLASS, "rtp_container"); - gboolean supported_stream_type = TRUE; - - /* Finds out if RTP is set for Server or Client part */ - if (rtp) { - GstPad *src_pad = NULL; - if (MS_ELEMENT_IS_VIDEO(new_pad_type)) { - src_pad = gst_element_get_static_pad(rtp, "video_out"); - supported_stream_type = src_pad ? TRUE : FALSE; - } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) { - src_pad = gst_element_get_static_pad(rtp, "audio_out"); - supported_stream_type = src_pad ? TRUE : FALSE; - } - } else { - ms_info("RTP element is not found. It`s client part."); - } - - if (rtp && !supported_stream_type) { - /* Carry out Decodebin callback if it is Server part */ - __decodebin_newpad_streamer(decodebin, new_pad, new_pad_type); - } else { - /* Collect decodebin`s pads to properly connect them afterwards at Client part */ - g_object_ref(new_pad); - ms_streamer->pads_types_list = g_list_insert_sorted(ms_streamer->pads_types_list, new_pad, __pad_type_compare); - } g_mutex_unlock(&ms_streamer->mutex_lock); } @@ -789,59 +740,105 @@ static void _sink_node_unlock_state(const GValue * item, gpointer user_data) gst_element_sync_state_with_parent(sink_element); } } - -static void __decodebin_nomore_pads_cb(GstElement * decodebin, gpointer user_data) +static void __decodebin_nomore_pads_streamer(GstElement * decodebin, media_streamer_s *ms_streamer) { - media_streamer_s *ms_streamer = (media_streamer_s *) user_data; - ms_retm_if(ms_streamer == NULL, "Handle is NULL"); - - g_mutex_lock(&ms_streamer->mutex_lock); - GstElement *found_element = NULL; - gboolean subtitles_exist = FALSE; - GList *iterator = NULL; GList *list = ms_streamer->pads_types_list; - const gchar *pad_type = NULL; + const gchar *new_pad_type = NULL; for (iterator = list; iterator; iterator = iterator->next) { - pad_type = __ms_get_pad_type(GST_PAD(iterator->data)); - if (MS_ELEMENT_IS_TEXT(pad_type)) - subtitles_exist = TRUE; + GstPad *new_pad = GST_PAD(iterator->data); + new_pad_type = __ms_get_pad_type(new_pad); + found_element = gst_pad_get_parent_element(new_pad); + + if (MS_ELEMENT_IS_VIDEO(new_pad_type)) { + if(__ms_bin_find_element_by_klass(ms_streamer->topology_bin, NULL, NULL, MEDIA_STREAMER_OVERLAY_KLASS, NULL)) { + found_element = __ms_combine_next_element(found_element, new_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); + new_pad = NULL; + } + found_element = __ms_combine_next_element(found_element, new_pad, ms_streamer->topology_bin, NULL, NULL, DEFAULT_QUEUE); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "video_encoder", NULL); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); + } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) { + found_element = __ms_combine_next_element(found_element, new_pad, ms_streamer->topology_bin, NULL, NULL, DEFAULT_QUEUE); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "audio_encoder", NULL); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, DEFAULT_AUDIO_RTPPAY); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); + } else if (MS_ELEMENT_IS_TEXT(new_pad_type)) { + found_element = __ms_combine_next_element(found_element, new_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); + } else { + ms_error("Unsupported pad type [%s]!", new_pad_type); + return; + } + __ms_generate_dots(ms_streamer->pipeline, "after_sink_linked"); } +} + +static void __decodebin_nomore_pads_client(GstElement * decodebin, media_streamer_s *ms_streamer) +{ + + GstElement *found_element = NULL; + GList *iterator = NULL; + GList *list = ms_streamer->pads_types_list; + const gchar *pad_type = NULL; for (iterator = list; iterator; iterator = iterator->next) { GstPad *src_pad = GST_PAD(iterator->data); pad_type = __ms_get_pad_type(src_pad); - GstElement *parent_decodebin = gst_pad_get_parent_element(src_pad); + found_element = gst_pad_get_parent_element(src_pad); if (MS_ELEMENT_IS_AUDIO(pad_type)) { - found_element = __ms_combine_next_element(parent_decodebin, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_AUDIO_CONVERT); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, NULL, NULL, DEFAULT_QUEUE); + found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_AUDIO_CONVERT); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); } else if (MS_ELEMENT_IS_VIDEO(pad_type)) { - if (subtitles_exist) { - found_element = __ms_combine_next_element(parent_decodebin, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_VIDEO_CONVERT); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, NULL, NULL, DEFAULT_QUEUE); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); - } else { - found_element = __ms_combine_next_element(parent_decodebin, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_VIDEO_CONVERT); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, NULL, NULL, DEFAULT_QUEUE); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); + if(__ms_bin_find_element_by_klass(ms_streamer->topology_bin, NULL, NULL, MEDIA_STREAMER_OVERLAY_KLASS, NULL)) { + found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); + src_pad = NULL; } + found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_VIDEO_CONVERT); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); } else if (MS_ELEMENT_IS_TEXT(pad_type)) { - found_element = __ms_combine_next_element(parent_decodebin, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); + found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); } else { ms_error("Unsupported pad type [%s]!", pad_type); - MS_SAFE_UNREF(found_element); - g_mutex_unlock(&ms_streamer->mutex_lock); return; } __ms_generate_dots(ms_streamer->pipeline, "after_sink_linked"); - MS_SAFE_UNREF(parent_decodebin); } MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, _sink_node_unlock_state, NULL); +} + +static void __decodebin_nomore_pads_cb(GstElement * decodebin, gpointer user_data) +{ + media_streamer_s *ms_streamer = (media_streamer_s *) user_data; + ms_retm_if(ms_streamer == NULL, "Handle is NULL"); + + g_mutex_lock(&ms_streamer->mutex_lock); + + char *param_value = NULL; + media_streamer_node_s *rtp_node = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "rtp_container"); + + if (rtp_node) { + /* It`s Streaming Scenario*/ + media_streamer_node_get_param(rtp_node, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT, ¶m_value); + if (param_value && (strtol(param_value, NULL, 10) > 0)) + + /* It`s Streamer part of Streaming */ + __decodebin_nomore_pads_streamer(decodebin, ms_streamer); + else + /* It`s Client part of Streaming */ + __decodebin_nomore_pads_client(decodebin, ms_streamer); + } else { + + /* It`s Client Scenario*/ + __decodebin_nomore_pads_client(decodebin, ms_streamer); + } + + MS_SAFE_FREE(param_value); g_mutex_unlock(&ms_streamer->mutex_lock); } @@ -889,6 +886,8 @@ static gboolean __ms_sink_bin_prepare(media_streamer_s * ms_streamer, GstPad * s } } else { previous_element = __ms_link_with_new_element(previous_element, src_pad, found_element); + previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); + previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); } } else if (MS_ELEMENT_IS_AUDIO(src_pad_type)) { previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_AUDIO_CONVERT); diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c index bc54893..b928f15 100755 --- a/src/media_streamer_node.c +++ b/src/media_streamer_node.c @@ -484,14 +484,16 @@ static void _src_node_prepare(const GValue *item, gpointer user_data) } if (MS_ELEMENT_IS_VIDEO(new_pad_type) || MS_ELEMENT_IS_IMAGE(new_pad_type)) { - found_element = __ms_combine_next_element(src_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "video_encoder", NULL); + found_element = __ms_combine_next_element(src_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "video_encoder", NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); } if (MS_ELEMENT_IS_AUDIO(new_pad_type)) { - found_element = __ms_combine_next_element(src_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "audio_encoder", NULL); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); + found_element = __ms_combine_next_element(src_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "audio_encoder", NULL); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, DEFAULT_AUDIO_RTPPAY); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); } __ms_generate_dots(ms_streamer->pipeline, "after_connecting_rtp"); -- 2.7.4 From eba940e66e7a68dd3ec343d7a85495449ae4a32f Mon Sep 17 00:00:00 2001 From: Vyacheslav Valkovoy Date: Thu, 17 Mar 2016 18:06:57 +0200 Subject: [PATCH 04/16] Added Encoding/Decoding of audio stream. Change-Id: I28441e5dab20bbf6f712463f1cc29b5088a04011 Signed-off-by: Vyacheslav Valkovoy --- include/media_streamer_util.h | 13 ++++++++----- src/media_streamer_gst.c | 42 +++++++++++++++++++++++------------------- src/media_streamer_node.c | 25 +++++++++++++++---------- 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/include/media_streamer_util.h b/include/media_streamer_util.h index b3e898d..99010a9 100644 --- a/include/media_streamer_util.h +++ b/include/media_streamer_util.h @@ -133,6 +133,7 @@ typedef struct { #define DEFAULT_GENERATE_DOT FALSE #define DEFAULT_USE_DECODEBIN FALSE #define DEFAULT_QUEUE "queue" +#define DEFAULT_FILTER "capsfilter" #define DEFAULT_TYPEFIND "typefind" #define DEFAULT_DECODEBIN "decodebin" #define DEFAULT_AUDIO_SOURCE "alsasrc" @@ -165,13 +166,15 @@ typedef struct { #define DEFAULT_VIDEO_RTPDEPAY "rtph263depay" /* audio format defaults */ -#define DEFAULT_AUDIO_PARSER "aacparse" -#define DEFAULT_AUDIO_RTPPAY "rtpL16pay" -#define DEFAULT_AUDIO_RTPDEPAY "rtpL16depay" +#define DEFAULT_AUDIO_ENCODER "amrnbenc" +#define DEFAULT_AUDIO_DECODER "amrnbdec" +#define DEFAULT_AUDIO_PARSER "amrparse" +#define DEFAULT_AUDIO_RTPPAY "rtpamrpay" +#define DEFAULT_AUDIO_RTPDEPAY "rtpamrdepay" #define DEFAULT_AUDIO "S16LE" -#define MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT "video/x-raw,width=1280,height=720" -#define MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT "audio/x-raw,channels=1,rate=44100,format="DEFAULT_AUDIO +#define MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT "video/x-raw,format=I420,width=1280,height=720" +#define MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT "audio/x-raw,channels=1,rate=8000,format="DEFAULT_AUDIO #define MEDIA_STREAMER_DEFAULT_ENCODER_FORMAT(format) "video/x-"format",stream-format=byte-stream" #define MS_ELEMENT_IS_OUTPUT(el) g_strrstr(el, "out") diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index e71a4bc..deef712 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -21,6 +21,7 @@ gst_pad_unlink(pad, peer) : \ gst_pad_unlink(peer, pad) #define H264_PARSER_CONFIG_INTERVAL 5 +#define H264_ENCODER_ZEROLATENCY 0x00000004 void __ms_generate_dots(GstElement *bin, gchar *name_tag) { @@ -764,7 +765,7 @@ static void __decodebin_nomore_pads_streamer(GstElement * decodebin, media_strea } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) { found_element = __ms_combine_next_element(found_element, new_pad, ms_streamer->topology_bin, NULL, NULL, DEFAULT_QUEUE); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "audio_encoder", NULL); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, DEFAULT_AUDIO_RTPPAY); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); } else if (MS_ELEMENT_IS_TEXT(new_pad_type)) { found_element = __ms_combine_next_element(found_element, new_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); @@ -890,7 +891,7 @@ static gboolean __ms_sink_bin_prepare(media_streamer_s * ms_streamer, GstPad * s previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); } } else if (MS_ELEMENT_IS_AUDIO(src_pad_type)) { - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_AUDIO_CONVERT); + previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_DECODER_KLASS, NULL, NULL); previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); } else { @@ -983,33 +984,35 @@ GstElement *__ms_video_encoder_element_create(dictionary * dict, media_format_mi GstElement *video_scale = __ms_element_create(DEFAULT_VIDEO_SCALE, NULL); GstElement *video_convert = __ms_element_create(DEFAULT_VIDEO_CONVERT, NULL); - GstElement *video_rate = __ms_element_create(DEFAULT_VIDEO_RATE, NULL); format_prefix = g_strdup_printf("%s:encoder", __ms_convert_mime_to_string(mime)); plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_ENCODER); GstElement *encoder_elem = __ms_element_create(plugin_name, NULL); + MS_SAFE_FREE(format_prefix); MS_SAFE_FREE(plugin_name); format_prefix = g_strdup_printf("%s:parser", __ms_convert_mime_to_string(mime)); plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_PARSER); GstElement *encoder_parser = __ms_element_create(plugin_name, NULL); + MS_SAFE_FREE(format_prefix); MS_SAFE_FREE(plugin_name); gboolean gst_ret = FALSE; GstElement *encoder_bin = gst_bin_new("video_encoder"); - GstElement *filter = __ms_element_create("capsfilter", NULL); - ms_retvm_if(!video_convert || !video_rate || !video_scale || !filter || !encoder_elem || !encoder_bin || !encoder_parser, (GstElement *) NULL, "Error: creating elements for video encoder bin"); - - format_prefix = g_strdup_printf(MEDIA_STREAMER_DEFAULT_ENCODER_FORMAT("%s"), __ms_convert_mime_to_string(mime)); - GstCaps *videoCaps = gst_caps_from_string(format_prefix); - g_object_set(G_OBJECT(filter), "caps", videoCaps, NULL); - MS_SAFE_FREE(format_prefix); - gst_caps_unref(videoCaps); + ms_retvm_if(!video_convert || !video_scale || !encoder_elem || !encoder_bin || !encoder_parser, (GstElement *) NULL, "Error: creating elements for video encoder bin"); + + if (mime == MEDIA_FORMAT_H264_SP) { + g_object_set(GST_OBJECT(encoder_parser), "config-interval", H264_PARSER_CONFIG_INTERVAL, NULL); + g_object_set(G_OBJECT(encoder_elem), "tune", H264_ENCODER_ZEROLATENCY, NULL); + g_object_set(G_OBJECT(encoder_elem), "byte-stream", TRUE, NULL); + g_object_set(G_OBJECT(encoder_elem), "bitrate", 3000, NULL); + g_object_set(G_OBJECT(encoder_elem), "threads", 2, NULL); + } - gst_bin_add_many(GST_BIN(encoder_bin), video_convert, video_scale, video_rate, encoder_elem, filter, encoder_parser, NULL); - gst_ret = gst_element_link_many(video_convert, video_scale, video_rate, encoder_elem, filter, encoder_parser, NULL); + gst_bin_add_many(GST_BIN(encoder_bin), video_convert, video_scale, encoder_elem, encoder_parser, NULL); + gst_ret = gst_element_link_many(video_convert, video_scale, encoder_elem, encoder_parser, NULL); if (gst_ret != TRUE) { ms_error("Failed to link elements into encoder_bin"); MS_SAFE_UNREF(encoder_bin); @@ -1088,21 +1091,22 @@ GstElement *__ms_audio_encoder_element_create(void) GstElement *audio_resample = __ms_element_create("audioresample", NULL); GstElement *audio_filter = __ms_element_create("capsfilter", NULL); GstElement *audio_postenc_convert = __ms_element_create("audioconvert", NULL); + GstElement *audio_encoder = __ms_element_create(DEFAULT_AUDIO_ENCODER, NULL); GstElement *audio_enc_bin = gst_bin_new("audio_encoder"); - ms_retvm_if(!audio_convert || !audio_postenc_convert || !audio_filter || !audio_enc_bin, (GstElement *) NULL, "Error: creating elements for encoder bin"); + ms_retvm_if(!audio_convert || !audio_postenc_convert || !audio_filter || !audio_encoder || !audio_enc_bin, (GstElement *) NULL, "Error: creating elements for encoder bin"); GstCaps *audioCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT); g_object_set(G_OBJECT(audio_filter), "caps", audioCaps, NULL); gst_caps_unref(audioCaps); - gst_bin_add_many(GST_BIN(audio_enc_bin), audio_convert, audio_postenc_convert, audio_filter, audio_resample, NULL); - gst_ret = gst_element_link_many(audio_convert, audio_resample, audio_filter, audio_postenc_convert, NULL); + gst_bin_add_many(GST_BIN(audio_enc_bin), audio_convert, audio_postenc_convert, audio_filter, audio_resample, audio_encoder, NULL); + gst_ret = gst_element_link_many(audio_convert, audio_resample, audio_filter, audio_postenc_convert, audio_encoder, NULL); if (gst_ret != TRUE) { ms_error("Failed to link elements into decoder_bin"); MS_SAFE_UNREF(audio_enc_bin); } - __ms_add_ghostpad(audio_postenc_convert, "src", audio_enc_bin, "src"); + __ms_add_ghostpad(audio_encoder, "src", audio_enc_bin, "src"); __ms_add_ghostpad(audio_convert, "sink", audio_enc_bin, "sink"); return audio_enc_bin; @@ -1206,9 +1210,9 @@ gboolean __ms_rtp_element_prepare(media_streamer_node_s *ms_node) ret = ret && gst_element_link_pads(rtpbin, "send_rtcp_src_0", rtcp_el, "sink"); g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val); - g_object_set(GST_OBJECT(rtp_el), "sync", FALSE, NULL); g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL); g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL); + g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL); g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL); g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL); } @@ -1230,9 +1234,9 @@ gboolean __ms_rtp_element_prepare(media_streamer_node_s *ms_node) ret = ret && gst_element_link_pads(rtpbin, "send_rtcp_src_1", rtcp_el, "sink"); g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val); - g_object_set(GST_OBJECT(rtp_el), "sync", FALSE, NULL); g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL); g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL); + g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL); g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL); g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL); } diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c index b928f15..29e6d7f 100755 --- a/src/media_streamer_node.c +++ b/src/media_streamer_node.c @@ -151,7 +151,7 @@ int __ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_f node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_TYPE_FILTER: - node->gst_element = __ms_element_create("capsfilter", NULL); + node->gst_element = __ms_element_create(DEFAULT_FILTER, NULL); break; case MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY: format_prefix = g_strdup_printf("%s:rtppay", __ms_convert_mime_to_string(mime)); @@ -180,14 +180,17 @@ int __ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_f case MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER: node->gst_element = __ms_audio_encoder_element_create(); break; + case MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER: + node->gst_element = __ms_element_create(DEFAULT_AUDIO_DECODER, NULL); + break; case MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER: - node->gst_element = __ms_element_create("videoconvert", NULL); + node->gst_element = __ms_element_create(DEFAULT_VIDEO_CONVERT, NULL); break; case MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER: - node->gst_element = __ms_element_create("audioconvert", NULL); + node->gst_element = __ms_element_create(DEFAULT_AUDIO_CONVERT, NULL); break; case MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE: - node->gst_element = __ms_element_create("audioresample", NULL); + node->gst_element = __ms_element_create(DEFAULT_AUDIO_RESAMPLE, NULL); break; default: ms_error("Error: invalid node Type [%d]", node->type); @@ -484,16 +487,18 @@ static void _src_node_prepare(const GValue *item, gpointer user_data) } if (MS_ELEMENT_IS_VIDEO(new_pad_type) || MS_ELEMENT_IS_IMAGE(new_pad_type)) { - found_element = __ms_combine_next_element(src_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); + found_element = __ms_combine_next_element(src_element, src_pad, ms_streamer->topology_bin, NULL, NULL, DEFAULT_FILTER); + GstCaps *videoCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT); + g_object_set(G_OBJECT(found_element), "caps", videoCaps,NULL); + gst_caps_unref(videoCaps); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "video_encoder", NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); } if (MS_ELEMENT_IS_AUDIO(new_pad_type)) { - found_element = __ms_combine_next_element(src_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "audio_encoder", NULL); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, DEFAULT_AUDIO_RTPPAY); + found_element = __ms_combine_next_element(src_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "audio_encoder", NULL); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); } __ms_generate_dots(ms_streamer->pipeline, "after_connecting_rtp"); @@ -821,7 +826,7 @@ int __ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, if (!strcmp(pad_name, MS_RTP_PAD_VIDEO_IN"_rtp")) { ret = media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL); if (MEDIA_FORMAT_ERROR_NONE == ret) { - rtp_caps_str = g_strdup_printf("application/x-rtp,media=video,clock-rate=90000,encoding-name=%s", __ms_convert_mime_to_rtp_format(mime)); + rtp_caps_str = g_strdup_printf("application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=%s", __ms_convert_mime_to_rtp_format(mime)); param_s param = {MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT, MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT}; ret = __ms_node_set_param_value(node, ¶m, rtp_caps_str); } @@ -829,7 +834,7 @@ int __ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, int audio_channels, audio_samplerate; ret = media_format_get_audio_info(fmt, &mime, &audio_channels, &audio_samplerate, NULL, NULL); if (MEDIA_FORMAT_ERROR_NONE == ret) { - rtp_caps_str = g_strdup_printf("application/x-rtp,media=audio,clock-rate=%d,encoding-name=%s,channels=%d,payload=96", audio_samplerate, __ms_convert_mime_to_rtp_format(mime), audio_channels); + rtp_caps_str = g_strdup_printf("application/x-rtp,media=(string)audio,clock-rate=(int)8000,encoding-name=(string)AMR,encoding-params=(string)1,octet-align=(string)1"); param_s param = {MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT, MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT}; ret = __ms_node_set_param_value(node, ¶m, rtp_caps_str); } -- 2.7.4 From c45d536e7a402c27ad9d0c241e01304c17aa07ee Mon Sep 17 00:00:00 2001 From: Vyacheslav Valkovoy Date: Thu, 17 Mar 2016 18:28:35 +0200 Subject: [PATCH 05/16] Modifying set/get pad_format() Change-Id: I5f9b4cd759496ab7a98bdd5f9b760cc1fcbe0556 Signed-off-by: Vyacheslav Valkovoy --- include/media_streamer_util.h | 19 +++++- src/media_streamer.c | 20 +++++- src/media_streamer_gst.c | 154 ++++++++++++++++-------------------------- src/media_streamer_node.c | 6 +- src/media_streamer_util.c | 92 +++++++++++++++++++++---- 5 files changed, 179 insertions(+), 112 deletions(-) diff --git a/include/media_streamer_util.h b/include/media_streamer_util.h index 99010a9..9644286 100644 --- a/include/media_streamer_util.h +++ b/include/media_streamer_util.h @@ -114,6 +114,16 @@ typedef struct __media_streamer_ini { } media_streamer_ini_t; /** + * @brief Media Streamer format type handle. + * + * @since_tizen 3.0 + */ +typedef struct { + media_format_mimetype_e format; + char *format_name; +} format_s; + +/** * @brief Media Streamer signal structure. * * @since_tizen 3.0 @@ -269,6 +279,13 @@ gchar *__ms_ini_get_string(dictionary *dict, const char *ini_path, char *default * * @since_tizen 3.0 */ +const gchar *__ms_convert_mime_to_string_format(media_format_mimetype_e mime); + +/** + * @brief Converts Media Format mime type into Caps media format string. + * + * @since_tizen 3.0 + */ const gchar *__ms_convert_mime_to_string(media_format_mimetype_e mime); /** @@ -283,7 +300,7 @@ const gchar *__ms_convert_mime_to_rtp_format(media_format_mimetype_e mime); * * @since_tizen 3.0 */ -media_format_mimetype_e __ms_convert_string_format_to_mime(const char *format_type); +media_format_mimetype_e __ms_convert_string_format_to_media_format(const char *format_type); /** * @brief Creates Media streamer signal structure, diff --git a/src/media_streamer.c b/src/media_streamer.c index da8a1e4..1110273 100644 --- a/src/media_streamer.c +++ b/src/media_streamer.c @@ -589,8 +589,24 @@ int media_streamer_node_link(media_streamer_node_h src_node, const char *src_pad gchar *src_element_name = gst_element_get_name(ms_src_node->gst_element); gchar *sink_element_name = gst_element_get_name(ms_dest_node->gst_element); - gboolean link_ret = gst_element_link_pads(ms_src_node->gst_element, src_pad_name, - ms_dest_node->gst_element, sink_pad_name); + GstCaps *src_pad_caps = NULL; + GstCaps *sink_pad_caps = NULL; + GValue *val = NULL; + + val = (GValue *) g_object_get_data(G_OBJECT(ms_src_node->gst_element), src_pad_name); + if (val) { + src_pad_caps = GST_CAPS(gst_value_get_caps(val)); + ms_info("Pad [%s] of node [%s] was set with caps [%s]\n", src_pad_name, ms_src_node->name, gst_caps_to_string(src_pad_caps)); + } + + val = (GValue *) g_object_get_data(G_OBJECT(ms_dest_node->gst_element), sink_pad_name); + if (val) { + sink_pad_caps = GST_CAPS(gst_value_get_caps(val)); + ms_info("Pad [%s] of node [%s] was set with caps [%s]\n", src_pad_name, ms_src_node->name, gst_caps_to_string(sink_pad_caps)); + } + + gboolean link_ret = gst_element_link_pads_filtered(ms_src_node->gst_element, src_pad_name, + ms_dest_node->gst_element, sink_pad_name, src_pad_caps ? src_pad_caps : sink_pad_caps); if (!link_ret) { ms_error("Can not link [%s]->%s pad to [%s]->%s pad, ret code [%d] ", ms_src_node->name, src_pad_name, ms_dest_node->name, sink_pad_name, link_ret); ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION; diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index deef712..900bd1d 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -83,37 +83,6 @@ static gboolean __ms_add_ghostpad(GstElement *gst_element, const char *pad_name, return ret; } -static GObject *__ms_get_property_owner(GstElement *element, const gchar *key, GValue *value) -{ - GParamSpec *param = NULL; - GObject *obj = NULL; - - if (GST_IS_CHILD_PROXY(element)) { - int i; - const int childs_count = gst_child_proxy_get_children_count(GST_CHILD_PROXY(element)); - - for (i = 0; (i < childs_count) && (param == NULL); ++i) { - obj = gst_child_proxy_get_child_by_index(GST_CHILD_PROXY(element), i); - param = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), key); - } - ms_retvm_if(param == NULL || obj == NULL, NULL, "Error: Bin object does not have property [%s].", key); - } else { - obj = G_OBJECT(element); - param = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), key); - } - - g_value_init(value, param->value_type); - - if (!(param->flags & G_PARAM_WRITABLE)) { - /* Skip properties which user can not change. */ - ms_error("Error: node param [%s] is not writable!", key); - return NULL; - } - ms_info("%-20s: %s\n", g_param_spec_get_name(param), g_param_spec_get_blurb(param)); - - return obj; -} - /* This unlinks from its peer and ghostpads on its way */ static gboolean __ms_pad_peer_unlink(GstPad *pad) { @@ -1452,43 +1421,33 @@ int __ms_pipeline_create(media_streamer_s *ms_streamer) static GstCaps *__ms_create_caps_from_fmt(media_format_h fmt) { GstCaps *caps = NULL; + gchar *caps_name = NULL; media_format_mimetype_e mime; - gchar *format_name = NULL; - int width; - int height; - int avg_bps; - int max_bps; - int channel; - int samplerate; - int bit; - - if (media_format_get_video_info(fmt, &mime, &width, &height, &avg_bps, &max_bps) == MEDIA_PACKET_ERROR_NONE) { - - ms_info("Creating video Caps from media format [width=%d, height=%d, bps=%d, mime=%d]", width, height, avg_bps, mime); - - if (mime & MEDIA_FORMAT_RAW) { - format_name = g_strdup(__ms_convert_mime_to_string(mime)); - caps = gst_caps_new_simple("video/x-raw", "framerate", GST_TYPE_FRACTION, max_bps, avg_bps, "format", G_TYPE_STRING, format_name, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); - } else { - /*mime & MEDIA_FORMAT_ENCODED */ - format_name = g_strdup_printf("video/x-%s", __ms_convert_mime_to_string(mime)); - caps = gst_caps_new_simple(format_name, "framerate", GST_TYPE_FRACTION, max_bps, avg_bps, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); - } - - } else if (media_format_get_audio_info(fmt, &mime, &channel, &samplerate, &bit, &avg_bps) == MEDIA_PACKET_ERROR_NONE) { - ms_info("Creating audio Caps from media format [channel=%d, samplerate=%d, bit=%d, avg_bps=%d, mime=%d]", channel, samplerate, bit, avg_bps, mime); - - if (mime & MEDIA_FORMAT_RAW) { - format_name = g_strdup(__ms_convert_mime_to_string(mime)); - caps = gst_caps_new_simple("audio/x-raw", "channels", G_TYPE_INT, channel, "format", G_TYPE_STRING, format_name, "rate", G_TYPE_INT, samplerate, NULL); - } else { - ms_error("Encoded audio formats does not supported yet."); - } - } else { - ms_error("Failed getting media info from fmt."); - } - MS_SAFE_GFREE(format_name); - + int width, height, avg_bps, max_bps, channel, samplerate, bit; + + if (!media_format_get_audio_info(fmt, &mime, &channel, &samplerate, &bit, &avg_bps)) { + if (MEDIA_FORMAT_RAW == (mime & MEDIA_FORMAT_RAW)) + caps = gst_caps_new_simple("audio/x-raw", "channels", G_TYPE_INT, channel, "format", + G_TYPE_STRING, __ms_convert_mime_to_string_format(mime), "rate", G_TYPE_INT, samplerate, NULL); + else if (MEDIA_FORMAT_ENCODED == (mime & MEDIA_FORMAT_ENCODED)) + caps = gst_caps_new_simple(__ms_convert_mime_to_string_format(mime), "channels",G_TYPE_INT, channel, "rate", G_TYPE_INT, samplerate, NULL); + caps_name = gst_caps_to_string(caps); + ms_info("Creating Audio Caps from media format [%s]", caps_name); + + } else if (!media_format_get_video_info(fmt, &mime, &width, &height, &avg_bps, &max_bps)) { + if (MEDIA_FORMAT_RAW == (mime & MEDIA_FORMAT_RAW)) + caps = gst_caps_new_simple("video/x-raw", "framerate", GST_TYPE_FRACTION, max_bps, + avg_bps, "format", G_TYPE_STRING, __ms_convert_mime_to_string_format(mime), "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); + else if (MEDIA_FORMAT_ENCODED == (mime & MEDIA_FORMAT_ENCODED)) + caps = gst_caps_new_simple(__ms_convert_mime_to_string_format(mime), "framerate", GST_TYPE_FRACTION, max_bps, + avg_bps, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); + caps_name = gst_caps_to_string(caps); + ms_info("Creating Video Caps from media format [%s]", caps_name); + + } else + ms_error("Error getting media format information"); + + MS_SAFE_GFREE(caps_name); return caps; } @@ -1524,14 +1483,14 @@ static media_format_h __ms_create_fmt_from_caps(GstCaps *caps) gst_structure_get_fraction(pad_struct, "framerate", &max_bps, &avg_bps); gst_structure_get_int(pad_struct, "height", &height); - media_format_set_video_mime(fmt, __ms_convert_string_format_to_mime(pad_format)); + media_format_set_video_mime(fmt, __ms_convert_string_format_to_media_format(pad_format)); media_format_set_video_width(fmt, width); media_format_set_video_height(fmt, height); media_format_set_video_avg_bps(fmt, avg_bps); media_format_set_video_max_bps(fmt, max_bps); } else if (MS_ELEMENT_IS_AUDIO(pad_type)) { int channels, bps; - media_format_set_audio_mime(fmt, __ms_convert_string_format_to_mime(pad_format)); + media_format_set_audio_mime(fmt, __ms_convert_string_format_to_media_format(pad_format)); gst_structure_get_int(pad_struct, "channels", &channels); media_format_set_audio_channel(fmt, channels); gst_structure_get_int(pad_struct, "rate", &bps); @@ -1590,38 +1549,33 @@ int __ms_element_pad_names(GstElement *gst_element, GstPadDirection pad_type, ch int __ms_element_get_pad_fmt(GstElement *gst_element, const char *pad_name, media_format_h *fmt) { GstCaps *allowed_caps = NULL; - GstCaps *property_caps = NULL; - GValue value = G_VALUE_INIT; + GstCaps *format_caps = NULL; ms_retvm_if(gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Element handle is NULL"); GstPad *pad = gst_element_get_static_pad(gst_element, pad_name); ms_retvm_if(pad == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Fail to get pad [%s] from element [%s].", pad_name, GST_ELEMENT_NAME(gst_element)); - GParamSpec *param = g_object_class_find_property(G_OBJECT_GET_CLASS(gst_element), "caps"); - if (param) { - g_value_init(&value, param->value_type); - if (param->flags & G_PARAM_READWRITE) { - g_object_get_property(G_OBJECT(gst_element), "caps", &value); - property_caps = GST_CAPS(gst_value_get_caps(&value)); - } - g_value_unset(&value); - } + GValue *value = (GValue *) g_object_get_data(G_OBJECT(gst_element), pad_name); + if (value) + format_caps = GST_CAPS(gst_value_get_caps(value)); + else + ms_info(" No any format is set for pad [%s]", pad_name); int ret = MEDIA_STREAMER_ERROR_NONE; allowed_caps = gst_pad_get_allowed_caps(pad); if (allowed_caps) { if (gst_caps_is_empty(allowed_caps) || gst_caps_is_any(allowed_caps)) { - if (property_caps) - *fmt = __ms_create_fmt_from_caps(property_caps); + if (format_caps) + *fmt = __ms_create_fmt_from_caps(format_caps); else ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION; } else { *fmt = __ms_create_fmt_from_caps(allowed_caps); } } else { - if (property_caps) - *fmt = __ms_create_fmt_from_caps(property_caps); + if (format_caps) + *fmt = __ms_create_fmt_from_caps(format_caps); else ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION; } @@ -1635,19 +1589,31 @@ int __ms_element_get_pad_fmt(GstElement *gst_element, const char *pad_name, medi int __ms_element_set_fmt(media_streamer_node_s *node, const char *pad_name, media_format_h fmt) { - ms_retvm_if(!node || !pad_name || !fmt, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL"); + ms_retvm_if(!node || !pad_name || !fmt, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL"); + gboolean can_accept = FALSE; - GValue value = G_VALUE_INIT; - GObject *obj = __ms_get_property_owner(node->gst_element, "caps", &value); - ms_retvm_if(!obj, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Can't find object"); + GstCaps *fmt_caps = __ms_create_caps_from_fmt(fmt); + ms_retvm_if(!fmt_caps, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Can't convert fmt into Caps"); - GstCaps *caps = __ms_create_caps_from_fmt(fmt); - ms_retvm_if(!caps, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Can't convert fmt into Caps"); + GstElementFactory *factory = gst_element_get_factory(node->gst_element); + GstPad *node_pad = gst_element_get_static_pad(node->gst_element, pad_name); + + if (GST_PAD_IS_SRC(node_pad)) + can_accept = gst_element_factory_can_src_any_caps(factory, fmt_caps); + else if (GST_PAD_IS_SINK(node_pad)) + can_accept = gst_element_factory_can_sink_any_caps(factory, fmt_caps); + else + ms_error(" Node [%s] doesn`t have valid pad [%s]", node->name, pad_name); - gst_value_set_caps(&value, caps); - g_object_set_property(obj, "caps", &value); - g_value_unset(&value); - gst_caps_unref(caps); + if (!can_accept) { + if (fmt_caps) + gst_caps_unref(fmt_caps); + ms_error("Node`s pad [%s] can`t be set with the given format", pad_name); + return MEDIA_STREAMER_ERROR_INVALID_OPERATION; + } else { + MS_SET_INT_CAPS_PARAM(node->gst_element, pad_name, fmt_caps); + ms_info("Pad [%s] of node [%s] was set with given format", pad_name, node->name); + } return MEDIA_STREAMER_ERROR_NONE; } diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c index 29e6d7f..222780e 100755 --- a/src/media_streamer_node.c +++ b/src/media_streamer_node.c @@ -468,6 +468,10 @@ static void _src_node_prepare(const GValue *item, gpointer user_data) media_streamer_s *ms_streamer = (media_streamer_s *) user_data; GstElement *src_element = GST_ELEMENT(g_value_get_object(item)); + media_streamer_node_s *found_node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table, GST_ELEMENT_NAME(src_element)); + if (!found_node) + return; + ms_retm_if(!ms_streamer || !src_element, "Handle is NULL"); ms_debug("Autoplug: found src element [%s]", GST_ELEMENT_NAME(src_element)); @@ -489,7 +493,7 @@ static void _src_node_prepare(const GValue *item, gpointer user_data) if (MS_ELEMENT_IS_VIDEO(new_pad_type) || MS_ELEMENT_IS_IMAGE(new_pad_type)) { found_element = __ms_combine_next_element(src_element, src_pad, ms_streamer->topology_bin, NULL, NULL, DEFAULT_FILTER); GstCaps *videoCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT); - g_object_set(G_OBJECT(found_element), "caps", videoCaps,NULL); + g_object_set(G_OBJECT(found_element), "caps", videoCaps, NULL); gst_caps_unref(videoCaps); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "video_encoder", NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); diff --git a/src/media_streamer_util.c b/src/media_streamer_util.c index 98cab1d..8ed41a3 100644 --- a/src/media_streamer_util.c +++ b/src/media_streamer_util.c @@ -19,6 +19,60 @@ #include #include +format_s format_table[] = { + /* Audio - ENCODED */ + {MEDIA_FORMAT_L16, "audio/x-raw"}, + {MEDIA_FORMAT_ALAW, "audio/x-alaw"}, + {MEDIA_FORMAT_ULAW, "audio/x-mulaw"}, + {MEDIA_FORMAT_AMR, "audio/AMR"}, + {MEDIA_FORMAT_AMR_NB, "audio/AMR"}, + {MEDIA_FORMAT_AMR_WB, "audio/AMR-WB"}, + {MEDIA_FORMAT_G729, "audio/G729"}, + {MEDIA_FORMAT_AAC, "audio/mpeg"}, + {MEDIA_FORMAT_AAC_LC, "audio/mpeg"}, + {MEDIA_FORMAT_AAC_HE, "audio/mpeg"}, + {MEDIA_FORMAT_AAC_HE_PS, "audio/mpeg"}, + {MEDIA_FORMAT_MP3, "audio/mpeg"}, + /* Audio - RAW */ + {MEDIA_FORMAT_PCM, "S16LE"}, + /* {MEDIA_FORMAT_PCMA, "audio/x-alaw"}, */ + /* {MEDIA_FORMAT_PCMU, "audio/x-mulaw"}, */ + /* Video - ENCODED */ + {MEDIA_FORMAT_H261, "video/x-h261"}, + {MEDIA_FORMAT_H263, "video/x-h263"}, + {MEDIA_FORMAT_H263P, "video/x-h263"}, + {MEDIA_FORMAT_H264_SP, "video/x-h264"}, + {MEDIA_FORMAT_H264_MP, "video/x-h264"}, + {MEDIA_FORMAT_H264_HP, "video/x-h264"}, + {MEDIA_FORMAT_MJPEG, "image/jpeg"}, + {MEDIA_FORMAT_MPEG1, "video/mpeg"}, + {MEDIA_FORMAT_MPEG2_SP, "video/mpeg"}, + {MEDIA_FORMAT_MPEG2_MP, "video/mpeg"}, + {MEDIA_FORMAT_MPEG2_HP, "video/mpeg"}, + {MEDIA_FORMAT_MPEG4_SP, "video/mpeg"}, + {MEDIA_FORMAT_MPEG4_ASP, "video/mpeg"}, + {MEDIA_FORMAT_HEVC, "video/x-h265"}, + {MEDIA_FORMAT_VP8, "video/x-vp8"}, + {MEDIA_FORMAT_VP9, "video/x-vp9"}, + {MEDIA_FORMAT_VC1, "video/x-wmv"}, + /* Video - RAW */ + {MEDIA_FORMAT_I420, "I420"}, + {MEDIA_FORMAT_NV12, "NV12"}, + {MEDIA_FORMAT_NV12T, "NV12T"}, + {MEDIA_FORMAT_YV12, "YV12"}, + {MEDIA_FORMAT_NV21, "NV21"}, + {MEDIA_FORMAT_NV16, "NV16"}, + {MEDIA_FORMAT_YUYV, "YUYV"}, + {MEDIA_FORMAT_UYVY, "UYVY"}, + {MEDIA_FORMAT_422P, "422P"}, + {MEDIA_FORMAT_RGB565, "RGB565"}, + {MEDIA_FORMAT_RGB888, "RGB888"}, + {MEDIA_FORMAT_RGBA, "RGBA"}, + {MEDIA_FORMAT_ARGB, "ARGB"}, + {MEDIA_FORMAT_NATIVE_VIDEO, "NATIVE_VIDEO"}, + {MEDIA_FORMAT_MAX, NULL} +}; + static void __ms_check_ini_status(void); gchar *__ms_ini_get_string(dictionary *dict, const char *ini_path, char *default_str) @@ -145,6 +199,20 @@ static void __ms_check_ini_status(void) } } +const gchar *__ms_convert_mime_to_string_format(media_format_mimetype_e mime) +{ + gchar *format_name = NULL; + int it_format; + for (it_format = 0; format_table[it_format].format != MEDIA_FORMAT_MAX; it_format++) { + if (mime == format_table[it_format].format) { + format_name = format_table[it_format].format_name; + break; + } + } + + return format_name; +} + const gchar *__ms_convert_mime_to_string(media_format_mimetype_e mime) { switch (mime) { @@ -186,22 +254,18 @@ const gchar *__ms_convert_mime_to_rtp_format(media_format_mimetype_e mime) } } -media_format_mimetype_e __ms_convert_string_format_to_mime(const char *format_type) +media_format_mimetype_e __ms_convert_string_format_to_media_format(const char *format_type) { - if (g_strrstr(format_type, "I420")) { - return MEDIA_FORMAT_I420; - } else if (g_strrstr(format_type, "YV12")) { - return MEDIA_FORMAT_YV12; - } else if (g_strrstr(format_type, "h263")) { - return MEDIA_FORMAT_H263; - } else if (g_strrstr(format_type, "h264")) { - return MEDIA_FORMAT_H264_SP; - } else if (g_strrstr(format_type, DEFAULT_AUDIO)) { - return MEDIA_FORMAT_PCM; - } else { - ms_error("Invalid or Unsupported media format [%s].", format_type); - return MEDIA_FORMAT_NONE; + media_format_mimetype_e mime = 0; + int it_format; + for (it_format = 0; format_table[it_format].format != MEDIA_FORMAT_MAX; it_format++) { + if (g_strrstr(format_type, format_table[it_format].format_name)) { + mime = format_table[it_format].format; + break; + } } + + return mime; } void __ms_signal_create(GList **sig_list, GstElement *obj, const char *sig_name, GCallback cb, gpointer user_data) -- 2.7.4 From a4c661fd0e1a9d54fdbcc34d2d4dbc59c3daabf0 Mon Sep 17 00:00:00 2001 From: Vyacheslav Valkovoy Date: Thu, 17 Mar 2016 18:33:09 +0200 Subject: [PATCH 06/16] Combine DecodeBin callbacks. Change-Id: I74b3ed60473bf18065fc2c7d5386d77e5e0dd189 Signed-off-by: Vyacheslav Valkovoy --- src/media_streamer_gst.c | 104 +++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 67 deletions(-) diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index 900bd1d..4178458 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -710,76 +710,45 @@ static void _sink_node_unlock_state(const GValue * item, gpointer user_data) gst_element_sync_state_with_parent(sink_element); } } -static void __decodebin_nomore_pads_streamer(GstElement * decodebin, media_streamer_s *ms_streamer) + +static void __decodebin_nomore_pads_combine(GstPad *src_pad, media_streamer_s *ms_streamer, gboolean is_server_part) { - GstElement *found_element = NULL; - GList *iterator = NULL; - GList *list = ms_streamer->pads_types_list; - const gchar *new_pad_type = NULL; + GstElement *found_element = gst_pad_get_parent_element(src_pad); + const gchar *new_pad_type = __ms_get_pad_type(src_pad); - for (iterator = list; iterator; iterator = iterator->next) { - GstPad *new_pad = GST_PAD(iterator->data); - new_pad_type = __ms_get_pad_type(new_pad); - found_element = gst_pad_get_parent_element(new_pad); - - if (MS_ELEMENT_IS_VIDEO(new_pad_type)) { - if(__ms_bin_find_element_by_klass(ms_streamer->topology_bin, NULL, NULL, MEDIA_STREAMER_OVERLAY_KLASS, NULL)) { - found_element = __ms_combine_next_element(found_element, new_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); - new_pad = NULL; - } - found_element = __ms_combine_next_element(found_element, new_pad, ms_streamer->topology_bin, NULL, NULL, DEFAULT_QUEUE); + if (MS_ELEMENT_IS_VIDEO(new_pad_type)) { + if (__ms_bin_find_element_by_klass(ms_streamer->topology_bin, NULL, NULL, MEDIA_STREAMER_OVERLAY_KLASS, NULL)) { + found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); + src_pad = NULL; + } + if (is_server_part) { + found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, NULL, NULL, DEFAULT_QUEUE); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "video_encoder", NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); - } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) { - found_element = __ms_combine_next_element(found_element, new_pad, ms_streamer->topology_bin, NULL, NULL, DEFAULT_QUEUE); + } else { + found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_VIDEO_CONVERT); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); + } + } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) { + if (is_server_part) { + found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, NULL, NULL, DEFAULT_QUEUE); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "audio_encoder", NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); - } else if (MS_ELEMENT_IS_TEXT(new_pad_type)) { - found_element = __ms_combine_next_element(found_element, new_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); } else { - ms_error("Unsupported pad type [%s]!", new_pad_type); - return; - } - __ms_generate_dots(ms_streamer->pipeline, "after_sink_linked"); - } -} - -static void __decodebin_nomore_pads_client(GstElement * decodebin, media_streamer_s *ms_streamer) -{ - - GstElement *found_element = NULL; - GList *iterator = NULL; - GList *list = ms_streamer->pads_types_list; - const gchar *pad_type = NULL; - - for (iterator = list; iterator; iterator = iterator->next) { - GstPad *src_pad = GST_PAD(iterator->data); - pad_type = __ms_get_pad_type(src_pad); - found_element = gst_pad_get_parent_element(src_pad); - - if (MS_ELEMENT_IS_AUDIO(pad_type)) { found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_AUDIO_CONVERT); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); - } else if (MS_ELEMENT_IS_VIDEO(pad_type)) { - if(__ms_bin_find_element_by_klass(ms_streamer->topology_bin, NULL, NULL, MEDIA_STREAMER_OVERLAY_KLASS, NULL)) { - found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); - src_pad = NULL; - } - found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_VIDEO_CONVERT); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); - } else if (MS_ELEMENT_IS_TEXT(pad_type)) { - found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); - } else { - ms_error("Unsupported pad type [%s]!", pad_type); - return; } - __ms_generate_dots(ms_streamer->pipeline, "after_sink_linked"); + } else if (MS_ELEMENT_IS_TEXT(new_pad_type)) { + found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); + } else { + ms_error("Unsupported pad type [%s]!", new_pad_type); + return; } - MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, _sink_node_unlock_state, NULL); + __ms_generate_dots(ms_streamer->pipeline, "after_sink_linked"); } static void __decodebin_nomore_pads_cb(GstElement * decodebin, gpointer user_data) @@ -789,26 +758,27 @@ static void __decodebin_nomore_pads_cb(GstElement * decodebin, gpointer user_dat g_mutex_lock(&ms_streamer->mutex_lock); - char *param_value = NULL; + gboolean is_server_part = FALSE; media_streamer_node_s *rtp_node = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "rtp_container"); + /* It`s server part of Streaming Scenario*/ if (rtp_node) { - /* It`s Streaming Scenario*/ + char *param_value = NULL; media_streamer_node_get_param(rtp_node, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT, ¶m_value); if (param_value && (strtol(param_value, NULL, 10) > 0)) + is_server_part = TRUE; - /* It`s Streamer part of Streaming */ - __decodebin_nomore_pads_streamer(decodebin, ms_streamer); - else - /* It`s Client part of Streaming */ - __decodebin_nomore_pads_client(decodebin, ms_streamer); - } else { + MS_SAFE_FREE(param_value); + } - /* It`s Client Scenario*/ - __decodebin_nomore_pads_client(decodebin, ms_streamer); + GList *iterator = NULL; + GList *list = ms_streamer->pads_types_list; + for (iterator = list; iterator; iterator = iterator->next) { + GstPad *src_pad = GST_PAD(iterator->data); + __decodebin_nomore_pads_combine(src_pad, ms_streamer, is_server_part); } - MS_SAFE_FREE(param_value); + MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, _sink_node_unlock_state, NULL); g_mutex_unlock(&ms_streamer->mutex_lock); } -- 2.7.4 From dd603b794a9040576d060b5e637555a385b9c799 Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Mon, 21 Mar 2016 17:07:07 +0900 Subject: [PATCH 07/16] remove warning Change-Id: I928686b6e147d4e58a37a342fdd0a2eb7aadc3e4 --- src/media_streamer_gst.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index 640441f..7c631ed 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -698,7 +698,6 @@ static gint __decodebin_autoplug_select_cb(GstElement * bin, GstPad * pad, GstCa } } -DONE: return result; } -- 2.7.4 From ab92e79ad006e816336cd0092c2110967d7a8368 Mon Sep 17 00:00:00 2001 From: Andrey Shelest Date: Wed, 23 Mar 2016 15:47:11 +0200 Subject: [PATCH 08/16] Enable sprd hw codecs Change-Id: I752c21dba60082dd066c5d7b001d393500dc542e Signed-off-by: Andrey Shelest --- src/media_streamer_gst.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index 4178458..8016d11 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -727,7 +727,6 @@ static void __decodebin_nomore_pads_combine(GstPad *src_pad, media_streamer_s *m found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); } else { - found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_VIDEO_CONVERT); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); } @@ -967,7 +966,7 @@ GstElement *__ms_video_decoder_element_create(dictionary * dict, media_format_mi { char *plugin_name = NULL; char *format_prefix = NULL; - gboolean is_omx = FALSE; + gboolean is_hw_codec = FALSE; GstElement *last_elem = NULL; format_prefix = g_strdup_printf("%s:decoder", __ms_convert_mime_to_string(mime)); @@ -983,8 +982,8 @@ GstElement *__ms_video_decoder_element_create(dictionary * dict, media_format_mi if (mime == MEDIA_FORMAT_H264_SP) g_object_set(G_OBJECT(decoder_parser), "config-interval", H264_PARSER_CONFIG_INTERVAL, NULL); - if (g_strrstr(format_prefix, "omx")) - is_omx = TRUE; + if (g_strrstr(format_prefix, "omx") || g_strrstr(format_prefix, "sprd")) + is_hw_codec = TRUE; MS_SAFE_FREE(format_prefix); MS_SAFE_FREE(plugin_name); @@ -1003,7 +1002,7 @@ GstElement *__ms_video_decoder_element_create(dictionary * dict, media_format_mi } last_elem = decoder_elem; - if (!is_omx) { + if (!is_hw_codec) { GstElement *video_conv = __ms_element_create("videoconvert", NULL); GstElement *video_scale = __ms_element_create("videoscale", NULL); ms_retvm_if(!video_conv || !video_scale, (GstElement *) NULL, "Error: creating elements for video decoder bin"); -- 2.7.4 From 1df1d324c49a938886b8c8c419d46c9197844a4f Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Mon, 28 Mar 2016 11:27:18 +0900 Subject: [PATCH 09/16] sync module group name for Native API doc Change-Id: I334b5c344680f6e259b81d0325f3e20a508d140b Signed-off-by: Eunhae Choi --- doc/mediastreamer_doc.h | 8 ++++---- include/media_streamer.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/mediastreamer_doc.h b/doc/mediastreamer_doc.h index c050b94..3d07310 100755 --- a/doc/mediastreamer_doc.h +++ b/doc/mediastreamer_doc.h @@ -24,13 +24,13 @@ /** * @ingroup CAPI_MEDIA_FRAMEWORK - * @defgroup CAPI_MEDIA_MEDIASTREAMER_MODULE Media Streamer - * @brief The @ref CAPI_MEDIA_MEDIASTREAMER_MODULE APIs provides functions for building custom pipeline + * @defgroup CAPI_MEDIA_STREAMER_MODULE Media Streamer + * @brief The @ref CAPI_MEDIA_STREAMER_MODULE APIs provides functions for building custom pipeline * - * @section CAPI_MEDIA_MEDIASTREAMER_MODULE_HEADER Required Header + * @section CAPI_MEDIA_STREAMER_MODULE_HEADER Required Header * \#include * - * @section CAPI_MEDIASTREAMER_MODULE_OVERVIEW Overview + * @section CAPI_MEDIA_STREAMER_MODULE_OVERVIEW Overview * * MEDIASTREAMER allows : * Create streamer handle and elements to build custom pipeline. diff --git a/include/media_streamer.h b/include/media_streamer.h index de3495d..c62f19f 100644 --- a/include/media_streamer.h +++ b/include/media_streamer.h @@ -32,7 +32,7 @@ extern "C" { */ /** -* @addtogroup CAPI_MEDIASTREAMER_MODULE +* @addtogroup CAPI_MEDIA_STREAMER_MODULE * @{ */ -- 2.7.4 From 799eac2a256ebfc07e76e335a03a9e440931ff20 Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Fri, 1 Apr 2016 13:30:53 +0900 Subject: [PATCH 10/16] apply tizen coding convention Change-Id: I0c43e11d91221f85d2096ca2258ab8fce26e45a4 Signed-off-by: Eunhae Choi --- src/media_streamer_gst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index 8016d11..7ebdee1 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -1399,7 +1399,7 @@ static GstCaps *__ms_create_caps_from_fmt(media_format_h fmt) caps = gst_caps_new_simple("audio/x-raw", "channels", G_TYPE_INT, channel, "format", G_TYPE_STRING, __ms_convert_mime_to_string_format(mime), "rate", G_TYPE_INT, samplerate, NULL); else if (MEDIA_FORMAT_ENCODED == (mime & MEDIA_FORMAT_ENCODED)) - caps = gst_caps_new_simple(__ms_convert_mime_to_string_format(mime), "channels",G_TYPE_INT, channel, "rate", G_TYPE_INT, samplerate, NULL); + caps = gst_caps_new_simple(__ms_convert_mime_to_string_format(mime), "channels", G_TYPE_INT, channel, "rate", G_TYPE_INT, samplerate, NULL); caps_name = gst_caps_to_string(caps); ms_info("Creating Audio Caps from media format [%s]", caps_name); -- 2.7.4 From 1d67562fff8e66f6f675265d44730ab7c444df96 Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Thu, 28 Apr 2016 19:10:30 +0900 Subject: [PATCH 11/16] apply ASLR Change-Id: If8aa254a225b8fe4085043afe21f2e100bc0512c --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cccb136..9cf8385 100755 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -11,7 +11,7 @@ FOREACH(flag ${${fw_test}_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -pie") aux_source_directory(. sources) -- 2.7.4 From 4920986ff87df5c1b60eecee2a9c9945c5c8b5ab Mon Sep 17 00:00:00 2001 From: Vyacheslav Valkovoy Date: Wed, 25 May 2016 20:45:19 +0300 Subject: [PATCH 12/16] Modified node creation logic Change-Id: I73a66dfd79848a984ae5b6941e06e12115cdb05b Signed-off-by: Vyacheslav Valkovoy --- include/media_streamer_gst.h | 17 +++++- include/media_streamer_priv.h | 22 +++++++ include/media_streamer_util.h | 19 +++++- src/media_streamer.c | 3 +- src/media_streamer_gst.c | 132 +++++++++++++++++++++++++++++++++++++----- src/media_streamer_node.c | 119 ++++++++++++++----------------------- src/media_streamer_util.c | 10 ++-- 7 files changed, 222 insertions(+), 100 deletions(-) diff --git a/include/media_streamer_gst.h b/include/media_streamer_gst.h index 2598423..07f964b 100644 --- a/include/media_streamer_gst.h +++ b/include/media_streamer_gst.h @@ -36,6 +36,8 @@ #define MEDIA_STREAMER_CONVERTER_KLASS "Filter/Converter" #define MEDIA_STREAMER_DECODER_KLASS "Codec/Decoder" #define MEDIA_STREAMER_SINK_KLASS "Sink" +#define MEDIA_STREAMER_STRICT "_strict_" + /** * @brief Generates dot files for GStreamer pipeline. @@ -75,6 +77,13 @@ GstElement *__ms_link_with_new_element(GstElement *previous_element, GstPad *pre GstElement *__ms_element_create(const char *plugin_name, const char *name); /** + * @brief Creates GstElement from specified node_plug_s structure. + * + * @since_tizen 3.0 + */ +GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node_type_e type); + +/** * @brief Creates encoder GstElement by mime type. * * @since_tizen 3.0 @@ -100,7 +109,7 @@ GstElement *__ms_audio_encoder_element_create(void); * * @since_tizen 3.0 */ -GstElement *__ms_rtp_element_create(media_streamer_node_s *ms_node); +GstElement *__ms_rtp_element_create(void); /** * @brief Prepares rtp container according to parameters data. @@ -193,6 +202,12 @@ int __ms_element_get_pad_fmt(GstElement *gst_element, const char *pad_name, medi int __ms_element_set_fmt(media_streamer_node_s *node, const char *pad_name, media_format_h fmt); /** + * @brief Creates GstCap's from mediaformat. + * + * @since_tizen 3.0 + */ +GstCaps *__ms_create_caps_from_fmt(media_format_h fmt); +/** * @brief Seeks GstElement to according time value. * * @since_tizen 3.0 diff --git a/include/media_streamer_priv.h b/include/media_streamer_priv.h index 07aaee4..c930c6c 100755 --- a/include/media_streamer_priv.h +++ b/include/media_streamer_priv.h @@ -61,6 +61,28 @@ typedef struct { } param_s; /** + * @brief Media Streamer node_info type handle. + * + * @since_tizen 3.0 + */ +typedef struct { + char *klass_name; + char *default_name; +} node_info_s; + +/** + * @brief Media Streamer node_plug type handle. + * + * @since_tizen 3.0 + */ +typedef struct { + node_info_s *info; + GstCaps *src_caps; + GstCaps *sink_caps; + gchar **exclude_names; +} node_plug_s; + +/** * @brief Media Streamer type handle. * * @since_tizen 3.0 diff --git a/include/media_streamer_util.h b/include/media_streamer_util.h index 9644286..2cb2d73 100644 --- a/include/media_streamer_util.h +++ b/include/media_streamer_util.h @@ -93,10 +93,10 @@ extern "C" { /* Ini Utils */ #ifndef MEDIA_STREAMER_INI_PATH - #define MEDIA_STREAMER_INI_PATH "/etc/media_streamer.ini" + #define MEDIA_STREAMER_INI_PATH "/etc/media_streamer.ini" #endif -#define MEDIA_STREAMER_INI_MAX_STRLEN 100 +#define MEDIA_STREAMER_INI_MAX_STRLEN 100 #define RTP_STREAM_DISABLED (0) /** @@ -245,6 +245,14 @@ typedef struct { g_object_set_data_full(G_OBJECT(obj), key, (gpointer)val, __ms_rtp_param_value_destroy); \ } while (0) +#define MS_GET_CAPS_TYPE(caps, type) \ + do { \ + if (caps && gst_caps_get_size(caps) > 0) \ + type = gst_structure_get_name(gst_caps_get_structure(caps, 0)); \ + else \ + type = NULL; \ + } while (0) + /** * @brief Loads media streamer settings from ini file. * The default values will be used if error has occurred. @@ -275,6 +283,13 @@ gboolean __ms_destroy_ini_dictionary(dictionary *dict); gchar *__ms_ini_get_string(dictionary *dict, const char *ini_path, char *default_str); /** + * @brief Reads comma-separated string list from ini file. + * + * @since_tizen 3.0 + */ +void __ms_ini_read_list(dictionary *dict, const char *key, gchar ***list); + +/** * @brief Converts Media Format mime type into Caps media format string. * * @since_tizen 3.0 diff --git a/src/media_streamer.c b/src/media_streamer.c index 1110273..d573a54 100644 --- a/src/media_streamer.c +++ b/src/media_streamer.c @@ -98,9 +98,10 @@ int media_streamer_node_create(media_streamer_node_type_e type, media_format_h i __ms_node_destroy(ms_node); ms_error("Error creating Node [%d]", ret); return ret; + } else { + ms_info("Node [%s] created", ms_node->name); } - ms_info("Node [%s] created", ms_node->name); *node = (media_streamer_node_h) ms_node; return ret; diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index 7ebdee1..583a1c5 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -23,6 +23,8 @@ #define H264_PARSER_CONFIG_INTERVAL 5 #define H264_ENCODER_ZEROLATENCY 0x00000004 +#define NODE_CONF_FIELD_LEN 100 + void __ms_generate_dots(GstElement *bin, gchar *name_tag) { gchar *dot_name; @@ -236,16 +238,11 @@ static gboolean __ms_get_peer_element(GstPad *source_pad, GstElement *found_elem const gchar *__ms_get_pad_type(GstPad *element_pad) { - const gchar *element_pad_type = NULL; - GstCaps *element_pad_caps = gst_pad_query_caps(element_pad, 0); - if (gst_caps_get_size(element_pad_caps) > 0) { - GstStructure *element_pad_struct = gst_caps_get_structure(element_pad_caps, 0); - element_pad_type = gst_structure_get_name(element_pad_struct); - } else { - ms_debug("Caps size of element is 0"); - } - gst_caps_unref(element_pad_caps); - return element_pad_type; + const gchar *pad_type = NULL; + GstCaps *pad_caps = gst_pad_query_caps(element_pad, 0); + MS_GET_CAPS_TYPE(pad_caps, pad_type); + gst_caps_unref(pad_caps); + return pad_type; } static gboolean __ms_intersect_pads(GstPad *src_pad, GstPad *sink_pad) @@ -829,7 +826,7 @@ static gboolean __ms_sink_bin_prepare(media_streamer_s * ms_streamer, GstPad * s previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); } } else if (MS_ELEMENT_IS_AUDIO(src_pad_type)) { - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_DECODER_KLASS, NULL, NULL); + previous_element = __ms_combine_next_element(previous_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_DECODER_KLASS, NULL, NULL); previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); } else { @@ -915,6 +912,113 @@ GstElement *__ms_element_create(const char *plugin_name, const char *name) return plugin_elem; } +static gboolean __ms_feature_node_filter(GstPluginFeature *feature, gpointer data) +{ + node_plug_s *plug_info = (node_plug_s*)data; + + if (!GST_IS_ELEMENT_FACTORY(feature)) + return FALSE; + + gboolean can_accept = FALSE; + GstElementFactory *factory = GST_ELEMENT_FACTORY(feature); + const gchar *factory_klass = gst_element_factory_get_klass(factory); + + if (plug_info && g_strrstr(factory_klass, plug_info->info->klass_name)) { + + if (GST_IS_CAPS(plug_info->src_caps)) + can_accept = can_accept || gst_element_factory_can_src_any_caps(factory, plug_info->src_caps); + + if (GST_IS_CAPS(plug_info->sink_caps)) + can_accept = can_accept || gst_element_factory_can_sink_any_caps(factory, plug_info->sink_caps); + + if (can_accept) { + int index = 0; + for ( ; plug_info->exclude_names && plug_info->exclude_names[index]; ++index) { + if (g_strrstr(GST_OBJECT_NAME(factory), plug_info->exclude_names[index])) { + ms_debug("Skipping compatible factory [%s] as excluded.", GST_OBJECT_NAME(factory)); + return FALSE; + } + } + + ms_info("[INFO] Found compatible factory [%s] for klass [%s]", + GST_OBJECT_NAME(factory), factory_klass); + return TRUE; + } + + } + + return FALSE; +} + +GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node_type_e type) +{ + dictionary *dict = NULL; + GstElement *gst_element = NULL; + + const gchar *src_type, *sink_type; + MS_GET_CAPS_TYPE(plug_info->src_caps, src_type); + MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type); + + /* 1. Main priority: + * If Node klass defined as MEDIA_STREAMER_STRICT, + * element will be created immediately by default_name */ + if (!strncmp(plug_info->info->klass_name, MEDIA_STREAMER_STRICT, 10) + || ( !src_type && !sink_type)) { + + if(type == MEDIA_STREAMER_NODE_TYPE_RTP) + gst_element = __ms_rtp_element_create(); + else + gst_element = __ms_element_create(plug_info->info->default_name, NULL); + } else { + /* 2. Second priority: + * Try to get plugin name that defined in ini file + * according with node type and specified format. */ + ms_info("Specified node formats types: in[%s] - out[%s]", sink_type, src_type); + gchar conf_key[NODE_CONF_FIELD_LEN] = {0,}; + if (snprintf(conf_key, NODE_CONF_FIELD_LEN, "node type %d:%s", type, (sink_type ? sink_type : src_type)) >= NODE_CONF_FIELD_LEN) { + ms_error("Failed to generate config field name, size >= %d", NODE_CONF_FIELD_LEN); + return NULL; + } + + __ms_load_ini_dictionary(&dict); + gchar *plugin_name = __ms_ini_get_string(dict, conf_key, NULL); + + if (plugin_name) { + gst_element = __ms_element_create(plugin_name, NULL); + MS_SAFE_GFREE(plugin_name); + } + __ms_destroy_ini_dictionary(dict); + } + + /* 3. Third priority: + * If previous cases did not create a valid gst_element, + * try to find compatible plugin in gstreamer registry. + * Elements that are compatible but defined as excluded will be skipped*/ + if(!gst_element) { + __ms_load_ini_dictionary(&dict); + + /* Read exclude elements list */ + __ms_ini_read_list(dict, "general:exclude elements", &plug_info->exclude_names); + + GList *factories = gst_registry_feature_filter(gst_registry_get(), + __ms_feature_node_filter, TRUE, plug_info); + + if (factories) { + GstElementFactory *factory = GST_ELEMENT_FACTORY(factories->data); + gst_element = __ms_element_create(GST_OBJECT_NAME(factory), NULL); + } else { + ms_error("Error: could not found any compatible element for node [%d]: in[%s] - out[%s]", + type, sink_type, src_type); + } + + g_strfreev(plug_info->exclude_names); + gst_plugin_list_free(factories); + __ms_destroy_ini_dictionary(dict); + } + + return gst_element; +} + GstElement *__ms_video_encoder_element_create(dictionary * dict, media_format_mimetype_e mime) { char *plugin_name = NULL; @@ -1050,10 +1154,8 @@ GstElement *__ms_audio_encoder_element_create(void) return audio_enc_bin; } -GstElement *__ms_rtp_element_create(media_streamer_node_s * ms_node) +GstElement *__ms_rtp_element_create(void) { - ms_retvm_if(ms_node == NULL, (GstElement *) NULL, "Error empty rtp node Handle"); - GstElement *rtp_container = gst_bin_new("rtp_container"); ms_retvm_if(!rtp_container, (GstElement *) NULL, "Error: creating elements for rtp container"); @@ -1387,7 +1489,7 @@ int __ms_pipeline_create(media_streamer_s *ms_streamer) return ret; } -static GstCaps *__ms_create_caps_from_fmt(media_format_h fmt) +GstCaps *__ms_create_caps_from_fmt(media_format_h fmt) { GstCaps *caps = NULL; gchar *caps_name = NULL; diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c index 222780e..849a61b 100755 --- a/src/media_streamer_node.c +++ b/src/media_streamer_node.c @@ -46,6 +46,35 @@ param_s param_table[] = { {NULL, NULL} }; +node_info_s nodes_info[] = { + {NULL, NULL}, /* MEDIA_STREAMER_NODE_TYPE_NONE */ + {"Source", "fakesrc"}, /* MEDIA_STREAMER_NODE_TYPE_SRC */ + {"Sink", "fakesink"}, /* MEDIA_STREAMER_NODE_TYPE_SINK */ + {"Codec/Encoder", "x264enc"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER */ + {"Codec/Decoder", "avdec_h264"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER */ + {"Codec/Encoder", "amrnbenc"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER */ + {"Codec/Decoder", "amrnbdec"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER */ + {MEDIA_STREAMER_STRICT, "videoconvert"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER */ + {MEDIA_STREAMER_STRICT, "audioconvert"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER */ + {MEDIA_STREAMER_STRICT, "audioresample"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE */ + {"Payloader", "rtph264pay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY */ + {"Payloader", "rtpamrpay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY */ + {"Depayloader", "rtph264depay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY */ + {"Depayloader", "rtpamrdepay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY */ + {MEDIA_STREAMER_STRICT, "capsfilter"}, /* MEDIA_STREAMER_NODE_TYPE_FILTER */ + {MEDIA_STREAMER_STRICT, "tee"}, /* MEDIA_STREAMER_NODE_TYPE_TEE */ + {MEDIA_STREAMER_STRICT, "queue"}, /* MEDIA_STREAMER_NODE_TYPE_QUEUE */ + {MEDIA_STREAMER_STRICT, "multiqueue"}, /* MEDIA_STREAMER_NODE_TYPE_MQUEUE */ + {"Codec/Muxer", "qtmux"}, /* MEDIA_STREAMER_NODE_TYPE_MUXER */ + {"Codec/Demuxer", "qtdemux"}, /* MEDIA_STREAMER_NODE_TYPE_DEMUXER */ + {MEDIA_STREAMER_STRICT, "rtpbin"}, /* MEDIA_STREAMER_NODE_TYPE_RTP */ + {MEDIA_STREAMER_STRICT, "input-selector"}, /* MEDIA_STREAMER_NODE_TYPE_INPUT_SELECTOR */ + {MEDIA_STREAMER_STRICT, "output-selector"},/* MEDIA_STREAMER_NODE_TYPE_OUTPUT_SELECTOR */ + {MEDIA_STREAMER_STRICT, "interleave"}, /* MEDIA_STREAMER_NODE_TYPE_INTERLEAVE */ + {MEDIA_STREAMER_STRICT, "deinterleave"}, /* MEDIA_STREAMER_NODE_TYPE_DEINTERLEAVE */ + {NULL, NULL} +}; + static gboolean __ms_rtp_node_has_property(media_streamer_node_s *ms_node, const gchar *param_name) { ms_retvm_if(!ms_node || !ms_node->gst_element, FALSE, "Error: empty node"); @@ -124,87 +153,25 @@ int __ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_f ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL"); int ret = MEDIA_STREAMER_ERROR_NONE; - dictionary *dict = NULL; - char *plugin_name = NULL; - media_format_mimetype_e mime; - if (MEDIA_FORMAT_ERROR_NONE != media_format_get_video_info(out_fmt, &mime, NULL, NULL, NULL, NULL)) - media_format_get_audio_info(out_fmt, &mime, NULL, NULL, NULL, NULL); - char *format_prefix = NULL; + GstCaps *sink_caps = in_fmt ? __ms_create_caps_from_fmt(in_fmt) : NULL; + GstCaps *src_caps = out_fmt ? __ms_create_caps_from_fmt(out_fmt) : NULL; - __ms_load_ini_dictionary(&dict); + node_plug_s plug_info = {&(nodes_info[node->type]), src_caps, sink_caps, NULL}; + ms_info("Creating node with info: klass_name[%s]; default[%s]", + plug_info.info->klass_name, plug_info.info->default_name); - switch (node->type) { - case MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER: - format_prefix = g_strdup_printf("%s:encoder", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_ENCODER); - node->gst_element = __ms_video_encoder_element_create(dict, mime); - break; - case MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER: - format_prefix = g_strdup_printf("%s:decoder", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_DECODER); - node->gst_element = __ms_video_decoder_element_create(dict, mime); - break; - case MEDIA_STREAMER_NODE_TYPE_PARSER: - format_prefix = g_strdup_printf("%s:parser", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_PARSER); - node->gst_element = __ms_element_create(plugin_name, NULL); - break; - case MEDIA_STREAMER_NODE_TYPE_FILTER: - node->gst_element = __ms_element_create(DEFAULT_FILTER, NULL); - break; - case MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY: - format_prefix = g_strdup_printf("%s:rtppay", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_RTPPAY); - node->gst_element = __ms_element_create(plugin_name, NULL); - break; - case MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY: - plugin_name = __ms_ini_get_string(dict, "audio-raw:rtppay", DEFAULT_AUDIO_RTPPAY); - node->gst_element = __ms_element_create(plugin_name, NULL); - break; - case MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY: - format_prefix = g_strdup_printf("%s:rtpdepay", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_RTPDEPAY); - node->gst_element = __ms_element_create(plugin_name, NULL); - break; - case MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY: - plugin_name = __ms_ini_get_string(dict, "audio-raw:rtpdepay", DEFAULT_AUDIO_RTPDEPAY); - node->gst_element = __ms_element_create(plugin_name, NULL); - break; - case MEDIA_STREAMER_NODE_TYPE_RTP: - node->gst_element = __ms_rtp_element_create(node); - break; - case MEDIA_STREAMER_NODE_TYPE_QUEUE: - node->gst_element = __ms_element_create(DEFAULT_QUEUE, NULL); - break; - case MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER: - node->gst_element = __ms_audio_encoder_element_create(); - break; - case MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER: - node->gst_element = __ms_element_create(DEFAULT_AUDIO_DECODER, NULL); - break; - case MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER: - node->gst_element = __ms_element_create(DEFAULT_VIDEO_CONVERT, NULL); - break; - case MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER: - node->gst_element = __ms_element_create(DEFAULT_AUDIO_CONVERT, NULL); - break; - case MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE: - node->gst_element = __ms_element_create(DEFAULT_AUDIO_RESAMPLE, NULL); - break; - default: - ms_error("Error: invalid node Type [%d]", node->type); - break; - } + node->gst_element = __ms_node_element_create(&plug_info, node->type); + if (node->gst_element) + node->name = gst_element_get_name(node->gst_element); + else + ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION; - MS_SAFE_FREE(plugin_name); - MS_SAFE_FREE(format_prefix); - __ms_destroy_ini_dictionary(dict); + if (src_caps) + gst_caps_unref(src_caps); - if (node->gst_element == NULL) - ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION; - else - node->name = gst_element_get_name(node->gst_element); + if (sink_caps) + gst_caps_unref(sink_caps); return ret; } diff --git a/src/media_streamer_util.c b/src/media_streamer_util.c index 8ed41a3..818e208 100644 --- a/src/media_streamer_util.c +++ b/src/media_streamer_util.c @@ -82,16 +82,16 @@ gchar *__ms_ini_get_string(dictionary *dict, const char *ini_path, char *default ms_retvm_if(ini_path == NULL, NULL, "Invalid ini path"); if (dict == NULL) { - result_str = g_strdup(default_str); + result_str = default_str; } else { gchar *str = NULL; str = iniparser_getstring(dict, ini_path, default_str); if (str && (strlen(str) > 0) && (strlen(str) < MEDIA_STREAMER_INI_MAX_STRLEN)) - result_str = g_strdup(str); + result_str = str; else - result_str = g_strdup(default_str); + result_str = default_str; } - return result_str; + return result_str ? g_strdup(result_str) : NULL; } gboolean __ms_load_ini_dictionary(dictionary **dict) @@ -127,7 +127,7 @@ gboolean __ms_destroy_ini_dictionary(dictionary *dict) return TRUE; } -static void __ms_ini_read_list(dictionary *dict, const char* key, gchar ***list) +void __ms_ini_read_list(dictionary *dict, const char* key, gchar ***list) { ms_retm_if(!dict || !list || !key, "Handle is NULL"); -- 2.7.4 From bb53afe449b0aa72dc16ee3c540ea3b3886dd897 Mon Sep 17 00:00:00 2001 From: Vyacheslav Valkovoy Date: Wed, 25 May 2016 20:54:23 +0300 Subject: [PATCH 13/16] Modified loading .ini file Change-Id: Ie8dfff92625d01b04b6f9a29b04e5e7fa87c5ec5 Signed-off-by: Vyacheslav Valkovoy --- include/media_streamer_gst.h | 4 +-- include/media_streamer_util.h | 18 ++++------- src/media_streamer_gst.c | 37 ++++++++--------------- src/media_streamer_node.c | 57 ++++++++++++++++++----------------- src/media_streamer_util.c | 69 ++++++++++++++++--------------------------- 5 files changed, 77 insertions(+), 108 deletions(-) diff --git a/include/media_streamer_gst.h b/include/media_streamer_gst.h index 07f964b..f41b532 100644 --- a/include/media_streamer_gst.h +++ b/include/media_streamer_gst.h @@ -88,14 +88,14 @@ GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node * * @since_tizen 3.0 */ -GstElement *__ms_video_encoder_element_create(dictionary *dict, media_format_mimetype_e mime); +GstElement *__ms_video_encoder_element_create(media_format_mimetype_e mime); /** * @brief Creates decoder GstElement by mime type. * * @since_tizen 3.0 */ -GstElement *__ms_video_decoder_element_create(dictionary *dict, media_format_mimetype_e mime); +GstElement *__ms_video_decoder_element_create(media_format_mimetype_e mime); /** * @brief Creates audio encoder GstElement. diff --git a/include/media_streamer_util.h b/include/media_streamer_util.h index 2cb2d73..f7ed569 100644 --- a/include/media_streamer_util.h +++ b/include/media_streamer_util.h @@ -96,7 +96,7 @@ extern "C" { #define MEDIA_STREAMER_INI_PATH "/etc/media_streamer.ini" #endif -#define MEDIA_STREAMER_INI_MAX_STRLEN 100 +#define INI_MAX_STRLEN (100) #define RTP_STREAM_DISABLED (0) /** @@ -165,6 +165,7 @@ typedef struct { #define DEFAULT_UDP_SOURCE "udpsrc" #define DEFAULT_FILE_SOURCE "filesrc" #define DEFAULT_HTTP_SOURCE "souphttpsrc" +#define DEFAULT_FILE_SINK "filesink" #define DEFAULT_UDP_SINK "udpsink" #define DEFAULT_RTP_BIN "rtpbin" @@ -262,32 +263,25 @@ typedef struct { void __ms_load_ini_settings(media_streamer_ini_t *ini); /** - * @brief Load settings from ini file into dictionary object. + * @brief Get instance of ini dictionary or create one if it doesn`t exist. * * @since_tizen 3.0 */ -gboolean __ms_load_ini_dictionary(dictionary **dict); - -/** - * @brief Destroys ini dictionary object and frees all resources. - * - * @since_tizen 3.0 - */ -gboolean __ms_destroy_ini_dictionary(dictionary *dict); +dictionary *__ms_get_ini_instance(void); /** * @brief Read and copy string reading from ini file. * * @since_tizen 3.0 */ -gchar *__ms_ini_get_string(dictionary *dict, const char *ini_path, char *default_str); +gchar *__ms_ini_get_string(const char *ini_path, char *default_str); /** * @brief Reads comma-separated string list from ini file. * * @since_tizen 3.0 */ -void __ms_ini_read_list(dictionary *dict, const char *key, gchar ***list); +void __ms_ini_read_list(const char *key, gchar ***list); /** * @brief Converts Media Format mime type into Caps media format string. diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index 583a1c5..c3624f6 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -23,7 +23,6 @@ #define H264_PARSER_CONFIG_INTERVAL 5 #define H264_ENCODER_ZEROLATENCY 0x00000004 -#define NODE_CONF_FIELD_LEN 100 void __ms_generate_dots(GstElement *bin, gchar *name_tag) { @@ -592,17 +591,12 @@ GstElement *__ms_combine_next_element(GstElement * previous_element, GstPad * pr /* Create element by predefined format element type */ } else if (!found_element && next_elem_bin_name && MS_ELEMENT_IS_ENCODER(next_elem_bin_name)) { - dictionary *dict = NULL; - - __ms_load_ini_dictionary(&dict); if (MS_ELEMENT_IS_VIDEO(next_elem_bin_name)) - found_element = __ms_video_encoder_element_create(dict, MEDIA_FORMAT_H263); + found_element = __ms_video_encoder_element_create(MEDIA_FORMAT_H263); else found_element = __ms_audio_encoder_element_create(); - __ms_destroy_ini_dictionary(dict); - /* Create element by caps of the previous element */ } else if (!found_element) { GstPad *src_pad = NULL; @@ -724,6 +718,7 @@ static void __decodebin_nomore_pads_combine(GstPad *src_pad, media_streamer_s *m found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); } else { + found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_VIDEO_CONVERT); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); } @@ -952,7 +947,6 @@ static gboolean __ms_feature_node_filter(GstPluginFeature *feature, gpointer dat GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node_type_e type) { - dictionary *dict = NULL; GstElement *gst_element = NULL; const gchar *src_type, *sink_type; @@ -974,20 +968,18 @@ GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node * Try to get plugin name that defined in ini file * according with node type and specified format. */ ms_info("Specified node formats types: in[%s] - out[%s]", sink_type, src_type); - gchar conf_key[NODE_CONF_FIELD_LEN] = {0,}; - if (snprintf(conf_key, NODE_CONF_FIELD_LEN, "node type %d:%s", type, (sink_type ? sink_type : src_type)) >= NODE_CONF_FIELD_LEN) { - ms_error("Failed to generate config field name, size >= %d", NODE_CONF_FIELD_LEN); + gchar conf_key[INI_MAX_STRLEN] = {0,}; + if (snprintf(conf_key, INI_MAX_STRLEN, "node type %d:%s", type, (sink_type ? sink_type : src_type)) >= INI_MAX_STRLEN) { + ms_error("Failed to generate config field name, size >= %d", INI_MAX_STRLEN); return NULL; } - __ms_load_ini_dictionary(&dict); - gchar *plugin_name = __ms_ini_get_string(dict, conf_key, NULL); + gchar *plugin_name = __ms_ini_get_string(conf_key, NULL); if (plugin_name) { gst_element = __ms_element_create(plugin_name, NULL); MS_SAFE_GFREE(plugin_name); } - __ms_destroy_ini_dictionary(dict); } /* 3. Third priority: @@ -995,10 +987,8 @@ GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node * try to find compatible plugin in gstreamer registry. * Elements that are compatible but defined as excluded will be skipped*/ if(!gst_element) { - __ms_load_ini_dictionary(&dict); - /* Read exclude elements list */ - __ms_ini_read_list(dict, "general:exclude elements", &plug_info->exclude_names); + __ms_ini_read_list("general:exclude elements", &plug_info->exclude_names); GList *factories = gst_registry_feature_filter(gst_registry_get(), __ms_feature_node_filter, TRUE, plug_info); @@ -1013,13 +1003,12 @@ GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node g_strfreev(plug_info->exclude_names); gst_plugin_list_free(factories); - __ms_destroy_ini_dictionary(dict); } return gst_element; } -GstElement *__ms_video_encoder_element_create(dictionary * dict, media_format_mimetype_e mime) +GstElement *__ms_video_encoder_element_create(media_format_mimetype_e mime) { char *plugin_name = NULL; char *format_prefix = NULL; @@ -1028,14 +1017,14 @@ GstElement *__ms_video_encoder_element_create(dictionary * dict, media_format_mi GstElement *video_convert = __ms_element_create(DEFAULT_VIDEO_CONVERT, NULL); format_prefix = g_strdup_printf("%s:encoder", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_ENCODER); + plugin_name = __ms_ini_get_string(format_prefix, DEFAULT_VIDEO_ENCODER); GstElement *encoder_elem = __ms_element_create(plugin_name, NULL); MS_SAFE_FREE(format_prefix); MS_SAFE_FREE(plugin_name); format_prefix = g_strdup_printf("%s:parser", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_PARSER); + plugin_name = __ms_ini_get_string(format_prefix, DEFAULT_VIDEO_PARSER); GstElement *encoder_parser = __ms_element_create(plugin_name, NULL); MS_SAFE_FREE(format_prefix); @@ -1066,7 +1055,7 @@ GstElement *__ms_video_encoder_element_create(dictionary * dict, media_format_mi return encoder_bin; } -GstElement *__ms_video_decoder_element_create(dictionary * dict, media_format_mimetype_e mime) +GstElement *__ms_video_decoder_element_create(media_format_mimetype_e mime) { char *plugin_name = NULL; char *format_prefix = NULL; @@ -1074,13 +1063,13 @@ GstElement *__ms_video_decoder_element_create(dictionary * dict, media_format_mi GstElement *last_elem = NULL; format_prefix = g_strdup_printf("%s:decoder", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_DECODER); + plugin_name = __ms_ini_get_string(format_prefix, DEFAULT_VIDEO_DECODER); GstElement *decoder_elem = __ms_element_create(plugin_name, NULL); MS_SAFE_FREE(format_prefix); MS_SAFE_FREE(plugin_name); format_prefix = g_strdup_printf("%s:parser", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(dict, format_prefix, DEFAULT_VIDEO_PARSER); + plugin_name = __ms_ini_get_string(format_prefix, DEFAULT_VIDEO_PARSER); GstElement *decoder_parser = __ms_element_create(plugin_name, NULL); if (mime == MEDIA_FORMAT_H264_SP) diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c index 849a61b..7a1bdd6 100755 --- a/src/media_streamer_node.c +++ b/src/media_streamer_node.c @@ -209,41 +209,43 @@ int __ms_src_node_create(media_streamer_node_s *node) ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL"); int ret = MEDIA_STREAMER_ERROR_NONE; - dictionary *dict = NULL; char *plugin_name = NULL; - __ms_load_ini_dictionary(&dict); - switch (node->subtype) { case MEDIA_STREAMER_NODE_SRC_TYPE_FILE: - node->gst_element = __ms_element_create(DEFAULT_FILE_SOURCE, NULL); + plugin_name = __ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE); + node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP: - node->gst_element = __ms_element_create(DEFAULT_UDP_SOURCE, NULL); + plugin_name = __ms_ini_get_string("node type 1:rtsp", DEFAULT_UDP_SOURCE); + node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP: - node->gst_element = __ms_element_create(DEFAULT_HTTP_SOURCE, NULL); + plugin_name = __ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE); + node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA: - plugin_name = __ms_ini_get_string(dict, "sources:camera_source", DEFAULT_CAMERA_SOURCE); + plugin_name = __ms_ini_get_string("node type 1:camera", DEFAULT_CAMERA_SOURCE); node->gst_element = __ms_element_create(plugin_name, NULL); - break; case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE: - plugin_name = __ms_ini_get_string(dict, "sources:audio_source", DEFAULT_AUDIO_SOURCE); + plugin_name = __ms_ini_get_string("node type 1:audio capture", DEFAULT_AUDIO_SOURCE); node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE: - plugin_name = __ms_ini_get_string(dict, "sources:video_source", DEFAULT_VIDEO_SOURCE); + plugin_name = __ms_ini_get_string("node type 1:video capture", DEFAULT_VIDEO_SOURCE); node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST: - node->gst_element = __ms_element_create(DEFAULT_VIDEO_TEST_SOURCE, NULL); + plugin_name = __ms_ini_get_string("node type 1:video test", DEFAULT_VIDEO_TEST_SOURCE); + node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_TEST: - node->gst_element = __ms_element_create(DEFAULT_AUDIO_TEST_SOURCE, NULL); + plugin_name = __ms_ini_get_string("node type 1:audio test", DEFAULT_AUDIO_TEST_SOURCE); + node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM: + plugin_name = __ms_ini_get_string("node type 1:custom", DEFAULT_APP_SOURCE); node->gst_element = __ms_element_create(DEFAULT_APP_SOURCE, NULL); __ms_signal_create(&node->sig_list, node->gst_element, "need-data", G_CALLBACK(__ms_src_start_feed_cb), node); __ms_signal_create(&node->sig_list, node->gst_element, "enough-data", G_CALLBACK(__ms_src_stop_feed_cb), node); @@ -254,7 +256,6 @@ int __ms_src_node_create(media_streamer_node_s *node) } MS_SAFE_FREE(plugin_name); - __ms_destroy_ini_dictionary(dict); if (node->gst_element == NULL) ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION; @@ -299,41 +300,44 @@ int __ms_sink_node_create(media_streamer_node_s *node) ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL"); int ret = MEDIA_STREAMER_ERROR_NONE; - dictionary *dict = NULL; char *plugin_name = NULL; - __ms_load_ini_dictionary(&dict); - switch (node->subtype) { case MEDIA_STREAMER_NODE_SINK_TYPE_FILE: - ms_error("Error: not implemented yet"); + plugin_name = __ms_ini_get_string("node type 2:file", DEFAULT_FILE_SINK); + node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP: - node->gst_element = __ms_element_create(DEFAULT_UDP_SINK, NULL); + plugin_name = __ms_ini_get_string("node type 2:rtsp", DEFAULT_UDP_SINK); + node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP: ms_error("Error: not implemented yet"); break; case MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO: - plugin_name = __ms_ini_get_string(dict, "sinks:audio_sink", DEFAULT_AUDIO_SINK); + plugin_name = __ms_ini_get_string("node type 2:audio", DEFAULT_AUDIO_SINK); node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY: - plugin_name = __ms_ini_get_string(dict, "sinks:video_sink", DEFAULT_VIDEO_SINK); + plugin_name = __ms_ini_get_string("node type 2:overlay", DEFAULT_VIDEO_SINK); node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SINK_TYPE_EVAS: - plugin_name = __ms_ini_get_string(dict, "sinks:evas_sink", DEFAULT_EVAS_SINK); + plugin_name = __ms_ini_get_string("node type 2:evas", DEFAULT_EVAS_SINK); node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SINK_TYPE_FAKE: - node->gst_element = __ms_element_create(DEFAULT_FAKE_SINK, NULL); + plugin_name = __ms_ini_get_string("node type 2:fake", DEFAULT_FAKE_SINK); + node->gst_element = __ms_element_create(plugin_name, NULL); break; case MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM: - node->gst_element = __ms_element_create(DEFAULT_APP_SINK, NULL); - g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL); - __ms_signal_create(&node->sig_list, node->gst_element, "new-sample", G_CALLBACK(__ms_sink_new_buffer_cb), node); - __ms_signal_create(&node->sig_list, node->gst_element, "eos", G_CALLBACK(sink_eos), node); + plugin_name = __ms_ini_get_string("node type 2:custom", DEFAULT_APP_SINK); + node->gst_element = __ms_element_create(plugin_name, NULL); + if (node->gst_element) { + g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL); + __ms_signal_create(&node->sig_list, node->gst_element, "new-sample", G_CALLBACK(__ms_sink_new_buffer_cb), node); + __ms_signal_create(&node->sig_list, node->gst_element, "eos", G_CALLBACK(sink_eos), node); + } break; default: ms_error("Error: invalid Sink node Type [%d]", node->subtype); @@ -341,7 +345,6 @@ int __ms_sink_node_create(media_streamer_node_s *node) } MS_SAFE_FREE(plugin_name); - __ms_destroy_ini_dictionary(dict); if (node->gst_element == NULL) ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION; diff --git a/src/media_streamer_util.c b/src/media_streamer_util.c index 818e208..b713c05 100644 --- a/src/media_streamer_util.c +++ b/src/media_streamer_util.c @@ -75,18 +75,18 @@ format_s format_table[] = { static void __ms_check_ini_status(void); -gchar *__ms_ini_get_string(dictionary *dict, const char *ini_path, char *default_str) +gchar *__ms_ini_get_string(const char *ini_path, char *default_str) { gchar *result_str = NULL; ms_retvm_if(ini_path == NULL, NULL, "Invalid ini path"); - if (dict == NULL) { + if (__ms_get_ini_instance() == NULL) { result_str = default_str; } else { gchar *str = NULL; - str = iniparser_getstring(dict, ini_path, default_str); - if (str && (strlen(str) > 0) && (strlen(str) < MEDIA_STREAMER_INI_MAX_STRLEN)) + str = iniparser_getstring(__ms_get_ini_instance(), ini_path, default_str); + if (str && (strlen(str) > 0) && (strlen(str) < INI_MAX_STRLEN)) result_str = str; else result_str = default_str; @@ -94,45 +94,32 @@ gchar *__ms_ini_get_string(dictionary *dict, const char *ini_path, char *default return result_str ? g_strdup(result_str) : NULL; } -gboolean __ms_load_ini_dictionary(dictionary **dict) +dictionary *__ms_get_ini_instance(void) { - ms_retvm_if(dict == NULL, FALSE, "Handle is NULL"); + static dictionary *instance = NULL; + if (NULL == instance) { + dictionary *ms_dict = NULL; + __ms_check_ini_status(); - __ms_check_ini_status(); + /* loading existing ini file */ + ms_dict = iniparser_load(MEDIA_STREAMER_INI_PATH); - dictionary *ms_dict = NULL; - - /* loading existing ini file */ - ms_dict = iniparser_load(MEDIA_STREAMER_INI_PATH); - - /* if no file exists. create one with set of default values */ - if (!ms_dict) { - ms_debug("Could not open ini [%s]. Media-streamer will use default values.", MEDIA_STREAMER_INI_PATH); - return FALSE; - } else { - ms_debug("Open ini file [%s].", MEDIA_STREAMER_INI_PATH); + if (!ms_dict) + ms_debug("Could not open ini [%s]. Media-streamer will use default values.", MEDIA_STREAMER_INI_PATH); + else + ms_debug("Open ini file [%s].", MEDIA_STREAMER_INI_PATH); + instance = ms_dict; } - *dict = ms_dict; - return TRUE; + return instance; } -gboolean __ms_destroy_ini_dictionary(dictionary *dict) +void __ms_ini_read_list(const char *key, gchar ***list) { - ms_retvm_if(dict == NULL, FALSE, "Handle is null"); - - /* free dict as we got our own structure */ - iniparser_freedict(dict); - - return TRUE; -} - -void __ms_ini_read_list(dictionary *dict, const char* key, gchar ***list) -{ - ms_retm_if(!dict || !list || !key, "Handle is NULL"); + ms_retm_if(!__ms_get_ini_instance() || !list || !key, "Handle is NULL"); /* Read exclude elements list */ - gchar *str = iniparser_getstring(dict, key, NULL); + gchar *str = iniparser_getstring(__ms_get_ini_instance(), key, NULL); if (str && strlen(str) > 0) { gchar *strtmp = g_strdup(str); g_strstrip(strtmp); @@ -144,26 +131,24 @@ void __ms_ini_read_list(dictionary *dict, const char* key, gchar ***list) void __ms_load_ini_settings(media_streamer_ini_t *ini) { - dictionary *dict = NULL; - /* get ini values */ memset(ini, 0, sizeof(media_streamer_ini_t)); - if (__ms_load_ini_dictionary(&dict)) { + if (__ms_get_ini_instance()) { /* general */ - ini->generate_dot = iniparser_getboolean(dict, "general:generate dot", DEFAULT_GENERATE_DOT); + ini->generate_dot = iniparser_getboolean(__ms_get_ini_instance(), "general:generate dot", DEFAULT_GENERATE_DOT); if (ini->generate_dot == TRUE) { - gchar *dot_path = iniparser_getstring(dict, "general:dot dir", MEDIA_STREAMER_DEFAULT_DOT_DIR); + gchar *dot_path = iniparser_getstring(__ms_get_ini_instance(), "general:dot dir", MEDIA_STREAMER_DEFAULT_DOT_DIR); ms_debug("generate_dot is TRUE, dot file will be stored into %s", dot_path); g_setenv("GST_DEBUG_DUMP_DOT_DIR", dot_path, FALSE); } - ini->use_decodebin = iniparser_getboolean(dict, "general:use decodebin", DEFAULT_USE_DECODEBIN); + ini->use_decodebin = iniparser_getboolean(__ms_get_ini_instance(), "general:use decodebin", DEFAULT_USE_DECODEBIN); /* Read exclude elements list */ - __ms_ini_read_list(dict, "general:exclude elements", &ini->exclude_elem_names); + __ms_ini_read_list("general:exclude elements", &ini->exclude_elem_names); /* Read gstreamer arguments list */ - __ms_ini_read_list(dict, "general:gstreamer arguments", &ini->gst_args); + __ms_ini_read_list("general:gstreamer arguments", &ini->gst_args); } else { /* if dict is not available just fill the structure with default values */ @@ -171,8 +156,6 @@ void __ms_load_ini_settings(media_streamer_ini_t *ini) ini->use_decodebin = DEFAULT_USE_DECODEBIN; } - __ms_destroy_ini_dictionary(dict); - /* general */ ms_debug("Media Streamer param [generate_dot] : %d", ini->generate_dot); ms_debug("Media Streamer param [use_decodebin] : %d", ini->use_decodebin); -- 2.7.4 From 7c66ecce3228094ae2ff157e4d3b28f897d6000b Mon Sep 17 00:00:00 2001 From: Vyacheslav Valkovoy Date: Wed, 25 May 2016 21:18:57 +0300 Subject: [PATCH 14/16] Fixed Manual Mode according to new node creation logic Change-Id: I05b07e87225abbd0694219de2d5e0fbb1982b3d6 Signed-off-by: Vyacheslav Valkovoy --- include/media_streamer.h | 2 + include/media_streamer_gst.h | 14 ++- include/media_streamer_util.h | 2 +- src/media_streamer_gst.c | 225 ++++++++++++++++++++++-------------------- src/media_streamer_node.c | 11 ++- test/media_streamer_test.c | 42 ++++---- 6 files changed, 162 insertions(+), 134 deletions(-) diff --git a/include/media_streamer.h b/include/media_streamer.h index c62f19f..3754fc0 100644 --- a/include/media_streamer.h +++ b/include/media_streamer.h @@ -70,6 +70,8 @@ typedef enum { MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY, /**< Rtp audio payloader */ MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY, /**< Rtp video depayloader */ MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY, /**< Rtp audio depayloader */ + MEDIA_STREAMER_NODE_TYPE_VIDEO_RATE, /**< Rate node type */ + MEDIA_STREAMER_NODE_TYPE_VIDEO_SCALE, /**< Scale node type */ MEDIA_STREAMER_NODE_TYPE_PARSER, /**< Parser node type */ MEDIA_STREAMER_NODE_TYPE_FILTER, /**< Filter node type, to limit formats of data */ MEDIA_STREAMER_NODE_TYPE_TEE, /**< Tee node type, splits data to multiple path */ diff --git a/include/media_streamer_gst.h b/include/media_streamer_gst.h index f41b532..c5add3c 100644 --- a/include/media_streamer_gst.h +++ b/include/media_streamer_gst.h @@ -88,21 +88,21 @@ GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node * * @since_tizen 3.0 */ -GstElement *__ms_video_encoder_element_create(media_format_mimetype_e mime); +GstElement *__ms_video_encoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type); /** * @brief Creates decoder GstElement by mime type. * * @since_tizen 3.0 */ -GstElement *__ms_video_decoder_element_create(media_format_mimetype_e mime); +GstElement *__ms_video_decoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type); /** * @brief Creates audio encoder GstElement. * * @since_tizen 3.0 */ -GstElement *__ms_audio_encoder_element_create(void); +GstElement *__ms_audio_encoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type); /** * @brief Creates rtp container GstElement. @@ -207,6 +207,14 @@ int __ms_element_set_fmt(media_streamer_node_s *node, const char *pad_name, medi * @since_tizen 3.0 */ GstCaps *__ms_create_caps_from_fmt(media_format_h fmt); + +/** + * @brief Creates mediaformat from GstCaps. + * + * @since_tizen 3.0 + */ +media_format_h __ms_create_fmt_from_caps(GstCaps *caps); + /** * @brief Seeks GstElement to according time value. * diff --git a/include/media_streamer_util.h b/include/media_streamer_util.h index f7ed569..67bd310 100644 --- a/include/media_streamer_util.h +++ b/include/media_streamer_util.h @@ -146,7 +146,7 @@ typedef struct { #define DEFAULT_FILTER "capsfilter" #define DEFAULT_TYPEFIND "typefind" #define DEFAULT_DECODEBIN "decodebin" -#define DEFAULT_AUDIO_SOURCE "alsasrc" +#define DEFAULT_AUDIO_SOURCE "pulsesrc" #define DEFAULT_CAMERA_SOURCE "v4l2src" #define DEFAULT_VIDEO_SOURCE "ximagesrc" #define DEFAULT_APP_SOURCE "appsrc" diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index c3624f6..f6ace1a 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -433,39 +433,9 @@ GstElement *__ms_bin_find_element_by_klass(GstElement *sink_bin, GstElement *pre return element_found ? found_element : NULL; } -int __ms_get_rank_increase(const char *factory_name) -{ - gint rank_priority = 20; - gint rank_second = 10; - gint rank_skip = -10; - gint ret = 0; - - if (g_strrstr(factory_name, "av")) - ret = rank_priority; - else if (g_strrstr(factory_name, "omx")) - ret = rank_second; - else if (g_strrstr(factory_name, "v4l2video")) - ret = rank_skip; - else if (g_strrstr(factory_name, "rtph263ppay")) - ret = rank_skip; - else if (g_strrstr(factory_name, "sprd")) - ret = rank_skip; - - return ret; -} - int __ms_factory_rank_compare(GstPluginFeature * first_feature, GstPluginFeature * second_feature) { - const gchar *name; - int first_feature_rank_inc = 0, second_feature_rank_inc = 0; - - name = gst_plugin_feature_get_plugin_name(first_feature); - first_feature_rank_inc = __ms_get_rank_increase(name); - - name = gst_plugin_feature_get_plugin_name(second_feature); - second_feature_rank_inc = __ms_get_rank_increase(name); - - return (gst_plugin_feature_get_rank(second_feature) + second_feature_rank_inc) - (gst_plugin_feature_get_rank(first_feature) + first_feature_rank_inc); + return (gst_plugin_feature_get_rank(second_feature) - gst_plugin_feature_get_rank(first_feature)); } gboolean __ms_feature_filter(GstPluginFeature * feature, gpointer data) @@ -588,15 +558,6 @@ GstElement *__ms_combine_next_element(GstElement * previous_element, GstPad * pr if (!found_element && !next_elem_bin_name && default_element) { found_element = __ms_element_create(default_element, NULL); - /* Create element by predefined format element type */ - } else if (!found_element && next_elem_bin_name && MS_ELEMENT_IS_ENCODER(next_elem_bin_name)) { - - - if (MS_ELEMENT_IS_VIDEO(next_elem_bin_name)) - found_element = __ms_video_encoder_element_create(MEDIA_FORMAT_H263); - else - found_element = __ms_audio_encoder_element_create(); - /* Create element by caps of the previous element */ } else if (!found_element) { GstPad *src_pad = NULL; @@ -915,16 +876,24 @@ static gboolean __ms_feature_node_filter(GstPluginFeature *feature, gpointer dat return FALSE; gboolean can_accept = FALSE; + gboolean src_can_accept = FALSE; + gboolean sink_can_accept = FALSE; GstElementFactory *factory = GST_ELEMENT_FACTORY(feature); const gchar *factory_klass = gst_element_factory_get_klass(factory); if (plug_info && g_strrstr(factory_klass, plug_info->info->klass_name)) { if (GST_IS_CAPS(plug_info->src_caps)) - can_accept = can_accept || gst_element_factory_can_src_any_caps(factory, plug_info->src_caps); + src_can_accept = gst_element_factory_can_src_any_caps(factory, plug_info->src_caps); if (GST_IS_CAPS(plug_info->sink_caps)) - can_accept = can_accept || gst_element_factory_can_sink_any_caps(factory, plug_info->sink_caps); + sink_can_accept = gst_element_factory_can_sink_any_caps(factory, plug_info->sink_caps); + + if (GST_IS_CAPS(plug_info->src_caps) && GST_IS_CAPS(plug_info->sink_caps)) { + if (src_can_accept && sink_can_accept) + can_accept = TRUE; + } else if (src_can_accept || sink_can_accept) + can_accept = TRUE; if (can_accept) { int index = 0; @@ -945,6 +914,64 @@ static gboolean __ms_feature_node_filter(GstPluginFeature *feature, gpointer dat return FALSE; } +static GstElement *__ms_element_create_from_ini(node_plug_s *plug_info, media_streamer_node_type_e type) +{ + const gchar *src_type, *sink_type; + const gchar *format_type = NULL; + MS_GET_CAPS_TYPE(plug_info->src_caps, src_type); + MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type); + + GstElement *gst_element = NULL; + ms_info("Specified node formats types: in[%s] - out[%s]", sink_type, src_type); + gchar conf_key[INI_MAX_STRLEN] = {0,}; + + if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER || type == MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER) + format_type = src_type; + else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER || type == MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER) + format_type = sink_type; + else + format_type = sink_type ? sink_type : src_type; + + if (snprintf(conf_key, INI_MAX_STRLEN, "node type %d:%s", type, format_type) >= INI_MAX_STRLEN) { + ms_error("Failed to generate config field name, size >= %d", INI_MAX_STRLEN); + return NULL; + } + gchar *plugin_name = __ms_ini_get_string(conf_key, NULL); + + if (plugin_name) { + gst_element = __ms_element_create(plugin_name, NULL); + MS_SAFE_GFREE(plugin_name); + } + return gst_element; +} + +static GstElement *__ms_element_create_by_registry(node_plug_s *plug_info, media_streamer_node_type_e type) +{ + GstElement *gst_element = NULL; + const gchar *src_type, *sink_type; + MS_GET_CAPS_TYPE(plug_info->src_caps, src_type); + MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type); + + __ms_ini_read_list("general:exclude elements", &plug_info->exclude_names); + + GList *factories = gst_registry_feature_filter(gst_registry_get(), + __ms_feature_node_filter, FALSE, plug_info); + factories = g_list_sort(factories,(GCompareFunc) __ms_factory_rank_compare); + + if (factories) { + GstElementFactory *factory = GST_ELEMENT_FACTORY(factories->data); + gst_element = __ms_element_create(GST_OBJECT_NAME(factory), NULL); + } else { + ms_error("Error: could not found any compatible element for node [%d]: in[%s] - out[%s]", + type, sink_type, src_type); + } + + g_strfreev(plug_info->exclude_names); + gst_plugin_list_free(factories); + + return gst_element; +} + GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node_type_e type) { GstElement *gst_element = NULL; @@ -963,23 +990,18 @@ GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node gst_element = __ms_rtp_element_create(); else gst_element = __ms_element_create(plug_info->info->default_name, NULL); - } else { + } else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER) + gst_element = __ms_audio_encoder_element_create(plug_info, type); + else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER) + gst_element = __ms_video_encoder_element_create(plug_info, type); + else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER) + gst_element = __ms_video_decoder_element_create(plug_info, type); + else { + /* 2. Second priority: * Try to get plugin name that defined in ini file * according with node type and specified format. */ - ms_info("Specified node formats types: in[%s] - out[%s]", sink_type, src_type); - gchar conf_key[INI_MAX_STRLEN] = {0,}; - if (snprintf(conf_key, INI_MAX_STRLEN, "node type %d:%s", type, (sink_type ? sink_type : src_type)) >= INI_MAX_STRLEN) { - ms_error("Failed to generate config field name, size >= %d", INI_MAX_STRLEN); - return NULL; - } - - gchar *plugin_name = __ms_ini_get_string(conf_key, NULL); - - if (plugin_name) { - gst_element = __ms_element_create(plugin_name, NULL); - MS_SAFE_GFREE(plugin_name); - } + gst_element = __ms_element_create_from_ini(plug_info, type); } /* 3. Third priority: @@ -988,53 +1010,34 @@ GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node * Elements that are compatible but defined as excluded will be skipped*/ if(!gst_element) { /* Read exclude elements list */ - __ms_ini_read_list("general:exclude elements", &plug_info->exclude_names); - - GList *factories = gst_registry_feature_filter(gst_registry_get(), - __ms_feature_node_filter, TRUE, plug_info); - - if (factories) { - GstElementFactory *factory = GST_ELEMENT_FACTORY(factories->data); - gst_element = __ms_element_create(GST_OBJECT_NAME(factory), NULL); - } else { - ms_error("Error: could not found any compatible element for node [%d]: in[%s] - out[%s]", - type, sink_type, src_type); - } - - g_strfreev(plug_info->exclude_names); - gst_plugin_list_free(factories); + gst_element = __ms_element_create_by_registry(plug_info, type); } return gst_element; } -GstElement *__ms_video_encoder_element_create(media_format_mimetype_e mime) +GstElement *__ms_video_encoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type) { - char *plugin_name = NULL; - char *format_prefix = NULL; + const gchar *src_type; + MS_GET_CAPS_TYPE(plug_info->src_caps, src_type); GstElement *video_scale = __ms_element_create(DEFAULT_VIDEO_SCALE, NULL); GstElement *video_convert = __ms_element_create(DEFAULT_VIDEO_CONVERT, NULL); - format_prefix = g_strdup_printf("%s:encoder", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(format_prefix, DEFAULT_VIDEO_ENCODER); - GstElement *encoder_elem = __ms_element_create(plugin_name, NULL); + GstElement *encoder_elem = __ms_element_create_from_ini(plug_info, type); + media_format_mimetype_e encoder_type = __ms_convert_string_format_to_media_format(src_type); - MS_SAFE_FREE(format_prefix); - MS_SAFE_FREE(plugin_name); - - format_prefix = g_strdup_printf("%s:parser", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(format_prefix, DEFAULT_VIDEO_PARSER); - GstElement *encoder_parser = __ms_element_create(plugin_name, NULL); - - MS_SAFE_FREE(format_prefix); - MS_SAFE_FREE(plugin_name); + node_info_s nodes_info = {MEDIA_STREAMER_PARSER_KLASS, DEFAULT_VIDEO_PARSER}; + node_plug_s plug_info_parser = { &nodes_info, plug_info->src_caps, NULL, NULL}; + GstElement *encoder_parser = __ms_element_create_from_ini(plug_info, MEDIA_STREAMER_NODE_TYPE_PARSER); + if (!encoder_parser) + encoder_parser = __ms_element_create_by_registry(&plug_info_parser, MEDIA_STREAMER_NODE_TYPE_PARSER); gboolean gst_ret = FALSE; GstElement *encoder_bin = gst_bin_new("video_encoder"); ms_retvm_if(!video_convert || !video_scale || !encoder_elem || !encoder_bin || !encoder_parser, (GstElement *) NULL, "Error: creating elements for video encoder bin"); - if (mime == MEDIA_FORMAT_H264_SP) { + if (encoder_type == MEDIA_FORMAT_H264_SP) { g_object_set(GST_OBJECT(encoder_parser), "config-interval", H264_PARSER_CONFIG_INTERVAL, NULL); g_object_set(G_OBJECT(encoder_elem), "tune", H264_ENCODER_ZEROLATENCY, NULL); g_object_set(G_OBJECT(encoder_elem), "byte-stream", TRUE, NULL); @@ -1055,31 +1058,31 @@ GstElement *__ms_video_encoder_element_create(media_format_mimetype_e mime) return encoder_bin; } -GstElement *__ms_video_decoder_element_create(media_format_mimetype_e mime) +GstElement *__ms_video_decoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type) { - char *plugin_name = NULL; - char *format_prefix = NULL; gboolean is_hw_codec = FALSE; GstElement *last_elem = NULL; - format_prefix = g_strdup_printf("%s:decoder", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(format_prefix, DEFAULT_VIDEO_DECODER); - GstElement *decoder_elem = __ms_element_create(plugin_name, NULL); - MS_SAFE_FREE(format_prefix); - MS_SAFE_FREE(plugin_name); + const gchar *sink_type; + MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type); + + GstElement *decoder_elem = __ms_element_create_from_ini(plug_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER); + media_format_mimetype_e encoder_type = __ms_convert_string_format_to_media_format(sink_type); - format_prefix = g_strdup_printf("%s:parser", __ms_convert_mime_to_string(mime)); - plugin_name = __ms_ini_get_string(format_prefix, DEFAULT_VIDEO_PARSER); - GstElement *decoder_parser = __ms_element_create(plugin_name, NULL); + node_info_s nodes_info = {MEDIA_STREAMER_PARSER_KLASS, DEFAULT_VIDEO_PARSER}; + node_plug_s plug_info_parser = { &nodes_info, plug_info->sink_caps, NULL, NULL}; - if (mime == MEDIA_FORMAT_H264_SP) + GstElement *decoder_parser = __ms_element_create_from_ini(plug_info, MEDIA_STREAMER_NODE_TYPE_PARSER); + if (!decoder_parser) + decoder_parser = __ms_element_create_by_registry(&plug_info_parser, MEDIA_STREAMER_NODE_TYPE_PARSER); + + + if (encoder_type == MEDIA_FORMAT_H264_SP) g_object_set(G_OBJECT(decoder_parser), "config-interval", H264_PARSER_CONFIG_INTERVAL, NULL); - if (g_strrstr(format_prefix, "omx") || g_strrstr(format_prefix, "sprd")) + if (g_strrstr(plug_info->info->default_name, "omx") || g_strrstr(plug_info->info->default_name, "sprd")) is_hw_codec = TRUE; - MS_SAFE_FREE(format_prefix); - MS_SAFE_FREE(plugin_name); gboolean gst_ret = FALSE; GstElement *decoder_bin = gst_bin_new("video_decoder"); @@ -1115,14 +1118,18 @@ GstElement *__ms_video_decoder_element_create(media_format_mimetype_e mime) return decoder_bin; } -GstElement *__ms_audio_encoder_element_create(void) +GstElement *__ms_audio_encoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type) { gboolean gst_ret = FALSE; - GstElement *audio_convert = __ms_element_create("audioconvert", NULL); - GstElement *audio_resample = __ms_element_create("audioresample", NULL); - GstElement *audio_filter = __ms_element_create("capsfilter", NULL); - GstElement *audio_postenc_convert = __ms_element_create("audioconvert", NULL); - GstElement *audio_encoder = __ms_element_create(DEFAULT_AUDIO_ENCODER, NULL); + + GstElement *audio_convert = __ms_element_create(DEFAULT_AUDIO_CONVERT, NULL); + GstElement *audio_resample = __ms_element_create(DEFAULT_AUDIO_RESAMPLE, NULL); + GstElement *audio_filter = __ms_element_create(DEFAULT_FILTER, NULL); + GstElement *audio_postenc_convert = __ms_element_create(DEFAULT_AUDIO_CONVERT, NULL); + GstElement *audio_encoder = __ms_element_create_from_ini(plug_info, type); + if (!audio_encoder) + audio_encoder = __ms_element_create_by_registry(plug_info, type); + GstElement *audio_enc_bin = gst_bin_new("audio_encoder"); ms_retvm_if(!audio_convert || !audio_postenc_convert || !audio_filter || !audio_encoder || !audio_enc_bin, (GstElement *) NULL, "Error: creating elements for encoder bin"); @@ -1511,7 +1518,7 @@ GstCaps *__ms_create_caps_from_fmt(media_format_h fmt) return caps; } -static media_format_h __ms_create_fmt_from_caps(GstCaps *caps) +media_format_h __ms_create_fmt_from_caps(GstCaps *caps) { media_format_h fmt; GstStructure *pad_struct; diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c index 7a1bdd6..8cb7818 100755 --- a/src/media_streamer_node.c +++ b/src/media_streamer_node.c @@ -57,10 +57,13 @@ node_info_s nodes_info[] = { {MEDIA_STREAMER_STRICT, "videoconvert"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER */ {MEDIA_STREAMER_STRICT, "audioconvert"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER */ {MEDIA_STREAMER_STRICT, "audioresample"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE */ - {"Payloader", "rtph264pay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY */ - {"Payloader", "rtpamrpay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY */ - {"Depayloader", "rtph264depay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY */ - {"Depayloader", "rtpamrdepay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY */ + {"Payloader/Network", "rtph264pay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY */ + {"Payloader/Network", "rtpamrpay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY */ + {"Depayloader/Network", "rtph264depay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY */ + {"Depayloader/Network", "rtpamrdepay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY */ + {"Filter/Effect/Video", "videorate"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_RATE */ + {"Scaler", "videoscale"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_SCALE */ + {"Parser", "h264parse"}, /* MEDIA_STREAMER_NODE_TYPE_PARSER */ {MEDIA_STREAMER_STRICT, "capsfilter"}, /* MEDIA_STREAMER_NODE_TYPE_FILTER */ {MEDIA_STREAMER_STRICT, "tee"}, /* MEDIA_STREAMER_NODE_TYPE_TEE */ {MEDIA_STREAMER_STRICT, "queue"}, /* MEDIA_STREAMER_NODE_TYPE_QUEUE */ diff --git a/test/media_streamer_test.c b/test/media_streamer_test.c index 722afee..b096954 100644 --- a/test/media_streamer_test.c +++ b/test/media_streamer_test.c @@ -117,6 +117,7 @@ gboolean g_audio_is_on = FALSE; media_format_h vfmt_raw = NULL; media_format_h vfmt_encoded = NULL; media_format_h afmt_raw = NULL; +media_format_h afmt_encoded = NULL; static void streamer_error_cb(media_streamer_h streamer, media_streamer_error_e error, void *user_data) { @@ -264,7 +265,7 @@ static void create_formats(void) /* Define video raw format */ media_format_create(&vfmt_raw); - if (media_format_set_video_mime(vfmt_raw, MEDIA_FORMAT_YV12) != MEDIA_FORMAT_ERROR_NONE) + if (media_format_set_video_mime(vfmt_raw, MEDIA_FORMAT_I420) != MEDIA_FORMAT_ERROR_NONE) g_print("media_format_set_video_mime failed!"); media_format_set_video_width(vfmt_raw, 800); @@ -288,8 +289,15 @@ static void create_formats(void) g_print("media_format_set_audio_mime failed!"); media_format_set_audio_channel(afmt_raw, 1); - media_format_set_audio_samplerate(afmt_raw, 44100); - media_format_set_audio_bit(afmt_raw, 16); + media_format_set_audio_samplerate(afmt_raw, 8000); + + /* Define audio encoded format */ + media_format_create(&afmt_encoded); + if (media_format_set_audio_mime(afmt_encoded, MEDIA_FORMAT_AMR_NB) != MEDIA_FORMAT_ERROR_NONE) + g_print("media_format_set_audio_mime failed!"); + + media_format_set_audio_channel(afmt_encoded, 1); + media_format_set_audio_samplerate(afmt_encoded, 8000); } static void set_rtp_params(media_streamer_node_h rtp_node, const char *ip, int video_port, int audio_port, gboolean port_reverse) @@ -430,13 +438,13 @@ static void _create_rtp_streamer(media_streamer_node_h rtp_bin) /*********************** encoder **************************************** */ media_streamer_node_h video_enc = NULL; - media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER, NULL, vfmt_encoded, &video_enc); + media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER, vfmt_raw, vfmt_encoded, &video_enc); media_streamer_node_add(current_media_streamer, video_enc); APPEND_NODE(video_enc); /*********************** videopay *************************************** */ media_streamer_node_h video_pay = NULL; - media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY, NULL, vfmt_encoded, &video_pay); + media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY, vfmt_encoded, NULL, &video_pay); media_streamer_node_add(current_media_streamer, video_pay); APPEND_NODE(video_pay); @@ -463,13 +471,13 @@ static void _create_rtp_streamer(media_streamer_node_h rtp_bin) /*********************** audioencoder *********************************** */ media_streamer_node_h audio_enc = NULL; - media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER, NULL, NULL, &audio_enc); + media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER, afmt_raw, afmt_encoded, &audio_enc); media_streamer_node_add(current_media_streamer, audio_enc); APPEND_NODE(audio_enc); - /*********************** rtpL16pay *********************************** */ + /*********************** rtpamrpay *********************************** */ media_streamer_node_h audio_pay = NULL; - media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY, NULL, NULL, &audio_pay); + media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY, afmt_encoded, NULL, &audio_pay); media_streamer_node_add(current_media_streamer, audio_pay); APPEND_NODE(audio_pay); @@ -532,13 +540,13 @@ static void _create_rtp_client(media_streamer_node_h rtp_bin) /* ********************** videodec ************************************ */ media_streamer_node_h video_dec = NULL; - media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER, NULL, vfmt_encoded, &video_dec); + media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER, vfmt_encoded, vfmt_raw, &video_dec); media_streamer_node_add(current_media_streamer, video_dec); APPEND_NODE(video_dec); /* ********************** videoqueue ************************************ */ media_streamer_node_h video_queue = NULL; - media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_QUEUE, NULL, vfmt_encoded, &video_queue); + media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_QUEUE, NULL, NULL, &video_queue); media_streamer_node_add(current_media_streamer, video_queue); APPEND_NODE(video_queue); @@ -564,11 +572,11 @@ static void _create_rtp_client(media_streamer_node_h rtp_bin) media_streamer_node_add(current_media_streamer, audio_depay); APPEND_NODE(audio_depay); - /* ********************** audioconverter ****************************** */ - media_streamer_node_h audio_conv = NULL; - media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER, NULL, NULL, &audio_conv); - media_streamer_node_add(current_media_streamer, audio_conv); - APPEND_NODE(audio_conv); + /* ********************** audiodecoder ****************************** */ + media_streamer_node_h audio_dec = NULL; + media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER, NULL, NULL, &audio_dec); + media_streamer_node_add(current_media_streamer, audio_dec); + APPEND_NODE(audio_dec); /* ********************** audioqueue ********************************** */ media_streamer_node_h audio_queue = NULL; @@ -583,8 +591,8 @@ static void _create_rtp_client(media_streamer_node_h rtp_bin) APPEND_NODE(audio_sink); /* ====================Linking Audio Client=========================== */ - media_streamer_node_link(audio_depay, "src", audio_conv, "sink"); - media_streamer_node_link(audio_conv, "src", audio_queue, "sink"); + media_streamer_node_link(audio_depay, "src", audio_dec, "sink"); + media_streamer_node_link(audio_dec, "src", audio_queue, "sink"); media_streamer_node_link(audio_queue, "src", audio_sink, "sink"); /* =================================================================== */ -- 2.7.4 From 0dcca9096d40ce5a89d57af1f167ac102d9c3277 Mon Sep 17 00:00:00 2001 From: Volodymyr Brynza Date: Thu, 9 Jun 2016 11:57:50 +0300 Subject: [PATCH 15/16] Fixed Autoplug Mode according to new node creation logic Change-Id: I4cb30c27ba8f29bfe8aab507415955a7322d1a02 Signed-off-by: Volodymyr Brynza --- include/media_streamer.h | 1 + include/media_streamer_gst.h | 26 +- include/media_streamer_util.h | 19 +- src/media_streamer.c | 3 +- src/media_streamer_gst.c | 610 +++++++++++++++++++----------------------- src/media_streamer_node.c | 93 ++++--- src/media_streamer_util.c | 23 +- test/media_streamer_test.c | 35 ++- 8 files changed, 376 insertions(+), 434 deletions(-) diff --git a/include/media_streamer.h b/include/media_streamer.h index 3754fc0..99ab4a1 100644 --- a/include/media_streamer.h +++ b/include/media_streamer.h @@ -72,6 +72,7 @@ typedef enum { MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY, /**< Rtp audio depayloader */ MEDIA_STREAMER_NODE_TYPE_VIDEO_RATE, /**< Rate node type */ MEDIA_STREAMER_NODE_TYPE_VIDEO_SCALE, /**< Scale node type */ + MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY, /**< Overlay node type */ MEDIA_STREAMER_NODE_TYPE_PARSER, /**< Parser node type */ MEDIA_STREAMER_NODE_TYPE_FILTER, /**< Filter node type, to limit formats of data */ MEDIA_STREAMER_NODE_TYPE_TEE, /**< Tee node type, splits data to multiple path */ diff --git a/include/media_streamer_gst.h b/include/media_streamer_gst.h index c5add3c..8428e1c 100644 --- a/include/media_streamer_gst.h +++ b/include/media_streamer_gst.h @@ -38,7 +38,6 @@ #define MEDIA_STREAMER_SINK_KLASS "Sink" #define MEDIA_STREAMER_STRICT "_strict_" - /** * @brief Generates dot files for GStreamer pipeline. * @@ -47,27 +46,33 @@ void __ms_generate_dots(GstElement *bin, gchar *name_tag); /** - * @brief Finds GstElement by klass name. + * @brief Gets Node`s information by its type. * * @since_tizen 3.0 */ -GstElement *__ms_bin_find_element_by_klass(GstElement *sink_bin, GstElement *previous_elem, - GstPad *source_pad, const gchar *klass_name, const gchar *bin_name); +node_info_s *__ms_node_get_klass_by_its_type(media_streamer_node_type_e element_type); /** - * @brief Creates GstElement by klass name. + * @brief Link two elements. * * @since_tizen 3.0 */ -GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar *klass_name); +gboolean __ms_link_two_elements(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *found_element); + +/** + * @brief Finds GstElement by klass name. + * + * @since_tizen 3.0 + */ +GstElement *__ms_bin_find_element_by_klass(GstElement *sink_bin, GstElement *previous_elem, + GstPad *source_pad, const gchar *klass_name, const gchar *bin_name); /** - * @brief Links two Gstelements and returns the last one. + * @brief Creates GstElement by klass name. * * @since_tizen 3.0 */ -GstElement *__ms_link_with_new_element(GstElement *previous_element, GstPad *prev_elem_src_pad, - GstElement *new_element); +GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar *klass_name); /** * @brief Creates GstElement by plugin name. @@ -156,8 +161,7 @@ GstElement *__ms_decodebin_create(media_streamer_s *ms_streamer); * * @since_tizen 3.0 */ -GstElement *__ms_combine_next_element(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *bin_to_find_in, - const gchar *next_elem_klass_name, const gchar *next_elem_bin_name, gchar *default_element); +GstElement *__ms_combine_next_element(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *bin_to_find_in, media_streamer_node_type_e node_type); /** * @brief Creates pipeline, bus and src/sink/topology bins. diff --git a/include/media_streamer_util.h b/include/media_streamer_util.h index 67bd310..7377677 100644 --- a/include/media_streamer_util.h +++ b/include/media_streamer_util.h @@ -183,10 +183,14 @@ typedef struct { #define DEFAULT_AUDIO_RTPPAY "rtpamrpay" #define DEFAULT_AUDIO_RTPDEPAY "rtpamrdepay" -#define DEFAULT_AUDIO "S16LE" -#define MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT "video/x-raw,format=I420,width=1280,height=720" -#define MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT "audio/x-raw,channels=1,rate=8000,format="DEFAULT_AUDIO -#define MEDIA_STREAMER_DEFAULT_ENCODER_FORMAT(format) "video/x-"format",stream-format=byte-stream" +#define MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT "video/x-raw,format=I420,width=352,height=288" +#define MEDIA_STREAMER_DEFAULT_AUDIO_RAW_FORMAT "audio/x-raw,channels=1,rate=8000,format=S16LE" +#define MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT "video/x-h263,width=352,height=288,framrate = 3/1" +#define MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT "audio/AMR ,rate = 8000,channels = 1" +#define MEDIA_STREAMER_DEFAULT_VIDEO_RTP_FORMAT "application/x-rtp,media=video" +#define MEDIA_STREAMER_DEFAULT_AUDIO_RTP_FORMAT "application/x-rtp,media=(string)audio,clock-rate=(int)8000,encoding-name=(string)AMR,encoding-params=(string)1,octet-align=(string)1" + + #define MS_ELEMENT_IS_OUTPUT(el) g_strrstr(el, "out") #define MS_ELEMENT_IS_INPUT(el) g_strrstr(el, "in") @@ -291,13 +295,6 @@ void __ms_ini_read_list(const char *key, gchar ***list); const gchar *__ms_convert_mime_to_string_format(media_format_mimetype_e mime); /** - * @brief Converts Media Format mime type into Caps media format string. - * - * @since_tizen 3.0 - */ -const gchar *__ms_convert_mime_to_string(media_format_mimetype_e mime); - -/** * @brief Converts Media Format mime type into rtp media type. * * @since_tizen 3.0 diff --git a/src/media_streamer.c b/src/media_streamer.c index d573a54..ce28edc 100644 --- a/src/media_streamer.c +++ b/src/media_streamer.c @@ -609,9 +609,10 @@ int media_streamer_node_link(media_streamer_node_h src_node, const char *src_pad gboolean link_ret = gst_element_link_pads_filtered(ms_src_node->gst_element, src_pad_name, ms_dest_node->gst_element, sink_pad_name, src_pad_caps ? src_pad_caps : sink_pad_caps); if (!link_ret) { - ms_error("Can not link [%s]->%s pad to [%s]->%s pad, ret code [%d] ", ms_src_node->name, src_pad_name, ms_dest_node->name, sink_pad_name, link_ret); + ms_error("Can not link [%s]:%s pad to [%s]:%s pad, ret code [%d] ", ms_src_node->name, src_pad_name, ms_dest_node->name, sink_pad_name, link_ret); ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION; } else { + ms_info("Linked successfully [%s]:%s pad to [%s]:%s pad, ret code [%d] ", ms_src_node->name, src_pad_name, ms_dest_node->name, sink_pad_name, link_ret); ms_src_node->linked_by_user = TRUE; ms_dest_node->linked_by_user = TRUE; } diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index f6ace1a..46cddcc 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -220,21 +220,6 @@ gboolean __ms_bin_add_element(GstElement *bin, GstElement *element, gboolean do_ return ret; } -static gboolean __ms_get_peer_element(GstPad *source_pad, GstElement *found_element) -{ - GstElement *peer_element = NULL; - - peer_element = __ms_pad_get_peer_element(source_pad); - if (peer_element && (peer_element == found_element)) - /* Source pad of previous element has peer pad element */ - /* Previous element is connected to found element */ - return TRUE; - else - /* Source pad of previous element doesn`t have peer pad element */ - /* or is not connected to found element */ - return FALSE; -} - const gchar *__ms_get_pad_type(GstPad *element_pad) { const gchar *pad_type = NULL; @@ -244,193 +229,129 @@ const gchar *__ms_get_pad_type(GstPad *element_pad) return pad_type; } -static gboolean __ms_intersect_pads(GstPad *src_pad, GstPad *sink_pad) +static GstElement *__ms_find_peer_element_by_type(GstElement *previous_element, GstPad *prev_elem_src_pad, node_info_s *node_klass_type) { - GstCaps *src_pad_caps = NULL; - const gchar *src_pad_type = NULL; - GstStructure *src_pad_struct = NULL; - const gchar *src_pad_struct_string = NULL; - - GstCaps *sink_pad_caps = NULL; - const gchar *sink_pad_type = NULL; - GstStructure *sink_pad_struct = NULL; - const gchar *sink_pad_struct_string = NULL; + GstElement *peer_element = NULL; + GstIterator *src_pad_iterator = NULL; + GValue src_pad_value = G_VALUE_INIT; + const gchar *found_klass = NULL; - gboolean can_intersect = FALSE; - gboolean intersect_res = FALSE; + if (prev_elem_src_pad) { - src_pad_caps = gst_pad_query_caps(src_pad, 0); - if (gst_caps_get_size(src_pad_caps) > 0) { - src_pad_struct = gst_caps_get_structure(src_pad_caps, 0); - src_pad_type = gst_structure_get_name(src_pad_struct); - } + /* Check if previous element`s source pad is connected with element */ + peer_element = __ms_pad_get_peer_element(prev_elem_src_pad); + if (peer_element) { + found_klass = gst_element_factory_get_klass(gst_element_get_factory(peer_element)); + if (g_strrstr(found_klass, node_klass_type->klass_name) || g_strrstr(GST_ELEMENT_NAME(peer_element), node_klass_type->default_name)) + ms_info(" Found peer element [%s] ", GST_ELEMENT_NAME(peer_element)); + else + peer_element = NULL; + } + } else { - sink_pad_caps = gst_pad_query_caps(sink_pad, 0); - if (gst_caps_get_size(sink_pad_caps) > 0) { - sink_pad_struct = gst_caps_get_structure(sink_pad_caps, 0); - sink_pad_type = gst_structure_get_name(sink_pad_struct); + /* Check if any of previous element`s source pads is connected with element */ + src_pad_iterator = gst_element_iterate_src_pads(previous_element); + while (GST_ITERATOR_OK == gst_iterator_next(src_pad_iterator, &src_pad_value)) { + GstPad *src_pad = (GstPad *) g_value_get_object(&src_pad_value); + peer_element = __ms_pad_get_peer_element(src_pad); + if (peer_element) { + found_klass = gst_element_factory_get_klass(gst_element_get_factory(peer_element)); + if (g_strrstr(found_klass, node_klass_type->klass_name) || g_strrstr(GST_ELEMENT_NAME(peer_element), node_klass_type->default_name)) { + ms_info(" Found peer element [%s] ", GST_ELEMENT_NAME(peer_element)); + break; + } else { + peer_element = NULL; + } + } + g_value_reset(&src_pad_value); + } + g_value_unset(&src_pad_value); + gst_iterator_free(src_pad_iterator); } - if (src_pad_struct && sink_pad_struct) { - src_pad_struct_string = gst_structure_get_string(src_pad_struct, "media"); - sink_pad_struct_string = gst_structure_get_string(sink_pad_struct, "media"); - can_intersect = gst_structure_can_intersect(src_pad_struct, sink_pad_struct); - if (can_intersect || (src_pad_struct_string && (g_strrstr(src_pad_type, sink_pad_struct_string) || - g_strrstr(sink_pad_type, src_pad_struct_string) || g_strrstr(src_pad_struct_string, sink_pad_struct_string))) || - (!src_pad_struct_string && g_strrstr(src_pad_type, sink_pad_type))) - intersect_res = TRUE; - else - intersect_res = FALSE; - } else { - intersect_res = FALSE; - } + if (!peer_element) + ms_info(" Element [%s] is not connected", GST_ELEMENT_NAME(previous_element)); - gst_caps_unref(src_pad_caps); - gst_caps_unref(sink_pad_caps); - return intersect_res; + return peer_element; } -static gboolean __ms_check_unlinked_element(GstElement *previous_elem, - GstPad *prev_elem_src_pad, GstPad *found_elem_sink_pad) +gboolean __ms_link_two_elements(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *found_element) { - gboolean intersect_res = FALSE; - GstIterator *src_pad_iterator = NULL; GValue src_pad_value = G_VALUE_INIT; - gboolean ret = FALSE; - - GstElement *found_element = gst_pad_get_parent_element(found_elem_sink_pad); - ms_retvm_if(!found_element, FALSE, "Fail to get parent element"); + gboolean elements_linked = FALSE; + GstPad * found_sink_pad = NULL; + + if (prev_elem_src_pad) { + if (!gst_pad_is_linked(prev_elem_src_pad)) { + + /* Check compatibility of previous element and unlinked found element */ + found_sink_pad = gst_element_get_compatible_pad(found_element, prev_elem_src_pad, NULL); + if (found_sink_pad) + elements_linked = gst_element_link_pads_filtered(previous_element, GST_PAD_NAME(prev_elem_src_pad), found_element, GST_PAD_NAME(found_sink_pad), NULL); + } else if (__ms_pad_get_peer_element(prev_elem_src_pad) == found_element) { + elements_linked = TRUE; + } + } else { - if (previous_elem) { - /* Previous element is set. */ - if (prev_elem_src_pad) { - /* Previous element`s source pad is set. */ - /* Compare if previous element`s source pad caps are compatible with found element`s */ - intersect_res = __ms_intersect_pads(prev_elem_src_pad, found_elem_sink_pad); - } else { - /* Previous element`s source pad is not set. */ - /* Compare if any of previous element`s source pads caps are compatible with found element`s */ - src_pad_iterator = gst_element_iterate_src_pads(previous_elem); - while (GST_ITERATOR_OK == gst_iterator_next(src_pad_iterator, &src_pad_value)) { - GstPad *src_pad = (GstPad *) g_value_get_object(&src_pad_value); - if (!gst_pad_is_linked(src_pad)) { - intersect_res = __ms_intersect_pads(src_pad, found_elem_sink_pad); - if (intersect_res) + /* Check if previous element has any unlinked src pad */ + GstIterator *src_pad_iterator = gst_element_iterate_src_pads(previous_element); + while (GST_ITERATOR_OK == gst_iterator_next(src_pad_iterator, &src_pad_value)) { + GstPad *src_pad = (GstPad *) g_value_get_object(&src_pad_value); + if (!gst_pad_is_linked(src_pad)) { + + /* Check compatibility of previous element and unlinked found element */ + found_sink_pad = gst_element_get_compatible_pad(found_element, src_pad, NULL); + if (found_sink_pad) { + elements_linked = gst_element_link_pads_filtered(previous_element, GST_PAD_NAME(src_pad), found_element, GST_PAD_NAME(found_sink_pad), NULL); + if (elements_linked) break; } - g_value_reset(&src_pad_value); + } else if (__ms_pad_get_peer_element(src_pad) == found_element) { + elements_linked = TRUE; } - g_value_unset(&src_pad_value); - gst_iterator_free(src_pad_iterator); + g_value_reset(&src_pad_value); } - /* If previous element and found element are compatible, return found element */ - if (intersect_res) { - ret = TRUE; - } else { - ms_info(" Element [%s] and element [%s] have incompatible pads to be linked", GST_ELEMENT_NAME(previous_elem), GST_ELEMENT_NAME(found_element)); - ret = FALSE; - } - } else { - /* Previous element is not set. Nothing to compare with. Choose found element */ - ms_info("Previous element is not set. Next element will be [%s]", GST_ELEMENT_NAME(found_element)); - ret = TRUE; + g_value_unset(&src_pad_value); + gst_iterator_free(src_pad_iterator); } - MS_SAFE_UNREF(found_element); - return ret; -} - -static gboolean __ms_check_peer_element(GstElement *previous_elem, GstPad *prev_elem_src_pad, GstElement *found_element) -{ - gboolean peer_element_found = FALSE; - GstIterator *src_pad_iterator = NULL; - GValue src_pad_value = G_VALUE_INIT; - gboolean ret = FALSE; - - if (previous_elem) { - /* Previous element is set. */ - if (prev_elem_src_pad) { - /* Previous element`s source pad is set. */ - /* Check if found element is connected with previous element */ - peer_element_found = __ms_get_peer_element(prev_elem_src_pad, found_element); - } else { - /* Previous element`s source pad is not set. */ - /* Check if any of previous element`s source pads is connected with found element */ - src_pad_iterator = gst_element_iterate_src_pads(previous_elem); - while (GST_ITERATOR_OK == gst_iterator_next(src_pad_iterator, &src_pad_value)) { - GstPad *src_pad = (GstPad *) g_value_get_object(&src_pad_value); - peer_element_found = __ms_get_peer_element(src_pad, found_element); - if (peer_element_found) - break; - g_value_reset(&src_pad_value); - } - g_value_unset(&src_pad_value); - gst_iterator_free(src_pad_iterator); - } - /* If previous element and found element are already connected, return found element */ - if (peer_element_found) { - ms_info("Elements [%s] and [%s] are already linked to each other!", GST_ELEMENT_NAME(previous_elem), GST_ELEMENT_NAME(found_element)); - ret = TRUE; - } else { - ms_info("Found element [%s] has already been linked with other element", GST_ELEMENT_NAME(found_element)); - ret = FALSE; - } + if (found_sink_pad) { + if (elements_linked) + ms_info("Succeeded to link [%s] -> [%s]", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(found_element)); + else + ms_debug("Failed to link [%s] and [%s]", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(found_element)); } else { - /* Previous element is not set. */ - /* Previous element is not set. Nothing to check the connection with. Choose found element */ - ret = TRUE; + ms_info("Element [%s] has no free pad to be connected with [%s] or linked", GST_ELEMENT_NAME(found_element), GST_ELEMENT_NAME(previous_element)); } - return ret; + + return elements_linked; } -GstElement *__ms_bin_find_element_by_klass(GstElement *sink_bin, GstElement *previous_elem, GstPad *source_pad, const gchar *klass_name, const gchar *bin_name) +static GstElement *__ms_bin_find_element_by_type(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *search_bin, node_info_s *node_klass_type) { GValue element_value = G_VALUE_INIT; GstElement *found_element = NULL; + gboolean elements_linked = FALSE; - GValue sink_pad_value = G_VALUE_INIT; - gboolean element_found = FALSE; - - GstIterator *bin_iterator = gst_bin_iterate_sorted(GST_BIN(sink_bin)); + GstIterator *bin_iterator = gst_bin_iterate_sorted(GST_BIN(search_bin)); while (GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &element_value)) { - found_element = (GstElement *) g_value_get_object(&element_value); const gchar *found_klass = gst_element_factory_get_klass(gst_element_get_factory(found_element)); - ms_retvm_if(!found_element, NULL, "Fail to get element from element value"); /* Check if found element is of appropriate needed plugin class */ - if ((klass_name && g_strrstr(found_klass, klass_name)) && (bin_name == NULL || g_strrstr(GST_ELEMENT_NAME(found_element), bin_name))) { - - /* Check if found element has any unlinked sink pad */ - GstIterator *sink_pad_iterator = gst_element_iterate_sink_pads(found_element); - while (GST_ITERATOR_OK == gst_iterator_next(sink_pad_iterator, &sink_pad_value)) { - GstPad *sink_pad = (GstPad *) g_value_get_object(&sink_pad_value); - - if (!gst_pad_is_linked(sink_pad)) { - /* Check compatibility of previous element and unlinked found element */ - element_found = __ms_check_unlinked_element(previous_elem, source_pad, sink_pad); - if (element_found) - break; - } else { - /* Check if previous element linked to found element */ - element_found = __ms_check_peer_element(previous_elem, source_pad, found_element); - if (element_found) - break; - } - g_value_reset(&sink_pad_value); - } - g_value_unset(&sink_pad_value); - gst_iterator_free(sink_pad_iterator); - - if (element_found && (bin_name == NULL || g_strrstr(GST_ELEMENT_NAME(found_element), bin_name))) + if (g_strrstr(found_klass, node_klass_type->klass_name) || g_strrstr(GST_ELEMENT_NAME(found_element), node_klass_type->default_name)) { + ms_info("Found element by type [%s]", GST_ELEMENT_NAME(found_element)); + if (__ms_link_two_elements(previous_element, prev_elem_src_pad, found_element)) { + elements_linked = TRUE; break; + } } - element_found = FALSE; g_value_reset(&element_value); } g_value_unset(&element_value); gst_iterator_free(bin_iterator); - return element_found ? found_element : NULL; + + return elements_linked ? found_element : NULL; } int __ms_factory_rank_compare(GstPluginFeature * first_feature, GstPluginFeature * second_feature) @@ -491,99 +412,56 @@ GstElement *__ms_create_element_by_registry(GstPad * src_pad, const gchar * klas return next_element; } -GstElement *__ms_link_with_new_element(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *new_element) +GstElement *__ms_combine_next_element(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *bin_to_find_in, media_streamer_node_type_e node_type) { - const gchar *prev_elem_pad_type = NULL; - GValue element_value = G_VALUE_INIT; - - gboolean ret = FALSE; - GstPad *new_elem_sink_pad = NULL; - gchar *sink_pad_name = NULL; - gchar *src_pad_name = NULL; - - if (MS_ELEMENT_IS_RTP(GST_ELEMENT_NAME(new_element))) { - GstPad *prev_elem_sink_pad = gst_element_get_static_pad(previous_element, "sink"); - prev_elem_pad_type = __ms_get_pad_type(prev_elem_sink_pad); - if (MS_ELEMENT_IS_VIDEO(prev_elem_pad_type)) - sink_pad_name = g_strdup(MS_RTP_PAD_VIDEO_IN); - else if (MS_ELEMENT_IS_AUDIO(prev_elem_pad_type)) - sink_pad_name = g_strdup(MS_RTP_PAD_AUDIO_IN); - MS_SAFE_UNREF(prev_elem_sink_pad); - } - - if (prev_elem_src_pad) - src_pad_name = GST_PAD_NAME(prev_elem_src_pad); - GstIterator *pad_iterator = gst_element_iterate_sink_pads(new_element); - while (GST_ITERATOR_OK == gst_iterator_next(pad_iterator, &element_value)) { - new_elem_sink_pad = (GstPad *) g_value_get_object(&element_value); - if (!gst_pad_is_linked(new_elem_sink_pad)) { - ret = gst_element_link_pads_filtered(previous_element, src_pad_name, new_element, sink_pad_name, NULL); - break; - } else { - new_elem_sink_pad = NULL; - } - g_value_reset(&element_value); - } - g_value_unset(&element_value); - gst_iterator_free(pad_iterator); - - if (new_elem_sink_pad) { - if (ret) - ms_info("Succeeded to link [%s] -> [%s]", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(new_element)); - else - ms_debug("Failed to link [%s] and [%s]", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(new_element)); - } else { - ms_info("Element [%s] has no free pad to be connected with [%s]", GST_ELEMENT_NAME(new_element), GST_ELEMENT_NAME(previous_element)); - } - MS_SAFE_GFREE(sink_pad_name); - return new_element; -} - -GstElement *__ms_combine_next_element(GstElement * previous_element, GstPad * prev_elem_src_pad, GstElement * bin_to_find_in, const gchar * next_elem_klass_name, const gchar * next_elem_bin_name, gchar * default_element) -{ - GstElement *found_element = NULL; - if (!previous_element) return NULL; - /* Look for node created by user */ - if (next_elem_klass_name) - found_element = __ms_bin_find_element_by_klass(bin_to_find_in, previous_element, prev_elem_src_pad, next_elem_klass_name, next_elem_bin_name); - - /* Link with found node created by user */ - if (found_element) { - previous_element = __ms_link_with_new_element(previous_element, prev_elem_src_pad, found_element); - } else { - /* Create element by element name */ - if (!found_element && !next_elem_bin_name && default_element) { - found_element = __ms_element_create(default_element, NULL); - - /* Create element by caps of the previous element */ - } else if (!found_element) { - GstPad *src_pad = NULL; - if (!prev_elem_src_pad) - src_pad = gst_element_get_static_pad(previous_element, "src"); - else - src_pad = prev_elem_src_pad; - found_element = __ms_create_element_by_registry(src_pad, next_elem_klass_name); - MS_SAFE_UNREF(src_pad); + GstCaps *prev_caps = NULL; + GstElement *found_element = NULL; + node_info_s *node_klass_type = __ms_node_get_klass_by_its_type(node_type); + + /* - 1 - If previous element is linked - check for peer element */ + found_element = __ms_find_peer_element_by_type(GST_ELEMENT(previous_element), prev_elem_src_pad, node_klass_type); + + /* - 2 - If previous element is not linked - find in bin by type */ + if (!found_element) + found_element = __ms_bin_find_element_by_type(previous_element, prev_elem_src_pad, bin_to_find_in, node_klass_type); + + /* - 3 - If element by type is not found in bin - create element by type */ + if (!found_element) { + + /* Create Node type information for a New element */ + GstPad *src_pad = NULL; + if (prev_elem_src_pad) + prev_caps = gst_pad_query_caps(prev_elem_src_pad, 0); + else { + src_pad = gst_element_get_static_pad(previous_element, "src"); + if (src_pad) + prev_caps = gst_pad_query_caps(src_pad, 0); } + node_plug_s plug_info = {node_klass_type, NULL, prev_caps, NULL}; - /* Add created element */ + /* Create Node by ini or registry */ + found_element = __ms_node_element_create(&plug_info, node_type); if (found_element) { + ms_info("New Element [%s] is created ", GST_ELEMENT_NAME(found_element)); + + /* Add created element */ if (__ms_bin_add_element(bin_to_find_in, found_element, FALSE)) { gst_element_sync_state_with_parent(found_element); - previous_element = __ms_link_with_new_element(previous_element, prev_elem_src_pad, found_element); + __ms_link_two_elements(previous_element, prev_elem_src_pad, found_element); __ms_generate_dots(bin_to_find_in, GST_ELEMENT_NAME(found_element)); } else { ms_error("Element [%s] was not added into [%s] bin", GST_ELEMENT_NAME(found_element), GST_ELEMENT_NAME(bin_to_find_in)); MS_SAFE_UNREF(found_element); found_element = NULL; } - } else { - ms_error("Could not find compatible element to link [%s]", GST_ELEMENT_NAME(previous_element)); - } - } + } else + ms_info("New Element is not created "); + } else + ms_info("Next element is not combined"); + return found_element; } @@ -665,37 +543,38 @@ static void _sink_node_unlock_state(const GValue * item, gpointer user_data) static void __decodebin_nomore_pads_combine(GstPad *src_pad, media_streamer_s *ms_streamer, gboolean is_server_part) { - GstElement *found_element = gst_pad_get_parent_element(src_pad); + GstElement *found_element = NULL; + GstElement *parent_element = gst_pad_get_parent_element(src_pad); const gchar *new_pad_type = __ms_get_pad_type(src_pad); if (MS_ELEMENT_IS_VIDEO(new_pad_type)) { - if (__ms_bin_find_element_by_klass(ms_streamer->topology_bin, NULL, NULL, MEDIA_STREAMER_OVERLAY_KLASS, NULL)) { - found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); - src_pad = NULL; - } + found_element = __ms_bin_find_element_by_type(parent_element, src_pad, ms_streamer->topology_bin, __ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY)); + if (found_element) { + ms_info(" Overlay Element [%s]", GST_ELEMENT_NAME(found_element)); + src_pad = NULL; + } else { + found_element = parent_element; + } if (is_server_part) { - found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, NULL, NULL, DEFAULT_QUEUE); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "video_encoder", NULL); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); + found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_RTP); } else { - found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_VIDEO_CONVERT); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); + found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_QUEUE); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK); } } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) { if (is_server_part) { - found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, NULL, NULL, DEFAULT_QUEUE); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "audio_encoder", NULL); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); + found_element = __ms_combine_next_element(parent_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_RTP); } else { - found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_AUDIO_CONVERT); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); + found_element = __ms_combine_next_element(parent_element, src_pad, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_QUEUE); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK); } } else if (MS_ELEMENT_IS_TEXT(new_pad_type)) { - found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_OVERLAY_KLASS, NULL, DEFAULT_TEXT_OVERLAY); + found_element = __ms_combine_next_element(parent_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY); } else { ms_error("Unsupported pad type [%s]!", new_pad_type); return; @@ -757,37 +636,34 @@ static gboolean __ms_sink_bin_prepare(media_streamer_s * ms_streamer, GstPad * s /* Getting Depayloader */ GstElement *parent_rtp_element = gst_pad_get_parent_element(source_pad); - previous_element = __ms_combine_next_element(parent_rtp_element, source_pad, ms_streamer->topology_bin, MEDIA_STREAMER_DEPAYLOADER_KLASS, NULL, NULL); - GstPad *src_pad = gst_element_get_static_pad(previous_element, "src"); - MS_SAFE_UNREF(parent_rtp_element); - if (MS_ELEMENT_IS_VIDEO(src_pad_type)) { - found_element = __ms_bin_find_element_by_klass(ms_streamer->topology_bin, previous_element, src_pad, MEDIA_STREAMER_BIN_KLASS, "video_decoder"); + previous_element = __ms_combine_next_element(parent_rtp_element, source_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY); + found_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER); + if (!found_element) { if (ms_streamer->ini.use_decodebin) { found_element = __ms_decodebin_create(ms_streamer); - found_element = __ms_link_with_new_element(previous_element, src_pad, found_element); + __ms_link_two_elements(previous_element, NULL, found_element); return TRUE; } else { - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PARSER_KLASS, NULL, NULL); - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_DECODER_KLASS, NULL, NULL); - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_CONVERTER_KLASS, NULL, DEFAULT_VIDEO_CONVERT); - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); + previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER); + previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_QUEUE); + previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK); } } else { - previous_element = __ms_link_with_new_element(previous_element, src_pad, found_element); - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); + __ms_link_two_elements(previous_element, NULL, found_element); + previous_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_QUEUE); + previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK); } } else if (MS_ELEMENT_IS_AUDIO(src_pad_type)) { - previous_element = __ms_combine_next_element(previous_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_DECODER_KLASS, NULL, NULL); - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_QUEUE_KLASS, NULL, DEFAULT_QUEUE); - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_SINK_KLASS, NULL, NULL); + previous_element = __ms_combine_next_element(parent_rtp_element, source_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY); + previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER); + previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_QUEUE); + previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK); } else { ms_info("Unknown media type received from rtp element!"); } + MS_SAFE_UNREF(parent_rtp_element); MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, _sink_node_unlock_state, NULL); return TRUE; @@ -917,7 +793,8 @@ static gboolean __ms_feature_node_filter(GstPluginFeature *feature, gpointer dat static GstElement *__ms_element_create_from_ini(node_plug_s *plug_info, media_streamer_node_type_e type) { const gchar *src_type, *sink_type; - const gchar *format_type = NULL; + const gchar *format_type; + MS_GET_CAPS_TYPE(plug_info->src_caps, src_type); MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type); @@ -925,11 +802,23 @@ static GstElement *__ms_element_create_from_ini(node_plug_s *plug_info, media_st ms_info("Specified node formats types: in[%s] - out[%s]", sink_type, src_type); gchar conf_key[INI_MAX_STRLEN] = {0,}; - if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER || type == MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER) + if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER) { format_type = src_type; - else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER || type == MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER) + if (!format_type) + MS_GET_CAPS_TYPE(gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT), format_type); + } else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER) { + format_type = src_type; + if (!format_type) + MS_GET_CAPS_TYPE(gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT), format_type); + } else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER) { format_type = sink_type; - else + if (!format_type) + MS_GET_CAPS_TYPE(gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT), format_type); + } else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER) { + format_type = sink_type; + if (!format_type) + MS_GET_CAPS_TYPE(gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT), format_type); + } else format_type = sink_type ? sink_type : src_type; if (snprintf(conf_key, INI_MAX_STRLEN, "node type %d:%s", type, format_type) >= INI_MAX_STRLEN) { @@ -955,15 +844,15 @@ static GstElement *__ms_element_create_by_registry(node_plug_s *plug_info, media __ms_ini_read_list("general:exclude elements", &plug_info->exclude_names); GList *factories = gst_registry_feature_filter(gst_registry_get(), - __ms_feature_node_filter, FALSE, plug_info); - factories = g_list_sort(factories,(GCompareFunc) __ms_factory_rank_compare); + __ms_feature_node_filter, FALSE, plug_info); + factories = g_list_sort(factories, (GCompareFunc) __ms_factory_rank_compare); if (factories) { GstElementFactory *factory = GST_ELEMENT_FACTORY(factories->data); gst_element = __ms_element_create(GST_OBJECT_NAME(factory), NULL); } else { - ms_error("Error: could not found any compatible element for node [%d]: in[%s] - out[%s]", - type, sink_type, src_type); + ms_debug("Could not find any compatible element for node [%d]: in[%s] - out[%s]", + type, sink_type, src_type); } g_strfreev(plug_info->exclude_names); @@ -981,22 +870,20 @@ GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type); /* 1. Main priority: - * If Node klass defined as MEDIA_STREAMER_STRICT, - * element will be created immediately by default_name */ - if (!strncmp(plug_info->info->klass_name, MEDIA_STREAMER_STRICT, 10) - || ( !src_type && !sink_type)) { - - if(type == MEDIA_STREAMER_NODE_TYPE_RTP) - gst_element = __ms_rtp_element_create(); - else - gst_element = __ms_element_create(plug_info->info->default_name, NULL); - } else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER) + * If Node klass defined as MEDIA_STREAMER_STRICT or ENCODER/DECODER types, + * element will be created immediately by format ot name */ + if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER) gst_element = __ms_audio_encoder_element_create(plug_info, type); else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER) gst_element = __ms_video_encoder_element_create(plug_info, type); else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER) gst_element = __ms_video_decoder_element_create(plug_info, type); - else { + else if (g_strrstr(MEDIA_STREAMER_STRICT, plug_info->info->klass_name) || (!src_type && !sink_type)) { + if (type == MEDIA_STREAMER_NODE_TYPE_RTP) + gst_element = __ms_rtp_element_create(); + else + gst_element = __ms_element_create(plug_info->info->default_name, NULL); + } else { /* 2. Second priority: * Try to get plugin name that defined in ini file @@ -1008,7 +895,7 @@ GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node * If previous cases did not create a valid gst_element, * try to find compatible plugin in gstreamer registry. * Elements that are compatible but defined as excluded will be skipped*/ - if(!gst_element) { + if (!gst_element) { /* Read exclude elements list */ gst_element = __ms_element_create_by_registry(plug_info, type); } @@ -1018,25 +905,39 @@ GstElement *__ms_node_element_create(node_plug_s *plug_info, media_streamer_node GstElement *__ms_video_encoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type) { - const gchar *src_type; - MS_GET_CAPS_TYPE(plug_info->src_caps, src_type); + GstCaps *enc_caps = plug_info->src_caps; + if (!enc_caps) { + enc_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT); + ms_debug("No Video encoding format is set! Deafault will be: [%s]", MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT); + } + /* Creating Scaler, Converter */ GstElement *video_scale = __ms_element_create(DEFAULT_VIDEO_SCALE, NULL); GstElement *video_convert = __ms_element_create(DEFAULT_VIDEO_CONVERT, NULL); - GstElement *encoder_elem = __ms_element_create_from_ini(plug_info, type); - media_format_mimetype_e encoder_type = __ms_convert_string_format_to_media_format(src_type); - - node_info_s nodes_info = {MEDIA_STREAMER_PARSER_KLASS, DEFAULT_VIDEO_PARSER}; - node_plug_s plug_info_parser = { &nodes_info, plug_info->src_caps, NULL, NULL}; - GstElement *encoder_parser = __ms_element_create_from_ini(plug_info, MEDIA_STREAMER_NODE_TYPE_PARSER); + /* Creating Video Encoder */ + node_info_s *node_klass_type = __ms_node_get_klass_by_its_type(type); + node_plug_s encoder_info = {node_klass_type, enc_caps, plug_info->sink_caps, NULL}; + GstElement *encoder_elem = __ms_element_create_from_ini(&encoder_info, type); + if (!encoder_elem) + encoder_elem = __ms_element_create_by_registry(&encoder_info, type); + + /* Creating Video Parser */ + node_info_s node_info = {MEDIA_STREAMER_PARSER_KLASS, DEFAULT_VIDEO_PARSER}; + node_plug_s parser_info = {&node_info, enc_caps, enc_caps, NULL}; + GstElement *encoder_parser = __ms_element_create_from_ini(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER); if (!encoder_parser) - encoder_parser = __ms_element_create_by_registry(&plug_info_parser, MEDIA_STREAMER_NODE_TYPE_PARSER); + encoder_parser = __ms_element_create_by_registry(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER); + /* Creating bin - Video Encoder */ gboolean gst_ret = FALSE; GstElement *encoder_bin = gst_bin_new("video_encoder"); ms_retvm_if(!video_convert || !video_scale || !encoder_elem || !encoder_bin || !encoder_parser, (GstElement *) NULL, "Error: creating elements for video encoder bin"); + /* Settings if H264 format is set*/ + const gchar *src_type; + MS_GET_CAPS_TYPE(enc_caps, src_type); + media_format_mimetype_e encoder_type = __ms_convert_string_format_to_media_format(src_type); if (encoder_type == MEDIA_FORMAT_H264_SP) { g_object_set(GST_OBJECT(encoder_parser), "config-interval", H264_PARSER_CONFIG_INTERVAL, NULL); g_object_set(G_OBJECT(encoder_elem), "tune", H264_ENCODER_ZEROLATENCY, NULL); @@ -1045,6 +946,7 @@ GstElement *__ms_video_encoder_element_create(node_plug_s *plug_info, media_stre g_object_set(G_OBJECT(encoder_elem), "threads", 2, NULL); } + /* Adding elements to bin Video Encoder */ gst_bin_add_many(GST_BIN(encoder_bin), video_convert, video_scale, encoder_elem, encoder_parser, NULL); gst_ret = gst_element_link_many(video_convert, video_scale, encoder_elem, encoder_parser, NULL); if (gst_ret != TRUE) { @@ -1060,35 +962,46 @@ GstElement *__ms_video_encoder_element_create(node_plug_s *plug_info, media_stre GstElement *__ms_video_decoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type) { + GstCaps *dec_caps = plug_info->sink_caps; + if (!dec_caps) { + dec_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT); + ms_debug("No Video decoding format is set! Deafault will be: [%s]", MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT); + } + gboolean is_hw_codec = FALSE; GstElement *last_elem = NULL; - const gchar *sink_type; - MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type); - - GstElement *decoder_elem = __ms_element_create_from_ini(plug_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER); - media_format_mimetype_e encoder_type = __ms_convert_string_format_to_media_format(sink_type); + /* Creating Video Decoder */ + node_info_s *node_klass_type = __ms_node_get_klass_by_its_type(type); + node_plug_s decoder_info = {node_klass_type, plug_info->src_caps, dec_caps, NULL}; + GstElement *decoder_elem = __ms_element_create_from_ini(&decoder_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER); + if (!decoder_elem) + decoder_elem = __ms_element_create_by_registry(&decoder_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER); + /* Creating Video Parser */ node_info_s nodes_info = {MEDIA_STREAMER_PARSER_KLASS, DEFAULT_VIDEO_PARSER}; - node_plug_s plug_info_parser = { &nodes_info, plug_info->sink_caps, NULL, NULL}; - - GstElement *decoder_parser = __ms_element_create_from_ini(plug_info, MEDIA_STREAMER_NODE_TYPE_PARSER); + node_plug_s parser_info = {&nodes_info, dec_caps, dec_caps, NULL}; + GstElement *decoder_parser = __ms_element_create_from_ini(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER); if (!decoder_parser) - decoder_parser = __ms_element_create_by_registry(&plug_info_parser, MEDIA_STREAMER_NODE_TYPE_PARSER); + decoder_parser = __ms_element_create_by_registry(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER); - - if (encoder_type == MEDIA_FORMAT_H264_SP) + /* Settings if H264 format is set*/ + const gchar *sink_type; + MS_GET_CAPS_TYPE(dec_caps, sink_type); + media_format_mimetype_e decoder_type = __ms_convert_string_format_to_media_format(sink_type); + if (decoder_type == MEDIA_FORMAT_H264_SP) g_object_set(G_OBJECT(decoder_parser), "config-interval", H264_PARSER_CONFIG_INTERVAL, NULL); if (g_strrstr(plug_info->info->default_name, "omx") || g_strrstr(plug_info->info->default_name, "sprd")) is_hw_codec = TRUE; - + /* Creating bin - Video Decoder */ gboolean gst_ret = FALSE; GstElement *decoder_bin = gst_bin_new("video_decoder"); GstElement *decoder_queue = __ms_element_create("queue", NULL); ms_retvm_if(!decoder_elem || !decoder_queue || !decoder_bin || !decoder_parser, (GstElement *) NULL, "Error: creating elements for video decoder bin"); + /* Adding elements to bin Audio Encoder */ gst_bin_add_many(GST_BIN(decoder_bin), decoder_queue, decoder_elem, decoder_parser, NULL); gst_ret = gst_element_link_many(decoder_queue, decoder_parser, decoder_elem, NULL); if (gst_ret != TRUE) { @@ -1120,23 +1033,36 @@ GstElement *__ms_video_decoder_element_create(node_plug_s *plug_info, media_stre GstElement *__ms_audio_encoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type) { + GstCaps *enc_caps = plug_info->src_caps; + if (!enc_caps) { + enc_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT); + ms_debug("No Audio encoding format is set! Deafault will be: [%s]", MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT); + } + gboolean gst_ret = FALSE; + /* Creating Converter, Resampler, Filter */ GstElement *audio_convert = __ms_element_create(DEFAULT_AUDIO_CONVERT, NULL); GstElement *audio_resample = __ms_element_create(DEFAULT_AUDIO_RESAMPLE, NULL); GstElement *audio_filter = __ms_element_create(DEFAULT_FILTER, NULL); GstElement *audio_postenc_convert = __ms_element_create(DEFAULT_AUDIO_CONVERT, NULL); - GstElement *audio_encoder = __ms_element_create_from_ini(plug_info, type); + + /* Creating Audio Encoder */ + node_info_s *node_klass_type = __ms_node_get_klass_by_its_type(type); + node_plug_s plug_info_encoder = {node_klass_type, enc_caps, plug_info->sink_caps, NULL}; + GstElement *audio_encoder = __ms_element_create_from_ini(&plug_info_encoder, type); if (!audio_encoder) - audio_encoder = __ms_element_create_by_registry(plug_info, type); + audio_encoder = __ms_element_create_by_registry(&plug_info_encoder, type); + /* Creating bin - Audio Encoder */ GstElement *audio_enc_bin = gst_bin_new("audio_encoder"); ms_retvm_if(!audio_convert || !audio_postenc_convert || !audio_filter || !audio_encoder || !audio_enc_bin, (GstElement *) NULL, "Error: creating elements for encoder bin"); - GstCaps *audioCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT); + GstCaps *audioCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_RAW_FORMAT); g_object_set(G_OBJECT(audio_filter), "caps", audioCaps, NULL); gst_caps_unref(audioCaps); + /* Adding elements to bin Audio Encoder */ gst_bin_add_many(GST_BIN(audio_enc_bin), audio_convert, audio_postenc_convert, audio_filter, audio_resample, audio_encoder, NULL); gst_ret = gst_element_link_many(audio_convert, audio_resample, audio_filter, audio_postenc_convert, audio_encoder, NULL); if (gst_ret != TRUE) { @@ -1236,11 +1162,17 @@ gboolean __ms_rtp_element_prepare(media_streamer_node_s *ms_node) rtcp_el = __ms_element_create("udpsink", MS_RTP_PAD_VIDEO_OUT"_rctp"); __ms_bin_add_element(ms_node->gst_element, rtcp_el, FALSE); - GstPad *rtp_sink = gst_element_get_request_pad(rtpbin, "send_rtp_sink_0"); - GstPad *ghost_sink = gst_element_get_static_pad(ms_node->gst_element, MS_RTP_PAD_VIDEO_IN); - gst_ghost_pad_set_target(GST_GHOST_PAD(ghost_sink), rtp_sink); - MS_SAFE_UNREF(rtp_sink); - MS_SAFE_UNREF(ghost_sink); + GstElement *video_filter = __ms_element_create("capsfilter", NULL); + __ms_bin_add_element(ms_node->gst_element, video_filter, FALSE); + GstCaps *video_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_RTP_FORMAT); + g_object_set(G_OBJECT(video_filter), "caps", video_caps, NULL); + gst_element_link_pads(video_filter, "src", rtpbin, "send_rtp_sink_0"); + + GstGhostPad *ghost_pad = (GstGhostPad *)gst_element_get_static_pad(ms_node->gst_element, MS_RTP_PAD_VIDEO_IN); + if (ghost_pad) { + if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(video_filter, "sink"))) + ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_RTP_PAD_VIDEO_IN); + } ret = ret && gst_element_link_pads(rtpbin, "send_rtp_src_0", rtp_el, "sink"); ret = ret && gst_element_link_pads(rtpbin, "send_rtcp_src_0", rtcp_el, "sink"); @@ -1260,11 +1192,19 @@ gboolean __ms_rtp_element_prepare(media_streamer_node_s *ms_node) rtcp_el = __ms_element_create("udpsink", MS_RTP_PAD_AUDIO_OUT"_rctp"); __ms_bin_add_element(ms_node->gst_element, rtcp_el, FALSE); - GstPad *rtp_sink = gst_element_get_request_pad(rtpbin, "send_rtp_sink_1"); - GstPad *ghost_sink = gst_element_get_static_pad(ms_node->gst_element, MS_RTP_PAD_AUDIO_IN); - gst_ghost_pad_set_target(GST_GHOST_PAD(ghost_sink), rtp_sink); - MS_SAFE_UNREF(rtp_sink); - MS_SAFE_UNREF(ghost_sink); + GstElement *audio_filter = __ms_element_create("capsfilter", NULL); + __ms_bin_add_element(ms_node->gst_element, audio_filter, FALSE); + GstCaps *audio_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_RTP_FORMAT); + g_object_set(G_OBJECT(audio_filter), "caps", audio_caps, NULL); + gst_element_link_pads(audio_filter, "src", rtpbin, "send_rtp_sink_1"); + + GstGhostPad *ghost_pad = (GstGhostPad *)gst_element_get_static_pad(ms_node->gst_element, MS_RTP_PAD_AUDIO_IN); + if (ghost_pad) { + if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(audio_filter, "sink"))) + ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_RTP_PAD_AUDIO_IN); + } + + ret = ret && gst_element_link_pads(rtpbin, "send_rtp_src_1", rtp_el, "sink"); ret = ret && gst_element_link_pads(rtpbin, "send_rtcp_src_1", rtcp_el, "sink"); diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c index 8cb7818..3525748 100755 --- a/src/media_streamer_node.c +++ b/src/media_streamer_node.c @@ -47,34 +47,35 @@ param_s param_table[] = { }; node_info_s nodes_info[] = { - {NULL, NULL}, /* MEDIA_STREAMER_NODE_TYPE_NONE */ - {"Source", "fakesrc"}, /* MEDIA_STREAMER_NODE_TYPE_SRC */ - {"Sink", "fakesink"}, /* MEDIA_STREAMER_NODE_TYPE_SINK */ - {"Codec/Encoder", "x264enc"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER */ - {"Codec/Decoder", "avdec_h264"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER */ - {"Codec/Encoder", "amrnbenc"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER */ - {"Codec/Decoder", "amrnbdec"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER */ - {MEDIA_STREAMER_STRICT, "videoconvert"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER */ - {MEDIA_STREAMER_STRICT, "audioconvert"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER */ - {MEDIA_STREAMER_STRICT, "audioresample"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE */ - {"Payloader/Network", "rtph264pay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY */ - {"Payloader/Network", "rtpamrpay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY */ - {"Depayloader/Network", "rtph264depay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY */ - {"Depayloader/Network", "rtpamrdepay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY */ - {"Filter/Effect/Video", "videorate"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_RATE */ - {"Scaler", "videoscale"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_SCALE */ - {"Parser", "h264parse"}, /* MEDIA_STREAMER_NODE_TYPE_PARSER */ - {MEDIA_STREAMER_STRICT, "capsfilter"}, /* MEDIA_STREAMER_NODE_TYPE_FILTER */ - {MEDIA_STREAMER_STRICT, "tee"}, /* MEDIA_STREAMER_NODE_TYPE_TEE */ - {MEDIA_STREAMER_STRICT, "queue"}, /* MEDIA_STREAMER_NODE_TYPE_QUEUE */ - {MEDIA_STREAMER_STRICT, "multiqueue"}, /* MEDIA_STREAMER_NODE_TYPE_MQUEUE */ - {"Codec/Muxer", "qtmux"}, /* MEDIA_STREAMER_NODE_TYPE_MUXER */ - {"Codec/Demuxer", "qtdemux"}, /* MEDIA_STREAMER_NODE_TYPE_DEMUXER */ - {MEDIA_STREAMER_STRICT, "rtpbin"}, /* MEDIA_STREAMER_NODE_TYPE_RTP */ - {MEDIA_STREAMER_STRICT, "input-selector"}, /* MEDIA_STREAMER_NODE_TYPE_INPUT_SELECTOR */ - {MEDIA_STREAMER_STRICT, "output-selector"},/* MEDIA_STREAMER_NODE_TYPE_OUTPUT_SELECTOR */ - {MEDIA_STREAMER_STRICT, "interleave"}, /* MEDIA_STREAMER_NODE_TYPE_INTERLEAVE */ - {MEDIA_STREAMER_STRICT, "deinterleave"}, /* MEDIA_STREAMER_NODE_TYPE_DEINTERLEAVE */ + {"Generic", "none"}, /* MEDIA_STREAMER_NODE_TYPE_NONE */ + {"Source", "fakesrc"}, /* MEDIA_STREAMER_NODE_TYPE_SRC */ + {"Sink", "fakesink"}, /* MEDIA_STREAMER_NODE_TYPE_SINK */ + {"Codec/Encoder/Video", "video_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER */ + {"Codec/Decoder/Video", "video_decoder"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER */ + {"Codec/Encoder/Audio", "audio_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER */ + {"Codec/Decoder/Audio", "audio_decoder"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER */ + {"Filter/Converter/Video", "videoconvert"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER */ + {"Filter/Converter/Audio", "audioconvert"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER */ + {MEDIA_STREAMER_STRICT, "audioresample"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE */ + {"Codec/Payloader/Network/RTP", "rtph264pay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY */ + {"Codec/Payloader/Network/RTP", "rtpamrpay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY */ + {"Codec/Depayloader/Network/RTP", "rtph264depay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY */ + {"Codec/Depayloader/Network/RTP", "rtpamrdepay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY */ + {"Filter/Effect/Video", "videorate"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_RATE */ + {"Filter/Converter/Video/Scaler", "videoscale"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_SCALE */ + {MEDIA_STREAMER_STRICT, "textoverlay"}, /* MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY */ + {"Codec/Parser/Converter/Video", "h264parse"}, /* MEDIA_STREAMER_NODE_TYPE_PARSER */ + {MEDIA_STREAMER_STRICT, "capsfilter"}, /* MEDIA_STREAMER_NODE_TYPE_FILTER */ + {MEDIA_STREAMER_STRICT, "tee"}, /* MEDIA_STREAMER_NODE_TYPE_TEE */ + {MEDIA_STREAMER_STRICT, "queue"}, /* MEDIA_STREAMER_NODE_TYPE_QUEUE */ + {MEDIA_STREAMER_STRICT, "multiqueue"}, /* MEDIA_STREAMER_NODE_TYPE_MQUEUE */ + {"Codec/Muxer", "qtmux"}, /* MEDIA_STREAMER_NODE_TYPE_MUXER */ + {"Codec/Demuxer", "qtdemux"}, /* MEDIA_STREAMER_NODE_TYPE_DEMUXER */ + {"Generic/Bin", "rtpbin"}, /* MEDIA_STREAMER_NODE_TYPE_RTP */ + {MEDIA_STREAMER_STRICT, "input-selector"}, /* MEDIA_STREAMER_NODE_TYPE_INPUT_SELECTOR */ + {MEDIA_STREAMER_STRICT, "output-selector"}, /* MEDIA_STREAMER_NODE_TYPE_OUTPUT_SELECTOR */ + {MEDIA_STREAMER_STRICT, "interleave"}, /* MEDIA_STREAMER_NODE_TYPE_INTERLEAVE */ + {MEDIA_STREAMER_STRICT, "deinterleave"}, /* MEDIA_STREAMER_NODE_TYPE_DEINTERLEAVE */ {NULL, NULL} }; @@ -436,6 +437,19 @@ static void _sink_node_lock_state(const GValue *item, gpointer user_data) } } +node_info_s * __ms_node_get_klass_by_its_type(media_streamer_node_type_e element_type) +{ + int it_klass; + for (it_klass = 0; nodes_info[it_klass].klass_name != NULL; it_klass++) { + if (it_klass == element_type) { + ms_info(" Node`s type klass is [%s]", nodes_info[it_klass].klass_name); + break; + } + } + + return &nodes_info[it_klass]; +} + static void _src_node_prepare(const GValue *item, gpointer user_data) { media_streamer_s *ms_streamer = (media_streamer_s *) user_data; @@ -453,7 +467,7 @@ static void _src_node_prepare(const GValue *item, gpointer user_data) if (__ms_src_need_typefind(src_pad)) { found_element = __ms_decodebin_create(ms_streamer); - found_element = __ms_link_with_new_element(src_element, src_pad, found_element); + __ms_link_two_elements(src_element, src_pad, found_element); } else { /* Check the source element`s pad type */ const gchar *new_pad_type = __ms_get_pad_type(src_pad); @@ -462,21 +476,20 @@ static void _src_node_prepare(const GValue *item, gpointer user_data) MS_SAFE_UNREF(src_pad); return; } - if (MS_ELEMENT_IS_VIDEO(new_pad_type) || MS_ELEMENT_IS_IMAGE(new_pad_type)) { - found_element = __ms_combine_next_element(src_element, src_pad, ms_streamer->topology_bin, NULL, NULL, DEFAULT_FILTER); + found_element = __ms_combine_next_element(src_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_FILTER); GstCaps *videoCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT); g_object_set(G_OBJECT(found_element), "caps", videoCaps, NULL); gst_caps_unref(videoCaps); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "video_encoder", NULL); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); - } + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_RTP); + } if (MS_ELEMENT_IS_AUDIO(new_pad_type)) { - found_element = __ms_combine_next_element(src_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "audio_encoder", NULL); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL); + found_element = __ms_combine_next_element(src_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY); + found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_RTP); } __ms_generate_dots(ms_streamer->pipeline, "after_connecting_rtp"); } @@ -800,14 +813,14 @@ int __ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, gchar *rtp_caps_str = NULL; /* It is needed to set 'application/x-rtp' for audio and video udpsrc */ - if (!strcmp(pad_name, MS_RTP_PAD_VIDEO_IN"_rtp")) { + if (g_strrstr(pad_name, MS_RTP_PAD_VIDEO_IN)) { ret = media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL); if (MEDIA_FORMAT_ERROR_NONE == ret) { rtp_caps_str = g_strdup_printf("application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=%s", __ms_convert_mime_to_rtp_format(mime)); param_s param = {MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT, MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT}; ret = __ms_node_set_param_value(node, ¶m, rtp_caps_str); } - } else if (!strcmp(pad_name, MS_RTP_PAD_AUDIO_IN"_rtp")) { + } else if (g_strrstr(pad_name, MS_RTP_PAD_AUDIO_IN)) { int audio_channels, audio_samplerate; ret = media_format_get_audio_info(fmt, &mime, &audio_channels, &audio_samplerate, NULL, NULL); if (MEDIA_FORMAT_ERROR_NONE == ret) { diff --git a/src/media_streamer_util.c b/src/media_streamer_util.c index b713c05..8f9a11f 100644 --- a/src/media_streamer_util.c +++ b/src/media_streamer_util.c @@ -196,27 +196,6 @@ const gchar *__ms_convert_mime_to_string_format(media_format_mimetype_e mime) return format_name; } -const gchar *__ms_convert_mime_to_string(media_format_mimetype_e mime) -{ - switch (mime) { - case MEDIA_FORMAT_I420: - return "I420"; - case MEDIA_FORMAT_YV12: - return "YV12"; - case MEDIA_FORMAT_H263: - return "h263"; - case MEDIA_FORMAT_H264_HP: - case MEDIA_FORMAT_H264_MP: - case MEDIA_FORMAT_H264_SP: - return "h264"; - case MEDIA_FORMAT_PCM: - return DEFAULT_AUDIO; - default: - ms_error("Invalid or Unsupported media format [%d].", mime); - return NULL; - } -} - const gchar *__ms_convert_mime_to_rtp_format(media_format_mimetype_e mime) { switch (mime) { @@ -239,7 +218,7 @@ const gchar *__ms_convert_mime_to_rtp_format(media_format_mimetype_e mime) media_format_mimetype_e __ms_convert_string_format_to_media_format(const char *format_type) { - media_format_mimetype_e mime = 0; + media_format_mimetype_e mime = MEDIA_FORMAT_NATIVE_VIDEO; int it_format; for (it_format = 0; format_table[it_format].format != MEDIA_FORMAT_MAX; it_format++) { if (g_strrstr(format_type, format_table[it_format].format_name)) { diff --git a/test/media_streamer_test.c b/test/media_streamer_test.c index b096954..ffbc6c4 100644 --- a/test/media_streamer_test.c +++ b/test/media_streamer_test.c @@ -84,6 +84,13 @@ typedef enum { #define VIDEO_PORT 5000 #define AUDIO_PORT 6000 +#define VIDEO_WIDTH 352 +#define VIDEO_HIGHT 288 +#define VIDEO_AVG_BPS 1 +#define VIDEO_MAX_BPS 3 +#define AUDIO_CHANNEL 1 +#define AUDIO_SAMPLERATE 8000 + /*--------------------------------------------------------------------------- | GLOBAL VARIABLE DEFINITIONS: | ---------------------------------------------------------------------------*/ @@ -268,36 +275,36 @@ static void create_formats(void) if (media_format_set_video_mime(vfmt_raw, MEDIA_FORMAT_I420) != MEDIA_FORMAT_ERROR_NONE) g_print("media_format_set_video_mime failed!"); - media_format_set_video_width(vfmt_raw, 800); - media_format_set_video_height(vfmt_raw, 600); - media_format_set_video_avg_bps(vfmt_raw, 10000); - media_format_set_video_max_bps(vfmt_raw, 30000); + media_format_set_video_width(vfmt_raw, VIDEO_WIDTH); + media_format_set_video_height(vfmt_raw, VIDEO_HIGHT); + media_format_set_video_avg_bps(vfmt_raw, VIDEO_AVG_BPS); + media_format_set_video_max_bps(vfmt_raw, VIDEO_MAX_BPS); /* Define encoded video format */ media_format_create(&vfmt_encoded); if (media_format_set_video_mime(vfmt_encoded, MEDIA_FORMAT_H263) != MEDIA_FORMAT_ERROR_NONE) g_print("media_format_set_video_mime failed!"); - media_format_set_video_width(vfmt_encoded, 800); - media_format_set_video_height(vfmt_encoded, 600); - media_format_set_video_avg_bps(vfmt_encoded, 10000); - media_format_set_video_max_bps(vfmt_encoded, 30000); + media_format_set_video_width(vfmt_encoded, VIDEO_WIDTH); + media_format_set_video_height(vfmt_encoded, VIDEO_HIGHT); + media_format_set_video_avg_bps(vfmt_encoded, VIDEO_AVG_BPS); + media_format_set_video_max_bps(vfmt_encoded, VIDEO_MAX_BPS); /* Define audio raw format */ media_format_create(&afmt_raw); if (media_format_set_audio_mime(afmt_raw, MEDIA_FORMAT_PCM) != MEDIA_FORMAT_ERROR_NONE) g_print("media_format_set_audio_mime failed!"); - media_format_set_audio_channel(afmt_raw, 1); - media_format_set_audio_samplerate(afmt_raw, 8000); + media_format_set_audio_channel(afmt_raw, AUDIO_CHANNEL); + media_format_set_audio_samplerate(afmt_raw, AUDIO_SAMPLERATE); /* Define audio encoded format */ media_format_create(&afmt_encoded); if (media_format_set_audio_mime(afmt_encoded, MEDIA_FORMAT_AMR_NB) != MEDIA_FORMAT_ERROR_NONE) g_print("media_format_set_audio_mime failed!"); - media_format_set_audio_channel(afmt_encoded, 1); - media_format_set_audio_samplerate(afmt_encoded, 8000); + media_format_set_audio_channel(afmt_encoded, AUDIO_CHANNEL); + media_format_set_audio_samplerate(afmt_encoded, AUDIO_SAMPLERATE); } static void set_rtp_params(media_streamer_node_h rtp_node, const char *ip, int video_port, int audio_port, gboolean port_reverse) @@ -335,8 +342,8 @@ static void set_rtp_params(media_streamer_node_h rtp_node, const char *ip, int v bundle_add_str(params, MEDIA_STREAMER_PARAM_HOST, ip); media_streamer_node_set_params(rtp_node, params); - media_streamer_node_set_pad_format(rtp_node, "video_in_rtp", vfmt_encoded); - media_streamer_node_set_pad_format(rtp_node, "audio_in_rtp", afmt_raw); + media_streamer_node_set_pad_format(rtp_node, "video_in", vfmt_encoded); + media_streamer_node_set_pad_format(rtp_node, "audio_in", afmt_encoded); bundle_free(params); } -- 2.7.4 From 09fff555ca8ddb01e5b19f6cb903b5cfe5c217b5 Mon Sep 17 00:00:00 2001 From: Volodymyr Brynza Date: Thu, 9 Jun 2016 11:58:04 +0300 Subject: [PATCH 16/16] Modified mediastreamer prepare() functionality Change-Id: I94d6ef4c7a309d1f9447038d0e031b71818ff988 Signed-off-by: Volodymyr Brynza --- include/media_streamer_gst.h | 14 ++++++ src/media_streamer.c | 5 ++- src/media_streamer_gst.c | 102 ++++++++++++++++++++++++++++--------------- src/media_streamer_node.c | 31 ++++--------- src/media_streamer_priv.c | 7 ++- test/media_streamer_test.c | 18 +------- 6 files changed, 100 insertions(+), 77 deletions(-) diff --git a/include/media_streamer_gst.h b/include/media_streamer_gst.h index 8428e1c..671f8da 100644 --- a/include/media_streamer_gst.h +++ b/include/media_streamer_gst.h @@ -164,6 +164,20 @@ GstElement *__ms_decodebin_create(media_streamer_s *ms_streamer); GstElement *__ms_combine_next_element(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *bin_to_find_in, media_streamer_node_type_e node_type); /** + * @brief Locks gst_element being contained in GValue data. + * + * @since_tizen 3.0 + */ +void __ms_element_lock_state(const GValue *item, gpointer user_data); + +/** + * @brief Unlocks gst_element being contained in GValue data. + * + * @since_tizen 3.0 + */ +void __ms_element_unlock_state(const GValue *item, gpointer user_data); + +/** * @brief Creates pipeline, bus and src/sink/topology bins. * * @since_tizen 3.0 diff --git a/src/media_streamer.c b/src/media_streamer.c index ce28edc..1016f9d 100644 --- a/src/media_streamer.c +++ b/src/media_streamer.c @@ -190,8 +190,11 @@ int media_streamer_prepare(media_streamer_h streamer) ret = __ms_pipeline_prepare(ms_streamer); - if (ret == MEDIA_STREAMER_ERROR_NONE) + if (ret == MEDIA_STREAMER_ERROR_NONE) { ret = __ms_state_change(ms_streamer, MEDIA_STREAMER_STATE_READY); + if (ret != MEDIA_STREAMER_ERROR_NONE) + __ms_pipeline_unprepare(ms_streamer); + } __ms_generate_dots(ms_streamer->pipeline, "after_prepare"); diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index 46cddcc..f83e993 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -530,17 +530,6 @@ static void __decodebin_newpad_cb(GstElement * decodebin, GstPad * new_pad, gpoi g_mutex_unlock(&ms_streamer->mutex_lock); } -static void _sink_node_unlock_state(const GValue * item, gpointer user_data) -{ - GstElement *sink_element = GST_ELEMENT(g_value_get_object(item)); - ms_retm_if(!sink_element, "Handle is NULL"); - - if (gst_element_is_locked_state(sink_element)) { - gst_element_set_locked_state(sink_element, FALSE); - gst_element_sync_state_with_parent(sink_element); - } -} - static void __decodebin_nomore_pads_combine(GstPad *src_pad, media_streamer_s *ms_streamer, gboolean is_server_part) { GstElement *found_element = NULL; @@ -548,20 +537,19 @@ static void __decodebin_nomore_pads_combine(GstPad *src_pad, media_streamer_s *m const gchar *new_pad_type = __ms_get_pad_type(src_pad); if (MS_ELEMENT_IS_VIDEO(new_pad_type)) { - found_element = __ms_bin_find_element_by_type(parent_element, src_pad, ms_streamer->topology_bin, __ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY)); - if (found_element) { - ms_info(" Overlay Element [%s]", GST_ELEMENT_NAME(found_element)); - src_pad = NULL; - } else { - found_element = parent_element; - } + found_element = __ms_bin_find_element_by_type(parent_element, src_pad, ms_streamer->topology_bin, __ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY)); + if (found_element) { + ms_info(" Overlay Element [%s]", GST_ELEMENT_NAME(found_element)); + src_pad = NULL; + } else { + found_element = parent_element; + } if (is_server_part) { found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_RTP); } else { found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_QUEUE); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK); } } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) { @@ -570,8 +558,7 @@ static void __decodebin_nomore_pads_combine(GstPad *src_pad, media_streamer_s *m found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY); found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_RTP); } else { - found_element = __ms_combine_next_element(parent_element, src_pad, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_QUEUE); - found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK); + found_element = __ms_combine_next_element(parent_element, src_pad, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK); } } else if (MS_ELEMENT_IS_TEXT(new_pad_type)) { found_element = __ms_combine_next_element(parent_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY); @@ -582,7 +569,7 @@ static void __decodebin_nomore_pads_combine(GstPad *src_pad, media_streamer_s *m __ms_generate_dots(ms_streamer->pipeline, "after_sink_linked"); } -static void __decodebin_nomore_pads_cb(GstElement * decodebin, gpointer user_data) +static void __decodebin_nomore_pads_cb(GstElement *decodebin, gpointer user_data) { media_streamer_s *ms_streamer = (media_streamer_s *) user_data; ms_retm_if(ms_streamer == NULL, "Handle is NULL"); @@ -609,7 +596,6 @@ static void __decodebin_nomore_pads_cb(GstElement * decodebin, gpointer user_dat __decodebin_nomore_pads_combine(src_pad, ms_streamer, is_server_part); } - MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, _sink_node_unlock_state, NULL); g_mutex_unlock(&ms_streamer->mutex_lock); } @@ -647,24 +633,20 @@ static gboolean __ms_sink_bin_prepare(media_streamer_s * ms_streamer, GstPad * s return TRUE; } else { previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER); - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_QUEUE); previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK); } } else { __ms_link_two_elements(previous_element, NULL, found_element); - previous_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_QUEUE); - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK); + previous_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK); } } else if (MS_ELEMENT_IS_AUDIO(src_pad_type)) { previous_element = __ms_combine_next_element(parent_rtp_element, source_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY); previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER); - previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_QUEUE); previous_element = __ms_combine_next_element(previous_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK); } else { ms_info("Unknown media type received from rtp element!"); } MS_SAFE_UNREF(parent_rtp_element); - MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, _sink_node_unlock_state, NULL); return TRUE; } @@ -721,16 +703,13 @@ int __ms_element_set_state(GstElement * gst_element, GstState gst_state) ms_retvm_if(gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL"); GstStateChangeReturn ret_state; - gchar *element_name = gst_element_get_name(gst_element); ret_state = gst_element_set_state(gst_element, gst_state); if (ret_state == GST_STATE_CHANGE_FAILURE) { - ms_error("Failed to set element [%s] into %s state", element_name, gst_element_state_get_name(gst_state)); - MS_SAFE_GFREE(element_name); + ms_error("Failed to set element [%s] into %s state", GST_ELEMENT_NAME(gst_element), gst_element_state_get_name(gst_state)); return MEDIA_STREAMER_ERROR_INVALID_OPERATION; } - MS_SAFE_GFREE(element_name); return MEDIA_STREAMER_ERROR_NONE; } @@ -1238,9 +1217,6 @@ int __ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s case MEDIA_STREAMER_NODE_TYPE_SINK: bin = ms_streamer->sink_bin; break; - case MEDIA_STREAMER_NODE_TYPE_QUEUE: - bin = ms_streamer->sink_bin; - break; default: /* Another elements will be add into topology bin */ bin = ms_streamer->topology_bin; @@ -1282,6 +1258,62 @@ static gboolean __ms_parse_gst_error(media_streamer_s *ms_streamer, GstMessage * return TRUE; } +static GstPadProbeReturn __ms_element_event_probe(GstPad * pad, GstPadProbeInfo *info, gpointer user_data) +{ + GstElement *parent_element = gst_pad_get_parent_element(pad); + GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info); + if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM) { + if (GST_EVENT_TYPE(event) == GST_EVENT_BUFFERSIZE) { + GValue *val_ = (GValue *) g_object_get_data(G_OBJECT(parent_element), "pad_sink"); + ms_info("Set locking probe [%d] on [%s] pad of [%s] element", g_value_get_int(val_), GST_PAD_NAME(pad), GST_ELEMENT_NAME(parent_element)); + MS_SAFE_UNREF(parent_element); + return GST_PAD_PROBE_OK; + } + } + MS_SAFE_UNREF(parent_element); + return GST_PAD_PROBE_PASS; +} + +void __ms_element_lock_state(const GValue *item, gpointer user_data) +{ + GstElement *sink_element = GST_ELEMENT(g_value_get_object(item)); + ms_retm_if(!sink_element, "Handle is NULL"); + + GstPad *sink_pad = gst_element_get_static_pad(sink_element, "sink"); + if (!gst_pad_is_blocked(sink_pad)) { + int probe_id = gst_pad_add_probe(sink_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, __ms_element_event_probe, NULL, NULL); + + GValue *val = g_malloc0(sizeof(GValue)); + g_value_init(val, G_TYPE_INT); + g_value_set_int(val, probe_id); + g_object_set_data(G_OBJECT(sink_element), "pad_sink", (gpointer)val); + + val = (GValue *) g_object_get_data(G_OBJECT(sink_element), "pad_sink"); + if (val) + ms_info("Added locking probe [%d] on pad [%s] of element [%s]", g_value_get_int(val), GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element)); + } else { + ms_info("Pad [%s] of element [%s] is already locked", GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element)); + } + MS_SAFE_UNREF(sink_pad); +} + +void __ms_element_unlock_state(const GValue *item, gpointer user_data) +{ + GstElement *sink_element = GST_ELEMENT(g_value_get_object(item)); + ms_retm_if(!sink_element, "Handle is NULL"); + + GValue *val = (GValue *) g_object_get_data(G_OBJECT(sink_element), "pad_sink"); + if (val) { + GstPad *sink_pad = gst_element_get_static_pad(sink_element, "sink"); + if (gst_pad_is_blocked(sink_pad)) { + ms_info("Removing locking probe [%d] ID on [%s] pad of [%s] element", g_value_get_int(val), GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element)); + gst_pad_remove_probe(sink_pad, g_value_get_int(val)); + } else { + ms_info("No locking Probe on pad [%s] of element [%s]", GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element)); + } + } +} + static gboolean __ms_bus_cb(GstBus *bus, GstMessage *message, gpointer userdata) { int ret = MEDIA_STREAMER_ERROR_NONE; diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c index 3525748..2f55ed2 100755 --- a/src/media_streamer_node.c +++ b/src/media_streamer_node.c @@ -57,14 +57,14 @@ node_info_s nodes_info[] = { {"Filter/Converter/Video", "videoconvert"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER */ {"Filter/Converter/Audio", "audioconvert"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER */ {MEDIA_STREAMER_STRICT, "audioresample"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE */ - {"Codec/Payloader/Network/RTP", "rtph264pay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY */ + {"Codec/Payloader/Network/RTP", "rtph263pay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY */ {"Codec/Payloader/Network/RTP", "rtpamrpay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY */ - {"Codec/Depayloader/Network/RTP", "rtph264depay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY */ + {"Codec/Depayloader/Network/RTP", "rtph263depay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY */ {"Codec/Depayloader/Network/RTP", "rtpamrdepay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY */ {"Filter/Effect/Video", "videorate"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_RATE */ {"Filter/Converter/Video/Scaler", "videoscale"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_SCALE */ {MEDIA_STREAMER_STRICT, "textoverlay"}, /* MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY */ - {"Codec/Parser/Converter/Video", "h264parse"}, /* MEDIA_STREAMER_NODE_TYPE_PARSER */ + {"Codec/Parser/Converter/Video", "h263parse"}, /* MEDIA_STREAMER_NODE_TYPE_PARSER */ {MEDIA_STREAMER_STRICT, "capsfilter"}, /* MEDIA_STREAMER_NODE_TYPE_FILTER */ {MEDIA_STREAMER_STRICT, "tee"}, /* MEDIA_STREAMER_NODE_TYPE_TEE */ {MEDIA_STREAMER_STRICT, "queue"}, /* MEDIA_STREAMER_NODE_TYPE_QUEUE */ @@ -419,24 +419,6 @@ static gboolean __ms_src_need_typefind(GstPad *src_pad) return ret; } -static void _sink_node_lock_state(const GValue *item, gpointer user_data) -{ - GstElement *sink_element = GST_ELEMENT(g_value_get_object(item)); - ms_retm_if(!sink_element, "Handle is NULL"); - - if (!gst_element_is_locked_state(sink_element)) { - GstState current_state = GST_STATE_VOID_PENDING; - gst_element_set_locked_state(sink_element, TRUE); - - gst_element_get_state(sink_element, ¤t_state, NULL, GST_MSECOND); - - ms_debug("Locked sink element [%s] into state [%s]", GST_ELEMENT_NAME(sink_element), gst_element_state_get_name(current_state)); - } else { - gst_element_set_locked_state(sink_element, FALSE); - gst_element_sync_state_with_parent(sink_element); - } -} - node_info_s * __ms_node_get_klass_by_its_type(media_streamer_node_type_e element_type) { int it_klass; @@ -472,7 +454,6 @@ static void _src_node_prepare(const GValue *item, gpointer user_data) /* Check the source element`s pad type */ const gchar *new_pad_type = __ms_get_pad_type(src_pad); if (gst_pad_is_linked(src_pad)) { - MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, _sink_node_lock_state, NULL); MS_SAFE_UNREF(src_pad); return; } @@ -504,7 +485,7 @@ int __ms_pipeline_prepare(media_streamer_s *ms_streamer) if (rtp_node) __ms_rtp_element_prepare(rtp_node); - MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, _sink_node_lock_state, NULL); + MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_lock_state, ms_streamer); MS_BIN_FOREACH_ELEMENTS(ms_streamer->src_bin, _src_node_prepare, ms_streamer); return MEDIA_STREAMER_ERROR_NONE; @@ -560,6 +541,10 @@ int __ms_pipeline_unprepare(media_streamer_s *ms_streamer) ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL"); int ret = MEDIA_STREAMER_ERROR_NONE; + __ms_element_set_state(ms_streamer->pipeline, GST_STATE_NULL); + + MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_unlock_state, ms_streamer); + /* Disconnects and clean all autoplug signals */ g_list_free_full(ms_streamer->autoplug_sig_list, __ms_signal_destroy); ms_streamer->autoplug_sig_list = NULL; diff --git a/src/media_streamer_priv.c b/src/media_streamer_priv.c index a41a571..00e7e16 100644 --- a/src/media_streamer_priv.c +++ b/src/media_streamer_priv.c @@ -43,13 +43,16 @@ int __ms_state_change(media_streamer_s *ms_streamer, media_streamer_state_e stat /* * Unlink all gst_elements, set pipeline into state NULL */ - if (previous_state != MEDIA_STREAMER_STATE_NONE) + if (previous_state != MEDIA_STREAMER_STATE_NONE) { + MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_unlock_state, ms_streamer); ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_NULL); + } break; case MEDIA_STREAMER_STATE_READY: - ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_READY); + ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PAUSED); break; case MEDIA_STREAMER_STATE_PLAYING: + MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_unlock_state, ms_streamer); ret = __ms_element_set_state(ms_streamer->pipeline, GST_STATE_PLAYING); break; case MEDIA_STREAMER_STATE_PAUSED: diff --git a/test/media_streamer_test.c b/test/media_streamer_test.c index ffbc6c4..a285add 100644 --- a/test/media_streamer_test.c +++ b/test/media_streamer_test.c @@ -551,12 +551,6 @@ static void _create_rtp_client(media_streamer_node_h rtp_bin) media_streamer_node_add(current_media_streamer, video_dec); APPEND_NODE(video_dec); - /* ********************** videoqueue ************************************ */ - media_streamer_node_h video_queue = NULL; - media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_QUEUE, NULL, NULL, &video_queue); - media_streamer_node_add(current_media_streamer, video_queue); - APPEND_NODE(video_queue); - /* ********************** videosink *********************************** */ media_streamer_node_h video_sink = NULL; media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY, &video_sink); @@ -565,8 +559,7 @@ static void _create_rtp_client(media_streamer_node_h rtp_bin) /* ====================Linking Video Client=========================== */ media_streamer_node_link(video_depay, "src", video_dec, "sink"); - media_streamer_node_link(video_dec, "src", video_queue, "sink"); - media_streamer_node_link(video_queue, "src", video_sink, "sink"); + media_streamer_node_link(video_dec, "src", video_sink, "sink"); g_print("== success client video part \n"); } @@ -585,12 +578,6 @@ static void _create_rtp_client(media_streamer_node_h rtp_bin) media_streamer_node_add(current_media_streamer, audio_dec); APPEND_NODE(audio_dec); - /* ********************** audioqueue ********************************** */ - media_streamer_node_h audio_queue = NULL; - media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_QUEUE, NULL, NULL, &audio_queue); - media_streamer_node_add(current_media_streamer, audio_queue); - APPEND_NODE(audio_queue); - /* ********************** audiosink *********************************** */ media_streamer_node_h audio_sink = NULL; media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO, &audio_sink); @@ -599,8 +586,7 @@ static void _create_rtp_client(media_streamer_node_h rtp_bin) /* ====================Linking Audio Client=========================== */ media_streamer_node_link(audio_depay, "src", audio_dec, "sink"); - media_streamer_node_link(audio_dec, "src", audio_queue, "sink"); - media_streamer_node_link(audio_queue, "src", audio_sink, "sink"); + media_streamer_node_link(audio_dec, "src", audio_sink, "sink"); /* =================================================================== */ g_print("== success client audio part \n"); -- 2.7.4