X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmm_player_priv.c;h=eb5ad2a48ce39c4d3407a3c63a0b50b9ee6d684d;hb=6f697a1dac09947281a057e387ca2a5eb4e63a20;hp=575f8390f01757add77d480ba5841ade7e72af5f;hpb=781c17b6d81658a45600a6e8a017fff1ac0cc481;p=platform%2Fcore%2Fmultimedia%2Flibmm-player.git diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index 575f839..eb5ad2a 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -83,7 +83,7 @@ #define MM_VOLUME_FACTOR_MAX 1.0 /* Don't need to sleep for sound fadeout - * fadeout related fucntion will be deleted(Deprecated) + * fadeout related function will be deleted(Deprecated) */ #define MM_PLAYER_FADEOUT_TIME_DEFAULT 0 @@ -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); @@ -156,8 +156,7 @@ static int __mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_typ static gboolean __mmplayer_check_subtitle(mmplayer_t *player); static int __mmplayer_handle_missed_plugin(mmplayer_t *player); -static int __mmplayer_check_not_supported_codec(mmplayer_t *player, const gchar *factory_class, const gchar *mime); -static void __mmplayer_add_sink(mmplayer_t *player, GstElement *sink); +static void __mmplayer_add_sink(mmplayer_t *player, GstElement *sink, gboolean first); static void __mmplayer_del_sink(mmplayer_t *player, GstElement *sink); static void __mmplayer_release_signal_connection(mmplayer_t *player, mmplayer_signal_type_e type); static gpointer __mmplayer_gapless_play_thread(gpointer data); @@ -173,6 +172,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); @@ -195,6 +195,7 @@ static gboolean __mmplayer_swcodec_set_bo(mmplayer_t *player, mmplayer_video_dec static void __mmplayer_set_pause_state(mmplayer_t *player); static void __mmplayer_set_playing_state(mmplayer_t *player); +static int __mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int index); /*=========================================================================================== | | | FUNCTION DEFINITIONS | @@ -309,7 +310,7 @@ _mmplayer_get_stream_service_type(mmplayer_t *player) } /* this function sets the player state and also report - * it to applicaton by calling callback function + * it to application by calling callback function */ void _mmplayer_set_state(mmplayer_t *player, int state) @@ -389,7 +390,7 @@ _mmplayer_check_state(mmplayer_t *player, mmplayer_command_state_e command) MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); #ifdef __DEBUG__ - LOGD("incomming command : %d ", command); + LOGD("incoming command : %d ", command); #endif current_state = MMPLAYER_CURRENT_STATE(player); pending_state = MMPLAYER_PENDING_STATE(player); @@ -490,7 +491,7 @@ _mmplayer_check_state(mmplayer_t *player, mmplayer_command_state_e command) if (pending_state == MM_PLAYER_STATE_NONE) { if (current_state == MM_PLAYER_STATE_PAUSED) goto NO_OP; - else if (current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY) // support loading state of broswer + else if (current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY) // support loading state of browser goto INVALID_STATE; } else if (pending_state == MM_PLAYER_STATE_PAUSED) { goto ALREADY_GOING; @@ -583,6 +584,7 @@ int _mmplayer_acquire_hw_resource(mmplayer_t *player, mmplayer_resource_type_e t return MM_ERROR_PLAYER_INTERNAL; } + LOGD("commit [%d type] resource", type); rm_ret = mm_resource_manager_commit(player->resource_manager); if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) { LOGE("failed to commit of resource, ret(0x%x)", rm_ret); @@ -593,6 +595,36 @@ int _mmplayer_acquire_hw_resource(mmplayer_t *player, mmplayer_resource_type_e t return MM_ERROR_NONE; } +static void __mmplayer_destroy_hw_resource(mmplayer_t *player) +{ + int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE; + + MMPLAYER_RETURN_IF_FAIL(player); + MMPLAYER_RETURN_IF_FAIL(player->resource_manager); + + rm_ret = mm_resource_manager_mark_all_for_release(player->resource_manager); + if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) { + LOGW("failed to mark all for release of resource, ret(0x%x)", rm_ret); + goto rm_destroy; + } + + rm_ret = mm_resource_manager_commit(player->resource_manager); + if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) + LOGW("failed to commit resource, ret(0x%x)", rm_ret); + +rm_destroy: + /* de-initialize resource manager */ + rm_ret = mm_resource_manager_destroy(player->resource_manager); + if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) { + LOGW("failed to destroy resource manager, ret(0x%x)", rm_ret); + return; + } + + player->resource_manager = NULL; + + LOGD("resource manager is destroyed"); +} + static int __mmplayer_release_hw_resource(mmplayer_t *player, mmplayer_resource_type_e type) { int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE; @@ -613,9 +645,10 @@ static int __mmplayer_release_hw_resource(mmplayer_t *player, mmplayer_resource_ player->hw_resource[type] = NULL; + LOGD("commit [%d type] resource", type); rm_ret = mm_resource_manager_commit(player->resource_manager); if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) { - LOGE("failed to commit of resource, ret(0x%x)", rm_ret); + LOGE("failed to commit resource, ret(0x%x)", rm_ret); return MM_ERROR_PLAYER_INTERNAL; } @@ -669,12 +702,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; } @@ -716,11 +744,17 @@ __mmplayer_gapless_play_thread(gpointer data) mainbin = player->pipeline->mainbin; - MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER); - MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX); - MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG); - MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND); - MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC); + if (MMPLAYER_USE_DECODEBIN(player)) { + MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER); + MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG); /* decodebin */ + MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND); + MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC); + } else { + MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG); /* uridecodebin */ + mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = NULL; + mainbin[MMPLAYER_M_TYPEFIND].gst = NULL; + mainbin[MMPLAYER_M_SRC].gst = NULL; + } /* Initialize Player values */ __mmplayer_initialize_gapless_play(player); @@ -773,10 +807,14 @@ _mmplayer_bus_watcher_remove(MMHandleType hplayer) __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); + while (player->bus_watcher > 0) { + if (!MMPLAYER_BUS_WATCHER_WAIT_UNTIL(player, end_time)) { + LOGW("MMPLAYER_BUS_WATCHER_WAIT_UNTIL() timeout has passed - bus_watcher (%d)", + player->bus_watcher); + break; + } + } MMPLAYER_BUS_WATCHER_UNLOCK(player); - g_mutex_clear(&player->bus_watcher_mutex); g_cond_clear(&player->bus_watcher_cond); } @@ -846,7 +884,7 @@ _mmplayer_gst_remove_fakesink(mmplayer_t *player, mmplayer_gst_element_t *fakesi gst_element_set_locked_state(fakesink->gst, TRUE); /* setting the state to NULL never returns async - * so no need to wait for completion of state transiton + * so no need to wait for completion of state transition */ if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(fakesink->gst, GST_STATE_NULL)) LOGE("fakesink state change failure!"); @@ -967,7 +1005,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; @@ -1094,7 +1132,7 @@ ERROR: return ret; } -/* create fakesink for audio or video path witout audiobin or videobin */ +/* create fakesink for audio or video path without audiobin or videobin */ static void __mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name) { @@ -1111,13 +1149,13 @@ __mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name) fakesink = gst_element_factory_make("fakesink", NULL); if (fakesink == NULL) { LOGE("failed to create fakesink"); - goto EXIT; + return; } - /* store it as it's sink element */ - __mmplayer_add_sink(player, fakesink); - - gst_bin_add(GST_BIN(pipeline), fakesink); + if (!gst_bin_add(GST_BIN(pipeline), fakesink)) { + LOGE("failed to add fakesink to pipeline"); + goto ERROR; + } /* link */ sinkpad = gst_element_get_static_pad(fakesink, "sink"); @@ -1126,8 +1164,7 @@ __mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name) if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) { LOGE("failed to link fakesink"); - gst_object_unref(GST_OBJECT(fakesink)); - goto EXIT; + goto ERROR; } if (strstr(name, "video")) { @@ -1142,12 +1179,62 @@ __mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name) g_object_set(G_OBJECT(fakesink), "sync", TRUE, NULL); gst_element_set_state(fakesink, GST_STATE_PAUSED); -EXIT: + /* store it as it's sink element */ + __mmplayer_add_sink(player, fakesink, FALSE); + if (sinkpad) gst_object_unref(GST_OBJECT(sinkpad)); MMPLAYER_FLEAVE(); return; + +ERROR: + + if (sinkpad) + gst_object_unref(GST_OBJECT(sinkpad)); + + if (fakesink) { + gst_element_set_state(fakesink, GST_STATE_NULL); + + if (!gst_bin_remove(GST_BIN(pipeline), fakesink)) + gst_object_unref(GST_OBJECT(fakesink)); + } + + return; +} + +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; + } + + gst_element_set_state(concat, GST_STATE_PAUSED); + + pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst; + if (!gst_bin_add(GST_BIN(pipeline), concat)) { + LOGE("failed to add concat to pipeline"); + gst_element_set_state(concat, GST_STATE_NULL); + gst_object_unref(GST_OBJECT(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; + + MMPLAYER_FLEAVE(); + return concat; } static GstElement * @@ -1167,11 +1254,6 @@ __mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmp } g_object_set(selector, "sync-streams", TRUE, NULL); - player->pipeline->mainbin[elem_idx].id = elem_idx; - player->pipeline->mainbin[elem_idx].gst = selector; - - /* 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)); @@ -1183,10 +1265,29 @@ __mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmp gst_element_set_state(selector, GST_STATE_PAUSED); pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst; - gst_bin_add(GST_BIN(pipeline), selector); + if (!gst_bin_add(GST_BIN(pipeline), selector)) { + LOGE("failed to add selector to pipeline"); + + if (player->track[stream_type].block_id != 0) + gst_pad_remove_probe (srcpad, player->track[stream_type].block_id); + player->track[stream_type].block_id = 0; + + if (player->track[stream_type].event_probe_id != 0) + gst_pad_remove_probe (srcpad, player->track[stream_type].event_probe_id); + player->track[stream_type].event_probe_id = 0; + + gst_object_unref(GST_OBJECT(srcpad)); + + gst_element_set_state(selector, GST_STATE_NULL); + gst_object_unref(GST_OBJECT(selector)); + return NULL; + } gst_object_unref(GST_OBJECT(srcpad)); + player->pipeline->mainbin[elem_idx].id = elem_idx; + player->pipeline->mainbin[elem_idx].gst = selector; + MMPLAYER_FLEAVE(); return selector; } @@ -1195,7 +1296,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; @@ -1213,7 +1314,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; @@ -1238,8 +1339,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; } @@ -1250,17 +1351,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; } @@ -1271,14 +1377,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"); @@ -1286,33 +1401,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_request_pad_simple(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: @@ -1325,11 +1454,12 @@ ERROR: sinkpad = NULL; } + MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-pad-added"); return; } 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; @@ -1338,20 +1468,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) { @@ -1380,10 +1510,10 @@ __mmplayer_set_decode_track_info(mmplayer_t *player, mmplayer_track_type_e type) /* change track to active pad */ active_index = player->track[type].active_track_index; - if ((active_index != DEFAULT_TRACK) && + if ((active_index != DEFAULT_TRACK_INDEX) && (__mmplayer_change_selector_pad(player, type, active_index) != MM_ERROR_NONE)) { LOGW("failed to change %d type track to %d", type, active_index); - player->track[type].active_track_index = DEFAULT_TRACK; + player->track[type].active_track_index = DEFAULT_TRACK_INDEX; return; } @@ -1423,11 +1553,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; } @@ -1443,7 +1573,7 @@ __mmplayer_create_text_sink_path(mmplayer_t *player, GstElement *text_selector) MMPLAYER_RETURN_VAL_IF_FAIL(player && text_selector, FALSE); if (MMPLAYER_IS_MS_BUFF_SRC(player)) { - LOGD("text path is not supproted"); + LOGD("text path is not supported"); return TRUE; } @@ -1456,7 +1586,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; } @@ -1531,7 +1661,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 */ @@ -1612,7 +1742,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; @@ -1630,10 +1760,15 @@ __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(pad, caps, str, name, caps_ret); - if (!caps_ret) - goto ERROR; + 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; + if (caps) + gst_caps_unref(caps); + caps = gst_caps_ref(ref_caps); + } caps_str = gst_caps_to_string(caps); #ifdef __DEBUG__ @@ -1670,7 +1805,7 @@ __mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data) mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type); LOGD("display_surface_type (%d)", surface_type); - if ((surface_type == MM_DISPLAY_SURFACE_OVERLAY) && + if ((surface_type == MM_DISPLAY_SURFACE_OVERLAY || surface_type == MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) && (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE)) { LOGE("failed to acquire video overlay resource"); goto ERROR; @@ -1709,7 +1844,7 @@ __mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data) player->textsink_linked = 1; } else { /* linked textbin exist which means that the external subtitle path exist already */ - LOGW("ignoring internal subtutle since external subtitle is available"); + LOGW("ignoring internal subtitle since external subtitle is available"); } } sink_pad_name = "text_sink"; @@ -1775,7 +1910,7 @@ __mmplayer_get_property_value_for_rotation(mmplayer_t *player, int display_angle if (rotation_angle >= 360) rotation_angle -= 360; - /* chech if supported or not */ + /* check if supported or not */ if (rotation_angle % 90) { LOGD("not supported rotation angle = %d", rotation_angle); return FALSE; @@ -1814,7 +1949,7 @@ _mmplayer_get_video_angle(mmplayer_t *player, int *display_angle, int *orientati } if (display_angle) { - /* update user roation */ + /* update user rotation */ mm_attrs_get_int_by_name(attrs, "display_rotation", &display_rotation); /* Counter clockwise */ @@ -1887,7 +2022,8 @@ static void __mmplayer_video_param_set_display_visible(mmplayer_t *player) MMPLAYER_FENTER(); /* check video sinkbin is created */ - if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY)) + if (!(_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY) || + _mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI))) return; attrs = MMPLAYER_GET_ATTRS(player); @@ -1975,6 +2111,28 @@ static void __mmplayer_video_param_set_roi_area(mmplayer_t *player) win_roi_x, win_roi_y, win_roi_width, win_roi_height); } +static void __mmplayer_video_param_set_display_overlay_sync_ui(mmplayer_t *player) +{ + MMHandleType attrs = 0; + gchar *handle = NULL; + + /* check video sinkbin is created */ + if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI)) + return; + + attrs = MMPLAYER_GET_ATTRS(player); + MMPLAYER_RETURN_IF_FAIL(attrs); + + /* common case if using overlay surface */ + mm_attrs_get_string_by_name(attrs, "exported_shell_handle", &handle); + MMPLAYER_RETURN_IF_FAIL(handle); + + gst_video_overlay_set_wl_window_exported_shell_handle( + GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst), + handle); + LOGD("set video param: exported_shell_handle (%s)", handle); +} + static void __mmplayer_video_param_set_display_overlay(mmplayer_t *player) { MMHandleType attrs = 0; @@ -2002,14 +2160,24 @@ int _mmplayer_update_video_overlay_param(mmplayer_t *player, const char *param_name) { gboolean update_all_param = FALSE; + int curr_type = MM_DISPLAY_SURFACE_NUM; MMPLAYER_FENTER(); - if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY)) { + if (!player || !player->pipeline || !player->pipeline->mainbin || !player->pipeline->videobin || + !player->pipeline->videobin[MMPLAYER_V_BIN].gst || + !player->pipeline->videobin[MMPLAYER_V_SINK].gst) { LOGW("videosink is not ready yet"); return MM_ERROR_PLAYER_NOT_INITIALIZED; } + mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &curr_type); + + if (curr_type != MM_DISPLAY_SURFACE_OVERLAY && curr_type != MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) { + LOGE("current type(%d) is wrong", curr_type); + return MM_ERROR_PLAYER_INTERNAL; + } + if (strcmp(player->ini.videosink_element_overlay, "tizenwlsink")) { LOGE("invalid videosink [%s]", player->ini.videosink_element_overlay); return MM_ERROR_PLAYER_INTERNAL; @@ -2019,6 +2187,11 @@ _mmplayer_update_video_overlay_param(mmplayer_t *player, const char *param_name) if (!g_strcmp0(param_name, "update_all_param")) update_all_param = TRUE; + if (curr_type == MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) { + __mmplayer_video_param_set_display_overlay_sync_ui(player); + MMPLAYER_FLEAVE(); + return MM_ERROR_NONE; + } if (update_all_param || !g_strcmp0(param_name, "display_overlay")) __mmplayer_video_param_set_display_overlay(player); if (update_all_param || !g_strcmp0(param_name, "display_method")) @@ -2032,19 +2205,15 @@ _mmplayer_update_video_overlay_param(mmplayer_t *player, const char *param_name) if (update_all_param) __mmplayer_video_param_set_video_roi_area(player); - MMPLAYER_FLEAVE(); return MM_ERROR_NONE; } -int -_mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only) +static int __mmplayer_set_disable_overlay_option(mmplayer_t *player, bool disable) { gboolean disable_overlay = FALSE; - mmplayer_t *player = (mmplayer_t *)hplayer; MMPLAYER_FENTER(); - MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED); MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin && player->pipeline->videobin[MMPLAYER_V_SINK].gst, MM_ERROR_PLAYER_NO_OP); /* invalid op */ @@ -2056,65 +2225,75 @@ _mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only) g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL); - if (audio_only == (bool)disable_overlay) { - LOGE("It's the same with current setting: (%d)", audio_only); + if (disable == (bool)disable_overlay) { + LOGE("It's the same with current setting: (%d)", disable); return MM_ERROR_NONE; } - if (audio_only) { + if (disable) { LOGE("disable overlay"); g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", TRUE, NULL); /* release overlay resource */ if (__mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) { LOGE("failed to release overlay resource"); - goto ERROR; + return MM_ERROR_PLAYER_INTERNAL; } } else { if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) { LOGE("failed to acquire video overlay resource"); - goto ERROR; + return MM_ERROR_PLAYER_INTERNAL; } player->interrupted_by_resource = FALSE; LOGD("enable overlay"); __mmplayer_video_param_set_display_overlay(player); + __mmplayer_video_param_set_display_overlay_sync_ui(player); g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", FALSE, NULL); } -ERROR: MMPLAYER_FLEAVE(); return MM_ERROR_NONE; } int -_mmplayer_get_audio_only(MMHandleType hplayer, bool *paudio_only) +_mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only) { + int ret = MM_ERROR_NONE; mmplayer_t *player = (mmplayer_t *)hplayer; - gboolean disable_overlay = FALSE; MMPLAYER_FENTER(); - MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED); - MMPLAYER_RETURN_VAL_IF_FAIL(paudio_only, MM_ERROR_INVALID_ARGUMENT); - MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin && - player->pipeline->videobin[MMPLAYER_V_SINK].gst, - MM_ERROR_PLAYER_NO_OP); /* invalid op */ - if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) { - LOGW("Display control is not supported"); - return MM_ERROR_PLAYER_INTERNAL; + if (MMPLAYER_USE_DECODEBIN(player)) { + ret = __mmplayer_set_disable_overlay_option(player, audio_only); + goto EXIT; } - g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL); + if (audio_only) { + MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin && + player->pipeline->videobin[MMPLAYER_V_SINK].gst, + MM_ERROR_PLAYER_NO_OP); /* invalid op */ - *paudio_only = (bool)disable_overlay; + __mmplayer_del_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst); - LOGD("audio_only : %d", *paudio_only); + __mmplayer_switch_stream(player, MM_PLAYER_TRACK_TYPE_VIDEO, INVALID_TRACK_INDEX); - MMPLAYER_FLEAVE(); + /* release decoder resource */ + if (__mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) { + LOGE("failed to release video decoder resources"); + return MM_ERROR_PLAYER_INTERNAL; + } + player->can_support_codec &= ~FOUND_PLUGIN_VIDEO; + } else { + __mmplayer_switch_stream(player, MM_PLAYER_TRACK_TYPE_VIDEO, DEFAULT_TRACK_INDEX); + } - return MM_ERROR_NONE; +EXIT: + mm_player_set_attribute(hplayer, NULL, MM_PLAYER_AUDIO_ONLY, (int)audio_only, (char *)NULL); + + MMPLAYER_FLEAVE(); + return ret; } int @@ -2220,11 +2399,7 @@ __mmplayer_gst_caps_notify_cb(GstPad *pad, GParamSpec *unused, gpointer data) MMPLAYER_RETURN_IF_FAIL(unused); MMPLAYER_RETURN_IF_FAIL(data); - caps = gst_pad_get_current_caps(pad); - 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; @@ -2472,7 +2647,7 @@ __mmplayer_gst_audio_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpoin G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb), (gpointer)player); - __mmplayer_add_sink(player, sink); + __mmplayer_add_sink(player, sink, FALSE); if (gst_element_sync_state_with_parent(queue) == GST_STATE_CHANGE_FAILURE) { LOGE("failed to sync state"); @@ -2776,7 +2951,7 @@ __mmplayer_gst_make_audio_playback_sink(mmplayer_t *player, GList **bucket) "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), (gpointer)player); gst_object_unref(GST_OBJECT(sink_pad)); - __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst); + __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst, FALSE); MMPLAYER_FLEAVE(); return MM_ERROR_NONE; @@ -2918,7 +3093,7 @@ __mmplayer_gst_make_audio_extract_sink(mmplayer_t *player, GList **bucket) MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads", G_CALLBACK(__mmplayer_gst_audio_deinterleave_no_more_pads), (gpointer)player); player->no_more_pad = FALSE; } else { - /* 4-2. create fakesink to extract interlevaed pcm */ + /* 4-2. create fakesink to extract interleaved pcm */ LOGD("add audio fakesink for interleaved audio"); MMPLAYER_CREATE_ELEMENT(audiobin, extract_sink_id, "fakesink", "fakeaudiosink", *bucket, player); if (!(player->audio_extract_opt & MM_PLAYER_AUDIO_EXTRACT_NO_SYNC_WITH_CLOCK)) @@ -2932,7 +3107,7 @@ __mmplayer_gst_make_audio_extract_sink(mmplayer_t *player, GList **bucket) G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb), (gpointer)player); - __mmplayer_add_sink(player, audiobin[extract_sink_id].gst); + __mmplayer_add_sink(player, audiobin[extract_sink_id].gst, FALSE); } MMPLAYER_FLEAVE(); @@ -2963,7 +3138,7 @@ __mmplayer_gst_make_audio_bin_element(mmplayer_t *player, GList **bucket) g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "sync", TRUE, "volume", player->sound.volume, "mute", player->sound.mute, NULL); - __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst); + __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst, FALSE); goto DONE; } @@ -3094,7 +3269,7 @@ ERROR: } } - /* release audiobin with it's childs */ + /* release audiobin with it's children */ if (audiobin[MMPLAYER_A_BIN].gst) gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst)); @@ -3142,27 +3317,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; @@ -3178,6 +3353,7 @@ __mmplayer_video_stream_get_bo(mmplayer_t *player, int size) GList *l = NULL; MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL); gboolean ret = TRUE; + gint64 end_time = 0; /* check DRC, if it is, destroy the prev bo list to create again */ if (player->video_bo_size != size) { @@ -3230,6 +3406,9 @@ __mmplayer_video_stream_get_bo(mmplayer_t *player, int size) } } + if (player->ini.video_bo_timeout > 0) + end_time = g_get_monotonic_time() + player->ini.video_bo_timeout * G_TIME_SPAN_SECOND; + while (TRUE) { /* get bo from list*/ for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) { @@ -3241,20 +3420,20 @@ __mmplayer_video_stream_get_bo(mmplayer_t *player, int size) return tbm_bo_ref(tmp->bo); } } - if (!ret) { - LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout); - MMPLAYER_VIDEO_BO_UNLOCK(player); - return NULL; - } if (player->ini.video_bo_timeout <= 0) { MMPLAYER_VIDEO_BO_WAIT(player); } else { - gint64 timeout = g_get_monotonic_time() + player->ini.video_bo_timeout * G_TIME_SPAN_SECOND; - ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, timeout); + ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, end_time); + if (!ret) { + LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout); + break; + } } - continue; } + + MMPLAYER_VIDEO_BO_UNLOCK(player); + return NULL; } static void @@ -3302,7 +3481,7 @@ __mmplayer_video_stream_decoded_render_cb(GstElement *object, GstBuffer *buffer, /* set size and timestamp */ mem = gst_buffer_peek_memory(buffer, 0); stream->length_total = gst_memory_get_sizes(mem, NULL, NULL); - stream->timestamp = (unsigned int)(GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer))); /* nano sec -> mili sec */ + stream->timestamp = (unsigned int)(GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer))); /* nano sec -> milli sec */ /* check zero-copy */ if (player->set_mode.video_zc && @@ -3425,7 +3604,9 @@ __mmplayer_gst_create_video_filters(mmplayer_t *player, MMDisplaySurfaceType sur goto EXIT; } - if (surface_type != MM_DISPLAY_SURFACE_OVERLAY || player->set_mode.video_zc) { + if ((surface_type != MM_DISPLAY_SURFACE_OVERLAY && + surface_type != MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) || + player->set_mode.video_zc) { LOGD("skip creating the videoconv and rotator"); return MM_ERROR_NONE; } @@ -3455,10 +3636,13 @@ __mmplayer_get_videosink_factory_name(mmplayer_t *player, MMDisplaySurfaceType s switch (surface_type) { case MM_DISPLAY_SURFACE_OVERLAY: + /* fall through */ + case MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI: if (strlen(player->ini.videosink_element_overlay) > 0) factory_name = player->ini.videosink_element_overlay; break; case MM_DISPLAY_SURFACE_REMOTE: + /* fall through */ case MM_DISPLAY_SURFACE_NULL: if (strlen(player->ini.videosink_element_fake) > 0) factory_name = player->ini.videosink_element_fake; @@ -3492,7 +3676,7 @@ __mmplayer_gst_set_videosink_property(mmplayer_t *player, MMDisplaySurfaceType s return MM_ERROR_PLAYER_INTERNAL; } - if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) { + if (surface_type == MM_DISPLAY_SURFACE_OVERLAY || surface_type == MM_DISPLAY_SURFACE_OVERLAY_SYNC_UI) { bool use_tbm = (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical)); if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) { g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, @@ -3595,7 +3779,7 @@ __mmplayer_gst_create_video_sink_bin(mmplayer_t *player, GstCaps *caps, MMDispla } /* store it as it's sink element */ - __mmplayer_add_sink(player, videobin[MMPLAYER_V_SINK].gst); + __mmplayer_add_sink(player, videobin[MMPLAYER_V_SINK].gst, TRUE); /* adding created elements to bin */ if (!_mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket)) { @@ -3644,7 +3828,7 @@ ERROR: if (pad) gst_object_unref(GST_OBJECT(pad)); - /* release videobin with it's childs */ + /* release videobin with it's children */ if (videobin[MMPLAYER_V_BIN].gst) gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst)); @@ -3679,7 +3863,7 @@ __mmplayer_gst_create_plain_text_elements(mmplayer_t *player) if (!player->play_subtitle) { LOGD("add textbin sink as sink element of whole pipeline."); - __mmplayer_add_sink(player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst)); + __mmplayer_add_sink(player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst), FALSE); } /* adding created elements to bin */ @@ -3700,9 +3884,6 @@ __mmplayer_gst_create_plain_text_elements(mmplayer_t *player) goto ERROR; } - /* done. free allocated variables */ - g_list_free(element_bucket); - if (textbin[MMPLAYER_T_QUEUE].gst) { GstPad *pad = NULL; GstPad *ghostpad = NULL; @@ -3728,9 +3909,12 @@ __mmplayer_gst_create_plain_text_elements(mmplayer_t *player) } } + g_list_free(element_bucket); + return MM_ERROR_NONE; ERROR: + g_list_free(element_bucket); if (!player->play_subtitle && textbin[MMPLAYER_T_FAKE_SINK].gst) { @@ -3746,7 +3930,6 @@ static int __mmplayer_gst_create_text_sink_bin(mmplayer_t *player) { mmplayer_gst_element_t *textbin = NULL; - GList *element_bucket = NULL; int surface_type = 0; gint i = 0; @@ -3797,8 +3980,6 @@ ERROR: LOGD("ERROR : releasing textbin"); - g_list_free(element_bucket); - /* release signal */ __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN); @@ -3818,7 +3999,7 @@ ERROR: } } - /* release textbin with it's childs */ + /* release textbin with it's children */ if (textbin[MMPLAYER_T_BIN].gst) gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst)); @@ -3940,7 +4121,7 @@ __mmplayer_gst_create_text_pipeline(mmplayer_t *player) /* release signal */ __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN); - /* release textbin with it's childs */ + /* release textbin with it's children */ gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst)); MMPLAYER_FREEIF(player->pipeline->textbin); player->pipeline->textbin = textbin = NULL; @@ -3991,7 +4172,7 @@ ERROR: if (player->pipeline->textbin) { LOGE("remove textbin"); - /* release textbin with it's childs */ + /* release textbin with it's children */ MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN); MMPLAYER_FREEIF(player->pipeline->textbin); player->pipeline->textbin = NULL; @@ -4116,7 +4297,7 @@ __mmplayer_gst_adjust_subtitle_position(mmplayer_t *player, int position) return MM_ERROR_NONE; } - /* check current postion */ + /* check current position */ player->adjust_subtitle_pos = position; LOGD("save adjust_subtitle_pos in player"); @@ -4180,10 +4361,10 @@ __mmplayer_gst_create_pipeline(mmplayer_t *player) if (MMPLAYER_IS_MS_BUFF_SRC(player)) { ret = _mmplayer_gst_build_es_pipeline(player); } else { - if (player->ini.use_uridecodebin3) - ret = _mmplayer_gst_build_pipeline_with_src(player); + if (MMPLAYER_USE_DECODEBIN(player)) + ret = _mmplayer_gst_build_pipeline(player); /* TEMP: previous pipeline, will be removed.*/ else - ret = _mmplayer_gst_build_pipeline(player); + ret = _mmplayer_gst_build_pipeline_with_src(player); } if (ret != MM_ERROR_NONE) { @@ -4191,7 +4372,7 @@ __mmplayer_gst_create_pipeline(mmplayer_t *player) goto INIT_ERROR; } - /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */ + /* Note : check whether subtitle attribute uri is set. If uri is set, then try to play subtitle file */ if (__mmplayer_check_subtitle(player) && (__mmplayer_gst_create_text_pipeline(player) != MM_ERROR_NONE)) LOGE("failed to create text pipeline"); @@ -4273,9 +4454,6 @@ __mmplayer_gst_destroy_pipeline(mmplayer_t *player) __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_ALL); if (mainbin) { - mmplayer_gst_element_t *audiobin = player->pipeline->audiobin; - mmplayer_gst_element_t *videobin = player->pipeline->videobin; - mmplayer_gst_element_t *textbin = player->pipeline->textbin; GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst)); gst_bus_set_sync_handler(bus, NULL, NULL, NULL); gst_object_unref(bus); @@ -4295,13 +4473,9 @@ __mmplayer_gst_destroy_pipeline(mmplayer_t *player) if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst) gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst)); - /* free avsysaudiosink - avsysaudiosink should be unref when destory pipeline just after start play with BT. - Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed. - */ - MMPLAYER_FREEIF(audiobin); - MMPLAYER_FREEIF(videobin); - MMPLAYER_FREEIF(textbin); + MMPLAYER_FREEIF(player->pipeline->audiobin); + MMPLAYER_FREEIF(player->pipeline->videobin); + MMPLAYER_FREEIF(player->pipeline->textbin); MMPLAYER_FREEIF(mainbin); } @@ -4312,6 +4486,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; @@ -4402,7 +4581,7 @@ __mmplayer_gst_unrealize(mmplayer_t *player) /* destroy pipeline */ ret = __mmplayer_gst_destroy_pipeline(player); if (ret != MM_ERROR_NONE) { - LOGE("failed to destory pipeline"); + LOGE("failed to destroy pipeline"); return ret; } @@ -4486,55 +4665,6 @@ _mmplayer_parse_profile(const char *uri, void *param, mmplayer_parse_profile_t * return ret; } -static gboolean -__mmplayer_can_do_interrupt(mmplayer_t *player) -{ - if (!player || !player->pipeline || !player->attrs) { - LOGW("not initialized"); - goto FAILED; - } - - if (player->audio_decoded_cb) { - LOGW("not support in pcm extraction mode"); - goto FAILED; - } - - /* check if seeking */ - if (player->seek_state != MMPLAYER_SEEK_NONE) { - MMMessageParamType msg_param; - memset(&msg_param, 0, sizeof(MMMessageParamType)); - msg_param.code = MM_ERROR_PLAYER_SEEK; - player->seek_state = MMPLAYER_SEEK_NONE; - MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param); - goto FAILED; - } - - /* check other thread */ - if (!MMPLAYER_CMD_TRYLOCK(player)) { - LOGW("locked already, cmd state : %d", player->cmd); - - /* check application command */ - if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) { - LOGW("playing.. should wait cmd lock then, will be interrupted"); - - /* lock will be released at mrp_resource_release_cb() */ - MMPLAYER_CMD_LOCK(player); - goto INTERRUPT; - } - LOGW("nothing to do"); - goto FAILED; - } else { - LOGW("can interrupt immediately"); - goto INTERRUPT; - } - -FAILED: /* with CMD UNLOCKED */ - return FALSE; - -INTERRUPT: /* with CMD LOCKED, will do UNLOCK at __resource_release_cb() */ - return TRUE; -} - static int __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res, void *user_data) @@ -4548,18 +4678,31 @@ __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res, if (!user_data) { LOGE("user_data is null"); - return FALSE; + return TRUE; } + player = (mmplayer_t *)user_data; - if (!__mmplayer_can_do_interrupt(player)) { - LOGW("no need to interrupt, so leave"); - /* FIXME: there is no way to avoid releasing resource. */ - return FALSE; + if (!player->pipeline || !player->attrs) { + LOGW("not initialized"); + return TRUE; + } + + LOGD("cmd lock player, cmd state : %d", player->cmd); + MMPLAYER_CMD_LOCK(player); + LOGD("cmd locked player"); + + if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_NULL + || MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_NONE) { + LOGW("player already destroyed"); + MMPLAYER_CMD_UNLOCK(player); + return TRUE; } player->interrupted_by_resource = TRUE; + MMPLAYER_POST_MSG(player, MM_MESSAGE_INTERRUPT_STARTED, NULL); + /* get last play position */ if (_mmplayer_gst_get_position(player, &pos) == MM_ERROR_NONE) { msg.union_type = MM_MSG_UNION_TIME; @@ -4573,7 +4716,6 @@ __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res, if (_mmplayer_unrealize((MMHandleType)player) != MM_ERROR_NONE) LOGE("failed to unrealize"); - /* lock is called in __mmplayer_can_do_interrupt() */ MMPLAYER_CMD_UNLOCK(player); for (res_idx = MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER; res_idx < MMPLAYER_RESOURCE_TYPE_MAX; res_idx++) { @@ -4661,15 +4803,15 @@ _mmplayer_create_player(MMHandleType handle) ret = _mmplayer_initialize_video_capture(player); if (ret != MM_ERROR_NONE) { - LOGE("failed to initialize video capture"); - goto ERROR; + LOGW("video capture is not supported"); + /* do not handle as error for headless profile */ } /* initialize resource manager */ if (mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA, __resource_release_cb, player, &player->resource_manager) != MM_RESOURCE_MANAGER_ERROR_NONE) { - LOGE("failed to initialize resource manager"); + LOGE("failed to create resource manager"); ret = MM_ERROR_PLAYER_INTERNAL; goto ERROR; } @@ -4936,7 +5078,7 @@ _mmplayer_destroy(MMHandleType handle) MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player); MMPLAYER_GAPLESS_PLAY_THREAD_UNLOCK(player); - LOGD("waitting for gapless play thread exit"); + LOGD("waiting for gapless play thread exit"); g_thread_join(player->gapless_play_thread); g_mutex_clear(&player->gapless_play_thread_mutex); g_cond_clear(&player->gapless_play_thread_cond); @@ -4945,20 +5087,17 @@ _mmplayer_destroy(MMHandleType handle) _mmplayer_release_video_capture(player); - /* de-initialize resource manager */ - if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_destroy( - player->resource_manager)) - LOGE("failed to deinitialize resource manager"); - /* release miscellaneous information */ __mmplayer_release_misc(player); /* release pipeline */ - if (MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline(player)) { - LOGE("failed to destory pipeline"); + if (__mmplayer_gst_destroy_pipeline(player) != MM_ERROR_NONE) { + LOGE("failed to destroy pipeline"); return MM_ERROR_PLAYER_INTERNAL; } + __mmplayer_destroy_hw_resource(player); + g_queue_free(player->bus_msg_q); /* release subtitle info lock and cond */ @@ -4975,12 +5114,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; } @@ -5007,9 +5141,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 */ @@ -5092,23 +5224,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) @@ -5126,6 +5241,8 @@ _mmplayer_unrealize(MMHandleType hplayer) { mmplayer_t *player = (mmplayer_t *)hplayer; int ret = MM_ERROR_NONE; + int rm_ret = MM_ERROR_NONE; + mmplayer_resource_type_e res_idx = MMPLAYER_RESOURCE_TYPE_MAX; MMPLAYER_FENTER(); @@ -5147,17 +5264,14 @@ _mmplayer_unrealize(MMHandleType hplayer) /* unrealize pipeline */ ret = __mmplayer_gst_unrealize(player); - if (!player->interrupted_by_resource) { - int rm_ret = MM_ERROR_NONE; - mmplayer_resource_type_e res_idx = MMPLAYER_RESOURCE_TYPE_MAX; - - for (res_idx = MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER; res_idx < MMPLAYER_RESOURCE_TYPE_MAX; res_idx++) { - rm_ret = __mmplayer_release_hw_resource(player, res_idx); - if (rm_ret != MM_ERROR_NONE) - LOGE("failed to release [%d] resources", res_idx); - } + for (res_idx = MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER; res_idx < MMPLAYER_RESOURCE_TYPE_MAX; res_idx++) { + rm_ret = __mmplayer_release_hw_resource(player, res_idx); + if (rm_ret != MM_ERROR_NONE) + LOGE("failed to release [%d] resources", res_idx); } + player->interrupted_by_resource = FALSE; + MMPLAYER_FLEAVE(); return ret; } @@ -5565,14 +5679,14 @@ _mmplayer_pause(MMHandleType hplayer) /* check current state */ MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_PAUSE); - /* check pipline reconfigure state */ + /* check pipeline reconfigure state */ __mmplayer_check_pipeline_reconfigure_state(player); switch (MMPLAYER_CURRENT_STATE(player)) { case MM_PLAYER_STATE_READY: { /* check prepare async or not. - * In the case of streaming playback, it's recommned to avoid blocking wait. + * In the case of streaming playback, it's recommended to avoid blocking wait. */ mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async); LOGD("prepare working mode : %s", (async ? "async" : "sync")); @@ -5615,9 +5729,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) @@ -5625,8 +5741,7 @@ _mmplayer_pause(MMHandleType hplayer) } MMPLAYER_FLEAVE(); - - return ret; + return MM_ERROR_NONE; } /* in case of streaming, pause could take long time.*/ @@ -5643,11 +5758,24 @@ _mmplayer_abort_pause(MMHandleType hplayer) player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED); - LOGD("set the pipeline state to READY"); + if (player->pipeline->videobin && player->pipeline->videobin[MMPLAYER_V_BIN].gst) { + LOGD("set the videobin state to READY"); + ret = _mmplayer_gst_set_state(player, player->pipeline->videobin[MMPLAYER_V_BIN].gst, + GST_STATE_READY, TRUE, MMPLAYER_STATE_CHANGE_TIMEOUT(player)); - /* set state to READY */ + } + + if (player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_BIN].gst) { + LOGD("set the audiobin state to READY"); + ret = _mmplayer_gst_set_state(player, player->pipeline->audiobin[MMPLAYER_A_BIN].gst, + GST_STATE_READY, TRUE, MMPLAYER_STATE_CHANGE_TIMEOUT(player)); + + } + + LOGD("set the pipeline state to READY"); ret = _mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player)); + if (ret != MM_ERROR_NONE) { LOGE("fail to change state to READY"); return MM_ERROR_PLAYER_INTERNAL; @@ -5773,7 +5901,7 @@ _mmplayer_set_position(MMHandleType hplayer, gint64 position) MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); - /* check pipline reconfigure state */ + /* check pipeline reconfigure state */ __mmplayer_check_pipeline_reconfigure_state(player); ret = _mmplayer_gst_set_position(player, position, FALSE); @@ -5813,7 +5941,7 @@ _mmplayer_get_buffer_position(MMHandleType hplayer, int *start_pos, int *end_pos } int -_mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int position) +_mmplayer_adjust_subtitle_position(MMHandleType hplayer, int position) { mmplayer_t *player = (mmplayer_t *)hplayer; int ret = MM_ERROR_NONE; @@ -5932,6 +6060,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) @@ -6217,8 +6353,10 @@ ERROR: /* And, it still has a parent "player". * You need to let the parent manage the object instead of unreffing the object directly. */ - gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2); - gst_object_unref(queue2); + if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2)) { + LOGE("failed to remove queue2"); + gst_object_unref(queue2); + } queue2 = NULL; } @@ -6233,16 +6371,18 @@ ERROR: * You need to let the parent manage the object instead of unreffing the object directly. */ - gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin); - gst_object_unref(decodebin); + if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin)) { + LOGE("failed to remove decodebin"); + gst_object_unref(decodebin); + } decodebin = NULL; } return FALSE; } -static int -__mmplayer_check_not_supported_codec(mmplayer_t *player, const gchar *factory_class, const gchar *mime) +int +_mmplayer_update_not_supported_codec_info(mmplayer_t *player, const gchar *factory_class, const gchar *mime) { MMPLAYER_FENTER(); @@ -6482,6 +6622,92 @@ 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); + if (!sinkpad || !element) { + LOGE("invalid parameter"); + return; + } + + 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) { @@ -6564,7 +6790,11 @@ __mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type) 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); + if (!gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), + player->pipeline->mainbin[selectorId].gst)) { + LOGE("failed to remove selector"); + gst_object_unref(player->pipeline->mainbin[selectorId].gst); + } player->pipeline->mainbin[selectorId].gst = NULL; selector = NULL; @@ -6579,11 +6809,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); @@ -6660,9 +6899,9 @@ _mmplayer_set_next_uri(MMHandleType hplayer, const char *uri, bool is_first_path player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri)); SECURE_LOGD("add original path : %s", uri); } else { - player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0)); - player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0); - + g_free(g_list_nth_data(player->uri_info.uri_list, 0)); + player->uri_info.uri_list = g_list_prepend( + g_list_delete_link(player->uri_info.uri_list, player->uri_info.uri_list), g_strdup(uri)); SECURE_LOGD("change original path : %s", uri); } } else { @@ -6710,7 +6949,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; @@ -6744,7 +6983,7 @@ _mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad, MMPLAYER_FREEIF(caps_str); /* There is no available codec. */ - __mmplayer_check_not_supported_codec(player, klass, mime); + _mmplayer_update_not_supported_codec_info(player, klass, mime); } gboolean @@ -6781,8 +7020,13 @@ _mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, MMPLAYER_FREEIF(caps_str); } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) { - LOGD("already video linked"); - ret = FALSE; + if((MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) || (MMPLAYER_IS_DASH_STREAMING(player))) { + LOGD("video is already linked, allow the stream switch"); + ret = TRUE; + } else { + LOGD("video is already linked"); + ret = FALSE; + } } else { LOGD("found new stream"); } @@ -7235,7 +7479,7 @@ _mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad *pad, /* filtering exclude keyword */ for (idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++) { if (strstr(factory_name, player->ini.exclude_element_keyword[idx])) { - LOGW("skipping [%s] by exculde keyword [%s]", + LOGW("skipping [%s] by exclude keyword [%s]", factory_name, player->ini.exclude_element_keyword[idx]); result = GST_AUTOPLUG_SELECT_SKIP; @@ -7339,27 +7583,98 @@ DONE: } void -_mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad, +_mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *pad, gpointer data) { - //mmplayer_t *player = (mmplayer_t *)data; - GstCaps *caps = NULL; + int ret = MM_ERROR_NONE; + mmplayer_t *player = (mmplayer_t *)data; + mmplayer_gst_element_t *mainbin = player->pipeline->mainbin; + mmplayer_gst_element_t *videobin = player->pipeline->videobin; + gint timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player); + + MMPLAYER_FENTER(); + MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && mainbin); - LOGD("[Decodebin2] pad-removed signal"); + LOGD("decoded pad %s:%s removed", GST_DEBUG_PAD_NAME(pad)); - caps = gst_pad_query_caps(new_pad, NULL); - if (!caps) { - LOGW("query caps is NULL"); + if (MMPLAYER_USE_DECODEBIN(player)) + return; + + if (!videobin || !g_str_has_prefix(GST_PAD_NAME (pad), "video")) + return; + + __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN); + + __mmplayer_del_sink(player, videobin[MMPLAYER_V_SINK].gst); + + LOGD("remove videobin"); + ret = _mmplayer_gst_set_state(player, videobin[MMPLAYER_V_BIN].gst, + GST_STATE_NULL, FALSE, timeout); + if (ret != MM_ERROR_NONE) { + LOGE("fail to change state of videobin to NULL"); return; } - gchar *caps_str = NULL; - caps_str = gst_caps_to_string(caps); + if (!gst_bin_remove(GST_BIN_CAST(mainbin[MMPLAYER_M_PIPE].gst), videobin[MMPLAYER_V_BIN].gst)) { + LOGE("failed to remove videobin"); + gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst)); + } - LOGD("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem)); + LOGD("remove concat"); + ret = _mmplayer_gst_set_state(player, mainbin[MMPLAYER_M_V_CONCAT].gst, + GST_STATE_NULL, FALSE, timeout); + if (ret != MM_ERROR_NONE) { + LOGE("fail to change state of concat to NULL"); + return; + } - MMPLAYER_FREEIF(caps_str); - gst_caps_unref(caps); + if (!gst_bin_remove(GST_BIN_CAST(mainbin[MMPLAYER_M_PIPE].gst), mainbin[MMPLAYER_M_V_CONCAT].gst)) { + LOGE("failed to remove video concat"); + gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_V_CONCAT].gst)); + } + + mainbin[MMPLAYER_M_V_CONCAT].gst = NULL; + mainbin[MMPLAYER_M_V_CONCAT].id = 0; + MMPLAYER_FREEIF(player->pipeline->videobin); + + ret = __mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY); + if (ret != MM_ERROR_NONE) + LOGE("failed to release overlay resources"); + + player->videodec_linked = 0; + + MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-pad-removed"); + MMPLAYER_FLEAVE(); +} + +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_FLUSH_BUFFER, NULL); + __mmplayer_deactivate_old_path(player); + + MMPLAYER_FLEAVE(); } void @@ -7427,7 +7742,7 @@ _mmplayer_gst_decode_drained(GstElement *bin, gpointer data) player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_VIDEO] = FALSE; /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/ - MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL); /* post message for gapless */ + MMPLAYER_POST_MSG(player, MM_MESSAGE_FLUSH_BUFFER, NULL); /* post message for gapless */ __mmplayer_deactivate_old_path(player); MMPLAYER_FLEAVE(); @@ -7448,66 +7763,75 @@ _mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data) if (__mmplayer_add_dump_buffer_probe(player, element)) LOGD("add buffer probe"); - if (g_strrstr(klass, "Codec/Decoder/Audio")) { - 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")) { - player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].id = MMPLAYER_M_ADAPTIVE_DEMUX; - player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst = element; + if (g_strrstr(klass, "Decoder")) { + if (g_strrstr(klass, "Audio")) { + player->audio_decoders = g_list_append(player->audio_decoders, + g_strdup(GST_ELEMENT_NAME(element))); - LOGD("set max variant limit: %d, %d %d", player->adaptive_info.limit.bandwidth, - player->adaptive_info.limit.width, player->adaptive_info.limit.height); + /* 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, "Video")) { + GstElement *video_parse = player->pipeline->mainbin[MMPLAYER_M_V_PARSE].gst; + /* update codec info */ + player->not_supported_codec &= MISSING_PLUGIN_AUDIO; + player->can_support_codec |= FOUND_PLUGIN_VIDEO; + player->videodec_linked = 1; + + if (video_parse) { + GstPad *srcpad = gst_element_get_static_pad (video_parse, "src"); + if (srcpad) { + GstCaps *caps = NULL; + GstStructure *str = NULL; + const gchar *name = NULL; + gboolean caps_ret = TRUE; + + MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD (srcpad, caps, str, name, caps_ret); + if (caps_ret && str) { + const gchar *stream_format = gst_structure_get_string (str, "stream-format"); + if (stream_format && g_strrstr(stream_format, "byte-stream")) { + if ((g_object_class_find_property(G_OBJECT_GET_CLASS(video_parse), "config-interval"))) { + g_object_set(G_OBJECT(video_parse), "config-interval", -1, NULL); + LOGD("Send SPS and PPS Insertion every IDR frame"); + } + } + } + gst_object_unref(GST_OBJECT(srcpad)); + } + } + } + } else if (g_strrstr(klass, "Demuxer")) { + if (g_strrstr(klass, "Adaptive")) { + player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].id = MMPLAYER_M_ADAPTIVE_DEMUX; + player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst = element; - g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst, - "max-bandwidth", player->adaptive_info.limit.bandwidth, - "max-video-width", player->adaptive_info.limit.width, - "max-video-height", player->adaptive_info.limit.height, NULL); + LOGD("set max variant limit: %d, %d %d", player->adaptive_info.limit.bandwidth, + player->adaptive_info.limit.width, player->adaptive_info.limit.height); - } else if (g_strrstr(klass, "Demuxer")) { + g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst, + "max-bandwidth", player->adaptive_info.limit.bandwidth, + "max-video-width", player->adaptive_info.limit.width, + "max-video-height", player->adaptive_info.limit.height, NULL); + } else { #ifdef __DEBUG__ - LOGD("plugged element is demuxer. take it"); + LOGD("plugged element is demuxer. take it"); #endif - player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX; - player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element; - } - - if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux")) { - int surface_type = 0; - - mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type); + player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX; + player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element; + } + } else if (g_strrstr(klass, "Parser") && (g_strrstr(klass, "Video"))) { + player->pipeline->mainbin[MMPLAYER_M_V_PARSE].id = MMPLAYER_M_V_PARSE; + player->pipeline->mainbin[MMPLAYER_M_V_PARSE].gst = element; } - // to support trust-zone only - if (g_strrstr(factory_name, "asfdemux")) { - LOGD("set file-location %s", player->profile.uri); - g_object_set(G_OBJECT(element), "file-location", player->profile.uri, NULL); - } else if (g_strrstr(factory_name, "legacyh264parse")) { - LOGD("[%s] output-format to legacyh264parse", "mssdemux"); - g_object_set(G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */ - } else if (g_strrstr(factory_name, "mpegaudioparse")) { + if (g_strrstr(factory_name, "mpegaudioparse")) { if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (__mmplayer_is_only_mp3_type(player->type))) { LOGD("[mpegaudioparse] set streaming pull mode."); g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL); } - } else if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) { - player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element; - } - - if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) && + } else if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) && (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue"))) { LOGD("plugged element is multiqueue. take it %s", GST_ELEMENT_NAME(element)); @@ -7521,7 +7845,6 @@ _mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data) _mm_player_streaming_set_multiqueue(player->streamer, element); _mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst); } - } return; @@ -7612,7 +7935,7 @@ __mmplayer_release_misc(mmplayer_t *player) static void __mmplayer_release_misc_post(mmplayer_t *player) { - char *original_uri = NULL; + gchar *original_uri = NULL; MMPLAYER_FENTER(); /* player->pipeline is already released before. */ @@ -7629,34 +7952,28 @@ __mmplayer_release_misc_post(mmplayer_t *player) player->audio_stream_changed_cb = NULL; player->audio_stream_changed_cb_user_param = NULL; - mm_player_set_attribute((MMHandleType)player, NULL, "content_video_found", 0, NULL); + mm_player_set_attribute((MMHandleType)player, NULL, + "content_video_found", 0, MM_PLAYER_AUDIO_ONLY, 0, NULL); /* 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); - } + MMPLAYER_FREEIF(original_uri); } /* clear the audio stream buffer list */ @@ -7719,14 +8036,17 @@ _mmplayer_cancel_eos_timer(mmplayer_t *player) } static void -__mmplayer_add_sink(mmplayer_t *player, GstElement *sink) +__mmplayer_add_sink(mmplayer_t *player, GstElement *sink, gboolean first) { MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(player); MMPLAYER_RETURN_IF_FAIL(sink); - player->sink_elements = g_list_append(player->sink_elements, sink); + if (first) + player->sink_elements = g_list_prepend(player->sink_elements, sink); + else + player->sink_elements = g_list_append(player->sink_elements, sink); MMPLAYER_FLEAVE(); } @@ -7815,7 +8135,7 @@ __mmplayer_release_signal_connection(mmplayer_t *player, mmplayer_signal_type_e for (; sig_list; sig_list = sig_list->next) { item = sig_list->data; - if (item && item->obj && GST_IS_ELEMENT(item->obj)) { + if (item && item->obj) { if (g_signal_handler_is_connected(item->obj, item->sig)) g_signal_handler_disconnect(item->obj, item->sig); } @@ -7993,7 +8313,7 @@ ERROR: /* release signal */ __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN); - /* release textbin with it's childs */ + /* release textbin with it's children */ MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN); MMPLAYER_FREEIF(player->pipeline->textbin); player->pipeline->textbin = NULL; @@ -8193,16 +8513,19 @@ __mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int ind guint active_idx = 0; GstStream *stream = NULL; GList *streams = NULL; - GstEvent *ev = NULL; GstCaps *caps = NULL; + MMPLAYER_FENTER(); 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) { + LOGD("track type:%d, total: %d, active: %d", i, + player->track[i].total_track_num, player->track[i].active_track_index); + if (player->track[i].total_track_num > 0 && + player->track[i].active_track_index > INVALID_TRACK_INDEX) { 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)); @@ -8218,10 +8541,32 @@ __mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int ind } } - ev = gst_event_new_select_streams(streams); - gst_element_send_event(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, ev); - g_list_free(streams); + if (streams) { + LOGD("send select stream event"); + gst_element_send_event(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst, + gst_event_new_select_streams(streams)); + g_list_free(streams); + } + + /* in paused state, seek to current pos to flush mq buffer and release waiting task */ + if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) { + gint64 pos_nsec = GST_CLOCK_TIME_NONE; + + if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec)) + pos_nsec = player->last_position; + LOGD("current pos %" GST_TIME_FORMAT ", rate = %f", GST_TIME_ARGS(pos_nsec), player->playback_rate); + + if (!_mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, + player->playback_rate, GST_FORMAT_TIME, + (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE), + GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE)) { + LOGW("failed to seek"); + return MM_ERROR_PLAYER_INTERNAL; + } + } + + MMPLAYER_FLEAVE(); return MM_ERROR_NONE; } @@ -8351,15 +8696,15 @@ _mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst); if (current_state < GST_STATE_PAUSED) { result = MM_ERROR_PLAYER_INVALID_STATE; - LOGW("Pipeline not in porper state"); + LOGW("Pipeline not in proper state"); 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; @@ -8367,7 +8712,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, @@ -8584,7 +8929,7 @@ _mmplayer_manage_external_storage_state(MMHandleType hplayer, int id, int state) if (state != STORAGE_STATE_UNMOUNTABLE && state != STORAGE_STATE_REMOVED) return MM_ERROR_NONE; - /* FIXME: text path should be handled seperately. */ + /* FIXME: text path should be handled separately. */ if (((player->storage_info[MMPLAYER_PATH_VOD].type == STORAGE_TYPE_EXTERNAL) && (player->storage_info[MMPLAYER_PATH_VOD].id == id)) || ((player->storage_info[MMPLAYER_PATH_TEXT].type == STORAGE_TYPE_EXTERNAL) @@ -8728,47 +9073,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); @@ -9069,9 +9429,6 @@ __mmplayer_update_audio_attrs(mmplayer_t *player, MMHandleType attrs) } p = gst_caps_get_structure(caps_a, 0); - - mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate); - gst_structure_get_int(p, "rate", &samplerate); gst_structure_get_int(p, "channels", &channels); @@ -9115,7 +9472,7 @@ __mmplayer_update_video_attrs(mmplayer_t *player, MMHandleType attrs) } if (!caps_v) { - LOGD("no negitiated caps from videosink"); + LOGD("no negotiated caps from videosink"); gst_object_unref(pad); return FALSE; } @@ -9151,7 +9508,7 @@ __mmplayer_update_bitrate_attrs(mmplayer_t *player, MMHandleType attrs) gchar *path = NULL; struct stat sb; - /* FIXIT : please make it clear the dependancy with duration/codec/uritype */ + /* FIXIT : please make it clear the dependency with duration/codec/uritype */ if (!player->duration) return FALSE; @@ -9545,7 +9902,7 @@ __mmplayer_set_playing_state(mmplayer_t *player) /* try to get content metadata */ /* NOTE : giving ATTR_MISSING_ONLY may have dependency with - * c-api since c-api doesn't use _start() anymore. It may not work propery with + * c-api since c-api doesn't use _start() anymore. It may not work properly with * legacy mmfw-player api */ _mmplayer_update_content_attrs(player, ATTR_MISSING_ONLY);