X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmm_player_priv.c;h=1f13b3815fb0ba015afa3901dbfb99523375ad5b;hb=40cbaa95188c059a07f9b059ebe3ec8c8b96e185;hp=403cf19cd27807e5e9aef5b7d0eae9501074911f;hpb=b33c9d84e3c82acf3d606ff51010b23bf51c605a;p=platform%2Fcore%2Fmultimedia%2Flibmm-player.git diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index 403cf19..1f13b38 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -140,17 +140,10 @@ 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_decode_no_more_pads(GstElement *elem, gpointer data); -static void __mmplayer_gst_create_sinkbin(GstElement *decodebin, GstPad *pad, gpointer data); -static void __mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad, GstCaps *caps, gpointer data); -static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, GstCaps *caps, gpointer data); -static void __mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad, gpointer data); -static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data); -static void __mmplayer_pipeline_complete(GstElement *decodebin, 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); -static void __mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps); static gboolean __mmplayer_update_subtitle(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data); static void __mmplayer_release_misc(mmplayer_t *player); @@ -180,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); @@ -557,7 +551,7 @@ ALREADY_GOING: return MM_ERROR_PLAYER_NO_OP; } -static int __mmplayer_acquire_hw_resource(mmplayer_t *player, mmplayer_resource_type_e type) +int _mmplayer_acquire_hw_resource(mmplayer_t *player, mmplayer_resource_type_e type) { int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE; mm_resource_manager_res_type_e rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_MAX; @@ -676,12 +670,7 @@ __mmplayer_initialize_gapless_play(mmplayer_t *player) /* clean found audio decoders */ if (player->audio_decoders) { - GList *a_dec = player->audio_decoders; - for (; a_dec; a_dec = g_list_next(a_dec)) { - gchar *name = a_dec->data; - MMPLAYER_FREEIF(name); - } - g_list_free(player->audio_decoders); + g_list_free_full(player->audio_decoders, (GDestroyNotify)g_free); player->audio_decoders = NULL; } @@ -756,6 +745,42 @@ __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id) } void +_mmplayer_watcher_removed_notify(gpointer data) +{ + mmplayer_t *player = (mmplayer_t *)data; + MMPLAYER_RETURN_IF_FAIL(player); + + MMPLAYER_BUS_WATCHER_LOCK(player); + player->bus_watcher = 0; + MMPLAYER_BUS_WATCHER_SIGNAL(player); + MMPLAYER_BUS_WATCHER_UNLOCK(player); +} + +void +_mmplayer_bus_watcher_remove(MMHandleType hplayer) +{ + mmplayer_t *player = (mmplayer_t *)hplayer; + gint64 end_time = 0; + MMPLAYER_FENTER(); + MMPLAYER_RETURN_IF_FAIL(player); + + /* disconnecting bus watch */ + if (player->bus_watcher > 0) { + __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher); + MMPLAYER_BUS_WATCHER_LOCK(player); + end_time = g_get_monotonic_time () + 2 * G_TIME_SPAN_SECOND; + while (player->bus_watcher > 0) + MMPLAYER_BUS_WATCHER_WAIT_UNTIL(player, end_time); + MMPLAYER_BUS_WATCHER_UNLOCK(player); + + g_mutex_clear(&player->bus_watcher_mutex); + g_cond_clear(&player->bus_watcher_cond); + } + + MMPLAYER_FLEAVE(); +} + +void _mmplayer_bus_msg_thread_destroy(MMHandleType hplayer) { mmplayer_t *player = (mmplayer_t *)hplayer; @@ -765,11 +790,6 @@ _mmplayer_bus_msg_thread_destroy(MMHandleType hplayer) MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(player); - /* disconnecting bus watch */ - if (player->bus_watcher) - __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher); - player->bus_watcher = 0; - /* destroy the gst bus msg thread */ if (player->bus_msg_thread) { MMPLAYER_BUS_MSG_THREAD_LOCK(player); @@ -872,7 +892,7 @@ __mmplayer_gst_selector_update_start_time(mmplayer_t *player, mmplayer_track_typ for (idx = MM_PLAYER_TRACK_TYPE_AUDIO; idx < MM_PLAYER_TRACK_TYPE_TEXT; idx++) { if ((player->gapless.update_segment[idx] == TRUE) || - !(player->selector[idx].event_probe_id)) { + !(player->track[idx].event_probe_id)) { #ifdef __DEBUG__ LOGW("[%d] skip", idx); #endif @@ -943,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; @@ -1127,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; @@ -1146,14 +1195,14 @@ __mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmp player->pipeline->mainbin[elem_idx].id = elem_idx; player->pipeline->mainbin[elem_idx].gst = selector; - /* player->selector[stream_type].active_pad_index = DEFAULT_TRACK; */ + /* player->track[stream_type].active_track_index = DEFAULT_TRACK; */ srcpad = gst_element_get_static_pad(selector, "src"); LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad)); - player->selector[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, + player->track[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, __mmplayer_gst_selector_blocked, NULL, NULL); - player->selector[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH, + player->track[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH, __mmplayer_gst_selector_event_probe, player, NULL); gst_element_set_state(selector, GST_STATE_PAUSED); @@ -1171,12 +1220,13 @@ 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; GstPad *sinkpad = NULL; gboolean first_track = FALSE; + gboolean caps_ret = TRUE; main_element_id_e elem_idx = MMPLAYER_M_NUM; mmplayer_track_type_e stream_type = MM_PLAYER_TRACK_TYPE_AUDIO; @@ -1188,13 +1238,8 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) LOGD("pad-added signal handling"); /* get mimetype from caps */ - caps = gst_pad_get_current_caps(pad); - if (caps) { - str = gst_caps_get_structure(caps, 0); - if (str) - name = gst_structure_get_name(str); - } - if (!name) + MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret); + if (!caps_ret) goto ERROR; MMPLAYER_LOG_GST_CAPS_TYPE(caps); @@ -1219,7 +1264,7 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) LOGD("surface type : %d", stype); if (MMPLAYER_IS_MS_BUFF_SRC(player)) { - __mmplayer_gst_create_sinkbin(elem, pad, player); + __mmplayer_gst_create_sink_bin(elem, pad, caps, player); goto DONE; } @@ -1230,8 +1275,13 @@ _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; @@ -1240,7 +1290,7 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) 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; } @@ -1251,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"); @@ -1266,32 +1325,47 @@ _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); + } } - _mmplayer_track_update_selector_info(player, stream_type, sinkpad); + if (MMPLAYER_USE_DECODEBIN(player)) { + _mmplayer_track_update_stream(player, stream_type, sinkpad); + } else { + /* apply the text track information */ + if (stream_type == MM_PLAYER_TRACK_TYPE_TEXT) + mm_player_set_attribute((MMHandleType)player, NULL, + "content_text_track_num", player->track[stream_type].total_track_num, + "current_text_track_index", player->track[stream_type].active_track_index, NULL); + __mmplayer_create_sink_path(player, combiner, stream_type, caps); + } DONE: ERROR: @@ -1308,7 +1382,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; @@ -1317,25 +1391,25 @@ __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->selector[type].block_id) { - gst_pad_remove_probe(srcpad, player->selector[type].block_id); - player->selector[type].block_id = 0; + if (player->track[type].block_id) { + gst_pad_remove_probe(srcpad, player->track[type].block_id); + player->track[type].block_id = 0; } if (srcpad) { @@ -1355,21 +1429,21 @@ __mmplayer_set_decode_track_info(mmplayer_t *player, mmplayer_track_type_e type) MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(player); - LOGD("type: %d, the num of track: %d", type, player->selector[type].total_track_num); + LOGD("type: %d, the num of track: %d", type, player->track[type].total_track_num); /* change track to active pad */ - active_index = player->selector[type].active_pad_index; + active_index = player->track[type].active_track_index; if ((active_index != DEFAULT_TRACK) && (__mmplayer_change_selector_pad(player, type, active_index) != MM_ERROR_NONE)) { LOGW("failed to change %d type track to %d", type, active_index); - player->selector[type].active_pad_index = DEFAULT_TRACK; + player->track[type].active_track_index = DEFAULT_TRACK; return; } if (type == MM_PLAYER_TRACK_TYPE_TEXT) mm_player_set_attribute((MMHandleType)player, NULL, - "content_text_track_num", player->selector[type].total_track_num, - "current_text_track_index", player->selector[type].active_pad_index, NULL); + "content_text_track_num", player->track[type].total_track_num, + "current_text_track_index", player->track[type].active_track_index, NULL); MMPLAYER_FLEAVE(); return; @@ -1396,16 +1470,17 @@ __mmplayer_create_audio_sink_path(mmplayer_t *player, GstElement *audio_selector } if (player->num_dynamic_pad == 0) /* FIXME: num_dynamic_pad is only for rtsp? */ - __mmplayer_pipeline_complete(NULL, player); + _mmplayer_pipeline_complete(NULL, player); return TRUE; } /* apply the audio track information */ - __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_AUDIO); + if (MMPLAYER_USE_DECODEBIN(player)) + __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; } @@ -1428,13 +1503,13 @@ __mmplayer_create_text_sink_path(mmplayer_t *player, GstElement *text_selector) /* apply the text track information */ __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_TEXT); - if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0) + if (player->track[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0) player->has_closed_caption = TRUE; /* 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; } @@ -1467,8 +1542,8 @@ __mmplayer_gst_set_queue2_buffering(mmplayer_t *player) return TRUE; } -static void -__mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data) +void +_mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data) { mmplayer_t *player = NULL; GstElement *video_selector = NULL; @@ -1509,7 +1584,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 */ @@ -1590,7 +1665,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; @@ -1608,10 +1683,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__ @@ -1649,7 +1728,7 @@ __mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data) LOGD("display_surface_type (%d)", surface_type); if ((surface_type == MM_DISPLAY_SURFACE_OVERLAY) && - (__mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE)) { + (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE)) { LOGE("failed to acquire video overlay resource"); goto ERROR; } @@ -1712,7 +1791,7 @@ __mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data) LOGD("no more pads: %d, stream count dec : %d(num of dynamic pad)", player->no_more_pad, player->num_dynamic_pad); if ((player->no_more_pad) && (player->num_dynamic_pad == 0)) - __mmplayer_pipeline_complete(NULL, player); + _mmplayer_pipeline_complete(NULL, player); ERROR: @@ -2049,7 +2128,7 @@ _mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only) goto ERROR; } } else { - if (__mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) { + if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) { LOGE("failed to acquire video overlay resource"); goto ERROR; } @@ -2202,7 +2281,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; @@ -2492,7 +2571,7 @@ __mmplayer_gst_audio_deinterleave_no_more_pads(GstElement* object, gpointer data MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin); player->no_more_pad = TRUE; - __mmplayer_pipeline_complete(NULL, player); + _mmplayer_pipeline_complete(NULL, player); MMPLAYER_FLEAVE(); return; @@ -3120,27 +3199,27 @@ _mmplayer_video_stream_release_bo(mmplayer_t *player, void *bo) LOGW("failed to find bo %p", bo); return ret; } +static void +__mmplayer_video_stream_bo_list_free(mmplayer_video_bo_info_t *tmp) +{ + if (!tmp) + return; + + if (tmp->bo) + tbm_bo_unref(tmp->bo); + g_free(tmp); +} static void __mmplayer_video_stream_destroy_bo_list(mmplayer_t *player) { - GList *l = NULL; - MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(player); MMPLAYER_VIDEO_BO_LOCK(player); if (player->video_bo_list) { LOGD("destroy video_bo_list : %d", g_list_length(player->video_bo_list)); - for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) { - mmplayer_video_bo_info_t *tmp = (mmplayer_video_bo_info_t *)l->data; - if (tmp) { - if (tmp->bo) - tbm_bo_unref(tmp->bo); - g_free(tmp); - } - } - g_list_free(player->video_bo_list); + g_list_free_full(player->video_bo_list, (GDestroyNotify)__mmplayer_video_stream_bo_list_free); player->video_bo_list = NULL; } player->video_bo_size = 0; @@ -4155,10 +4234,14 @@ __mmplayer_gst_create_pipeline(mmplayer_t *player) player->pipeline->mainbin = mainbin; /* create the source and decoder elements */ - if (MMPLAYER_IS_MS_BUFF_SRC(player)) + if (MMPLAYER_IS_MS_BUFF_SRC(player)) { ret = _mmplayer_gst_build_es_pipeline(player); - else - ret = _mmplayer_gst_build_pipeline(player); + } else { + if (MMPLAYER_USE_DECODEBIN(player)) + ret = _mmplayer_gst_build_pipeline(player); /* TEMP: previous pipeline, will be removed.*/ + else + ret = _mmplayer_gst_build_pipeline_with_src(player); + } if (ret != MM_ERROR_NONE) { LOGE("failed to create some elements"); @@ -4181,6 +4264,7 @@ __mmplayer_gst_create_pipeline(mmplayer_t *player) return MM_ERROR_NONE; INIT_ERROR: + _mmplayer_bus_watcher_remove(player); __mmplayer_gst_destroy_pipeline(player); return MM_ERROR_PLAYER_INTERNAL; } @@ -4214,7 +4298,6 @@ __mmplayer_gst_destroy_pipeline(mmplayer_t *player) MMPLAYER_FREEIF(player->type); player->no_more_pad = FALSE; player->num_dynamic_pad = 0; - player->demux_pad_index = 0; MMPLAYER_SUBTITLE_INFO_LOCK(player); player->subtitle_language_list = NULL; @@ -4286,6 +4369,11 @@ __mmplayer_gst_destroy_pipeline(mmplayer_t *player) } MMPLAYER_FREEIF(player->album_art); + if (player->type_caps) { + gst_caps_unref(player->type_caps); + player->type_caps = NULL; + } + if (player->v_stream_caps) { gst_caps_unref(player->v_stream_caps); player->v_stream_caps = NULL; @@ -4949,12 +5037,7 @@ _mmplayer_destroy(MMHandleType handle) _mmplayer_deconstruct_attribute(handle); if (player->uri_info.uri_list) { - GList *uri_list = player->uri_info.uri_list; - for (; uri_list; uri_list = g_list_next(uri_list)) { - gchar *uri = uri_list->data; - MMPLAYER_FREEIF(uri); - } - g_list_free(player->uri_info.uri_list); + g_list_free_full(player->uri_info.uri_list, (GDestroyNotify)g_free); player->uri_info.uri_list = NULL; } @@ -4981,9 +5064,7 @@ _mmplayer_realize(MMHandleType hplayer) char *uri = NULL; void *param = NULL; MMHandleType attrs = 0; - int video_codec_type = 0; - int audio_codec_type = 0; - int default_codec_type = 0; + MMPLAYER_FENTER(); /* check player handle */ @@ -5035,7 +5116,6 @@ _mmplayer_realize(MMHandleType hplayer) player->is_subtitle_off = FALSE; /* set the subtitle ON default */ player->video360_metadata.is_spherical = -1; player->is_openal_plugin_used = FALSE; - player->demux_pad_index = 0; player->subtitle_language_list = NULL; player->is_subtitle_force_drop = FALSE; @@ -5067,23 +5147,6 @@ _mmplayer_realize(MMHandleType hplayer) player->streamer->buffering_req.rebuffer_time); } - mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, &audio_codec_type); - if (!strcmp(player->ini.audiocodec_default_type, "hw")) - default_codec_type = MM_PLAYER_CODEC_TYPE_HW; - else - default_codec_type = MM_PLAYER_CODEC_TYPE_SW; - - if (audio_codec_type != default_codec_type) { - LOGD("audio dec sorting is required"); - player->need_audio_dec_sorting = TRUE; - } - - mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_VIDEO_CODEC_TYPE, &video_codec_type); - if (video_codec_type != MM_PLAYER_CODEC_TYPE_DEFAULT) { - LOGD("video dec sorting is required"); - player->need_video_dec_sorting = TRUE; - } - /* realize pipeline */ ret = __mmplayer_gst_realize(player); if (ret != MM_ERROR_NONE) @@ -5107,6 +5170,7 @@ _mmplayer_unrealize(MMHandleType hplayer) MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); MMPLAYER_CMD_UNLOCK(player); + _mmplayer_bus_watcher_remove(player); /* destroy the gst bus msg thread which is created during realize. this funct have to be called before getting cmd lock. */ _mmplayer_bus_msg_thread_destroy(player); @@ -5589,9 +5653,11 @@ _mmplayer_pause(MMHandleType hplayer) /* pause pipeline */ ret = _mmplayer_gst_pause(player, async); - - if (ret != MM_ERROR_NONE) + if (ret != MM_ERROR_NONE) { LOGE("failed to pause player. ret : 0x%x", ret); + MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-pause-err"); + return ret; + } if (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) { if (_mmplayer_update_video_overlay_param(player, "display_rotation") != MM_ERROR_NONE) @@ -5599,8 +5665,7 @@ _mmplayer_pause(MMHandleType hplayer) } MMPLAYER_FLEAVE(); - - return ret; + return MM_ERROR_NONE; } /* in case of streaming, pause could take long time.*/ @@ -5829,8 +5894,8 @@ __mmplayer_is_only_mp3_type(gchar *str_caps) return FALSE; } -static void -__mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps) +void +_mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps) { GstStructure *caps_structure = NULL; gint samplerate = 0; @@ -5900,13 +5965,20 @@ _mmplayer_typefind_have_type(GstElement *tf, guint probability, GstCaps *caps, gpointer data) { mmplayer_t *player = (mmplayer_t *)data; - GstPad *pad = NULL; MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(player && tf && caps); /* store type string */ + if (player->type_caps) { + gst_caps_unref(player->type_caps); + player->type_caps = NULL; + } + + player->type_caps = gst_caps_copy(caps); + MMPLAYER_LOG_GST_CAPS_TYPE(player->type_caps); + MMPLAYER_FREEIF(player->type); player->type = gst_caps_to_string(caps); if (player->type) @@ -5932,27 +6004,27 @@ _mmplayer_typefind_have_type(GstElement *tf, guint probability, __mmplayer_update_content_type_info(player); - pad = gst_element_get_static_pad(tf, "src"); - if (!pad) { - LOGE("fail to get typefind src pad."); - return; - } + if (!player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst) { + GstPad *pad = NULL; - if (!_mmplayer_gst_create_decoder(player, pad, caps)) { - gboolean async = FALSE; - LOGE("failed to autoplug %s", player->type); + pad = gst_element_get_static_pad(tf, "src"); + if (!pad) { + LOGE("fail to get typefind src pad."); + return; + } - mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async); + if (!_mmplayer_gst_create_decoder(player, pad, caps)) { + gboolean async = FALSE; + LOGE("failed to autoplug %s", player->type); - if (async && player->msg_posted == FALSE) - __mmplayer_handle_missed_plugin(player); + mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async); + if (async && player->msg_posted == FALSE) + __mmplayer_handle_missed_plugin(player); + } + gst_object_unref(GST_OBJECT(pad)); } - - gst_object_unref(GST_OBJECT(pad)); - MMPLAYER_FLEAVE(); - return; } @@ -5977,20 +6049,20 @@ _mmplayer_gst_make_decodebin(mmplayer_t *player) /* no-more-pad pad handling signal */ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads", - G_CALLBACK(__mmplayer_gst_decode_no_more_pads), (gpointer)player); + G_CALLBACK(_mmplayer_gst_decode_no_more_pads), (gpointer)player); _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed", - G_CALLBACK(__mmplayer_gst_decode_pad_removed), (gpointer)player); + G_CALLBACK(_mmplayer_gst_decode_pad_removed), (gpointer)player); /* This signal is emitted when a pad for which there is no further possible decoding is added to the decodebin.*/ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type", - G_CALLBACK(__mmplayer_gst_decode_unknown_type), (gpointer)player); + G_CALLBACK(_mmplayer_gst_decode_unknown_type), (gpointer)player); /* This signal is emitted whenever decodebin finds a new stream. It is emitted before looking for any elements that can handle that stream.*/ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue", - G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), (gpointer)player); + 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(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort", @@ -6003,7 +6075,7 @@ _mmplayer_gst_make_decodebin(mmplayer_t *player) /* This signal is emitted once decodebin has finished decoding all the data.*/ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained", - G_CALLBACK(__mmplayer_gst_decode_drained), (gpointer)player); + G_CALLBACK(_mmplayer_gst_decode_drained), (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", @@ -6271,8 +6343,8 @@ DONE: return MM_ERROR_NONE; } -static void -__mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) +void +_mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) { mmplayer_t *player = (mmplayer_t *)data; @@ -6283,7 +6355,7 @@ __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) /* remove fakesink. */ if (!_mmplayer_gst_remove_fakesink(player, &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK])) { - /* NOTE : __mmplayer_pipeline_complete() can be called several time. because + /* NOTE : _mmplayer_pipeline_complete() can be called several time. because * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various * source element are not same. To overcome this situation, this function will called * several places and several times. Therefore, this is not an error case. @@ -6457,10 +6529,91 @@ 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) { - mmplayer_selector_t *selector = &player->selector[type]; + mmplayer_track_t *selector = &player->track[type]; mmplayer_gst_element_t *sinkbin = NULL; main_element_id_e selectorId = MMPLAYER_M_NUM; main_element_id_e sinkId = MMPLAYER_M_NUM; @@ -6531,11 +6684,12 @@ __mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type) LOGD("selector release"); /* release and unref requests pad from the selector */ - for (n = 0; n < selector->channels->len; n++) { - GstPad *sinkpad = g_ptr_array_index(selector->channels, n); + for (n = 0; n < selector->streams->len; n++) { + GstPad *sinkpad = g_ptr_array_index(selector->streams, n); gst_element_release_request_pad((player->pipeline->mainbin[selectorId].gst), sinkpad); } - g_ptr_array_set_size(selector->channels, 0); + + g_ptr_array_set_size(selector->streams, 0); gst_element_set_state(player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL); gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst); @@ -6553,11 +6707,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); @@ -6684,7 +6847,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; @@ -6699,8 +6862,8 @@ _mmplayer_get_next_uri(MMHandleType hplayer, char **uri) return MM_ERROR_NONE; } -static void -__mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad, +void +_mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad, GstCaps *caps, gpointer data) { mmplayer_t *player = (mmplayer_t *)data; @@ -6721,9 +6884,9 @@ __mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad, __mmplayer_check_not_supported_codec(player, klass, mime); } -static gboolean -__mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, - GstCaps *caps, gpointer data) +gboolean +_mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, + GstCaps *caps, gpointer data) { mmplayer_t *player = (mmplayer_t *)data; const char *mime = NULL; @@ -6971,7 +7134,7 @@ __mmplayer_can_build_audio_offload_path(mmplayer_t *player) } gst_object_unref(factory); - if (__mmplayer_acquire_hw_resource(player, + if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_AUDIO_OFFLOAD) != MM_ERROR_NONE) { LOGE("failed to acquire audio offload decoder resource"); goto DONE; @@ -7021,7 +7184,7 @@ __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps /* set stream information */ if (!player->audiodec_linked) - __mmplayer_set_audio_attrs(player, caps); + _mmplayer_set_audio_attrs(player, caps); /* update codec info */ player->not_supported_codec &= MISSING_PLUGIN_VIDEO; @@ -7040,7 +7203,7 @@ __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps goto DONE; } - if (__mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) { + if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) { LOGE("failed to acquire video decoder resource"); ret = GST_AUTOPLUG_SELECT_SKIP; goto DONE; @@ -7312,8 +7475,8 @@ DONE: return result; } -static void -__mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad, +void +_mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad, gpointer data) { //mmplayer_t *player = (mmplayer_t *)data; @@ -7336,8 +7499,38 @@ __mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad, gst_caps_unref(caps); } -static void -__mmplayer_gst_decode_drained(GstElement *bin, gpointer data) +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; GstIterator *iter = NULL; @@ -7349,7 +7542,7 @@ __mmplayer_gst_decode_drained(GstElement *bin, gpointer data) MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(player); - LOGD("__mmplayer_gst_decode_drained"); + LOGD("got drained signal"); if (!MMPLAYER_CMD_TRYLOCK(player)) { LOGW("Fail to get cmd lock"); @@ -7426,6 +7619,16 @@ _mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data) gchar *selected = NULL; selected = g_strdup(GST_ELEMENT_NAME(element)); player->audio_decoders = g_list_append(player->audio_decoders, selected); + + /* update codec info */ + player->not_supported_codec &= MISSING_PLUGIN_VIDEO; + player->can_support_codec |= FOUND_PLUGIN_AUDIO; + player->audiodec_linked = 1; + } else if (g_strrstr(klass, "Codec/Decoder/Video")) { + /* update codec info */ + player->not_supported_codec &= MISSING_PLUGIN_AUDIO; + player->can_support_codec |= FOUND_PLUGIN_VIDEO; + player->videodec_linked = 1; } if (g_strrstr(klass, "Demuxer/Adaptive")) { @@ -7597,30 +7800,23 @@ __mmplayer_release_misc_post(mmplayer_t *player) /* clean found audio decoders */ if (player->audio_decoders) { - GList *a_dec = player->audio_decoders; - for (; a_dec; a_dec = g_list_next(a_dec)) { - gchar *name = a_dec->data; - MMPLAYER_FREEIF(name); - } - g_list_free(player->audio_decoders); + g_list_free_full(player->audio_decoders, (GDestroyNotify)g_free); player->audio_decoders = NULL; } /* clean the uri list except original uri */ if (player->uri_info.uri_list && g_list_length(player->uri_info.uri_list) > 1) { + GList *tmp = NULL; original_uri = g_list_nth_data(player->uri_info.uri_list, 0); + tmp = g_list_remove_link(player->uri_info.uri_list, player->uri_info.uri_list); + g_list_free_full(tmp, (GDestroyNotify)g_free); + if (!original_uri) LOGW("failed to get original uri info"); mm_player_set_attribute((MMHandleType)player, NULL, "profile_uri", original_uri, (original_uri) ? strlen(original_uri) : (0), NULL); - GList *uri_list = player->uri_info.uri_list; - for (; uri_list; uri_list = g_list_next(uri_list)) { - gchar *uri = uri_list->data; - if (original_uri != uri) - MMPLAYER_FREEIF(uri); - } } /* clear the audio stream buffer list */ @@ -8152,6 +8348,44 @@ _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char *filepath) } static int +__mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int index) +{ + guint active_idx = 0; + GstStream *stream = NULL; + GList *streams = NULL; + GstEvent *ev = NULL; + GstCaps *caps = NULL; + + LOGD("Switching Streams... type: %d, index: %d", type, index); + + player->track[type].active_track_index = index; + + for (int i = 0; i < MM_PLAYER_TRACK_TYPE_MAX; i++) { + /* FIXME: need to consider the non display type or audio only in case of MM_PLAYER_TRACK_TYPE_VIDEO */ + if (player->track[i].total_track_num > 0) { + active_idx = player->track[i].active_track_index; + stream = g_ptr_array_index(player->track[i].streams, active_idx); + streams = g_list_append (streams, (gchar *)gst_stream_get_stream_id(stream)); + LOGD("Selecting %d type stream : %s\n", i, gst_stream_get_stream_id(stream)); + + if (i == MM_PLAYER_TRACK_TYPE_AUDIO) { + caps = gst_stream_get_caps(stream); + if (caps) { + _mmplayer_set_audio_attrs(player, caps); + gst_caps_unref(caps); + } + } + } + } + + ev = gst_event_new_select_streams(streams); + gst_element_send_event(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, ev); + g_list_free(streams); + + return MM_ERROR_NONE; +} + +static int __mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_type_e type, int index) { int result = MM_ERROR_NONE; @@ -8187,7 +8421,7 @@ __mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_type_e type, i goto EXIT; } - total_track_num = player->selector[type].total_track_num; + total_track_num = player->track[type].total_track_num; if (total_track_num <= 0) { result = MM_ERROR_PLAYER_NO_OP; LOGD("Language list is not available"); @@ -8227,7 +8461,10 @@ __mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_type_e type, i gst_object_unref(sinkpad); if (type == MM_PLAYER_TRACK_TYPE_AUDIO) - __mmplayer_set_audio_attrs(player, caps); + _mmplayer_set_audio_attrs(player, caps); + + if (caps) + gst_caps_unref(caps); EXIT: MMPLAYER_FREEIF(change_pad_name); @@ -8244,7 +8481,6 @@ _mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type gint current_active_index = 0; GstState current_state = GST_STATE_VOID_PENDING; - GstEvent *event = NULL; gint64 time = 0; MMPLAYER_FENTER(); @@ -8255,13 +8491,13 @@ _mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type if (!player->pipeline) { LOGE("Track %d pre setting -> %d", type, index); - player->selector[type].active_pad_index = index; + player->track[type].active_track_index = index; goto EXIT; } mainbin = player->pipeline->mainbin; - current_active_index = player->selector[type].active_pad_index; + current_active_index = player->track[type].active_track_index; /*If index is same as running index no need to change the pad*/ if (current_active_index == index) @@ -8279,23 +8515,30 @@ _mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type goto EXIT; } - result = __mmplayer_change_selector_pad(player, type, index); + if (MMPLAYER_USE_DECODEBIN(player)) + result = __mmplayer_change_selector_pad(player, type, index); + else + result = __mmplayer_switch_stream(player, type, index); + if (result != MM_ERROR_NONE) { - LOGE("change selector pad error"); + LOGE("failed to change track"); goto EXIT; } - player->selector[type].active_pad_index = index; + player->track[type].active_track_index = index; - if (current_state == GST_STATE_PLAYING) { - event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME, - (GstSeekFlags)(GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), - GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1); - if (event) { - _mmplayer_gst_send_event_to_sink(player, event); - } else { - result = MM_ERROR_PLAYER_INTERNAL; - goto EXIT; + if (MMPLAYER_USE_DECODEBIN(player)) { + GstEvent *event = NULL; + if (current_state == GST_STATE_PLAYING) { + event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME, + (GstSeekFlags)(GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), + GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1); + if (event) { + _mmplayer_gst_send_event_to_sink(player, event); + } else { + result = MM_ERROR_PLAYER_INTERNAL; + goto EXIT; + } } } @@ -8645,47 +8888,62 @@ _mmplayer_set_codec_type(MMHandleType hplayer, mmplayer_stream_type_e stream_typ { #define IDX_FIRST_SW_CODEC 0 mmplayer_t *player = (mmplayer_t *)hplayer; - const char *attr_name = (stream_type == MM_PLAYER_STREAM_TYPE_AUDIO) ? (MM_PLAYER_AUDIO_CODEC_TYPE) : (MM_PLAYER_VIDEO_CODEC_TYPE); + int default_codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT; + const char *attr_name = NULL; + const char *default_type = NULL; + const char *element_hw = NULL; + const char *element_sw = NULL; MMPLAYER_FENTER(); MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); - LOGD("ini setting : [a][h:%s][s:%s] / [v][h:%s][s:%s]", - player->ini.audiocodec_element_hw, player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC], - player->ini.videocodec_element_hw, player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC]); + LOGD("stream type: %d, codec_type: %d", stream_type, codec_type); + /* FIXME: player need to know whether the decoder exist or not about required codec type since 6.0*/ switch (stream_type) { case MM_PLAYER_STREAM_TYPE_AUDIO: - /* to support audio codec selection, codec info have to be added in ini file as below. - audio codec element hw = xxxx - audio codec element sw = avdec - and in case of audio hw codec is supported and selected, - audio filter elements should be applied depending on the hw capabilities. - */ - if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) && - (!strcmp(player->ini.audiocodec_element_hw, ""))) || - ((codec_type == MM_PLAYER_CODEC_TYPE_SW) && - (!strcmp(player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) { - LOGE("There is no audio codec info for codec_type %d", codec_type); - return MM_ERROR_PLAYER_NO_OP; - } - break; + attr_name = MM_PLAYER_AUDIO_CODEC_TYPE; + default_type = player->ini.audiocodec_default_type; + element_hw = player->ini.audiocodec_element_hw; + element_sw = player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC]; + break; case MM_PLAYER_STREAM_TYPE_VIDEO: - /* to support video codec selection, codec info have to be added in ini file as below. - video codec element hw = omx - video codec element sw = avdec */ - if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) && - (!strcmp(player->ini.videocodec_element_hw, ""))) || - ((codec_type == MM_PLAYER_CODEC_TYPE_SW) && - (!strcmp(player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) { - LOGE("There is no video codec info for codec_type %d", codec_type); - return MM_ERROR_PLAYER_NO_OP; - } - break; + attr_name = MM_PLAYER_VIDEO_CODEC_TYPE; + default_type = player->ini.videocodec_default_type; + element_hw = player->ini.videocodec_element_hw; + element_sw = player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC]; + break; default: LOGE("Invalid stream type %s", MMPLAYER_STREAM_TYPE_GET_NAME(stream_type)); return MM_ERROR_COMMON_INVALID_ARGUMENT; - break; + break; + } + + LOGD("default setting: [%s][%s][h:%s][s:%s]", attr_name, default_type, element_hw, element_sw); + + if (!strcmp(default_type, "sw")) + default_codec_type = MM_PLAYER_CODEC_TYPE_SW; + else + default_codec_type = MM_PLAYER_CODEC_TYPE_HW; + + if (codec_type == MM_PLAYER_CODEC_TYPE_DEFAULT) + codec_type = default_codec_type; + + /* to support codec selection, codec info have to be added in ini file. + in case of hw codec is selected, filter elements should be applied + depending on the hw capabilities. */ + if (codec_type != default_codec_type) { + if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) && (!strcmp(element_hw, ""))) || + ((codec_type == MM_PLAYER_CODEC_TYPE_SW) && (!strcmp(element_sw, "")))) { + LOGE("There is no codec for type %d", codec_type); + return MM_ERROR_PLAYER_NO_OP; + } + + LOGD("sorting is required"); + if (stream_type == MM_PLAYER_STREAM_TYPE_AUDIO) + player->need_audio_dec_sorting = TRUE; + else + player->need_video_dec_sorting = TRUE; } LOGD("update %s codec_type to %d", attr_name, codec_type);