X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmm_player_gst.c;h=da38d539c7b484bcacae974fd8f6bc2f6aedc01d;hb=fb4ccd152b91377ac03a0cbd9e2bb644f766c046;hp=7e5e69ec018e843af022876eae468fb5baac16fd;hpb=acf607e216dfc978fcb2c240134b98799a1555c1;p=platform%2Fcore%2Fmultimedia%2Flibmm-player.git diff --git a/src/mm_player_gst.c b/src/mm_player_gst.c index 7e5e69e..da38d53 100644 --- a/src/mm_player_gst.c +++ b/src/mm_player_gst.c @@ -227,7 +227,7 @@ __mmplayer_gst_transform_gsterror(mmplayer_t *player, GstMessage *message, GErro LOGD("error code=%d, msg=%s, src element=%s, class=%s", error->code, error->message, src_element_name, klass); - if (!MMPLAYER_USE_URIDECODEBIN3(player) && + if (MMPLAYER_USE_DECODEBIN(player) && !__mmplayer_check_error_posted_from_activated_track(player, src_element_name)) return MM_ERROR_NONE; @@ -973,7 +973,7 @@ __mmplayer_gst_check_useful_message(mmplayer_t *player, GstMessage *message) } case GST_MESSAGE_STREAMS_SELECTED: { - if (!MMPLAYER_USE_URIDECODEBIN3(player)) + if (MMPLAYER_USE_DECODEBIN(player)) break; /* drop msg */ if ((MMPLAYER_IS_HTTP_STREAMING(player)) && @@ -996,6 +996,7 @@ __mmplayer_gst_check_useful_message(mmplayer_t *player, GstMessage *message) LOGD("GST_MESSAGE_STREAMS_SELECTED"); player->no_more_pad = TRUE; + _mmplayer_set_reconfigure_state(player, FALSE); _mmplayer_pipeline_complete(NULL, player); retval = TRUE; break; @@ -2867,6 +2868,17 @@ __mmplayer_gst_found_source(GObject *object, GObject *orig, GParamSpec *pspec, g if (MMPLAYER_IS_HTTP_STREAMING(player)) { __mmplayer_http_src_setup(source, data); + } else if (MMPLAYER_IS_RTSP_STREAMING(player)) { + gchar *user_agent = NULL; + + /* get attribute */ + mm_attrs_get_string_by_name(player->attrs, "streaming_user_agent", &user_agent); + + SECURE_LOGD("user_agent : %s", user_agent); + + /* setting property to streaming source */ + if (user_agent) + g_object_set(G_OBJECT(source), "user-agent", user_agent, NULL); } else if (MMPLAYER_IS_SMOOTH_STREAMING(player)) { g_object_set(G_OBJECT(source), "timeout", DEFAULT_HTTP_TIMEOUT, NULL); } else if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM) { @@ -2881,47 +2893,144 @@ __mmplayer_gst_found_source(GObject *object, GObject *orig, GParamSpec *pspec, g MMPLAYER_FLEAVE(); } -gint __mmplayer_gst_select_stream (GstElement * uridecodebin, GstStreamCollection * collection, +static gint +__mmplayer_gst_select_stream (GstElement * uridecodebin, GstStreamCollection * collection, GstStream * stream, gpointer data) { - GstStreamType stype = gst_stream_get_stream_type (stream); + gint ret = 0; /* 1: select, 0: skip, -1: depends on decodebin */ + GstStreamType stype = gst_stream_get_stream_type(stream); mmplayer_t *player = (mmplayer_t *)data; mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_MAX; + GstCaps *caps = gst_stream_get_caps(stream); + gchar *caps_str = NULL; - if (stype & GST_STREAM_TYPE_AUDIO) { - LOGW("AUDIO type 0x%X", stype); - type = MM_PLAYER_TRACK_TYPE_AUDIO; + LOGD("Stream type %s flags 0x%x", + gst_stream_type_get_name(stype), + gst_stream_get_stream_flags(stream)); + LOGD(" ID: %s", gst_stream_get_stream_id(stream)); + + if (caps) { + caps_str = gst_caps_to_string(caps); + LOGD(" caps: %s", caps_str); } - if (stype & GST_STREAM_TYPE_VIDEO) { - LOGW("VIDEO type 0x%X", stype); - if (type != MM_PLAYER_TRACK_TYPE_MAX) { - LOGE("Multi Stream 0x%X", type); - return -1; + switch (stype) { + case GST_STREAM_TYPE_AUDIO: + { + GstStructure *caps_structure = NULL; + gint samplerate = 0; + gint channels = 0; + + type = MM_PLAYER_TRACK_TYPE_AUDIO; + + if (caps) { + caps_structure = gst_caps_get_structure(caps, 0); + gst_structure_get_int(caps_structure, "rate", &samplerate); + gst_structure_get_int(caps_structure, "channels", &channels); + + if (channels > 0 && samplerate == 0) { + LOGW("Skip corrupted audio stream"); + goto EXIT; + } + + if (g_strrstr(caps_str, "mobile-xmf")) + mm_player_set_attribute((MMHandleType)player, NULL, + "content_audio_codec", "mobile-xmf", strlen("mobile-xmf"), NULL); } - type = MM_PLAYER_TRACK_TYPE_VIDEO; + break; } + case GST_STREAM_TYPE_VIDEO: + { + GstStructure *caps_structure = NULL; + gint stype = 0; + gint width = 0; + + type = MM_PLAYER_TRACK_TYPE_VIDEO; + + /* do not support multi track video */ + if (player->track[MM_PLAYER_TRACK_TYPE_VIDEO].total_track_num >= 1) + goto EXIT; + + mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype); + + /* don't make video because of not required */ + if ((stype == MM_DISPLAY_SURFACE_NULL) && + (!player->set_mode.video_export)) { + LOGD("no need video decoding, skip video stream"); + goto EXIT; + } + + if (caps) { + caps_structure = gst_caps_get_structure(caps, 0); + gst_structure_get_int(caps_structure, "width", &width); + + if (width != 0) { + if (player->v_stream_caps) { + gst_caps_unref(player->v_stream_caps); + player->v_stream_caps = NULL; + } - if (stype & GST_STREAM_TYPE_TEXT) { - LOGW("TEXT type 0x%X", stype); - if (type != MM_PLAYER_TRACK_TYPE_MAX) { - LOGE("Multi Stream 0x%X", type); - return -1; + player->v_stream_caps = gst_caps_copy(caps); + MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps); + } } + break; + } + case GST_STREAM_TYPE_TEXT: type = MM_PLAYER_TRACK_TYPE_TEXT; + break; + default: + LOGW("Skip not supported stream type"); + goto EXIT; } _mmplayer_track_update_stream(player, type, stream); if (player->track[type].active_track_index == (player->track[type].total_track_num - 1)) { - LOGD("select this stream, type : %d, idx : %d", type, player->track[type].active_track_index); - return 1; + LOGD("select this stream, active idx : %d", player->track[type].active_track_index); + if (type == MM_PLAYER_TRACK_TYPE_AUDIO) + _mmplayer_set_audio_attrs(player, caps); + ret = 1; } - return -1; +EXIT: + g_free(caps_str); + if (caps) + gst_caps_unref(caps); + + LOGD("ret %d", ret); + return ret; } -void +static gboolean +__mmplayer_gst_decode_request_resource(GstElement * uridecodebin, GstStreamCollection * collection, + GstStream * stream, gpointer data) +{ + mmplayer_t *player = (mmplayer_t *)data; + GstStreamType stype = gst_stream_get_stream_type(stream); + + MMPLAYER_FENTER(); + MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE); + + LOGD("stream type %s", gst_stream_type_get_name(stype)); + + /* public does not support audio hw decoder at the moment */ + + if (player->hw_resource[MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER] != NULL) { + LOGW("video decoder resource is already acquired, skip it."); + return TRUE; + } + + if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) { + LOGE("failed to acquire video decoder resource"); + return FALSE; + } + player->interrupted_by_resource = FALSE; + MMPLAYER_FLEAVE(); + return TRUE; +} + +static void __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *element, gpointer data) { gchar *factory_name = NULL; @@ -2948,41 +3057,40 @@ __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *el return; } - 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; - - mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER; - mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element; + if ((MMPLAYER_IS_STREAMING(player)) && (!MMPLAYER_IS_RTSP_STREAMING(player))) { + /* update queue2 setting */ + if (g_strrstr(factory_name, "queue2") && (!mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) { + gint64 dur_bytes = 0L; + muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE; - 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)); + mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER; + mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element; - LOGD("type %s, dur_bytes = %"G_GINT64_FORMAT, player->type, dur_bytes); + 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)); - /* 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; + 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; } - } else { - dur_bytes = 0; - } - - _mm_player_streaming_set_queue2(player->streamer, - element, - FALSE, - type, - (guint64)dur_bytes); /* no meaning at the moment */ - return; - } + _mm_player_streaming_set_queue2(player->streamer, + element, + FALSE, + type, + (guint64)dur_bytes); /* no meaning at the moment */ + return; + } - if (g_strrstr(factory_name, "parsebin")) { - if (!mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) { + /* update mq setting */ + if (g_strrstr(factory_name, "parsebin") && (!mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst)) { GstIterator *iter = NULL; GValue item = {0, }; GstElement *ch_element = NULL; @@ -2993,16 +3101,14 @@ __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *el while (gst_iterator_next(iter, &item) == GST_ITERATOR_OK) { ch_element = g_value_get_object(&item); ch_factory = gst_element_get_factory(ch_element); - + LOGD("children factory %s", GST_OBJECT_NAME(ch_factory)); if (g_strrstr(GST_OBJECT_NAME(ch_factory), "multiqueue")) { + LOGD("get 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); - } + /* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h */ + _mm_player_streaming_set_multiqueue(player->streamer, ch_element); g_value_reset(&item); break; } @@ -3014,10 +3120,24 @@ __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *el } if (g_strrstr(factory_name, "parsebin")) { + int video_codec_type = 0; + int audio_codec_type = 0; g_object_set(G_OBJECT(child), "message-forward", TRUE, NULL); g_object_set(G_OBJECT(element), "message-forward", TRUE, NULL); + mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_VIDEO_CODEC_TYPE, &video_codec_type); + mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, &audio_codec_type); + + /* CAUTION: if there is hw decoder, the rank value has to be higher than sw decoder + and codec default type in ini has to be hw. + */ + LOGD("set codec type v(%d) a(%d)", video_codec_type, audio_codec_type); + if (video_codec_type == MM_PLAYER_CODEC_TYPE_SW) + g_object_set(G_OBJECT(child), "force-sw-decoders-for-video", TRUE, NULL); + if (audio_codec_type == MM_PLAYER_CODEC_TYPE_SW) + g_object_set(G_OBJECT(child), "force-sw-decoders-for-audio", 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), @@ -3026,13 +3146,12 @@ __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *el _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); + _mmplayer_add_signal_connection(player, G_OBJECT(child), + MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "request-resource", G_CALLBACK(__mmplayer_gst_decode_request_resource), (gpointer)player); + } else { _mmplayer_gst_element_added((GstElement *)child, element, data); } @@ -3083,10 +3202,8 @@ __mmplayer_gst_make_uridecodebin(mmplayer_t *player) _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "select-stream", G_CALLBACK(__mmplayer_gst_select_stream), (gpointer)player); -/* FIXME: need to be added for gapless playback - _mmplayer_add_signal_connection(player, G_OBJECT(element), - MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "about-to-finish", G_CALLBACK(_mmplayer_gst_decode_drained), (gpointer)player); -*/ + _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3), + MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "about-to-finish", G_CALLBACK(_mmplayer_gst_about_to_finish), (gpointer)player); _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "deep-element-added", G_CALLBACK(__mmplayer_gst_deep_element_added), (gpointer)player); @@ -3198,7 +3315,6 @@ __mmplayer_gst_msg_push(GstBus *bus, GstMessage *msg, gpointer data) g_return_val_if_fail(player, FALSE); g_return_val_if_fail(msg && GST_IS_MESSAGE(msg), FALSE); - gst_message_ref(msg); g_mutex_lock(&player->bus_msg_q_lock); @@ -3215,7 +3331,6 @@ static gpointer __mmplayer_gst_bus_msg_thread(gpointer data) { mmplayer_t *player = (mmplayer_t *)(data); GstMessage *msg = NULL; - GstBus *bus = NULL; MMPLAYER_FENTER(); MMPLAYER_RETURN_VAL_IF_FAIL(player && @@ -3224,12 +3339,6 @@ static gpointer __mmplayer_gst_bus_msg_thread(gpointer data) player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL); - bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst)); - if (!bus) { - LOGE("cannot get BUS from the pipeline"); - return NULL; - } - MMPLAYER_BUS_MSG_THREAD_LOCK(player); LOGD("[handle: %p] gst bus msg thread will be started.", player); @@ -3249,9 +3358,8 @@ static gpointer __mmplayer_gst_bus_msg_thread(gpointer data) } MMPLAYER_BUS_MSG_THREAD_UNLOCK(player); - gst_object_unref(GST_OBJECT(bus)); - MMPLAYER_FLEAVE(); + return NULL; } @@ -3598,7 +3706,7 @@ _mmplayer_gst_pause(mmplayer_t *player, gboolean async) return ret; } - if (!MMPLAYER_USE_URIDECODEBIN3(player)) { + if (MMPLAYER_USE_DECODEBIN(player)) { if ((!MMPLAYER_IS_RTSP_STREAMING(player)) && (!player->video_decoded_cb) && (!player->pipeline->videobin) && (!player->pipeline->audiobin)) return MM_ERROR_PLAYER_CODEC_NOT_FOUND; @@ -4122,8 +4230,8 @@ _mmplayer_gst_build_es_pipeline(mmplayer_t *player) return MM_ERROR_NONE; } -static int -__mmplayer_gst_build_pipeline_with_src(mmplayer_t *player) +int +_mmplayer_gst_build_pipeline_with_src(mmplayer_t *player) { mmplayer_gst_element_t *mainbin = NULL; GstElement *autoplug_elem = NULL; @@ -4136,6 +4244,15 @@ __mmplayer_gst_build_pipeline_with_src(mmplayer_t *player) LOGD("uri type %d", player->profile.uri_type); + if ((player->profile.uri_type == MM_PLAYER_URI_TYPE_FILE) && + (!_mmplayer_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD]))) { + return MM_ERROR_PLAYER_INTERNAL; + } + + if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM) { + g_strlcpy(player->profile.uri, "appsrc://", MM_MAX_URL_LEN); + } + autoplug_elem = __mmplayer_gst_make_uridecodebin(player); if (!autoplug_elem) { LOGE("failed to create uridecodebin3 element"); @@ -4209,31 +4326,14 @@ _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) { - LOGD("uridecodebin include src element."); - 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); @@ -4253,13 +4353,6 @@ _mmplayer_gst_build_pipeline(mmplayer_t *player) { GstAppStreamType stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS; - if (player->ini.use_uridecodebin3) { - LOGD("uridecodebin include src element."); - - g_strlcpy(player->profile.uri, "appsrc://", MM_MAX_URL_LEN); - return __mmplayer_gst_build_pipeline_with_src(player); - } - src_elem = gst_element_factory_make("appsrc", "mem-source"); if (!src_elem) { LOGE("failed to create appsrc element"); @@ -4404,7 +4497,17 @@ _mmplayer_gst_add_bus_watch(mmplayer_t *player) return MM_ERROR_PLAYER_INTERNAL; } - player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_msg_push, player); + player->bus_watcher = gst_bus_add_watch_full(bus, G_PRIORITY_DEFAULT, + (GstBusFunc)__mmplayer_gst_msg_push, player, + (GDestroyNotify)_mmplayer_watcher_removed_notify); + if (player->bus_watcher == 0) { + LOGE("failed to add bus watch"); + return MM_ERROR_PLAYER_INTERNAL; + } + + g_mutex_init(&player->bus_watcher_mutex); + g_cond_init(&player->bus_watcher_cond); + player->context.thread_default = g_main_context_get_thread_default(); if (player->context.thread_default == NULL) { player->context.thread_default = g_main_context_default(); @@ -4436,6 +4539,7 @@ _mmplayer_gst_add_bus_watch(mmplayer_t *player) void _mmplayer_activate_next_source(mmplayer_t *player, GstState target) { + int ret = MM_ERROR_NONE; mmplayer_gst_element_t *mainbin = NULL; MMMessageParamType msg_param = {0,}; GstElement *element = NULL; @@ -4474,6 +4578,18 @@ _mmplayer_activate_next_source(mmplayer_t *player, GstState target) goto ERROR; } + if (!MMPLAYER_USE_DECODEBIN(player)) { + ret = _mmplayer_gst_build_pipeline_with_src(player); + if (ret != MM_ERROR_NONE) + goto ERROR; + + if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) { + LOGE("Failed to change state of uridecodebin3 element"); + goto ERROR; + } + goto DONE; + } + element = _mmplayer_gst_create_source(player); if (!element) { LOGE("no source element was created"); @@ -4515,7 +4631,7 @@ _mmplayer_activate_next_source(mmplayer_t *player, GstState target) } if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) { - LOGE("failed to add sinkbin to pipeline"); + LOGE("failed to add %s to pipeline", GST_ELEMENT_NAME(element)); gst_object_unref(GST_OBJECT(element)); element = NULL; goto ERROR; @@ -4546,6 +4662,7 @@ _mmplayer_activate_next_source(mmplayer_t *player, GstState target) goto ERROR; } +DONE: player->gapless.stream_changed = TRUE; player->gapless.running = TRUE; MMPLAYER_FLEAVE();