From: Vyacheslav Valkovoy Date: Wed, 23 Sep 2015 20:54:09 +0000 (+0300) Subject: Added File Streaming scenario. Bug fixes. X-Git-Tag: submit/tizen/20151002.091040^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c6c47a3efe44f8aeac7de7798f16e3b3d7860d00;p=platform%2Fcore%2Fapi%2Fmediastreamer.git Added File Streaming scenario. Bug fixes. Change-Id: If64b2745f650018eefcb0107baa0cc2f2b05487d --- diff --git a/include/media_streamer_gst.h b/include/media_streamer_gst.h index 5fbeef5..fb253cc 100755 --- a/include/media_streamer_gst.h +++ b/include/media_streamer_gst.h @@ -26,9 +26,12 @@ #define MEDIA_STREAMER_AUDIO_SINK_BIN_NAME "streamer_audio_sink" #define MEDIA_STREAMER_TOPOLOGY_BIN_NAME "streamer_topology" +#define MEDIA_STREAMER_PAYLOADER_KLASS "Codec/Payloader/Network/RTP" +#define MEDIA_STREAMER_RTP_KLASS "Filter/Network/RTP" #define MEDIA_STREAMER_DEPAYLOADER_KLASS "Depayloader/Network/RTP" -#define MEDIA_STREAMER_DECODEBIN_KLASS "Generic/Bin" -#define MEDIA_STREAMER_PARSER_KLASS "Parser/Converter" +#define MEDIA_STREAMER_BIN_KLASS "Generic/Bin" +#define MEDIA_STREAMER_PARSER_KLASS "Codec/Parser/Converter" +#define MEDIA_STREAMER_CONVERTER_KLASS "Filter/Converter" #define MEDIA_STREAMER_DECODER_KLASS "Codec/Decoder" #define MEDIA_STREAMER_SINK_KLASS "Sink" @@ -39,6 +42,22 @@ */ void __ms_generate_dots(GstElement *bin, gchar *name_tag); +/** + * @brief Creates GstElement by klass name. + * + * @since_tizen 3.0 + */ +GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar *klass_name); + +/** + * @brief Links two Gstelements and returns the last one. + * + * @since_tizen 3.0 + */ +GstElement * __ms_link_with_new_element(GstElement *previous_element, + GstElement *new_element, + const gchar *next_elem_bin_name); + /** * @brief Creates GstElement by plugin name. * @@ -110,12 +129,30 @@ gboolean __ms_element_set_property(GstElement *src_element, gboolean __ms_element_unlink(GstElement *src_element); /** - * @brief Callback function to link decodebin with the sink element. + * @brief Callback function to link decodebin with the sink element at the streamer part. + * + * @since_tizen 3.0 + */ +void __decodebin_newpad_streamer_cb(GstElement *decodebin, GstPad *pad, gpointer user_data); + +/** + * @brief Callback function to link decodebin with the sink element at the client part. * * @since_tizen 3.0 */ void __decodebin_newpad_cb(GstElement *decodebin, GstPad *pad, gpointer user_data); +/** + * @brief Creates next element by klass or by properties and links with the previous one. + * + * @since_tizen 3.0 + */ +GstElement * __ms_combine_next_element(GstElement *previous_element, + const gchar *next_elem_klass_name, + const gchar *next_elem_bin_name, + const gchar *element_type, + gchar *default_element); + /** * @brief Creates pipeline, bus and src/sink/topology bins. * diff --git a/include/media_streamer_node.h b/include/media_streamer_node.h index e40cf2f..afb522f 100755 --- a/include/media_streamer_node.h +++ b/include/media_streamer_node.h @@ -16,6 +16,15 @@ #include +/** + * @brief Sets property to media streamer node with key and value. + * + * @since_tizen 3.0 + */ +int __ms_node_set_property(media_streamer_node_s *ms_node, + const gchar *param_key, + const gchar *param_value); + /** * @brief Creates media streamer node using input and output format. * diff --git a/include/media_streamer_util.h b/include/media_streamer_util.h index 066c409..e1ffa30 100755 --- a/include/media_streamer_util.h +++ b/include/media_streamer_util.h @@ -76,7 +76,6 @@ extern "C" { } \ } while(0) - #define MS_SAFE_FREE(src) {if(src) {free(src); src = NULL;}} #define MS_SAFE_GFREE(src) {if(src) {g_free(src); src = NULL;}} #define MS_SAFE_UNREF(src) {if(src) {gst_object_unref(GST_OBJECT(src)); src = NULL;}} @@ -98,6 +97,8 @@ typedef struct __media_streamer_ini { } media_streamer_ini_t; +#define COMPARED_NUMBER 5 + /*Test elements*/ #define DEFAULT_VIDEO_TEST_SOURCE "videotestsrc" #define DEFAULT_AUDIO_TEST_SOURCE "audiotestsrc" @@ -132,6 +133,7 @@ typedef struct __media_streamer_ini { #define DEFAULT_VIDEO_RTPDEPAY "rtph263depay" /* audio format defaults */ +#define DEFAULT_AUDIO_PARSER "aacparse" #define DEFAULT_AUDIO_RTPPAY "rtpL16pay" #define DEFAULT_AUDIO_RTPDEPAY "rtpL16depay" @@ -143,6 +145,8 @@ typedef struct __media_streamer_ini { #define MS_ELEMENT_IS_INPUT(el) g_strrstr(el, "in") #define MS_ELEMENT_IS_AUDIO(el) g_strrstr(el, "audio") #define MS_ELEMENT_IS_VIDEO(el) g_strrstr(el, "video") +#define MS_ELEMENT_IS_ENCODER(el) g_strrstr(el, "encoder") +#define MS_ELEMENT_IS_DECODER(el) g_strrstr(el, "decoder") #define MEDIA_STREAMER_DEFAULT_DOT_DIR "/tmp" #define MEDIA_STREAMER_DEFAULT_INI \ diff --git a/packaging/capi-media-streamer.spec b/packaging/capi-media-streamer.spec index 020d2a0..7251a8a 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.2 +Version: 0.1.3 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index dc459cf..511b2f7 100755 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -42,7 +42,8 @@ static int __ms_add_no_target_ghostpad(GstElement *gst_bin, gchar *bin_name = gst_element_get_name(gst_bin); GstPad *ghost_pad = gst_ghost_pad_new_no_target(ghost_pad_name, pad_direction); if (gst_element_add_pad(GST_ELEMENT(gst_bin), ghost_pad)) { - ms_info("Added [%s] empty ghostpad into [%s]", ghost_pad_name, bin_name); + gst_pad_set_active(ghost_pad, TRUE); + ms_info("Added [%s] empty ghostpad into [%s]", ghost_pad_name, bin_name); } else { ms_info("Error: Failed to add empty [%s] ghostpad into [%s]", ghost_pad_name, bin_name); ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION; @@ -111,7 +112,7 @@ static GObject *__ms_get_property_owner(GstElement *element, const gchar *key, G g_value_init(value, param->value_type); - if (!param->flags & G_PARAM_WRITABLE) { + if (!(param->flags & G_PARAM_WRITABLE)) { /* Skip properties which user can not change. */ ms_error("Error: node param [%s] is not writable!", key); @@ -143,94 +144,94 @@ gboolean __ms_element_set_property(GstElement *element, const char *key, const g return FALSE; } - if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_CAMERA_ID)) { + if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_CAMERA_ID)) { pint = atoi(param_value); g_value_set_int(&value, pint); g_object_set(obj, init_name, pint, NULL); ms_info("Set int value: [%d]", g_value_get_int(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH)) { pint = atoi(param_value); g_value_set_int(&value, pint); g_object_set(obj, init_name, pint, NULL); ms_info("Set int value: [%d]", g_value_get_int(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT)) { pint = atoi(param_value); g_value_set_int(&value, pint); g_object_set(obj, init_name, pint, NULL); ms_info("Set int value: [%d]", g_value_get_int(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM)) { bool_val = !g_strcmp0(param_value, "true") ? TRUE : FALSE; g_value_set_boolean(&value, bool_val); g_object_set(obj, init_name, bool_val, NULL); ms_info("Set boolean value: [%d]", g_value_get_boolean(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_URI)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_URI)) { g_value_set_string(&value, param_value); g_object_set(obj, init_name, param_value, NULL); ms_info("Set string value: [%s]", g_value_get_string(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_USER_AGENT)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_USER_AGENT)) { g_value_set_string(&value, param_value); g_object_set(obj, init_name, param_value, NULL); ms_info("Set string value: [%s]", g_value_get_string(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_STREAM_TYPE)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_STREAM_TYPE)) { pint = atoi(param_value); g_object_set(obj, init_name, pint, NULL); ms_info("Set int value: [%d] ", pint); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_PORT)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_PORT)) { pint = atoi(param_value); g_value_set_int(&value, pint); g_object_set(obj, init_name, pint, NULL); ms_info("Set int value: [%d]", g_value_get_int(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT)) { pint = atoi(param_value); g_value_set_int(&value, pint); g_object_set(obj, init_name, pint, NULL); ms_info("Set int value: [%d]", g_value_get_int(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT)) { pint = atoi(param_value); g_value_set_int(&value, pint); g_object_set(obj, init_name, pint, NULL); ms_info("Set int value: [%d]", g_value_get_int(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT)) { pint = atoi(param_value); g_value_set_int(&value, pint); g_object_set(obj, init_name, pint, NULL); ms_info("Set int value: [%d]", g_value_get_int(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) { pint = atoi(param_value); g_value_set_int(&value, pint); g_object_set(obj, init_name, pint, NULL); ms_info("Set int value: [%d]", g_value_get_int(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_IP_ADDRESS)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_IP_ADDRESS)) { g_value_set_string(&value, param_value); g_object_set(obj, init_name, param_value, NULL); ms_info("Set string value: [%s]", g_value_get_string(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_AUDIO_DEVICE)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_AUDIO_DEVICE)) { g_value_set_string(&value, param_value); g_object_set(obj, init_name, param_value, NULL); ms_info("Set string value: [%s]", g_value_get_string(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED)) { bool_val = !g_strcmp0(param_value, "true") ? TRUE : FALSE; g_value_set_boolean(&value, bool_val); g_object_set(obj, init_name, bool_val, NULL); ms_info("Set boolean value: [%d]", g_value_get_boolean(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_ROTATE)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_ROTATE)) { pint = atoi(param_value); g_object_set(obj, init_name, pint, NULL); ms_info("Set int value: [%d] ", pint); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_FLIP)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_FLIP)) { pint = atoi(param_value); g_object_set(obj, init_name, pint, NULL); ms_info("Set int value: [%d] ", pint); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) { pint = atoi(param_value); g_object_set(obj, init_name, pint, NULL); ms_info("Set int value: [%d] ", pint); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_VISIBLE)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_VISIBLE)) { bool_val = !g_strcmp0(param_value, "true") ? TRUE : FALSE; g_value_set_boolean(&value, bool_val); g_object_set(obj, init_name, bool_val, NULL); ms_info("Set boolean value: [%d]", g_value_get_boolean(&value)); - } else if (!g_strcmp0(init_name, MEDIA_STREAMER_PARAM_HOST)) { + } else if (!g_strcmp0(key, MEDIA_STREAMER_PARAM_HOST)) { g_value_set_string(&value, param_value); g_object_set(obj, init_name, param_value, NULL); ms_info("Set string value: [%s]", g_value_get_string(&value)); @@ -350,23 +351,49 @@ static void __ms_link_elements_on_pad_added_cb(GstPad *new_pad, GstElement *sink } #endif -static GstElement *__ms_bin_find_element_by_klass(GstElement *sink_bin, const gchar *klass_name) +static GstElement *__ms_bin_find_element_by_klass(GstElement *sink_bin, + const gchar *klass_name, + const gchar *bin_name) { GValue elem = G_VALUE_INIT; GstIterator *bin_iterator = gst_bin_iterate_sorted(GST_BIN(sink_bin)); GstElement *found_element; gboolean found = FALSE; - while (GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &elem)) { + gboolean unlinked_pad_found = FALSE; + + GValue element = G_VALUE_INIT; + GstPad *pad = NULL; + GstIterator *pad_iterator = NULL; - found_element = (GstElement *)g_value_get_object(&elem); + while (GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &elem)) { + found_element = (GstElement *) g_value_get_object(&elem); const gchar *found_klass = gst_element_factory_get_klass(gst_element_get_factory(found_element)); - if (g_strrstr(found_klass, klass_name)) { - found = TRUE; - break; - } + if (klass_name && g_strrstr(found_klass, klass_name)) { + + /* Check if found element has any unlinked sink pad */ + pad_iterator = gst_element_iterate_sink_pads(found_element); + while (GST_ITERATOR_OK == gst_iterator_next(pad_iterator, &element)) { + pad = (GstPad *) g_value_get_object(&element); + if (!gst_pad_is_linked(pad)) { + unlinked_pad_found = TRUE; + } + g_value_reset(&element); + } + + g_value_unset(&element); + gst_iterator_free(pad_iterator); + /* If found element is not linked yet, check it by klass */ + if (unlinked_pad_found) { + if (bin_name == NULL || g_strrstr(GST_ELEMENT_NAME(found_element), bin_name)) { + found = TRUE; + break; + } + } + } + unlinked_pad_found = FALSE; g_value_reset(&elem); } @@ -375,15 +402,45 @@ static GstElement *__ms_bin_find_element_by_klass(GstElement *sink_bin, const gc return found ? found_element : NULL; } +int __ms_get_rank_increase(const char *factory_class) +{ + gint rank_priority = 20; + gint rank_second = 10; + gint ret = 0; + + if (g_strrstr(factory_class, "Dsp")) + ret = rank_priority; + else if (g_strrstr(factory_class, "HW")) + ret = rank_priority; + else if (g_strrstr(factory_class, "Arm")) + ret = rank_second; + + return ret; +} + +int __ms_factory_rank_compare(GstPluginFeature *first_feature, GstPluginFeature *second_feature) +{ + const gchar *class; + int first_feature_rank_inc=0, second_feature_rank_inc = 0; + + class = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(first_feature)); + first_feature_rank_inc = __ms_get_rank_increase(class); + class = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(second_feature)); + second_feature_rank_inc = __ms_get_rank_increase(class); + + return (gst_plugin_feature_get_rank(second_feature) + second_feature_rank_inc) - + (gst_plugin_feature_get_rank(first_feature) + first_feature_rank_inc ); +} + gboolean __ms_feature_filter(GstPluginFeature *feature, gpointer data) { - if (!GST_IS_ELEMENT_FACTORY(feature)) + if (!GST_IS_ELEMENT_FACTORY(feature)) { return FALSE; - + } return TRUE; } -static GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar *klass_name) +GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar *klass_name) { GList *factories; const GList *pads; @@ -394,6 +451,7 @@ static GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar factories = gst_registry_feature_filter(gst_registry_get(), (GstPluginFeatureFilter)__ms_feature_filter, FALSE, NULL); + factories = g_list_sort(factories, (GCompareFunc)__ms_factory_rank_compare); for(; factories != NULL ; factories = factories->next) { GstElementFactory *factory = GST_ELEMENT_FACTORY(factories->data); @@ -411,7 +469,7 @@ static GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar } if (GST_IS_CAPS(&pad_temp->static_caps.caps)) { - static_caps = gst_caps_ref(&pad_temp->static_caps.caps); + static_caps = gst_caps_ref(pad_temp->static_caps.caps); } else { static_caps = gst_caps_from_string(pad_temp->static_caps.string); } @@ -432,76 +490,235 @@ static GstElement *__ms_create_element_by_registry(GstPad *src_pad, const gchar return next_element; } -static GstElement *__ms_link_with_new_element (GstElement *previous_element, GstElement *new_element) +GstElement * __ms_link_with_new_element(GstElement *previous_element, + GstElement *new_element, + const gchar *next_elem_bin_name) { - gboolean ret = gst_element_link_pads_filtered(previous_element, NULL, new_element, NULL, NULL); + GstCaps *new_pad_caps = NULL; + GstStructure *new_pad_struct = NULL; + const gchar *new_pad_type = NULL; - if (!ret) { - ms_error("Failed to link [%s] and [%s] \n", GST_ELEMENT_NAME(previous_element), - GST_ELEMENT_NAME(new_element)); - new_element = NULL; + GValue element = G_VALUE_INIT; + GstPad *sink_pad = NULL; + GstPad *src_pad = NULL; + GstIterator *pad_iterator = NULL; + + if (next_elem_bin_name) { + pad_iterator = gst_element_iterate_sink_pads(new_element); + while (GST_ITERATOR_OK == gst_iterator_next(pad_iterator, &element)) + { + sink_pad = (GstPad *)g_value_get_object(&element); + src_pad = gst_element_get_static_pad(previous_element, "sink"); + + new_pad_caps = gst_pad_query_caps(src_pad, 0); + new_pad_struct = gst_caps_get_structure(new_pad_caps, 0); + new_pad_type = gst_structure_get_name(new_pad_struct); + + if (!gst_pad_is_linked(sink_pad)) { + if(!strncmp(new_pad_type,GST_PAD_NAME(sink_pad), COMPARED_NUMBER)) { + if (gst_element_link_pads_filtered(previous_element, "src", new_element, + GST_PAD_NAME(sink_pad), NULL)) { + ms_info("Succeeded to link [%s] -> [%s]\n", + GST_ELEMENT_NAME(previous_element), + GST_ELEMENT_NAME(new_element)); + } else { + ms_error("Failed to link [%s] -> [%s]\n", + GST_ELEMENT_NAME(previous_element), + GST_ELEMENT_NAME(new_element)); + } + } + } + g_value_reset(&element); + } + g_value_unset(&element); + gst_iterator_free(pad_iterator); } else { - ms_info("Succeeded to link [%s] -> [%s]\n", GST_ELEMENT_NAME(previous_element), - GST_ELEMENT_NAME(new_element)); - } + gboolean ret = gst_element_link_pads_filtered(previous_element, NULL, new_element, NULL, NULL); + if (ret) { + ms_info("Succeeded to link [%s] -> [%s]\n", + GST_ELEMENT_NAME(previous_element), + GST_ELEMENT_NAME(new_element)); + } else { + ms_error("Failed to link [%s] and [%s] \n", + GST_ELEMENT_NAME(previous_element), + GST_ELEMENT_NAME(new_element)); + new_element = NULL; + } + } return new_element; } -void __decodebin_newpad_cb(GstElement *decodebin, GstPad *new_pad, gpointer user_data) +GstElement *__ms_combine_next_element(GstElement *previous_element, + const gchar *next_elem_klass_name, + const gchar *next_elem_bin_name, + const gchar *element_type, + gchar *default_element) { - GstElement *previous_element = NULL; GstElement *found_element = NULL; - GstElement *parent = NULL; + GstElement *parent_element = NULL; + + char *plugin_name = NULL; + char *format_prefix = NULL; + + media_format_h vfmt_encoded = NULL; + media_format_create(&vfmt_encoded); + if (media_format_set_video_mime(vfmt_encoded, MEDIA_FORMAT_H264_SP) != MEDIA_FORMAT_ERROR_NONE) { + ms_error("media_format_set_video_mime failed!\n"); + } + + media_format_set_video_width(vfmt_encoded, 1280); + media_format_set_video_height(vfmt_encoded, 720); + media_format_set_video_avg_bps(vfmt_encoded, 1031); + media_format_set_video_max_bps(vfmt_encoded, 2063); + + parent_element = (GstElement *)gst_element_get_parent(previous_element); + + /*Look for node created by user*/ + if (next_elem_klass_name) { + found_element = __ms_bin_find_element_by_klass(parent_element, next_elem_klass_name, next_elem_bin_name); + } + + /* Link with found node created by user*/ + if (found_element && !element_type) { + previous_element = __ms_link_with_new_element(previous_element, found_element, next_elem_bin_name); + } else { + + /* Check if rtp_container was created*/ + if (!found_element && next_elem_bin_name && !element_type) { + ms_error("Bin [%s] was not found", next_elem_bin_name); + return NULL; + + /* Create element by element name*/ + } else if(!found_element && !next_elem_klass_name) { + found_element = __ms_element_create(default_element, NULL); + + /* Create element by predefined format element type*/ + } else if(!found_element && element_type) { + + dictionary *dict = NULL; + media_format_mimetype_e mime; + + if (MEDIA_FORMAT_ERROR_NONE != media_format_get_video_info(vfmt_encoded, &mime, + NULL, NULL, NULL, NULL)) { + media_format_get_audio_info(vfmt_encoded, &mime, NULL, NULL, NULL, NULL); + } + + __ms_load_ini_dictionary(&dict); + + format_prefix = g_strdup_printf("%s:%s", __ms_convert_mime_to_string(mime), element_type); + plugin_name = __ms_ini_get_string(dict, format_prefix, default_element); + + if (MS_ELEMENT_IS_ENCODER(next_elem_bin_name)) { + if (MS_ELEMENT_IS_VIDEO(next_elem_bin_name)) { + found_element = __ms_video_encoder_element_create(dict, mime); + } else if (MS_ELEMENT_IS_AUDIO(next_elem_bin_name)) { + found_element = __ms_audio_encoder_element_create(); + } + } else if (MS_ELEMENT_IS_DECODER(next_elem_bin_name)) { + if (MS_ELEMENT_IS_VIDEO(next_elem_bin_name)) { + found_element = __ms_video_decoder_element_create(dict, mime); + } + } + + __ms_destroy_ini_dictionary(dict); + + /* Create element by caps of the previous element */ + } else if (!found_element) { + GstPad *src_pad = gst_element_get_static_pad(previous_element, "src"); + found_element = __ms_create_element_by_registry(src_pad, next_elem_klass_name); + MS_SAFE_UNREF(src_pad); + } + + /*Add created element*/ + if (found_element && gst_bin_add(GST_BIN(parent_element), found_element)) { + ms_debug("Element [%s] added into [%s] bin", + GST_ELEMENT_NAME(found_element), + GST_ELEMENT_NAME(parent_element)); + } else { + ms_error("Element [%s] was not added into [%s] bin", + GST_ELEMENT_NAME(found_element), + GST_ELEMENT_NAME(parent_element)); + } + previous_element = __ms_link_with_new_element(previous_element, found_element, NULL); + } + + gst_element_sync_state_with_parent(found_element); + __ms_generate_dots(parent_element, GST_ELEMENT_NAME(found_element)); + + MS_SAFE_FREE(plugin_name); + MS_SAFE_FREE(format_prefix); + + return found_element; +} + + +void __decodebin_newpad_streamer_cb(GstElement *decodebin, GstPad *new_pad, gpointer user_data) +{ + media_streamer_s *ms_streamer = (media_streamer_s *)user_data; + ms_retm_if(ms_streamer == NULL, "Handle is NULL"); + + GstElement *found_element = NULL; GstCaps *new_pad_caps = NULL; GstStructure *new_pad_struct = NULL; const gchar *new_pad_type = NULL; - ms_info("Received new pad '%s' from [%s]", GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(decodebin)); - parent = (GstElement *)gst_element_get_parent(GST_OBJECT_CAST(decodebin)); + ms_info("Received new pad '%s' from [%s]\n", GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(decodebin)); /* Check the new pad's type */ - new_pad_caps = gst_pad_query_caps(new_pad,0); + new_pad_caps = gst_pad_query_caps(new_pad, 0); new_pad_struct = gst_caps_get_structure(new_pad_caps, 0); new_pad_type = gst_structure_get_name(new_pad_struct); - if (g_str_has_prefix(new_pad_type, "video")) { - found_element = __ms_element_create("videoconvert", NULL); - } else if (g_str_has_prefix(new_pad_type, "audio")) { - found_element = __ms_element_create("audioconvert", NULL); - } else { - ms_error("Could not create converting element according to media pad type"); + if (g_str_has_prefix(new_pad_type, "video")) + { + found_element = __ms_combine_next_element(decodebin, NULL, NULL, NULL, DEFAULT_QUEUE); + found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "video_encoder", "encoder", DEFAULT_VIDEO_ENCODER); + found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL, NULL); + found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL, NULL); } - if (!gst_bin_add(GST_BIN(parent), found_element)) { - ms_error("Failed to add element [%s] into bin [%s]", GST_ELEMENT_NAME(found_element), - GST_ELEMENT_NAME(parent)); - } - gst_element_sync_state_with_parent(found_element); + if (g_str_has_prefix(new_pad_type, "audio")) { - previous_element = __ms_link_with_new_element(decodebin, found_element); - if (!previous_element) { - gst_bin_remove(GST_BIN(parent), found_element); + found_element = __ms_combine_next_element(decodebin, NULL, NULL, NULL, DEFAULT_QUEUE); + found_element = __ms_combine_next_element(found_element, NULL, NULL, NULL, DEFAULT_AUDIO_CONVERT); + found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL, NULL); + found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL, NULL); } +} +void __decodebin_newpad_cb(GstElement *decodebin, GstPad *new_pad, gpointer user_data) +{ + media_streamer_s *ms_streamer = (media_streamer_s *)user_data; + ms_retm_if(ms_streamer == NULL, "Handle is NULL"); - /* Getting Sink */ - found_element = __ms_bin_find_element_by_klass(parent, MEDIA_STREAMER_SINK_KLASS); - if (!found_element) { - ms_error("There are no any SINK elements created by user"); - } - gst_element_sync_state_with_parent(found_element); + GstElement *found_element = NULL; + + GstCaps *new_pad_caps = NULL; + GstStructure *new_pad_struct = NULL; + const gchar *new_pad_type = NULL; + + ms_info("Received new pad '%s' from [%s]", GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(decodebin)); - previous_element = __ms_link_with_new_element(previous_element, found_element); - if (!previous_element) { - gst_bin_remove(GST_BIN(parent), found_element); + /* Check the new pad's type */ + new_pad_caps = gst_pad_query_caps(new_pad, 0); + new_pad_struct = gst_caps_get_structure(new_pad_caps, 0); + new_pad_type = gst_structure_get_name(new_pad_struct); + + if(MS_ELEMENT_IS_VIDEO(new_pad_type)) { + found_element = __ms_combine_next_element(decodebin, NULL, NULL, NULL, DEFAULT_VIDEO_CONVERT); + } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) { + found_element = __ms_combine_next_element(decodebin, NULL, NULL, NULL, DEFAULT_AUDIO_CONVERT); } - __ms_element_set_state(parent, GST_STATE_PLAYING); + /* Getting Sink */ + found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_SINK_KLASS, NULL, NULL, NULL); + __ms_generate_dots(ms_streamer->pipeline, "pipeline_linked"); } -static gboolean __ms_sink_bin_prepare(media_streamer_node_s *ms_node, GstElement *sink_bin, GstPad *source_pad) +static gboolean __ms_sink_bin_prepare(media_streamer_node_s *ms_node, + GstElement *sink_bin, GstPad *source_pad) { GstPad *src_pad = NULL; gboolean decodebin_usage = FALSE; @@ -512,166 +729,81 @@ static gboolean __ms_sink_bin_prepare(media_streamer_node_s *ms_node, GstElement GstStructure *new_pad_struct = NULL; const gchar *new_pad_type = NULL; - /* Getting Depayloader */ - found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_DEPAYLOADER_KLASS); + found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_DEPAYLOADER_KLASS, + MEDIA_STREAMER_NODE_TYPE_NONE); if (!found_element) { found_element = __ms_create_element_by_registry(source_pad, MEDIA_STREAMER_DEPAYLOADER_KLASS); - if (!gst_bin_add(GST_BIN(sink_bin), found_element)) { - ms_error("Failed to add element [%s] into bin [%s]", GST_ELEMENT_NAME(found_element), + if (gst_bin_add(GST_BIN(sink_bin), found_element)) { + ms_debug("Succeeded to add element [%s] into bin [%s]", + GST_ELEMENT_NAME(found_element), + GST_ELEMENT_NAME(sink_bin)); + } else { + ms_error("Failed to add element [%s] into bin [%s]", + GST_ELEMENT_NAME(found_element), GST_ELEMENT_NAME(sink_bin)); } } + previous_element = found_element; src_pad = gst_element_get_static_pad(found_element, "src"); __ms_add_ghostpad(found_element, "sink", sink_bin, "sink"); + previous_element = __ms_combine_next_element(previous_element, NULL, NULL, NULL, DEFAULT_QUEUE); /* Getting Decodebin */ decodebin_usage = ms_node->parent_streamer->ini.use_decodebin; - - found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_DECODEBIN_KLASS); + found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_BIN_KLASS, MEDIA_STREAMER_NODE_TYPE_NONE); if (!found_element) { if (decodebin_usage) { - found_element = __ms_create_element_by_registry(src_pad, MEDIA_STREAMER_DECODEBIN_KLASS); - if (!found_element) { - ms_error("Could not create element of MEDIA_STREAMER_DECODER_KLASS"); - } - if (!gst_bin_add(GST_BIN(sink_bin), found_element)) { - ms_error("Failed to add element [%s] into bin [%s]", GST_ELEMENT_NAME(found_element), - GST_ELEMENT_NAME(sink_bin)); - } - if (ms_node->parent_streamer->ini.use_decodebin) { - g_signal_connect(found_element, "pad-added", G_CALLBACK(__decodebin_newpad_cb), (gpointer)ms_node); - } - - previous_element = __ms_link_with_new_element(previous_element, found_element); - if (!previous_element) { - gst_bin_remove(sink_bin, found_element); - return FALSE; - } + previous_element = __ms_combine_next_element(previous_element, MEDIA_STREAMER_BIN_KLASS, NULL, NULL, NULL); + g_signal_connect(previous_element, "pad-added", G_CALLBACK(__decodebin_newpad_cb), (gpointer )ms_node); } else { - src_pad = gst_element_get_static_pad(previous_element, "src"); new_pad_caps = gst_pad_query_caps(src_pad, 0); new_pad_struct = gst_caps_get_structure(new_pad_caps, 0); new_pad_type = gst_structure_get_name(new_pad_struct); - if (g_str_has_prefix(new_pad_type, "video")) { - - /* Getting Parser */ - found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_PARSER_KLASS); - if (!found_element) { - found_element = __ms_create_element_by_registry(src_pad, MEDIA_STREAMER_PARSER_KLASS); - if (!found_element) { - ms_error("Could not create element of MEDIA_STREAMER_PARSER_KLASS"); - } - if (!gst_bin_add(GST_BIN(sink_bin), found_element)) { - ms_error("Failed to add element [%s] into bin [%s]", GST_ELEMENT_NAME(found_element), - GST_ELEMENT_NAME(sink_bin)); - } - } - previous_element = __ms_link_with_new_element(previous_element, found_element); - if (!previous_element) { - gst_bin_remove(GST_BIN(sink_bin), found_element); - return FALSE; - } - src_pad = gst_element_get_static_pad(found_element, "src"); - - - /* Getting Decoder */ - found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_DECODER_KLASS); - if (!found_element) { - found_element = __ms_create_element_by_registry(src_pad, MEDIA_STREAMER_DECODER_KLASS); - if (!found_element) { - ms_error("Could not create element of MEDIA_STREAMER_DECODER_KLASS"); - } - if (!gst_bin_add(GST_BIN(sink_bin), found_element)) { - ms_error("Failed to add element [%s] into bin [%s]", GST_ELEMENT_NAME(found_element), - GST_ELEMENT_NAME(sink_bin)); - } - } - previous_element = __ms_link_with_new_element(previous_element, found_element); - if (!previous_element) { - gst_bin_remove(GST_BIN(sink_bin), found_element); - return FALSE; - } - src_pad = gst_element_get_static_pad(found_element, "src"); - - - /* Getting Convertor */ - found_element = __ms_element_create("videoconvert", NULL); - - } else if (g_str_has_prefix(new_pad_type, "audio")) { - found_element = __ms_element_create("audioconvert", NULL); - } else { - ms_error("Could not create converting element according to media pad type"); + /* Getting elements if Decodebin is not used */ + if(MS_ELEMENT_IS_VIDEO(new_pad_type)) { + previous_element = __ms_combine_next_element(previous_element, MEDIA_STREAMER_PARSER_KLASS, NULL, NULL, NULL); + previous_element = __ms_combine_next_element(previous_element, MEDIA_STREAMER_DECODER_KLASS, NULL, NULL, NULL); + previous_element = __ms_combine_next_element(previous_element, NULL, NULL, NULL, DEFAULT_QUEUE); + previous_element = __ms_combine_next_element(previous_element, NULL, NULL, NULL, DEFAULT_VIDEO_CONVERT); } - - if (!found_element) { - ms_error("Could not create element of MEDIA_STREAMER_CONVERTER_KLASS"); - } - if (!gst_bin_add(GST_BIN(sink_bin), found_element)) { - ms_error("Failed to add element [%s] into bin [%s]", GST_ELEMENT_NAME(found_element), - GST_ELEMENT_NAME(sink_bin)); - } - previous_element = __ms_link_with_new_element(previous_element, found_element); - if (!previous_element) { - gst_bin_remove(GST_BIN(sink_bin), found_element); - return FALSE; + if(MS_ELEMENT_IS_AUDIO(new_pad_type)) { + previous_element = __ms_combine_next_element(previous_element, NULL, NULL, NULL, DEFAULT_AUDIO_CONVERT); } - - /* Getting Sink */ - found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_SINK_KLASS); - if (!found_element) { - ms_error("There are no any SINK elements created by user"); - } - previous_element = __ms_link_with_new_element(previous_element, found_element); - if (!previous_element) { - gst_bin_remove(GST_BIN(sink_bin), found_element); - return FALSE; - } - - __ms_generate_dots(ms_node->parent_streamer->pipeline, "pipeline_linked"); - __ms_element_set_state(ms_node->parent_streamer->pipeline, GST_STATE_PLAYING); + /* Getting Sink */ + previous_element = __ms_combine_next_element(previous_element, MEDIA_STREAMER_SINK_KLASS, NULL, NULL, NULL); } } else { - if(!gst_pad_is_linked(src_pad)) { - previous_element = __ms_link_with_new_element(previous_element, found_element); - if (!previous_element) { - gst_bin_remove(GST_BIN(sink_bin), found_element); - return FALSE; - } + + /* If decode element was added but not linked yet */ + if (!gst_pad_is_linked(src_pad)) { + previous_element = __ms_link_with_new_element(previous_element, found_element, NULL); } else { + + /* If decode element was added and linked */ previous_element = found_element; } + /* If decode element was made by user, not decodebin */ if (!decodebin_usage) { - /* Getting Sink */ - found_element = __ms_bin_find_element_by_klass(sink_bin, MEDIA_STREAMER_SINK_KLASS); - if (!found_element) { - ms_error("There are no any SINK elements created by user"); + /* Find sink element and link with it, if it was not linked yet */ + previous_element = __ms_combine_next_element(previous_element, MEDIA_STREAMER_SINK_KLASS, NULL,NULL, NULL); + if (!gst_pad_is_linked(src_pad)) { + previous_element = __ms_link_with_new_element(previous_element, found_element, NULL); } - - if(!gst_pad_is_linked(src_pad)) { - previous_element = __ms_link_with_new_element(previous_element, found_element); - if (!previous_element) { - gst_bin_remove(GST_BIN(sink_bin), found_element); - return FALSE; - } - } - - __ms_generate_dots(ms_node->parent_streamer->pipeline, "pipeline_linked"); - __ms_element_set_state(ms_node->parent_streamer->pipeline, GST_STATE_PLAYING); } } - + __ms_generate_dots(ms_node->parent_streamer->pipeline, "pipeline_linked"); MS_SAFE_UNREF(src_pad); return TRUE; @@ -808,7 +940,7 @@ GstElement *__ms_camera_element_create(const char *camera_plugin_name) return camera_bin; } -GstElement *__ms_video_encoder_element_create(dictionary *dict , media_format_mimetype_e mime) +GstElement *__ms_video_encoder_element_create(dictionary *dict, media_format_mimetype_e mime) { char *plugin_name = NULL; char *format_prefix = NULL; @@ -852,7 +984,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(dictionary *dict, media_format_mimetype_e mime) { char *plugin_name = NULL; char *format_prefix = NULL; @@ -870,7 +1002,7 @@ GstElement *__ms_video_decoder_element_create(dictionary *dict , media_format_mi GstElement *decoder_parser = __ms_element_create(plugin_name, NULL); if (mime == MEDIA_FORMAT_H264_SP) { - g_object_set(G_OBJECT(decoder_parser), "config-interval", 5, NULL); + g_object_set(G_OBJECT(decoder_parser), "config-interval", COMPARED_NUMBER, NULL); } if (g_strrstr(format_prefix, "omx")) { @@ -996,6 +1128,7 @@ gboolean __ms_get_rtp_elements(media_streamer_node_s *ms_node, gst_bin_add_many(GST_BIN(ms_node->gst_element), *rtp_elem, *rtcp_elem, NULL); } else { + /*rtp/rtcp elements already into rtp bin. */ MS_SAFE_GFREE(rtp_elem_name); MS_SAFE_GFREE(rtcp_elem_name); @@ -1080,10 +1213,6 @@ int __ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s gst_ret = gst_bin_add(GST_BIN(ms_streamer->topology_bin), ms_node->gst_element); bin_name = g_strdup(MEDIA_STREAMER_TOPOLOGY_BIN_NAME); break; - case MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER: - gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_video_bin), ms_node->gst_element); - bin_name = g_strdup(MEDIA_STREAMER_VIDEO_SINK_BIN_NAME); - break; case MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY: gst_ret = gst_bin_add(GST_BIN(ms_streamer->sink_video_bin), ms_node->gst_element); bin_name = g_strdup(MEDIA_STREAMER_VIDEO_SINK_BIN_NAME); diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c index 224b44f..e37bd6f 100755 --- a/src/media_streamer_node.c +++ b/src/media_streamer_node.c @@ -45,9 +45,9 @@ char *param_table[PROPERTY_COUNT][2] = { {MEDIA_STREAMER_PARAM_HOST, "host"} }; -static int __ms_node_set_property(media_streamer_node_s *ms_node, - const gchar *param_key, - const gchar *param_value) +int __ms_node_set_property(media_streamer_node_s *ms_node, + const gchar *param_key, + const gchar *param_value) { ms_retvm_if(!ms_node && !ms_node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node"); ms_retvm_if(!param_key && !param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter"); @@ -95,7 +95,7 @@ static int __ms_rtp_node_set_property(media_streamer_node_s *ms_node, g_strfreev(tokens); return MEDIA_STREAMER_ERROR_NONE; - } else if (tokens || tokens[0] || tokens[1] || tokens[2]) { + } else if (tokens && tokens[0] && tokens[1] && tokens[2]) { /* * Rtp node parameter name consist of three fields separated with symbol '_': @@ -278,7 +278,7 @@ int __ms_src_node_create(media_streamer_node_s *node) switch (node->subtype) { case MEDIA_STREAMER_NODE_SRC_TYPE_FILE: - ms_error("Error: not implemented yet"); + node->gst_element = __ms_element_create("filesrc", NULL); break; case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP: node->gst_element = __ms_element_create(DEFAULT_UDP_SOURCE, NULL); @@ -459,63 +459,94 @@ int __ms_node_remove_from_table(GHashTable *nodes_table, return MEDIA_STREAMER_ERROR_NONE; } +static gboolean __ms_src_need_typefind(GstElement *src) +{ + gboolean ret = FALSE; + g_assert(src); + + GstPad *src_pad = gst_element_get_static_pad(src, "src"); + if (!src_pad || gst_pad_is_linked(src_pad)) { + MS_SAFE_UNREF(src_pad); + return FALSE; + } + + GstCaps *src_caps = gst_pad_query_caps(src_pad, NULL); + if (gst_caps_is_any(src_caps)) { + ret = TRUE; + } + + gst_caps_unref(src_caps); + MS_SAFE_UNREF(src_pad); + return ret; +} + int __ms_autoplug_prepare(media_streamer_s *ms_streamer) { GstElement *unlinked_element = NULL; GstPad *unlinked_pad = NULL; - gchar *unlinked_element_name = NULL; - ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, - "Handle is NULL"); + GstElement *parent; + GstElement *found_element; + + GstCaps *new_pad_caps = NULL; + GstStructure *new_pad_struct = NULL; + const gchar *new_pad_type = NULL; + + ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL"); - /*Find unlinked element into src_bin */ + /* Find unlinked element in src_bin */ unlinked_pad = gst_bin_find_unlinked_pad(GST_BIN(ms_streamer->src_bin), GST_PAD_SRC); + while (unlinked_pad) { - GstCaps *pad_caps = gst_pad_query_caps(unlinked_pad, NULL); - GstStructure *src_pad_struct = gst_caps_get_structure(pad_caps, 0); - const gchar *field = gst_structure_get_name(src_pad_struct); - unlinked_element = gst_pad_get_parent_element(unlinked_pad); - unlinked_element_name = gst_element_get_name(unlinked_element); - ms_debug("Autoplug: found unlinked element [%s] in src_bin with pad type [%s].", - unlinked_element_name, field); - - /*find elements into topology */ - GstPad *unlinked_topo_pad = gst_bin_find_unlinked_pad(GST_BIN(ms_streamer->topology_bin), GST_PAD_SINK); - GstElement *unlinked_topo_element = gst_pad_get_parent_element(unlinked_topo_pad); - gchar *unlinked_topo_pad_name = gst_pad_get_name(unlinked_topo_pad); - - GstElement *encoder; - GstElement *pay; - if (MS_ELEMENT_IS_VIDEO(field)) { - dictionary *dict = NULL; - __ms_load_ini_dictionary(&dict); - - encoder = __ms_video_encoder_element_create(dict, MEDIA_FORMAT_H263); - pay = __ms_element_create(DEFAULT_VIDEO_RTPPAY, NULL); - gst_bin_add_many(GST_BIN(ms_streamer->topology_bin), encoder, pay, NULL); - - __ms_destroy_ini_dictionary(dict); - - gst_element_link_many(unlinked_element, encoder, pay, NULL); - gst_element_link_pads(pay, "src", unlinked_topo_element, unlinked_topo_pad_name); - } else if (MS_ELEMENT_IS_AUDIO(field)) { - encoder = __ms_audio_encoder_element_create(); - pay = __ms_element_create(DEFAULT_AUDIO_RTPPAY, NULL); - gst_bin_add_many(GST_BIN(ms_streamer->topology_bin), encoder, pay, NULL); - - gst_element_link_many(unlinked_element, encoder, pay, NULL); - gst_element_link_pads(pay, "src", unlinked_topo_element, unlinked_topo_pad_name); + ms_debug("Autoplug: found unlinked element [%s]\n", GST_ELEMENT_NAME(unlinked_element)); + + parent = (GstElement *)gst_element_get_parent(GST_OBJECT_CAST(unlinked_element)); + ms_info("Received new pad '%s' from [%s]\n", GST_PAD_NAME(unlinked_pad), GST_ELEMENT_NAME(unlinked_element)); + + /* If element in src bin is filesrc */ + if (__ms_src_need_typefind(unlinked_element)) + { + found_element = __ms_element_create("decodebin", NULL); + gst_bin_add_many((GstBin *)ms_streamer->topology_bin, found_element, NULL); + + gst_element_sync_state_with_parent(found_element); + g_signal_connect(found_element, "pad-added", G_CALLBACK (__decodebin_newpad_streamer_cb), ms_streamer); + + found_element = __ms_link_with_new_element(unlinked_element, found_element, NULL); + __ms_generate_dots(ms_streamer->pipeline, GST_ELEMENT_NAME(found_element)); + + MS_SAFE_UNREF(unlinked_pad); + } else { - ms_debug("Autoplug mode doesn't support [%s] type nodes.", field); - } - MS_SAFE_GFREE(unlinked_topo_pad_name); - MS_SAFE_GFREE(unlinked_element_name); - MS_SAFE_UNREF(unlinked_pad); - gst_caps_unref(pad_caps); + found_element = __ms_element_create(DEFAULT_QUEUE, NULL); + gst_bin_add_many((GstBin *)ms_streamer->topology_bin, found_element, NULL); + + gst_element_sync_state_with_parent(found_element); + found_element = __ms_link_with_new_element(unlinked_element, found_element, NULL); + __ms_generate_dots(parent, DEFAULT_QUEUE); + + /* Check the new pad's type */ + new_pad_caps = gst_pad_query_caps(unlinked_pad, 0); + new_pad_struct = gst_caps_get_structure(new_pad_caps, 0); + new_pad_type = gst_structure_get_name(new_pad_struct); + + if(MS_ELEMENT_IS_VIDEO(new_pad_type)) { + found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "video_encoder", "encoder", DEFAULT_VIDEO_ENCODER); + found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL, NULL); + found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL, NULL); + } + + if(MS_ELEMENT_IS_AUDIO(new_pad_type)) { + found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "audio_encoder", "encoder", DEFAULT_AUDIO_PARSER); + found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_PAYLOADER_KLASS, NULL, NULL, NULL); + found_element = __ms_combine_next_element(found_element, MEDIA_STREAMER_BIN_KLASS, "rtp_container", NULL, NULL); + } + __ms_generate_dots(parent, GST_ELEMENT_NAME(found_element)); + } unlinked_pad = gst_bin_find_unlinked_pad(GST_BIN(ms_streamer->src_bin), GST_PAD_SRC); } @@ -662,10 +693,10 @@ void __ms_node_check_param_name(GstElement *element, gboolean name_is_known, { set_param_name = param_table[it_param][0]; orig_param_name = param_table[it_param][1]; + param = g_object_class_find_property(G_OBJECT_GET_CLASS(element), orig_param_name); if (name_is_known) { if(!g_strcmp0(param_name, set_param_name)) { - param = g_object_class_find_property(G_OBJECT_GET_CLASS(element), orig_param_name); if (param) { *init_param_name = orig_param_name; break; @@ -673,7 +704,6 @@ void __ms_node_check_param_name(GstElement *element, gboolean name_is_known, } } else { if(!g_strcmp0(param_name, orig_param_name)) { - param = g_object_class_find_property(G_OBJECT_GET_CLASS(element), orig_param_name); if (param) { *init_param_name = set_param_name; break; @@ -762,4 +792,4 @@ int __ms_node_write_param_into_value(media_streamer_node_s *node, const char *pa *param_value = string_val; return MEDIA_STREAMER_ERROR_NONE; -} \ No newline at end of file +} diff --git a/test/media_streamer_test.c b/test/media_streamer_test.c index 3223ecd..d14b5e4 100755 --- a/test/media_streamer_test.c +++ b/test/media_streamer_test.c @@ -32,10 +32,11 @@ typedef enum { } menu_state_e; typedef enum { - SUBMENU_STATE_UNKNOWN = 0, + SUBMENU_STATE_UNKNOWN, SUBMENU_STATE_GETTING_IP, - SUBMENU_STATE_AUTOPLUG = 3, - SUBMENU_STATE_SCENARIO = 4, + SUBMENU_STATE_GETTING_URI, + SUBMENU_STATE_AUTOPLUG, + SUBMENU_STATE_SCENARIO, SUBMENU_STATE_FORMAT } submenu_state_e; @@ -56,14 +57,15 @@ typedef enum { typedef enum { - SCENARIO_MODE_UNKNOWN = 0, - SCENARIO_MODE_CAMERA_SCREEN = 1, - SCENARIO_MODE_MICROPHONE_PHONE = 2, - SCENARIO_MODE_FULL_VIDEO_AUDIO = 3, - SCENARIO_MODE_VIDEOTEST_SCREEN = 4, - SCENARIO_MODE_AUDIOTEST_PHONE = 5, - SCENARIO_MODE_TEST_VIDEO_AUDIO = 6, - SCENARIO_MODE_APPSRC_APPSINK = 7, + SCENARIO_MODE_UNKNOWN, + SCENARIO_MODE_CAMERA_SCREEN, + SCENARIO_MODE_MICROPHONE_PHONE, + SCENARIO_MODE_FULL_VIDEO_AUDIO, + SCENARIO_MODE_VIDEOTEST_SCREEN, + SCENARIO_MODE_AUDIOTEST_PHONE, + SCENARIO_MODE_TEST_VIDEO_AUDIO, + SCENARIO_MODE_FILESRC_VIDEO_AUDIO, + SCENARIO_MODE_APPSRC_APPSINK } scenario_mode_e; #define PACKAGE "media_streamer_test" @@ -87,6 +89,7 @@ static media_streamer_h current_media_streamer = &g_media_streamer; GMainLoop *g_loop; gchar *g_broadcast_address = NULL; +gchar *g_uri = NULL; menu_state_e g_menu_state = MENU_STATE_MAIN_MENU; submenu_state_e g_sub_menu_state = SUBMENU_STATE_UNKNOWN; preset_type_e g_menu_preset = PRESET_UNKNOWN; @@ -336,9 +339,11 @@ static gboolean _create_rtp_streamer(media_streamer_node_h rtp_bin) } else if (g_scenario_mode == SCENARIO_MODE_VIDEOTEST_SCREEN || g_scenario_mode == SCENARIO_MODE_TEST_VIDEO_AUDIO) { media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST, &video_src); + } else if (g_scenario_mode == SCENARIO_MODE_FILESRC_VIDEO_AUDIO) { + media_streamer_node_create_src( MEDIA_STREAMER_NODE_SRC_TYPE_FILE, &video_src); + media_streamer_node_set_param(video_src,MEDIA_STREAMER_PARAM_URI, g_uri); } - media_streamer_node_set_param(video_src, "is-live", "true"); media_streamer_node_add(current_media_streamer, video_src); /*********************** encoder **************************************** */ @@ -354,9 +359,9 @@ static gboolean _create_rtp_streamer(media_streamer_node_h rtp_bin) media_streamer_node_add(current_media_streamer, video_pay); /*====================Linking Video Streamer=========================== */ - media_streamer_node_link(video_src, "src", video_enc, "sink"); - media_streamer_node_link(video_enc, "src", video_pay, "sink"); - media_streamer_node_link(video_pay, "src", rtp_bin, "video_in"); + /* media_streamer_node_link(video_src, "src", video_enc, "sink"); */ + /* media_streamer_node_link(video_enc, "src", video_pay, "sink"); */ + /* media_streamer_node_link(video_pay, "src", rtp_bin, "video_in"); */ /*====================================================================== */ g_print("== success streamer video part \n"); @@ -388,9 +393,9 @@ static gboolean _create_rtp_streamer(media_streamer_node_h rtp_bin) media_streamer_node_add(current_media_streamer, audio_pay); /*====================Linking Audio Streamer========================== */ - media_streamer_node_link(audio_src, "src", audio_enc, "sink"); - media_streamer_node_link(audio_enc, "src", audio_pay, "sink"); - media_streamer_node_link(audio_pay, "src", rtp_bin, "audio_in"); + /* media_streamer_node_link(audio_src, "src", audio_enc, "sink"); */ + /* media_streamer_node_link(audio_enc, "src", audio_pay, "sink"); */ + /* media_streamer_node_link(audio_pay, "src", rtp_bin, "audio_in"); */ /*====================================================================== */ g_print("== success streamer audio part \n"); @@ -414,6 +419,9 @@ static gboolean _create_rtp_streamer_autoplug(media_streamer_node_h rtp_bin) } else if (g_scenario_mode == SCENARIO_MODE_VIDEOTEST_SCREEN || g_scenario_mode == SCENARIO_MODE_TEST_VIDEO_AUDIO) { media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST, &video_src); + } else if (g_scenario_mode == SCENARIO_MODE_FILESRC_VIDEO_AUDIO) { + media_streamer_node_create_src( MEDIA_STREAMER_NODE_SRC_TYPE_FILE, &video_src); + media_streamer_node_set_param(video_src,MEDIA_STREAMER_PARAM_URI, g_uri); } media_streamer_node_add(current_media_streamer, video_src); @@ -465,8 +473,8 @@ static gboolean _create_rtp_client(media_streamer_node_h rtp_bin) media_streamer_node_add(current_media_streamer, video_sink); /*====================Linking Video Client=========================== */ - media_streamer_node_link(video_depay, "src", video_dec, "sink"); - media_streamer_node_link(video_dec, "src", video_sink, "sink"); + /* media_streamer_node_link(video_depay, "src", video_dec, "sink"); */ + /* media_streamer_node_link(video_dec, "src", video_sink, "sink"); */ g_print("== success client video part \n"); } @@ -553,9 +561,10 @@ static void buffer_status_cb(media_streamer_node_h node, media_streamer_custom_buffer_status_e status, void *user_data) { - static int count = 0; /* Try send only 10 packets*/ - if (status == MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN - && count < 10) { + static int count = 0; + + /* Try send only 10 packets*/ + if (status == MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN && count < 10) { g_print("Buffer status cb got underflow\n"); char *test = g_strdup_printf("[%d]This is buffer_status_cb test!", count); @@ -587,7 +596,6 @@ static void new_buffer_cb(media_streamer_node_h node, void *user_data) static void eos_cb(media_streamer_node_h node, void *user_data) { - g_print("Got EOS cb from appsink\n"); } @@ -648,6 +656,11 @@ void reset_current_menu_state(void) g_free(g_broadcast_address); g_broadcast_address = NULL; } + + if (g_uri != NULL) { + g_free(g_uri); + g_uri = NULL; + } } void quit() @@ -663,6 +676,12 @@ static void display_getting_ip_menu(void) g_print("By default will be used [%s]\n", DEFAULT_IP_ADDR); } +static void display_getting_uri_menu(void) +{ + g_print("\n"); + g_print("Please input URI for playing\n"); +} + static void display_autoplug_select_menu(void) { g_print("\n"); @@ -685,7 +704,8 @@ static void display_scenario_select_menu(void) g_print("4. Video test -> Screen\n"); g_print("5. Audio test -> Phones\n"); g_print("6. Video test + Audio test -> Screen + Phones\n"); - g_print("7. Appsrc -> Appsink\n"); + g_print("7. Filesrc -> Screen + Phones\n"); + g_print("8. Appsrc -> Appsink\n"); } static void display_preset_menu(void) @@ -775,6 +795,9 @@ static void display_menu(void) case SUBMENU_STATE_GETTING_IP: display_getting_ip_menu(); break; + case SUBMENU_STATE_GETTING_URI: + display_getting_uri_menu(); + break; case SUBMENU_STATE_AUTOPLUG: display_autoplug_select_menu(); break; @@ -954,6 +977,14 @@ void _interpret_scenario_menu(char *cmd) g_video_is_on = TRUE; g_audio_is_on = TRUE; } else if (!strncmp(cmd, "7", len)) { + g_scenario_mode = SCENARIO_MODE_FILESRC_VIDEO_AUDIO; + g_video_is_on = TRUE; + g_audio_is_on = TRUE; + if (g_menu_preset & PRESET_RTP_STREAMER) { + g_sub_menu_state = SUBMENU_STATE_GETTING_URI; + return; + } + } else if (!strncmp(cmd, "8", len)) { g_scenario_mode = SCENARIO_MODE_APPSRC_APPSINK; g_video_is_on = FALSE; g_audio_is_on = FALSE; @@ -983,6 +1014,23 @@ void _interpret_getting_ip_menu(char *cmd) g_sub_menu_state = SUBMENU_STATE_SCENARIO; } +void _interpret_getting_uri_menu(char *cmd) +{ + if (cmd) { + if (g_uri != NULL) { + g_free(g_uri); + } + g_uri = g_strdup(cmd); + g_print("== URI set to [%s]\n", g_uri); + } else { + g_print("Empty URI!\n"); + return; + } + + g_sub_menu_state = SUBMENU_STATE_UNKNOWN; + run_preset(); +} + void _interpret_autoplug_menu(char *cmd) { int cmd_number = atoi(cmd) - 1; @@ -1076,6 +1124,9 @@ static void interpret_cmd(char *cmd) case SUBMENU_STATE_GETTING_IP: _interpret_getting_ip_menu(cmd); break; + case SUBMENU_STATE_GETTING_URI: + _interpret_getting_uri_menu(cmd); + break; case SUBMENU_STATE_AUTOPLUG: _interpret_autoplug_menu(cmd); break;