X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmm_player_priv.c;h=1f13b3815fb0ba015afa3901dbfb99523375ad5b;hb=40cbaa95188c059a07f9b059ebe3ec8c8b96e185;hp=db6036c16b212c0d38e9c42b3316e029631d4832;hpb=d328d537d79b18b9bd10de0f19e07e1f98d46696;p=platform%2Fcore%2Fmultimedia%2Flibmm-player.git diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index db6036c..1f13b38 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -140,11 +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_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); -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); @@ -174,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); @@ -551,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; @@ -670,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; } @@ -750,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; @@ -759,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); @@ -937,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; @@ -1121,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; @@ -1165,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; @@ -1183,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; @@ -1208,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_URIDECODEBIN3(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; } @@ -1220,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_URIDECODEBIN3(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; } @@ -1241,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"); @@ -1256,33 +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); + } } - if (!MMPLAYER_USE_URIDECODEBIN3(player)) + 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: @@ -1299,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; @@ -1308,20 +1391,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) { @@ -1393,11 +1476,11 @@ __mmplayer_create_audio_sink_path(mmplayer_t *player, GstElement *audio_selector } /* apply the audio track information */ - if (!MMPLAYER_USE_URIDECODEBIN3(player)) + 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; } @@ -1426,7 +1509,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; } @@ -1501,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 */ @@ -1582,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; @@ -1600,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__ @@ -1641,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; } @@ -2041,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; } @@ -2194,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; @@ -3112,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; @@ -4147,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"); @@ -4173,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; } @@ -4277,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; @@ -4940,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; } @@ -4972,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 */ @@ -5057,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) @@ -5097,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); @@ -5579,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) @@ -5589,8 +5665,7 @@ _mmplayer_pause(MMHandleType hplayer) } MMPLAYER_FLEAVE(); - - return ret; + return MM_ERROR_NONE; } /* in case of streaming, pause could take long time.*/ @@ -5819,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; @@ -5896,6 +5971,14 @@ _mmplayer_typefind_have_type(GstElement *tf, guint probability, 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) @@ -6446,6 +6529,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) { @@ -6543,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); @@ -6674,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; @@ -6961,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; @@ -7011,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; @@ -7030,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; @@ -7327,6 +7500,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; @@ -7416,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")) { @@ -7587,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 */ @@ -8148,6 +8354,7 @@ __mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int ind GstStream *stream = NULL; GList *streams = NULL; GstEvent *ev = NULL; + GstCaps *caps = NULL; LOGD("Switching Streams... type: %d, index: %d", type, index); @@ -8160,6 +8367,14 @@ __mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int ind 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); + } + } } } @@ -8246,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); @@ -8297,11 +8515,11 @@ _mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type goto EXIT; } - if (MMPLAYER_USE_URIDECODEBIN3(player)) { - result = __mmplayer_switch_stream(player, type, index); - } else { + 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("failed to change track"); goto EXIT; @@ -8309,7 +8527,7 @@ _mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type player->track[type].active_track_index = index; - if (!MMPLAYER_USE_URIDECODEBIN3(player)) { + 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, @@ -8670,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);