From 88fc0772baa9c68adb75c3c22faeb11a27d9a621 Mon Sep 17 00:00:00 2001 From: Gilbok Lee Date: Thu, 16 Apr 2020 13:07:02 +0900 Subject: [PATCH] [0.2.222] Add concat element for gapless playback Change-Id: I21ea5362e222b4435c0e1ce0e1a387029694154e --- packaging/libmm-player.spec | 2 +- src/include/mm_player_gst.h | 28 +++-- src/include/mm_player_priv.h | 4 + src/mm_player_gst.c | 23 +++- src/mm_player_priv.c | 272 +++++++++++++++++++++++++++++++++++-------- 5 files changed, 265 insertions(+), 64 deletions(-) diff --git a/packaging/libmm-player.spec b/packaging/libmm-player.spec index b6d3633..1929e3e 100644 --- a/packaging/libmm-player.spec +++ b/packaging/libmm-player.spec @@ -1,6 +1,6 @@ Name: libmm-player Summary: Multimedia Framework Player Library -Version: 0.6.221 +Version: 0.6.222 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/include/mm_player_gst.h b/src/include/mm_player_gst.h index 298cfab..4a8bc90 100644 --- a/src/include/mm_player_gst.h +++ b/src/include/mm_player_gst.h @@ -35,23 +35,31 @@ extern "C" #endif /* get caps info */ -#define MMPLAYER_GST_GET_CAPS_INFO(x_pad, x_caps, x_str, x_name, x_ret) \ +#define MMPLAYER_GST_GET_CAPS_INFO(x_caps, x_str, x_name, x_ret) \ do { \ - x_caps = gst_pad_get_current_caps(x_pad); \ - if (!x_caps) \ - x_caps = gst_pad_query_caps(x_pad, NULL); \ - if (x_caps) { \ - x_str = gst_caps_get_structure(x_caps, 0); \ - if (x_str) { \ - x_name = gst_structure_get_name(x_str); \ - } \ + x_ret = TRUE; \ + if (!(x_caps)) { \ + LOGE("input caps is NULL"); \ + x_ret = FALSE; \ + break; \ } \ - if (!x_caps || !x_str || !x_name) { \ + x_str = gst_caps_get_structure(x_caps, 0); \ + if (x_str) \ + x_name = gst_structure_get_name(x_str); \ + if (!(x_str) || !(x_name)) { \ LOGE("failed to get caps info"); \ x_ret = FALSE; \ } \ } while (0) +#define MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(x_pad, x_caps, x_str, x_name, x_ret) \ + do { \ + x_caps = gst_pad_get_current_caps(x_pad); \ + if (!(x_caps)) \ + x_caps = gst_pad_query_caps(x_pad, NULL); \ + MMPLAYER_GST_GET_CAPS_INFO(x_caps, x_str, x_name, x_ret); \ + } while (0) + /*======================================================================================= | GLOBAL FUNCTION PROTOTYPES | ========================================================================================*/ diff --git a/src/include/mm_player_priv.h b/src/include/mm_player_priv.h index 1f321f1..73264c6 100644 --- a/src/include/mm_player_priv.h +++ b/src/include/mm_player_priv.h @@ -194,6 +194,9 @@ typedef enum { MMPLAYER_M_V_INPUT_SELECTOR, // video input_select MMPLAYER_M_A_INPUT_SELECTOR, // audio input_select MMPLAYER_M_T_INPUT_SELECTOR, // text input_select + MMPLAYER_M_V_CONCAT, // video concat + MMPLAYER_M_A_CONCAT, // audio concat + MMPLAYER_M_T_CONCAT, // text concat MMPLAYER_M_NUM } main_element_id_e; @@ -902,6 +905,7 @@ void _mmplayer_set_reconfigure_state(mmplayer_t *player, gboolean state); void _mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad, gpointer data); void _mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data); void _mmplayer_gst_decode_drained(GstElement *bin, gpointer data); +void _mmplayer_gst_about_to_finish(GstElement *bin, gpointer data); void _mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad, GstCaps *caps, gpointer data); gboolean _mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, GstCaps *caps, gpointer data); void _mmplayer_pipeline_complete(GstElement *decodebin, gpointer data); diff --git a/src/mm_player_gst.c b/src/mm_player_gst.c index 154e97e..269a8d1 100644 --- a/src/mm_player_gst.c +++ b/src/mm_player_gst.c @@ -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; @@ -3200,10 +3201,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); @@ -4539,6 +4538,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; @@ -4577,6 +4577,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"); @@ -4618,7 +4630,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; @@ -4649,6 +4661,7 @@ _mmplayer_activate_next_source(mmplayer_t *player, GstState target) goto ERROR; } +DONE: player->gapless.stream_changed = TRUE; player->gapless.running = TRUE; MMPLAYER_FLEAVE(); diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index 78ae23a..c633373 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -140,8 +140,8 @@ static int __mmplayer_gst_create_text_pipeline(mmplayer_t *player); static int __mmplayer_gst_create_video_sink_bin(mmplayer_t *player, GstCaps *caps, MMDisplaySurfaceType surface_type); static int __mmplayer_gst_create_audio_sink_bin(mmplayer_t *player); static int __mmplayer_gst_create_text_sink_bin(mmplayer_t *player); - -static void __mmplayer_gst_create_sinkbin(GstElement *decodebin, GstPad *pad, gpointer data); +static void __mmplayer_gst_create_sink_bin(GstElement *decodebin, GstPad *pad, GstCaps *ref_caps, gpointer data); +static gboolean __mmplayer_create_sink_path(mmplayer_t *player, GstElement *combiner, mmplayer_track_type_e type, GstCaps *caps); static gboolean __mmplayer_is_midi_type(gchar *str_caps); static gboolean __mmplayer_is_only_mp3_type(gchar *str_caps); @@ -173,6 +173,7 @@ static int __mmplayer_gst_set_message_callback(mmplayer_t *player, MMMessageCal static gboolean __mmplayer_verify_gapless_play_path(mmplayer_t *player); static void __mmplayer_check_pipeline_reconfigure_state(mmplayer_t *player); static gboolean __mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type); +static gboolean __mmplayer_deactivate_combiner(mmplayer_t *player, mmplayer_track_type_e type); static void __mmplayer_deactivate_old_path(mmplayer_t *player); static int __mmplayer_gst_create_plain_text_elements(mmplayer_t *player); static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar *format_name); @@ -962,7 +963,7 @@ __mmplayer_gst_selector_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer GST_EVENT_TYPE(event) != GST_EVENT_QOS) return ret; - MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret); + MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret); if (!caps_ret) goto ERROR; @@ -1146,6 +1147,35 @@ EXIT: } static GstElement * +__mmplayer_gst_make_concat(mmplayer_t *player, main_element_id_e elem_idx) +{ + GstElement *pipeline = NULL; + GstElement *concat = NULL; + + MMPLAYER_FENTER(); + MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, NULL); + + concat = gst_element_factory_make("concat", NULL); + if (!concat) { + LOGE("failed to create concat"); + return NULL; + } + + LOGD("Create concat [%d] element", elem_idx); + + player->pipeline->mainbin[elem_idx].id = elem_idx; + player->pipeline->mainbin[elem_idx].gst = concat; + + gst_element_set_state(concat, GST_STATE_PAUSED); + + pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst; + gst_bin_add(GST_BIN(pipeline), concat); + + MMPLAYER_FLEAVE(); + return concat; +} + +static GstElement * __mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmplayer_track_type_e stream_type) { GstElement *pipeline = NULL; @@ -1190,7 +1220,7 @@ void _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) { mmplayer_t *player = (mmplayer_t *)data; - GstElement *selector = NULL; + GstElement *combiner = NULL; GstCaps *caps = NULL; GstStructure *str = NULL; const gchar *name = NULL; @@ -1208,7 +1238,7 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) LOGD("pad-added signal handling"); /* get mimetype from caps */ - MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret); + MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret); if (!caps_ret) goto ERROR; @@ -1233,8 +1263,8 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) LOGD("surface type : %d", stype); - if (MMPLAYER_IS_MS_BUFF_SRC(player) || !MMPLAYER_USE_DECODEBIN(player)) { - __mmplayer_gst_create_sinkbin(elem, pad, player); + if (MMPLAYER_IS_MS_BUFF_SRC(player)) { + __mmplayer_gst_create_sink_bin(elem, pad, caps, player); goto DONE; } @@ -1245,17 +1275,22 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) goto DONE; } - LOGD("video selector is required"); - elem_idx = MMPLAYER_M_V_INPUT_SELECTOR; + if (MMPLAYER_USE_DECODEBIN(player)) { + LOGD("video selector is required"); + elem_idx = MMPLAYER_M_V_INPUT_SELECTOR; + } else { + LOGD("video concat is required"); + elem_idx = MMPLAYER_M_V_CONCAT; + } stream_type = MM_PLAYER_TRACK_TYPE_VIDEO; } else if (strstr(name, "audio")) { gint samplerate = 0; gint channels = 0; - if (MMPLAYER_IS_MS_BUFF_SRC(player) || !MMPLAYER_USE_DECODEBIN(player) || player->build_audio_offload) { + if (MMPLAYER_IS_MS_BUFF_SRC(player) || player->build_audio_offload) { if (player->build_audio_offload) player->no_more_pad = TRUE; /* remove state holder */ - __mmplayer_gst_create_sinkbin(elem, pad, player); + __mmplayer_gst_create_sink_bin(elem, pad, caps, player); goto DONE; } @@ -1266,14 +1301,23 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) __mmplayer_gst_make_fakesink(player, pad, name); goto DONE; } - - LOGD("audio selector is required"); - elem_idx = MMPLAYER_M_A_INPUT_SELECTOR; + if (MMPLAYER_USE_DECODEBIN(player)) { + LOGD("audio selector is required"); + elem_idx = MMPLAYER_M_A_INPUT_SELECTOR; + } else { + LOGD("audio concat is required"); + elem_idx = MMPLAYER_M_A_CONCAT; + } stream_type = MM_PLAYER_TRACK_TYPE_AUDIO; } else if (strstr(name, "text")) { - LOGD("text selector is required"); - elem_idx = MMPLAYER_M_T_INPUT_SELECTOR; + if (MMPLAYER_USE_DECODEBIN(player)) { + LOGD("text selector is required"); + elem_idx = MMPLAYER_M_T_INPUT_SELECTOR; + } else { + LOGD("text concat is required"); + elem_idx = MMPLAYER_M_T_CONCAT; + } stream_type = MM_PLAYER_TRACK_TYPE_TEXT; } else { LOGE("invalid caps info"); @@ -1281,33 +1325,41 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) } /* check selector and create it */ - if (!(selector = player->pipeline->mainbin[elem_idx].gst)) { - selector = __mmplayer_gst_make_selector(player, elem_idx, stream_type); - if (!selector) + if (!(combiner = player->pipeline->mainbin[elem_idx].gst)) { + if (MMPLAYER_USE_DECODEBIN(player)) + combiner = __mmplayer_gst_make_selector(player, elem_idx, stream_type); + else + combiner = __mmplayer_gst_make_concat(player, elem_idx); + + if (!combiner) goto ERROR; first_track = TRUE; } else { - LOGD("input-selector is already created."); + LOGD("Combiner element is already created."); } /* link */ - sinkpad = gst_element_get_request_pad(selector, "sink_%u"); + sinkpad = gst_element_get_request_pad(combiner, "sink_%u"); LOGD("pad link: %s:%s - %s:%s", GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(sinkpad)); if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) { - LOGE("failed to link selector"); - gst_object_unref(GST_OBJECT(selector)); + LOGE("failed to link combiner"); + gst_object_unref(GST_OBJECT(combiner)); goto ERROR; } if (first_track) { - LOGD("this track will be activated"); - g_object_set(selector, "active-pad", sinkpad, NULL); + if (MMPLAYER_USE_DECODEBIN(player)) { + LOGD("this track will be activated"); + g_object_set(combiner, "active-pad", sinkpad, NULL); + } } if (MMPLAYER_USE_DECODEBIN(player)) _mmplayer_track_update_stream(player, stream_type, sinkpad); + else + __mmplayer_create_sink_path(player, combiner, stream_type, caps); DONE: ERROR: @@ -1324,7 +1376,7 @@ ERROR: } static gboolean -__mmplayer_create_sink_path(mmplayer_t *player, GstElement *selector, mmplayer_track_type_e type) +__mmplayer_create_sink_path(mmplayer_t *player, GstElement *combiner, mmplayer_track_type_e type, GstCaps *caps) { GstPad *srcpad = NULL; @@ -1333,20 +1385,20 @@ __mmplayer_create_sink_path(mmplayer_t *player, GstElement *selector, mmplayer_t LOGD("type %d", type); - if (!selector) { + if (!combiner) { LOGD("there is no %d track", type); return TRUE; } - srcpad = gst_element_get_static_pad(selector, "src"); + srcpad = gst_element_get_static_pad(combiner, "src"); if (!srcpad) { - LOGE("failed to get srcpad from selector"); + LOGE("failed to get srcpad from combiner"); return FALSE; } - LOGD("got pad %s:%s from selector", GST_DEBUG_PAD_NAME(srcpad)); + LOGD("got pad %s:%s from combiner", GST_DEBUG_PAD_NAME(srcpad)); - __mmplayer_gst_create_sinkbin(selector, srcpad, player); + __mmplayer_gst_create_sink_bin(combiner, srcpad, caps, player); LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad)); if (player->track[type].block_id) { @@ -1422,7 +1474,7 @@ __mmplayer_create_audio_sink_path(mmplayer_t *player, GstElement *audio_selector __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_AUDIO); /* create audio sink path */ - if (!__mmplayer_create_sink_path(player, audio_selector, MM_PLAYER_TRACK_TYPE_AUDIO)) { + if (!__mmplayer_create_sink_path(player, audio_selector, MM_PLAYER_TRACK_TYPE_AUDIO, NULL)) { LOGE("failed to create audio sink path"); return FALSE; } @@ -1451,7 +1503,7 @@ __mmplayer_create_text_sink_path(mmplayer_t *player, GstElement *text_selector) /* create text decode path */ player->no_more_pad = TRUE; - if (!__mmplayer_create_sink_path(player, text_selector, MM_PLAYER_TRACK_TYPE_TEXT)) { + if (!__mmplayer_create_sink_path(player, text_selector, MM_PLAYER_TRACK_TYPE_TEXT, NULL)) { LOGE("failed to create text sink path"); return FALSE; } @@ -1526,7 +1578,7 @@ _mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data) if (video_selector && !audio_selector && !text_selector) player->no_more_pad = TRUE; - if (!__mmplayer_create_sink_path(player, video_selector, MM_PLAYER_TRACK_TYPE_VIDEO)) + if (!__mmplayer_create_sink_path(player, video_selector, MM_PLAYER_TRACK_TYPE_VIDEO, NULL)) goto EXIT; /* create audio path followed by audio-select */ @@ -1607,7 +1659,7 @@ EXIT: } static void -__mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data) +__mmplayer_gst_create_sink_bin(GstElement *elem, GstPad *pad, GstCaps *ref_caps, gpointer data) { mmplayer_t *player = NULL; GstCaps *caps = NULL; @@ -1625,10 +1677,14 @@ __mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data) MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(elem && pad); MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && MMPLAYER_GET_ATTRS(player)); + MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret); + if (!caps_ret) { + MMPLAYER_GST_GET_CAPS_INFO(ref_caps, str, name, caps_ret); + if (!caps_ret) + goto ERROR; - MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret); - if (!caps_ret) - goto ERROR; + caps = gst_caps_ref(ref_caps); + } caps_str = gst_caps_to_string(caps); #ifdef __DEBUG__ @@ -2219,7 +2275,7 @@ __mmplayer_gst_caps_notify_cb(GstPad *pad, GParamSpec *unused, gpointer data) if (!caps) return; - MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret); + MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret); if (!caps_ret) goto ERROR; @@ -6472,6 +6528,87 @@ ERROR: return FALSE; } +static void +__mmplayer_remove_sinkpad (const GValue *item, gpointer user_data) +{ + GstPad *sinkpad = g_value_get_object (item); + GstElement *element = GST_ELEMENT(user_data); + LOGD("(%s)element release request pad(%s)", GST_ELEMENT_NAME(element), GST_PAD_NAME(sinkpad)); + gst_element_release_request_pad(element, GST_PAD(sinkpad)); +} + +static gboolean +__mmplayer_deactivate_combiner(mmplayer_t *player, mmplayer_track_type_e type) +{ + mmplayer_gst_element_t *sinkbin = NULL; + main_element_id_e concatId = MMPLAYER_M_NUM; + main_element_id_e sinkId = MMPLAYER_M_NUM; + gboolean send_notice = FALSE; + GstElement *element; + GstIterator *iter; + + MMPLAYER_FENTER(); + MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE); + + LOGD("type %d", type); + + switch (type) { + case MM_PLAYER_TRACK_TYPE_AUDIO: + concatId = MMPLAYER_M_A_CONCAT; + sinkId = MMPLAYER_A_BIN; + sinkbin = player->pipeline->audiobin; + break; + case MM_PLAYER_TRACK_TYPE_VIDEO: + concatId = MMPLAYER_M_V_CONCAT; + sinkId = MMPLAYER_V_BIN; + sinkbin = player->pipeline->videobin; + send_notice = TRUE; + break; + case MM_PLAYER_TRACK_TYPE_TEXT: + concatId = MMPLAYER_M_T_CONCAT; + sinkId = MMPLAYER_T_BIN; + sinkbin = player->pipeline->textbin; + break; + default: + LOGE("requested type is not supportable"); + return FALSE; + break; + } + + element = player->pipeline->mainbin[concatId].gst; + if (!element) + return TRUE; + + if ((sinkbin) && (sinkbin[sinkId].gst)) { + GstPad *srcpad = gst_element_get_static_pad(element, "src"); + GstPad *sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink"); + if (srcpad && sinkpad) { + /* after getting drained signal there is no data flows, so no need to do pad_block */ + LOGD("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad)); + gst_pad_unlink(srcpad, sinkpad); + + /* send custom event to sink pad to handle it at video sink */ + if (send_notice) { + LOGD("send custom event to sinkpad"); + GstStructure *s = gst_structure_new_empty("tizen/flush-buffer"); + GstEvent *event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, s); + gst_pad_send_event(sinkpad, event); + } + } + gst_object_unref(srcpad); + gst_object_unref(sinkpad); + } + + LOGD("release concat request pad"); + /* release and unref requests pad from the selector */ + iter = gst_element_iterate_sink_pads(element); + while (gst_iterator_foreach(iter, __mmplayer_remove_sinkpad, element) == GST_ITERATOR_RESYNC) + gst_iterator_resync(iter); + gst_iterator_free(iter); + + return TRUE; +} + static gboolean __mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type) { @@ -6569,11 +6706,20 @@ __mmplayer_deactivate_old_path(mmplayer_t *player) MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(player); - if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) || - (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) || - (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT))) { - LOGE("deactivate selector error"); - goto ERROR; + if (MMPLAYER_USE_DECODEBIN(player)) { + if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) || + (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) || + (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT))) { + LOGE("deactivate selector error"); + goto ERROR; + } + } else { + if ((!__mmplayer_deactivate_combiner(player, MM_PLAYER_TRACK_TYPE_AUDIO)) || + (!__mmplayer_deactivate_combiner(player, MM_PLAYER_TRACK_TYPE_VIDEO)) || + (!__mmplayer_deactivate_combiner(player, MM_PLAYER_TRACK_TYPE_TEXT))) { + LOGE("deactivate concat error"); + goto ERROR; + } } _mmplayer_track_destroy(player); @@ -6700,7 +6846,7 @@ _mmplayer_get_next_uri(MMHandleType hplayer, char **uri) if (num_of_list > 0) { gint uri_idx = player->uri_info.uri_idx; - if (uri_idx < num_of_list-1) + if (uri_idx < num_of_list - 1) uri_idx++; else uri_idx = 0; @@ -7353,6 +7499,36 @@ _mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad, } void +_mmplayer_gst_about_to_finish(GstElement *bin, gpointer data) +{ + mmplayer_t *player = (mmplayer_t *)data; + + MMPLAYER_FENTER(); + MMPLAYER_RETURN_IF_FAIL(player); + + LOGD("got about to finish signal"); + + if (!MMPLAYER_CMD_TRYLOCK(player)) { + LOGW("Fail to get cmd lock"); + return; + } + + if (!__mmplayer_verify_gapless_play_path(player)) { + LOGD("decoding is finished."); + MMPLAYER_CMD_UNLOCK(player); + return; + } + + _mmplayer_set_reconfigure_state(player, TRUE); + MMPLAYER_CMD_UNLOCK(player); + + MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL); + __mmplayer_deactivate_old_path(player); + + MMPLAYER_FLEAVE(); +} + +void _mmplayer_gst_decode_drained(GstElement *bin, gpointer data) { mmplayer_t *player = (mmplayer_t *)data; @@ -8338,11 +8514,11 @@ _mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type goto EXIT; } - if (MMPLAYER_USE_DECODEBIN(player)) { + if (MMPLAYER_USE_DECODEBIN(player)) result = __mmplayer_change_selector_pad(player, type, index); - } else { + else result = __mmplayer_switch_stream(player, type, index); - } + if (result != MM_ERROR_NONE) { LOGE("failed to change track"); goto EXIT; -- 2.7.4