Merge branch 'tizen' into tizen_5.5_devel
[platform/core/multimedia/libmm-player.git] / src / mm_player_gst.c
index 3312104..de2a740 100644 (file)
@@ -243,9 +243,6 @@ __mmplayer_gst_transform_gsterror(mmplayer_t *player, GstMessage *message, GErro
                                                                player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
 
        src_element = GST_ELEMENT_CAST(message->src);
-       if (!src_element)
-               return MM_ERROR_PLAYER_INTERNAL;
-
        src_element_name = GST_ELEMENT_NAME(src_element);
        if (!src_element_name)
                return MM_ERROR_PLAYER_INTERNAL;
@@ -1009,6 +1006,24 @@ __mmplayer_gst_check_useful_message(mmplayer_t *player, GstMessage *message)
                if (!MMPLAYER_USE_URIDECODEBIN3(player))
                        break; /* drop msg */
 
+               if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
+                       (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
+                       (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) {
+
+                       gint64 dur_bytes = 0L;
+
+                       if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
+                               LOGE("fail to get duration.");
+
+                       /* there is no mq, enable use-buffering on queue2 (ex) wav streaming
+                        * use file information was already set on Q2 when it was created. */
+                       _mm_player_streaming_set_queue2(player->streamer,
+                                                       player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
+                                                       TRUE,                                                           /* use_buffering */
+                                                       MUXED_BUFFER_TYPE_MAX,                          /* use previous buffer type setting */
+                                                       ((dur_bytes > 0) ? ((guint64)dur_bytes) : 0));
+               }
+
                LOGD("GST_MESSAGE_STREAMS_SELECTED");
                player->no_more_pad = TRUE;
                _mmplayer_pipeline_complete(NULL, player);
@@ -1832,18 +1847,12 @@ __mmplayer_gst_handle_element_message(mmplayer_t *player, GstMessage *msg)
                                        "rtsp_video_frame_size", G_TYPE_STRING, &video_frame_size, NULL);
                LOGD("rtsp_video_frame_size : %s", video_frame_size);
                if (video_frame_size) {
-                       char *seperator = strchr(video_frame_size, '-');
-                       if (seperator) {
-                               char video_width[10] = {0,};
-                               int frame_size_len = strlen(video_frame_size);
-                               int separtor_len = strlen(seperator);
-
-                               strncpy(video_width, video_frame_size, (frame_size_len - separtor_len));
-                               seperator++;
-
-                               mm_player_set_attribute((MMHandleType)player, NULL, MM_PLAYER_VIDEO_WIDTH,
-                                               atoi(video_width), MM_PLAYER_VIDEO_HEIGHT, atoi(seperator), NULL);
-                       }
+                       gchar **res_str = g_strsplit(video_frame_size, "-", 0);
+                       mm_player_set_attribute((MMHandleType)player, NULL,
+                               MM_PLAYER_VIDEO_WIDTH, atoi(res_str[0]),
+                               MM_PLAYER_VIDEO_HEIGHT, atoi(res_str[1]),
+                               NULL);
+                       g_strfreev(res_str);
                }
        }
 
@@ -1934,6 +1943,7 @@ __mmplayer_gst_bus_msg_callback(GstMessage *msg, gpointer data)
                break;
 
        case GST_MESSAGE_ERROR:
+               _mmplayer_set_reconfigure_state(player, FALSE);
                __mmplayer_gst_handle_error_message(player, msg);
                break;
 
@@ -2092,6 +2102,18 @@ __mmplayer_gst_bus_sync_callback(GstBus *bus, GstMessage *message, gpointer data
        case GST_MESSAGE_DURATION_CHANGED:
                __mmplayer_gst_handle_duration(player, message);
                break;
+       case GST_MESSAGE_ELEMENT:
+               {
+                       const gchar *klass = NULL;
+                       klass = gst_element_factory_get_metadata
+                               (gst_element_get_factory((GstElement *)message->src), GST_ELEMENT_METADATA_KLASS);
+                       if (!klass || !g_strrstr(klass, "Codec/Decoder")) {
+                               reply = GST_BUS_PASS;
+                               break;
+                       }
+                       __mmplayer_gst_handle_element_message(player, message);
+               }
+               break;
        case GST_MESSAGE_ASYNC_DONE:
                /* NOTE:Don't call gst_callback directly
                 * because previous frame can be showed even though this message is received for seek.
@@ -2313,6 +2335,10 @@ __mmplayer_gst_create_es_decoder(mmplayer_t *player, mmplayer_stream_type_e type
        _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
                                                                                G_CALLBACK(_mmplayer_gst_decode_autoplug_select), (gpointer)player);
 
+       if (player->need_video_dec_sorting || player->need_audio_dec_sorting)
+               _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort",
+                                                       G_CALLBACK(_mmplayer_gst_decode_autoplug_sort), (gpointer)player);
+
        /* This signal is emitted when a element is added to the bin.*/
        _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
                                                                                G_CALLBACK(_mmplayer_gst_element_added), (gpointer)player);
@@ -2772,34 +2798,106 @@ __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *el
 {
        gchar *factory_name = NULL;
        mmplayer_t *player = (mmplayer_t *)data;
+       mmplayer_gst_element_t *mainbin = NULL;
+
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
 
        factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
+       mainbin = player->pipeline->mainbin;
 
        LOGD("%s > %s > %s : %s", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(child),
                factory_name, GST_ELEMENT_NAME(element));
 
        /* keep the first typefind reference only */
-       if (!player->pipeline->mainbin[MMPLAYER_M_TYPEFIND].gst && g_strrstr(factory_name, "typefind")) {
-               player->pipeline->mainbin[MMPLAYER_M_TYPEFIND].id = MMPLAYER_M_TYPEFIND;
-               player->pipeline->mainbin[MMPLAYER_M_TYPEFIND].gst = element;
+       if (!mainbin[MMPLAYER_M_TYPEFIND].gst && g_strrstr(factory_name, "typefind")) {
+               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);
+
+       } else if (!mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst && g_strrstr(factory_name, "queue2")) {
+
+               gint64 dur_bytes = 0L;
+               muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE;
+
+               mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
+               mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
+
+               if (!gst_element_query_duration(mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
+                       LOGW("failed to get duration from source %s", GST_ELEMENT_NAME(mainbin[MMPLAYER_M_SRC].gst));
+
+               LOGD("type %s, dur_bytes = %"G_GINT64_FORMAT, player->type, dur_bytes);
+
+               /* NOTE : in case of ts streaming, player could not get the correct duration info *
+                *                skip the pull mode(file or ring buffering) setting. */
+               if (dur_bytes > 0) {
+                       if ((!g_strrstr(player->type, "video/mpegts")) && (!g_strrstr(player->type, "application/x-hls"))) {
+                               type = MUXED_BUFFER_TYPE_MEM_RING_BUFFER;
+                               player->streamer->ring_buffer_size = player->ini.http_ring_buffer_size;
+                       }
+               } else {
+                       dur_bytes = 0;
+               }
+
+               _mm_player_streaming_set_queue2(player->streamer,
+                                                                               element,
+                                                                               FALSE,
+                                                                               type,
+                                                                               (guint64)dur_bytes); /* no meaning at the moment */
+
        } else if (g_strrstr(factory_name, "parsebin")) {
-               player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG_PARSEBIN].id = MMPLAYER_M_AUTOPLUG_PARSEBIN;
-               player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG_PARSEBIN].gst = element;
+
+               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) {
+                                       ch_element = g_value_get_object(&item);
+                                       ch_factory = gst_element_get_factory(ch_element);
+
+                                       if (g_strrstr(GST_OBJECT_NAME(ch_factory), "multiqueue")) {
+                                               player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
+                                               player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = ch_element;
+
+                                               if ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
+                                                       (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) ||
+                                                       (MMPLAYER_IS_DASH_STREAMING(player))) {
+                                                       _mm_player_streaming_set_multiqueue(player->streamer, ch_element);
+                                               }
+                                               g_value_reset(&item);
+                                               break;
+                                       }
+                                       g_value_reset(&item);
+                               }
+                               gst_iterator_free(iter);
+                       }
+               }
+               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),
                        MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type", G_CALLBACK(_mmplayer_gst_decode_unknown_type), (gpointer)player);
 
                _mmplayer_add_signal_connection(player, G_OBJECT(element),
                        MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue", G_CALLBACK(_mmplayer_gst_decode_autoplug_continue), (gpointer)player);
 
+               if (player->need_video_dec_sorting || player->need_audio_dec_sorting)
+                       _mmplayer_add_signal_connection(player, G_OBJECT(element),
+                       MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort", G_CALLBACK(_mmplayer_gst_decode_autoplug_sort), (gpointer)player);
+
                _mmplayer_add_signal_connection(player, G_OBJECT(element),
                        MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select", G_CALLBACK(_mmplayer_gst_decode_autoplug_select), (gpointer)player);
+
        } else {
                _mmplayer_gst_element_added((GstElement *)child, element, data);
        }
-
        return;
 }
 
@@ -2814,7 +2912,6 @@ static GstElement *
 __mmplayer_gst_make_uridecodebin(mmplayer_t *player)
 {
        GstElement *uridecodebin3 = NULL;
-       GstElement *decodebin3 = NULL, *multiqueue = NULL;
 
        MMPLAYER_FENTER();
        MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
@@ -2828,21 +2925,6 @@ __mmplayer_gst_make_uridecodebin(mmplayer_t *player)
        /* get attribute */
        SECURE_LOGD("uri : %s", player->profile.uri);
 
-       decodebin3 = gst_bin_get_by_name((GstBin *)uridecodebin3, "decodebin3-0");
-
-       if (decodebin3) {
-               g_object_set(G_OBJECT(decodebin3), "message-forward", TRUE, NULL);
-               multiqueue = gst_bin_get_by_name((GstBin *)decodebin3, "multiqueue0");
-       }
-
-       if (multiqueue) {
-               player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
-               player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = multiqueue;
-
-               /* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h */
-               _mm_player_streaming_set_multiqueue(player->streamer, multiqueue);
-       }
-
        /* setting property to streaming source */
        g_object_set(G_OBJECT(uridecodebin3), "uri", player->profile.uri, "message-forward", TRUE, NULL);
 
@@ -4229,11 +4311,6 @@ _mmplayer_activate_next_source(mmplayer_t *player, GstState target)
                goto ERROR;
        }
 
-       if (gst_element_set_state(mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE) {
-               LOGE("Failed to change state of src element");
-               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");
@@ -4246,6 +4323,11 @@ _mmplayer_activate_next_source(mmplayer_t *player, GstState target)
                }
        }
 
+       if (gst_element_set_state(mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE) {
+               LOGE("Failed to change state of src element");
+               goto ERROR;
+       }
+
        player->gapless.stream_changed = TRUE;
        player->gapless.running = TRUE;
        MMPLAYER_FLEAVE();
@@ -4253,8 +4335,7 @@ _mmplayer_activate_next_source(mmplayer_t *player, GstState target)
 
 ERROR:
        if (player) {
-               MMPLAYER_PLAYBACK_UNLOCK(player);
-
+               _mmplayer_set_reconfigure_state(player, FALSE);
                if (!player->msg_posted) {
                        MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
                        player->msg_posted = TRUE;