support local playback
[platform/core/multimedia/libmm-player.git] / src / mm_player_gst.c
index de2a740..56e9500 100644 (file)
@@ -1925,6 +1925,73 @@ __mmplayer_gst_handle_async_done_message(mmplayer_t *player, GstMessage *msg)
 }
 
 static void
+__mmplayer_print_tag_foreach(const GstTagList *tags, const gchar *tag, gpointer user_data)
+{
+       GValue val = { 0, };
+       gchar *str = NULL;
+       gint depth = GPOINTER_TO_INT(user_data);
+
+       if (!gst_tag_list_copy_value(&val, tags, tag))
+               return;
+
+       if (G_VALUE_HOLDS_STRING(&val))
+               str = g_value_dup_string(&val);
+       else
+               str = gst_value_serialize(&val);
+
+       LOGD("%*s%s: %s\n", 2 * depth, " ", gst_tag_get_nick(tag), str);
+       g_free(str);
+       g_value_unset(&val);
+}
+
+static void
+__mmplayer_dump_collection(GstStreamCollection * collection)
+{
+       guint i = 0;
+       GstTagList *tags = NULL;
+       GstCaps *caps = NULL;
+
+       for (i = 0; i < gst_stream_collection_get_size(collection); i++) {
+               GstStream *stream = gst_stream_collection_get_stream(collection, i);
+               LOGD ("collection: Stream %u type %s flags 0x%x\n", i,
+                               gst_stream_type_get_name(gst_stream_get_stream_type(stream)),
+                               gst_stream_get_stream_flags(stream));
+               LOGD ("  ID: %s\n", gst_stream_get_stream_id(stream));
+
+               caps = gst_stream_get_caps(stream);
+               if (caps) {
+                       gchar *caps_str = gst_caps_to_string(caps);
+                       LOGD ("  caps: %s\n", caps_str);
+                       g_free(caps_str);
+                       gst_caps_unref(caps);
+               }
+
+               tags = gst_stream_get_tags(stream);
+               if (tags) {
+                       LOGD ("  tags:\n");
+                       gst_tag_list_foreach(tags, __mmplayer_print_tag_foreach, GUINT_TO_POINTER(3));
+                       gst_tag_list_unref(tags);
+               }
+       }
+}
+
+static void
+__mmplayer_stream_notify_cb(GstStreamCollection *collection,
+                       GstStream *stream, GParamSpec *pspec, gpointer data)
+{
+
+       LOGD ("Got stream-notify from stream %s for %s (collection %p)\n",
+                               stream->stream_id, pspec->name, collection);
+       if (g_str_equal(pspec->name, "caps")) {
+               GstCaps *caps = gst_stream_get_caps(stream);
+               gchar *caps_str = gst_caps_to_string(caps);
+               LOGD (" New caps: %s\n", caps_str);
+               g_free(caps_str);
+               gst_caps_unref(caps);
+       }
+}
+
+static void
 __mmplayer_gst_bus_msg_callback(GstMessage *msg, gpointer data)
 {
        mmplayer_t *player = (mmplayer_t *)(data);
@@ -2029,11 +2096,42 @@ __mmplayer_gst_bus_msg_callback(GstMessage *msg, gpointer data)
                __mmplayer_gst_handle_async_done_message(player, msg);
                break;
        case GST_MESSAGE_STREAM_COLLECTION:
+       {
+               GstStreamCollection *collection = NULL;
                LOGD("GST_MESSAGE_STREAM_COLLECTION : %s", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
-               break;
+
+               gst_message_parse_stream_collection(msg, &collection);
+               if (collection) {
+                       __mmplayer_dump_collection(collection);
+                       if (player->collection && player->stream_notify_id) {
+                               g_signal_handler_disconnect(player->collection, player->stream_notify_id);
+                               player->stream_notify_id = 0;
+                       }
+                       gst_object_replace((GstObject **)&player->collection, (GstObject *)collection);
+                       if (player->collection) {
+                               player->stream_notify_id = g_signal_connect(player->collection, "stream-notify",
+                                                       (GCallback)__mmplayer_stream_notify_cb, player);
+                       }
+                       gst_object_unref(collection);
+               }
+       } break;
        case GST_MESSAGE_STREAMS_SELECTED:
+       {
+               GstStreamCollection *collection = NULL;
                LOGD("GST_MESSAGE_STREAMS_SELECTED : %s", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
-               break;
+
+               gst_message_parse_streams_selected(msg, &collection);
+               if (collection) {
+                       guint i = 0, len = 0;
+                       len = gst_message_streams_selected_get_size(msg);
+                       for (i = 0; i < len; i++) {
+                               GstStream *stream = gst_message_streams_selected_get_stream(msg, i);
+                               LOGD ("  Stream #%d : %s\n", i, gst_stream_get_stream_id(stream));
+                               gst_object_unref(stream);
+                       }
+                       gst_object_unref (collection);
+               }
+       } break;
 
 #ifdef __DEBUG__
        case GST_MESSAGE_REQUEST_STATE:         LOGD("GST_MESSAGE_REQUEST_STATE"); break;
@@ -2747,9 +2845,6 @@ void __mmplayer_http_src_setup(GstElement *element, GstElement *source, gpointer
                return;
        }
 
-       player->pipeline->mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
-       player->pipeline->mainbin[MMPLAYER_M_SRC].gst = source;
-
        /* get attribute */
        mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
        mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
@@ -2778,6 +2873,22 @@ void __mmplayer_http_src_setup(GstElement *element, GstElement *source, gpointer
        return;
 }
 
+static void
+__mmplayer_source_setup_cb(GstElement *element, GstElement *source, gpointer data)
+{
+       mmplayer_t *player = (mmplayer_t *)data;
+       LOGD("%s >> %s", GST_ELEMENT_NAME(element), GST_ELEMENT_NAME(source));
+
+       player->pipeline->mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
+       player->pipeline->mainbin[MMPLAYER_M_SRC].gst = source;
+
+       if (MMPLAYER_IS_HTTP_STREAMING(player)) {
+               __mmplayer_http_src_setup(element, source, data);
+       } else if (MMPLAYER_IS_SMOOTH_STREAMING(player)) {
+               g_object_set(G_OBJECT(source), "timeout", DEFAULT_HTTP_TIMEOUT, NULL);
+       }
+}
+
 gint __mmplayer_gst_select_stream (GstElement * uridecodebin, GstStreamCollection * collection,
     GstStream * stream, gpointer data)
 {
@@ -2810,14 +2921,17 @@ __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *el
                factory_name, GST_ELEMENT_NAME(element));
 
        /* keep the first typefind reference only */
-       if (!mainbin[MMPLAYER_M_TYPEFIND].gst && g_strrstr(factory_name, "typefind")) {
+       if (!mainbin[MMPLAYER_M_TYPEFIND].gst && g_strrstr(factory_name, "typefind")) {  // FIXME : not required for local playback+
                mainbin[MMPLAYER_M_TYPEFIND].id = MMPLAYER_M_TYPEFIND;
                mainbin[MMPLAYER_M_TYPEFIND].gst = element;
 
                _mmplayer_add_signal_connection(player, G_OBJECT(element),
                        MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type", G_CALLBACK(_mmplayer_typefind_have_type), (gpointer)player);
+               LOGD("typefind reference is added");
+               return;
+       }
 
-       } else if (!mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst && g_strrstr(factory_name, "queue2")) {
+       if (!mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst && g_strrstr(factory_name, "queue2")) { // fix me :streaming only..
 
                gint64 dur_bytes = 0L;
                muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE;
@@ -2847,16 +2961,16 @@ __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *el
                                                                                type,
                                                                                (guint64)dur_bytes); /* no meaning at the moment */
 
-       } else if (g_strrstr(factory_name, "parsebin")) {
+               return;
+       }
 
+       if (g_strrstr(factory_name, "parsebin")) {
                if (!mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) {
                        GstIterator *iter = NULL;
                        GValue item = {0, };
                        GstElement *ch_element = NULL;
                        GstElementFactory *ch_factory = NULL;
 
-                       g_object_set(G_OBJECT(child), "message-forward", TRUE, NULL);
-
                        iter = gst_bin_iterate_recurse(child);
                        if (iter != NULL) {
                                while (gst_iterator_next(iter, &item) == GST_ITERATOR_OK) {
@@ -2880,6 +2994,13 @@ __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *el
                                gst_iterator_free(iter);
                        }
                }
+       }
+
+       if (g_strrstr(factory_name, "parsebin")) {
+
+               g_object_set(G_OBJECT(child), "message-forward", TRUE, NULL);
+               g_object_set(G_OBJECT(element), "message-forward", TRUE, NULL);
+
                mainbin[MMPLAYER_M_AUTOPLUG_PARSEBIN].id = MMPLAYER_M_AUTOPLUG_PARSEBIN;
                mainbin[MMPLAYER_M_AUTOPLUG_PARSEBIN].gst = element;
                _mmplayer_add_signal_connection(player, G_OBJECT(element),
@@ -2926,10 +3047,12 @@ __mmplayer_gst_make_uridecodebin(mmplayer_t *player)
        SECURE_LOGD("uri : %s", player->profile.uri);
 
        /* setting property to streaming source */
-       g_object_set(G_OBJECT(uridecodebin3), "uri", player->profile.uri, "message-forward", TRUE, NULL);
+       g_object_set(G_OBJECT(uridecodebin3), "uri", player->profile.uri,
+                       "message-forward", TRUE,
+                       "buffer-size", DEFAULT_BUFFER_SIZE_BYTES, NULL);
 
        _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
-               MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "source-setup", G_CALLBACK(__mmplayer_http_src_setup), (gpointer)player);
+               MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "source-setup", G_CALLBACK(__mmplayer_source_setup_cb), (gpointer)player);
 
        _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
                MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added", G_CALLBACK(_mmplayer_gst_decode_pad_added), (gpointer)player);
@@ -3982,6 +4105,72 @@ _mmplayer_gst_build_es_pipeline(mmplayer_t *player)
        return MM_ERROR_NONE;
 }
 
+static int
+__mmplayer_gst_build_pipeline_with_src(mmplayer_t *player)
+{
+       mmplayer_gst_element_t *mainbin = NULL;
+       GstElement *autoplug_elem = NULL;
+
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
+                               player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+       mainbin = player->pipeline->mainbin;
+
+       LOGD("uri type %d", player->profile.uri_type);
+
+       autoplug_elem = __mmplayer_gst_make_uridecodebin(player);
+       if (!autoplug_elem) {
+               LOGE("failed to create uridecodebin3 element");
+               goto ERROR;
+       }
+
+       LOGD("autoplug elem is created %s", GST_ELEMENT_NAME(autoplug_elem));
+       mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
+       mainbin[MMPLAYER_M_AUTOPLUG].gst = autoplug_elem;
+
+       if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), autoplug_elem)) {
+               LOGE("failed to add uridecodebin to pipeline");
+               goto ERROR;
+       }
+
+       /* FIXME: required ?*/
+       /* create fakesink element for keeping the pipeline state PAUSED. if needed */
+       mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
+       mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make("fakesink", "state-holder");
+
+       if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst) {
+               LOGE("failed to create fakesink");
+               goto ERROR;
+       }
+       GST_OBJECT_FLAG_UNSET(mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
+
+       /* take ownership of fakesink. we are reusing it */
+       gst_object_ref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
+
+       if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[MMPLAYER_M_SRC_FAKESINK].gst)) {
+               LOGE("failed to add fakesink to bin");
+               gst_object_unref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
+               goto ERROR;
+       }
+
+       MMPLAYER_FLEAVE();
+       return MM_ERROR_NONE;
+
+ERROR:
+
+       if (mainbin[MMPLAYER_M_AUTOPLUG].gst)
+               gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_AUTOPLUG].gst));
+
+       if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
+               gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
+
+       mainbin[MMPLAYER_M_AUTOPLUG].gst = NULL;
+       mainbin[MMPLAYER_M_SRC_FAKESINK].gst = NULL;
+
+       return MM_ERROR_PLAYER_INTERNAL;
+}
+
 int
 _mmplayer_gst_build_pipeline(mmplayer_t *player)
 {
@@ -3995,8 +4184,6 @@ _mmplayer_gst_build_pipeline(mmplayer_t *player)
        MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
                                player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
 
-       mainbin = player->pipeline->mainbin;
-
        LOGD("uri type %d", player->profile.uri_type);
 
        /* create source element */
@@ -4005,18 +4192,31 @@ _mmplayer_gst_build_pipeline(mmplayer_t *player)
                src_elem = __mmplayer_gst_make_rtsp_src(player);
                break;
        case MM_PLAYER_URI_TYPE_URL_HTTP:
-               if (player->ini.use_uridecodebin3) { /* or MMPLAYER_USE_URIDECODEBIN3(player) */
+               if (player->ini.use_uridecodebin3) {
                        LOGD("uridecodebin include src element.");
-                       goto ADD_DECODEBIN;
+                       return __mmplayer_gst_build_pipeline_with_src(player);
                }
                src_elem = __mmplayer_gst_make_http_src(player);
                break;
        case MM_PLAYER_URI_TYPE_FILE:
+               if (player->ini.use_uridecodebin3) {
+                       if (!_mmplayer_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
+                               LOGE("failed to get storage info");
+                               break;
+                       }
+                       LOGD("uridecodebin include src element.");
+                       return __mmplayer_gst_build_pipeline_with_src(player);
+               }
                src_elem = __mmplayer_gst_make_file_src(player);
                break;
        case MM_PLAYER_URI_TYPE_SS:
                {
                        gint http_timeout = DEFAULT_HTTP_TIMEOUT;
+                       if (player->ini.use_uridecodebin3) {
+                               LOGD("uridecodebin include src element.");
+                               return __mmplayer_gst_build_pipeline_with_src(player);
+                       }
+
                        src_elem = gst_element_factory_make("souphttpsrc", "http streaming source");
                        if (!src_elem) {
                                LOGE("failed to create http streaming source element[%s]", player->ini.httpsrc_element);
@@ -4061,6 +4261,8 @@ _mmplayer_gst_build_pipeline(mmplayer_t *player)
                return MM_ERROR_PLAYER_INTERNAL;
        }
 
+       mainbin = player->pipeline->mainbin;
+
        /* take source element */
        LOGD("source elem is created %s", GST_ELEMENT_NAME(src_elem));
 
@@ -4068,25 +4270,17 @@ _mmplayer_gst_build_pipeline(mmplayer_t *player)
        mainbin[MMPLAYER_M_SRC].gst = src_elem;
        element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
 
-ADD_DECODEBIN: /* create next element for auto-plugging */
+       /* create next element for auto-plugging */
        if (MMPLAYER_IS_HTTP_STREAMING(player)) {
-               if (!src_elem) { /* make uridecodebin3 which include src element */
-                       autoplug_elem_id = MMPLAYER_M_AUTOPLUG;
-                       autoplug_elem = __mmplayer_gst_make_uridecodebin(player);
-                       if (!autoplug_elem) {
-                               LOGE("failed to create uridecodebin3 element");
-                               goto ERROR;
-                       }
-               } else {
-                       autoplug_elem_id = MMPLAYER_M_TYPEFIND;
-                       autoplug_elem = gst_element_factory_make("typefind", "typefinder");
-                       if (!autoplug_elem) {
-                               LOGE("failed to create typefind element");
-                               goto ERROR;
-                       }
-                       _mmplayer_add_signal_connection(player, G_OBJECT(autoplug_elem), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
-                                                                               G_CALLBACK(_mmplayer_typefind_have_type), (gpointer)player);
+               autoplug_elem_id = MMPLAYER_M_TYPEFIND;
+               autoplug_elem = gst_element_factory_make("typefind", "typefinder");
+               if (!autoplug_elem) {
+                       LOGE("failed to create typefind element");
+                       goto ERROR;
                }
+
+               _mmplayer_add_signal_connection(player, G_OBJECT(autoplug_elem), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
+                                                                       G_CALLBACK(_mmplayer_typefind_have_type), (gpointer)player);
        } else if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
                autoplug_elem_id = MMPLAYER_M_AUTOPLUG;
                autoplug_elem = _mmplayer_gst_make_decodebin(player);
@@ -4311,14 +4505,14 @@ _mmplayer_activate_next_source(mmplayer_t *player, GstState target)
                goto ERROR;
        }
 
-       if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
-               if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
-                       LOGE("Failed to change state of decodebin");
+       if (MMPLAYER_IS_HTTP_STREAMING(player)) {
+               if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) {  // ????
+                       LOGE("Failed to change state of src element");
                        goto ERROR;
                }
        } else {
-               if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) {
-                       LOGE("Failed to change state of src element");
+               if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
+                       LOGE("Failed to change state of decodebin");
                        goto ERROR;
                }
        }