X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmm_player_priv.c;h=f6f63052a624b95187961e9b70c8c80d9ee4b681;hb=ed867ad4113fe0cd9a4af9062087edeaad0055eb;hp=2f41371f2ce8ba192d26fab7234e499114f730cc;hpb=85bbaaf404e4afaeb7daf81a538705135de1f0a8;p=platform%2Fcore%2Fmultimedia%2Flibmm-player.git diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index 2f41371..f6f6305 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -43,7 +43,6 @@ #include "mm_player_priv.h" #include "mm_player_ini.h" -#include "mm_player_attrs.h" #include "mm_player_capture.h" #include "mm_player_utils.h" #include "mm_player_tracks.h" @@ -84,12 +83,11 @@ #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 #define DEFAULT_PLAYBACK_RATE 1.0 -#define DEFAULT_NUM_OF_V_OUT_BUFFER 3 #define PLAYER_DISPLAY_MODE_DST_ROI 5 @@ -142,17 +140,10 @@ static int __mmplayer_gst_create_text_pipeline(mmplayer_t *player); static int __mmplayer_gst_create_video_sink_bin(mmplayer_t *player, GstCaps *caps, MMDisplaySurfaceType surface_type); static int __mmplayer_gst_create_audio_sink_bin(mmplayer_t *player); static int __mmplayer_gst_create_text_sink_bin(mmplayer_t *player); - -static void __mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data); -static void __mmplayer_gst_create_sinkbin(GstElement *decodebin, GstPad *pad, gpointer data); -static void __mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad, GstCaps *caps, gpointer data); -static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, GstCaps *caps, gpointer data); -static void __mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad, gpointer data); -static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data); -static void __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data); +static void __mmplayer_gst_create_sink_bin(GstElement *decodebin, GstPad *pad, GstCaps *ref_caps, gpointer data); +static gboolean __mmplayer_create_sink_path(mmplayer_t *player, GstElement *combiner, mmplayer_track_type_e type, GstCaps *caps); static gboolean __mmplayer_is_midi_type(gchar *str_caps); static gboolean __mmplayer_is_only_mp3_type(gchar *str_caps); -static void __mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps); static gboolean __mmplayer_update_subtitle(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data); static void __mmplayer_release_misc(mmplayer_t *player); @@ -166,7 +157,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); @@ -180,15 +171,15 @@ static int __mmplayer_gst_set_message_callback(mmplayer_t *player, MMMessageCal /* util */ static gboolean __mmplayer_verify_gapless_play_path(mmplayer_t *player); -static void __mmplayer_check_pipeline(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); static void __mmplayer_gst_caps_notify_cb(GstPad *pad, GParamSpec *unused, gpointer data); static void __mmplayer_audio_stream_send_data(mmplayer_t *player, mmplayer_audio_stream_buff_t *a_buffer); static void __mmplayer_initialize_storage_info(mmplayer_t *player, mmplayer_path_type_e path_type); -static int __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res, void *user_data); static gboolean __mmplayer_update_duration_value(mmplayer_t *player); static gboolean __mmplayer_update_audio_attrs(mmplayer_t *player, MMHandleType attrs); static gboolean __mmplayer_update_video_attrs(mmplayer_t *player, MMHandleType attrs); @@ -205,42 +196,13 @@ 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 | | | ========================================================================================== */ -#if 0 //debug -static void -print_tag(const GstTagList *list, const gchar *tag, gpointer unused) -{ - gint i, count; - - count = gst_tag_list_get_tag_size(list, tag); - - LOGD("count = %d", count); - - for (i = 0; i < count; i++) { - gchar *str; - - if (gst_tag_get_type(tag) == G_TYPE_STRING) { - if (!gst_tag_list_get_string_index(list, tag, i, &str)) - g_assert_not_reached(); - } else { - str = g_strdup_value_contents(gst_tag_list_get_value_index(list, tag, i)); - } - - if (i == 0) - g_print(" %15s: %s", gst_tag_get_nick(tag), str); - else - g_print(" : %s", str); - - g_free(str); - } -} -#endif - /* This function should be called after the pipeline goes PAUSED or higher state. */ gboolean @@ -306,12 +268,6 @@ _mmplayer_update_content_attrs(mmplayer_t *player, enum content_attr_flag flag) if ((flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all) has_bitrate = __mmplayer_update_bitrate_attrs(player, attrs); - /* validate all */ - if (mm_attrs_commit_all(attrs)) { - LOGE("failed to update attributes"); - return FALSE; - } - MMPLAYER_FLEAVE(); return TRUE; @@ -355,7 +311,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) @@ -434,9 +390,9 @@ _mmplayer_check_state(mmplayer_t *player, mmplayer_command_state_e command) mmplayer_state_e pending_state = MM_PLAYER_STATE_NUM; MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); - - //LOGD("incomming command : %d ", command); - +#ifdef __DEBUG__ + LOGD("incoming command : %d ", command); +#endif current_state = MMPLAYER_CURRENT_STATE(player); pending_state = MMPLAYER_PENDING_STATE(player); @@ -536,7 +492,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; @@ -596,11 +552,115 @@ ALREADY_GOING: return MM_ERROR_PLAYER_NO_OP; } +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; + + switch (type) { + case MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER: + rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER; + break; + case MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY: + rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY; + break; + case MMPLAYER_RESOURCE_TYPE_AUDIO_OFFLOAD: + rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_AUDIO_OFFLOAD; + break; + default: + LOGE("invalid mmplayer resource type %d", type); + return MM_ERROR_PLAYER_INTERNAL; + } + + if (player->hw_resource[type] != NULL) { + LOGD("[%d type] resource was already acquired", type); + return MM_ERROR_NONE; + } + + LOGD("mark for acquire [%d type] resource", type); + rm_ret = mm_resource_manager_mark_for_acquire(player->resource_manager, + rm_res_type, MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &player->hw_resource[type]); + if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) { + LOGE("failed to mark resource for acquire, ret(0x%x)", rm_ret); + 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); + return MM_ERROR_PLAYER_INTERNAL; + } + + MMPLAYER_FLEAVE(); + 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; + + MMPLAYER_FENTER(); + + if (player->hw_resource[type] == NULL) { + LOGD("there is no acquired [%d type] resource", type); + return MM_ERROR_NONE; + } + + LOGD("mark for release [%d type] resource", type); + rm_ret = mm_resource_manager_mark_for_release(player->resource_manager, player->hw_resource[type]); + if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) { + LOGE("failed to mark resource for release, ret(0x%x)", rm_ret); + return MM_ERROR_PLAYER_INTERNAL; + } + + 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 resource, ret(0x%x)", rm_ret); + return MM_ERROR_PLAYER_INTERNAL; + } + + MMPLAYER_FLEAVE(); + return MM_ERROR_NONE; +} + static void __mmplayer_initialize_gapless_play(mmplayer_t *player) { int i; - int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE; MMPLAYER_FENTER(); @@ -639,39 +699,29 @@ __mmplayer_initialize_gapless_play(mmplayer_t *player) player->v_stream_caps = NULL; } - mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0); + mm_player_set_attribute((MMHandleType)player, NULL, "content_video_found", 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; } - /* release video decoder resource */ - if (player->video_decoder_resource != NULL) { - rm_ret = mm_resource_manager_mark_for_release(player->resource_manager, - player->video_decoder_resource); - if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) { - LOGE("failed to mark the video decoder resource for release, ret(0x%x)", rm_ret); - return; - } - player->video_decoder_resource = NULL; - } - - 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); - return; - } + __mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER); MMPLAYER_FLEAVE(); } +void _mmplayer_set_reconfigure_state(mmplayer_t *player, gboolean state) +{ + LOGI("set pipeline reconfigure state %d", state); + MMPLAYER_RECONFIGURE_LOCK(player); + player->gapless.reconfigure = state; + if (!state) /* wake up the waiting job */ + MMPLAYER_RECONFIGURE_SIGNAL(player); + MMPLAYER_RECONFIGURE_UNLOCK(player); +} + static gpointer __mmplayer_gapless_play_thread(gpointer data) { @@ -688,10 +738,7 @@ __mmplayer_gapless_play_thread(gpointer data) LOGD("reconfigure pipeline for gapless play."); if (player->gapless_play_thread_exit) { - if (player->gapless.reconfigure) { - player->gapless.reconfigure = false; - MMPLAYER_PLAYBACK_UNLOCK(player); - } + _mmplayer_set_reconfigure_state(player, FALSE); LOGD("exiting gapless play thread"); break; } @@ -731,6 +778,46 @@ __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) { + 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); + } + + MMPLAYER_FLEAVE(); +} + +void _mmplayer_bus_msg_thread_destroy(MMHandleType hplayer) { mmplayer_t *player = (mmplayer_t *)hplayer; @@ -740,11 +827,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); @@ -797,7 +879,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!"); @@ -847,8 +929,10 @@ __mmplayer_gst_selector_update_start_time(mmplayer_t *player, mmplayer_track_typ for (idx = MM_PLAYER_TRACK_TYPE_AUDIO; idx < MM_PLAYER_TRACK_TYPE_TEXT; idx++) { if ((player->gapless.update_segment[idx] == TRUE) || - !(player->selector[idx].event_probe_id)) { - /* LOGW("[%d] skip", idx); */ + !(player->track[idx].event_probe_id)) { +#ifdef __DEBUG__ + LOGW("[%d] skip", idx); +#endif continue; } @@ -909,18 +993,14 @@ __mmplayer_gst_selector_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer mmplayer_track_type_e stream_type = MM_PLAYER_TRACK_TYPE_VIDEO; gboolean caps_ret = TRUE; - if (GST_EVENT_IS_DOWNSTREAM(event) && - GST_EVENT_TYPE(event) != GST_EVENT_STREAM_START && - GST_EVENT_TYPE(event) != GST_EVENT_FLUSH_STOP && - GST_EVENT_TYPE(event) != GST_EVENT_SEGMENT && - GST_EVENT_TYPE(event) != GST_EVENT_EOS) { + if (GST_EVENT_TYPE(event) != GST_EVENT_STREAM_START && + GST_EVENT_TYPE(event) != GST_EVENT_FLUSH_STOP && + GST_EVENT_TYPE(event) != GST_EVENT_SEGMENT && + GST_EVENT_TYPE(event) != GST_EVENT_EOS && + GST_EVENT_TYPE(event) != GST_EVENT_QOS) return ret; - } else if (GST_EVENT_IS_UPSTREAM(event) && - 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; @@ -1015,11 +1095,13 @@ __mmplayer_gst_selector_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer break; } +#ifdef __DEBUG__ LOGD("[%d] Adjusting QOS event: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT " = %" GST_TIME_FORMAT, stream_type, GST_TIME_ARGS(timestamp), GST_TIME_ARGS(running_time_diff), GST_TIME_ARGS(timestamp - running_time_diff)); +#endif timestamp -= running_time_diff; @@ -1045,7 +1127,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) { @@ -1066,7 +1148,7 @@ __mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name) } /* store it as it's sink element */ - __mmplayer_add_sink(player, fakesink); + __mmplayer_add_sink(player, fakesink, FALSE); gst_bin_add(GST_BIN(pipeline), fakesink); @@ -1102,6 +1184,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; @@ -1121,14 +1232,14 @@ __mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmp player->pipeline->mainbin[elem_idx].id = elem_idx; player->pipeline->mainbin[elem_idx].gst = selector; - /* player->selector[stream_type].active_pad_index = DEFAULT_TRACK; */ + /* player->track[stream_type].active_track_index = DEFAULT_TRACK; */ srcpad = gst_element_get_static_pad(selector, "src"); LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad)); - player->selector[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, + player->track[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, __mmplayer_gst_selector_blocked, NULL, NULL); - player->selector[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH, + player->track[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH, __mmplayer_gst_selector_event_probe, player, NULL); gst_element_set_state(selector, GST_STATE_PAUSED); @@ -1146,7 +1257,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; @@ -1164,12 +1275,14 @@ _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; MMPLAYER_LOG_GST_CAPS_TYPE(caps); - /* LOGD("detected mimetype : %s", name); */ +#ifdef __DEBUG__ + LOGD("detected mimetype : %s", name); +#endif if (strstr(name, "video")) { gint stype = 0; @@ -1182,13 +1295,13 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) MMPLAYER_FREEIF(caps_str); - mm_attrs_set_int_by_name(player->attrs, "content_video_found", TRUE); + mm_player_set_attribute((MMHandleType)player, NULL, "content_video_found", TRUE, NULL); mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype); LOGD("surface type : %d", stype); if (MMPLAYER_IS_MS_BUFF_SRC(player)) { - __mmplayer_gst_create_sinkbin(elem, pad, player); + __mmplayer_gst_create_sink_bin(elem, pad, caps, player); goto DONE; } @@ -1199,8 +1312,13 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) goto DONE; } - LOGD("video selector is required"); - elem_idx = MMPLAYER_M_V_INPUT_SELECTOR; + if (MMPLAYER_USE_DECODEBIN(player)) { + LOGD("video selector is required"); + elem_idx = MMPLAYER_M_V_INPUT_SELECTOR; + } else { + LOGD("video concat is required"); + elem_idx = MMPLAYER_M_V_CONCAT; + } stream_type = MM_PLAYER_TRACK_TYPE_VIDEO; } else if (strstr(name, "audio")) { gint samplerate = 0; @@ -1209,7 +1327,7 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) if (MMPLAYER_IS_MS_BUFF_SRC(player) || player->build_audio_offload) { if (player->build_audio_offload) player->no_more_pad = TRUE; /* remove state holder */ - __mmplayer_gst_create_sinkbin(elem, pad, player); + __mmplayer_gst_create_sink_bin(elem, pad, caps, player); goto DONE; } @@ -1220,14 +1338,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"); @@ -1235,32 +1362,47 @@ _mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data) } /* check selector and create it */ - if (!(selector = player->pipeline->mainbin[elem_idx].gst)) { - selector = __mmplayer_gst_make_selector(player, elem_idx, stream_type); - if (!selector) + if (!(combiner = player->pipeline->mainbin[elem_idx].gst)) { + if (MMPLAYER_USE_DECODEBIN(player)) + combiner = __mmplayer_gst_make_selector(player, elem_idx, stream_type); + else + combiner = __mmplayer_gst_make_concat(player, elem_idx); + + if (!combiner) goto ERROR; first_track = TRUE; } else { - LOGD("input-selector is already created."); + LOGD("Combiner element is already created."); } /* link */ - sinkpad = gst_element_get_request_pad(selector, "sink_%u"); + sinkpad = gst_element_get_request_pad(combiner, "sink_%u"); LOGD("pad link: %s:%s - %s:%s", GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(sinkpad)); if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) { - LOGE("failed to link selector"); - gst_object_unref(GST_OBJECT(selector)); + LOGE("failed to link combiner"); + gst_object_unref(GST_OBJECT(combiner)); goto ERROR; } if (first_track) { - LOGD("this track will be activated"); - g_object_set(selector, "active-pad", sinkpad, NULL); + if (MMPLAYER_USE_DECODEBIN(player)) { + LOGD("this track will be activated"); + g_object_set(combiner, "active-pad", sinkpad, NULL); + } } - _mmplayer_track_update_selector_info(player, stream_type, sinkpad); + if (MMPLAYER_USE_DECODEBIN(player)) { + _mmplayer_track_update_stream(player, stream_type, sinkpad); + } else { + /* apply the text track information */ + if (stream_type == MM_PLAYER_TRACK_TYPE_TEXT) + mm_player_set_attribute((MMHandleType)player, NULL, + "content_text_track_num", player->track[stream_type].total_track_num, + "current_text_track_index", player->track[stream_type].active_track_index, NULL); + __mmplayer_create_sink_path(player, combiner, stream_type, caps); + } DONE: ERROR: @@ -1277,7 +1419,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; @@ -1286,25 +1428,25 @@ __mmplayer_create_sink_path(mmplayer_t *player, GstElement *selector, mmplayer_t LOGD("type %d", type); - if (!selector) { + if (!combiner) { LOGD("there is no %d track", type); return TRUE; } - srcpad = gst_element_get_static_pad(selector, "src"); + srcpad = gst_element_get_static_pad(combiner, "src"); if (!srcpad) { - LOGE("failed to get srcpad from selector"); + LOGE("failed to get srcpad from combiner"); return FALSE; } - LOGD("got pad %s:%s from selector", GST_DEBUG_PAD_NAME(srcpad)); + LOGD("got pad %s:%s from combiner", GST_DEBUG_PAD_NAME(srcpad)); - __mmplayer_gst_create_sinkbin(selector, srcpad, player); + __mmplayer_gst_create_sink_bin(combiner, srcpad, caps, player); LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad)); - if (player->selector[type].block_id) { - gst_pad_remove_probe(srcpad, player->selector[type].block_id); - player->selector[type].block_id = 0; + if (player->track[type].block_id) { + gst_pad_remove_probe(srcpad, player->track[type].block_id); + player->track[type].block_id = 0; } if (srcpad) { @@ -1319,35 +1461,26 @@ __mmplayer_create_sink_path(mmplayer_t *player, GstElement *selector, mmplayer_t static void __mmplayer_set_decode_track_info(mmplayer_t *player, mmplayer_track_type_e type) { - MMHandleType attrs = 0; gint active_index = 0; MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(player); - LOGD("type: %d, the num of track: %d", type, player->selector[type].total_track_num); + LOGD("type: %d, the num of track: %d", type, player->track[type].total_track_num); /* change track to active pad */ - active_index = player->selector[type].active_pad_index; - if ((active_index != DEFAULT_TRACK) && + active_index = player->track[type].active_track_index; + 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->selector[type].active_pad_index = DEFAULT_TRACK; + player->track[type].active_track_index = DEFAULT_TRACK_INDEX; return; } - if (type == MM_PLAYER_TRACK_TYPE_TEXT) { - attrs = MMPLAYER_GET_ATTRS(player); - if (attrs) { - mm_attrs_set_int_by_name(attrs, "content_text_track_num", player->selector[type].total_track_num); - mm_attrs_set_int_by_name(attrs, "current_text_track_index", player->selector[type].active_pad_index); - - if (mm_attrs_commit_all(attrs)) - LOGW("failed to commit attrs."); - } else { - LOGW("cannot get content attribute"); - } - } + if (type == MM_PLAYER_TRACK_TYPE_TEXT) + mm_player_set_attribute((MMHandleType)player, NULL, + "content_text_track_num", player->track[type].total_track_num, + "current_text_track_index", player->track[type].active_track_index, NULL); MMPLAYER_FLEAVE(); return; @@ -1374,16 +1507,17 @@ __mmplayer_create_audio_sink_path(mmplayer_t *player, GstElement *audio_selector } if (player->num_dynamic_pad == 0) /* FIXME: num_dynamic_pad is only for rtsp? */ - __mmplayer_pipeline_complete(NULL, player); + _mmplayer_pipeline_complete(NULL, player); return TRUE; } /* apply the audio track information */ - __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_AUDIO); + if (MMPLAYER_USE_DECODEBIN(player)) + __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_AUDIO); /* create audio sink path */ - if (!__mmplayer_create_sink_path(player, audio_selector, MM_PLAYER_TRACK_TYPE_AUDIO)) { + if (!__mmplayer_create_sink_path(player, audio_selector, MM_PLAYER_TRACK_TYPE_AUDIO, NULL)) { LOGE("failed to create audio sink path"); return FALSE; } @@ -1399,20 +1533,20 @@ __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; } /* apply the text track information */ __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_TEXT); - if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0) + if (player->track[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0) player->has_closed_caption = TRUE; /* create text decode path */ player->no_more_pad = TRUE; - if (!__mmplayer_create_sink_path(player, text_selector, MM_PLAYER_TRACK_TYPE_TEXT)) { + if (!__mmplayer_create_sink_path(player, text_selector, MM_PLAYER_TRACK_TYPE_TEXT, NULL)) { LOGE("failed to create text sink path"); return FALSE; } @@ -1445,8 +1579,8 @@ __mmplayer_gst_set_queue2_buffering(mmplayer_t *player) return TRUE; } -static void -__mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data) +void +_mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data) { mmplayer_t *player = NULL; GstElement *video_selector = NULL; @@ -1487,7 +1621,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 */ @@ -1501,11 +1635,7 @@ __mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data) __mmplayer_create_text_sink_path(player, text_selector); EXIT: - if (player->gapless.reconfigure) { - player->gapless.reconfigure = FALSE; - MMPLAYER_PLAYBACK_UNLOCK(player); - } - + _mmplayer_set_reconfigure_state(player, FALSE); MMPLAYER_FLEAVE(); } @@ -1572,7 +1702,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; @@ -1590,20 +1720,27 @@ __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); - - /* LOGD("detected mimetype : %s", name); */ +#ifdef __DEBUG__ + LOGD("detected mimetype : %s", name); +#endif if (strstr(name, "audio")) { if (player->pipeline->audiobin == NULL) { const gchar *audio_format = gst_structure_get_string(str, "format"); if (audio_format) { LOGD("original audio format %s", audio_format); - mm_attrs_set_string_by_name(player->attrs, "content_audio_format", audio_format); + mm_player_set_attribute((MMHandleType)player, NULL, + "content_audio_format", audio_format, strlen(audio_format), NULL); } if (__mmplayer_gst_create_audio_sink_bin(player) != MM_ERROR_NONE) { @@ -1628,26 +1765,14 @@ __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 && player->video_overlay_resource == NULL) { - LOGD("mark video overlay for acquire"); - if (mm_resource_manager_mark_for_acquire(player->resource_manager, - MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY, - MM_RESOURCE_MANAGER_RES_VOLUME_FULL, - &player->video_overlay_resource) - != MM_RESOURCE_MANAGER_ERROR_NONE) { - LOGE("could not mark video_overlay resource for acquire"); - goto ERROR; - } + if ((surface_type == MM_DISPLAY_SURFACE_OVERLAY) && + (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE)) { + LOGE("failed to acquire video overlay resource"); + goto ERROR; } player->interrupted_by_resource = FALSE; - if (mm_resource_manager_commit(player->resource_manager) != - MM_RESOURCE_MANAGER_ERROR_NONE) { - LOGE("could not acquire resources for video playing"); - goto ERROR; - } - if (__mmplayer_gst_create_video_sink_bin(player, caps, surface_type) != MM_ERROR_NONE) { LOGE("failed to create videobin. continuing without video"); goto ERROR; @@ -1679,7 +1804,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"; @@ -1704,7 +1829,7 @@ __mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data) LOGD("no more pads: %d, stream count dec : %d(num of dynamic pad)", player->no_more_pad, player->num_dynamic_pad); if ((player->no_more_pad) && (player->num_dynamic_pad == 0)) - __mmplayer_pipeline_complete(NULL, player); + _mmplayer_pipeline_complete(NULL, player); ERROR: @@ -1745,7 +1870,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; @@ -1772,20 +1897,6 @@ __mmplayer_get_property_value_for_rotation(mmplayer_t *player, int display_angle } int -__mmplayer_video_param_check_video_sink_bin(mmplayer_t *player) -{ - /* check video sinkbin is created */ - MMPLAYER_RETURN_VAL_IF_FAIL(player && - player->pipeline && - player->pipeline->videobin && - player->pipeline->videobin[MMPLAYER_V_BIN].gst && - player->pipeline->videobin[MMPLAYER_V_SINK].gst, - MM_ERROR_PLAYER_NOT_INITIALIZED); - - return MM_ERROR_NONE; -} - -int _mmplayer_get_video_angle(mmplayer_t *player, int *display_angle, int *orientation) { int display_rotation = 0; @@ -1798,7 +1909,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 */ @@ -1845,8 +1956,7 @@ _mmplayer_get_video_angle(mmplayer_t *player, int *display_angle, int *orientati return MM_ERROR_NONE; } -void -__mmplayer_video_param_set_display_rotation(mmplayer_t *player) +static void __mmplayer_video_param_set_display_rotation(mmplayer_t *player) { int rotation_value = 0; int orientations = 0; // current supported angle values are 0, 90, 180, 270 @@ -1854,7 +1964,7 @@ __mmplayer_video_param_set_display_rotation(mmplayer_t *player) MMPLAYER_FENTER(); /* check video sinkbin is created */ - if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player)) + if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY)) return; _mmplayer_get_video_angle(player, &display_angle, &orientations); @@ -1865,15 +1975,14 @@ __mmplayer_video_param_set_display_rotation(mmplayer_t *player) LOGD("set video param : rotate %d", rotation_value); } -void -__mmplayer_video_param_set_display_visible(mmplayer_t *player) +static void __mmplayer_video_param_set_display_visible(mmplayer_t *player) { MMHandleType attrs = 0; int visible = 0; MMPLAYER_FENTER(); /* check video sinkbin is created */ - if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player)) + if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY)) return; attrs = MMPLAYER_GET_ATTRS(player); @@ -1884,15 +1993,14 @@ __mmplayer_video_param_set_display_visible(mmplayer_t *player) LOGD("set video param : visible %d", visible); } -void -__mmplayer_video_param_set_display_method(mmplayer_t *player) +static void __mmplayer_video_param_set_display_method(mmplayer_t *player) { MMHandleType attrs = 0; int display_method = 0; MMPLAYER_FENTER(); /* check video sinkbin is created */ - if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player)) + if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY)) return; attrs = MMPLAYER_GET_ATTRS(player); @@ -1903,36 +2011,33 @@ __mmplayer_video_param_set_display_method(mmplayer_t *player) LOGD("set video param : method %d", display_method); } -void -__mmplayer_video_param_set_video_roi_area(mmplayer_t *player) +static void __mmplayer_video_param_set_video_roi_area(mmplayer_t *player) { MMHandleType attrs = 0; - void *handle = NULL; + int handle = 0; MMPLAYER_FENTER(); /* check video sinkbin is created */ - if (__mmplayer_video_param_check_video_sink_bin(player) != MM_ERROR_NONE) { - LOGW("There is no video sink"); + if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY)) return; - } attrs = MMPLAYER_GET_ATTRS(player); MMPLAYER_RETURN_IF_FAIL(attrs); - mm_attrs_get_data_by_name(attrs, "display_overlay", &handle); - if (handle) { - gst_video_overlay_set_video_roi_area( - GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst), - player->video_roi.scale_x, player->video_roi.scale_y, player->video_roi.scale_width, player->video_roi.scale_height); - LOGD("set video param : video roi area scale value: x(%f) y(%f) width(%f) height(%f)", - player->video_roi.scale_x, player->video_roi.scale_y, player->video_roi.scale_width, player->video_roi.scale_height); - } + + mm_attrs_get_int_by_name(attrs, "display_overlay", &handle); + MMPLAYER_RETURN_IF_FAIL(handle); + + gst_video_overlay_set_video_roi_area( + GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst), + player->video_roi.scale_x, player->video_roi.scale_y, player->video_roi.scale_width, player->video_roi.scale_height); + LOGD("set video param : video roi area scale value: x(%f) y(%f) width(%f) height(%f)", + player->video_roi.scale_x, player->video_roi.scale_y, player->video_roi.scale_width, player->video_roi.scale_height); } -void -__mmplayer_video_param_set_roi_area(mmplayer_t *player) +static void __mmplayer_video_param_set_roi_area(mmplayer_t *player) { MMHandleType attrs = 0; - void *handle = NULL; + int handle = 0; /*set wl_display*/ int win_roi_x = 0; int win_roi_y = 0; @@ -1941,74 +2046,67 @@ __mmplayer_video_param_set_roi_area(mmplayer_t *player) MMPLAYER_FENTER(); /* check video sinkbin is created */ - if (__mmplayer_video_param_check_video_sink_bin(player) != MM_ERROR_NONE) { - LOGW("There is no video sink"); + if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY)) return; - } attrs = MMPLAYER_GET_ATTRS(player); MMPLAYER_RETURN_IF_FAIL(attrs); - mm_attrs_get_data_by_name(attrs, "display_overlay", &handle); + mm_attrs_get_int_by_name(attrs, "display_overlay", &handle); + MMPLAYER_RETURN_IF_FAIL(handle); - if (handle) { - /* It should be set after setting window */ - mm_attrs_get_int_by_name(attrs, "display_win_roi_x", &win_roi_x); - mm_attrs_get_int_by_name(attrs, "display_win_roi_y", &win_roi_y); - mm_attrs_get_int_by_name(attrs, "display_win_roi_width", &win_roi_width); - mm_attrs_get_int_by_name(attrs, "display_win_roi_height", &win_roi_height); + /* It should be set after setting window */ + mm_attrs_multiple_get(attrs, NULL, + "display_win_roi_x", &win_roi_x, + "display_win_roi_y", &win_roi_y, + "display_win_roi_width", &win_roi_width, + "display_win_roi_height", &win_roi_height, NULL); - /* After setting window handle, set display roi area */ - gst_video_overlay_set_display_roi_area( - GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst), - win_roi_x, win_roi_y, win_roi_width, win_roi_height); - LOGD("set video param : roi area : x(%d) y(%d) width(%d) height(%d)", - win_roi_x, win_roi_y, win_roi_width, win_roi_height); - } + /* After setting window handle, set display roi area */ + gst_video_overlay_set_display_roi_area( + GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst), + win_roi_x, win_roi_y, win_roi_width, win_roi_height); + LOGD("set video param : roi area : x(%d) y(%d) width(%d) height(%d)", + win_roi_x, win_roi_y, win_roi_width, win_roi_height); } -void -__mmplayer_video_param_set_display_overlay(mmplayer_t *player) +static void __mmplayer_video_param_set_display_overlay(mmplayer_t *player) { MMHandleType attrs = 0; - void *handle = NULL; + int handle = 0; /* check video sinkbin is created */ - if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player)) + if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY)) return; attrs = MMPLAYER_GET_ATTRS(player); MMPLAYER_RETURN_IF_FAIL(attrs); /* common case if using overlay surface */ - mm_attrs_get_data_by_name(attrs, "display_overlay", &handle); - - if (handle) { - /* default is using wl_surface_id */ - unsigned int wl_surface_id = 0; - wl_surface_id = *(int *)handle; - LOGD("set video param : wl_surface_id %d", wl_surface_id); - gst_video_overlay_set_wl_window_wl_surface_id( - GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst), - *(int *)handle); - } else { - /* FIXIT : is it error case? */ - LOGW("still we don't have a window handle on player attribute. create it's own surface."); - } + mm_attrs_get_int_by_name(attrs, "display_overlay", &handle); + MMPLAYER_RETURN_IF_FAIL(handle); + + /* default is using wl_surface_id */ + LOGD("set video param : wl_surface_id %d", handle); + gst_video_overlay_set_wl_window_wl_surface_id( + GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst), + handle); } int -__mmplayer_update_wayland_videosink_video_param(mmplayer_t *player, char *param_name) +_mmplayer_update_video_overlay_param(mmplayer_t *player, const char *param_name) { gboolean update_all_param = FALSE; + MMPLAYER_FENTER(); - /* check video sinkbin is created */ - if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player)) + if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY)) { + LOGW("videosink is not ready yet"); return MM_ERROR_PLAYER_NOT_INITIALIZED; + } if (strcmp(player->ini.videosink_element_overlay, "tizenwlsink")) { - LOGE("can not find tizenwlsink"); + LOGE("invalid videosink [%s]", player->ini.videosink_element_overlay); return MM_ERROR_PLAYER_INTERNAL; } @@ -2029,58 +2127,16 @@ __mmplayer_update_wayland_videosink_video_param(mmplayer_t *player, char *param_ if (update_all_param) __mmplayer_video_param_set_video_roi_area(player); - return MM_ERROR_NONE; -} - -int -_mmplayer_update_video_param(mmplayer_t *player, char *param_name) -{ - MMHandleType attrs = 0; - int surface_type = 0; - int ret = MM_ERROR_NONE; - - MMPLAYER_FENTER(); - - /* check video sinkbin is created */ - if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player)) - return MM_ERROR_PLAYER_NOT_INITIALIZED; - - attrs = MMPLAYER_GET_ATTRS(player); - if (!attrs) { - LOGE("cannot get content attribute"); - return MM_ERROR_PLAYER_INTERNAL; - } - LOGD("param_name : %s", param_name); - - /* update display surface */ - mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type); - LOGD("check display surface type attribute: %d", surface_type); - - /* configuring display */ - switch (surface_type) { - case MM_DISPLAY_SURFACE_OVERLAY: - { - ret = __mmplayer_update_wayland_videosink_video_param(player, param_name); - if (ret != MM_ERROR_NONE) - return ret; - } - break; - } 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; - int ret = MM_ERROR_NONE; 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 */ @@ -2092,90 +2148,72 @@ _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 (player->video_overlay_resource != NULL) { - ret = mm_resource_manager_mark_for_release(player->resource_manager, - player->video_overlay_resource); - if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) { - LOGE("failed to mark overlay resource for release, ret(0x%x)", ret); - goto ERROR; - } - player->video_overlay_resource = NULL; - } - - ret = mm_resource_manager_commit(player->resource_manager); - if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) { - LOGE("failed to commit acquiring of overlay resource, ret(0x%x)", ret); - goto ERROR; + if (__mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) { + LOGE("failed to release overlay resource"); + return MM_ERROR_PLAYER_INTERNAL; } } else { - /* mark video overlay for acquire */ - if (player->video_overlay_resource == NULL) { - ret = mm_resource_manager_mark_for_acquire(player->resource_manager, - MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY, - MM_RESOURCE_MANAGER_RES_VOLUME_FULL, - &player->video_overlay_resource); - if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) { - LOGE("could not prepare for video_overlay resource"); - goto ERROR; - } + if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) { + LOGE("failed to acquire video overlay resource"); + return MM_ERROR_PLAYER_INTERNAL; } - player->interrupted_by_resource = FALSE; - /* acquire resources for video overlay */ - ret = mm_resource_manager_commit(player->resource_manager); - if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) { - LOGE("could not acquire resources for video playing"); - goto ERROR; - } LOGD("enable overlay"); __mmplayer_video_param_set_display_overlay(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_switch_stream(player, MM_PLAYER_TRACK_TYPE_VIDEO, INVALID_TRACK_INDEX); - LOGD("audio_only : %d", *paudio_only); + /* 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); + } - MMPLAYER_FLEAVE(); +EXIT: + mm_player_set_attribute(hplayer, NULL, MM_PLAYER_AUDIO_ONLY, (int)audio_only, (char *)NULL); - return MM_ERROR_NONE; + MMPLAYER_FLEAVE(); + return ret; } int @@ -2281,11 +2319,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; @@ -2303,11 +2337,7 @@ __mmplayer_gst_caps_notify_cb(GstPad *pad, GParamSpec *unused, gpointer data) player->set_mode.video_zc = name[0] == 'S'; _mmplayer_update_content_attrs(player, ATTR_VIDEO); - - if (player->video_stream_changed_cb) { - LOGE("call the video stream changed cb"); - player->video_stream_changed_cb(player->video_stream_changed_cb_user_param); - } + MMPLAYER_POST_MSG(player, MM_MESSAGE_VIDEO_STREAM_CHANGED, NULL); } else { LOGW("invalid caps info"); } @@ -2358,14 +2388,13 @@ __mmplayer_audio_stream_send_data(mmplayer_t *player, mmplayer_audio_stream_buff audio_stream.bitrate = a_buffer->bitrate; audio_stream.channel = a_buffer->channel; - audio_stream.depth = a_buffer->depth; - audio_stream.is_little_endian = a_buffer->is_little_endian; audio_stream.channel_mask = a_buffer->channel_mask; audio_stream.data_size = a_buffer->data_size; audio_stream.data = a_buffer->pcm_data; audio_stream.pcm_format = a_buffer->pcm_format; - - /* LOGD("[%"G_GUINT64_FORMAT"] send data size:%d, %p", audio_stream.channel_mask, audio_stream.data_size, player->audio_decoded_cb_user_param); */ +#ifdef __DEBUG__ + LOGD("[%"G_GUINT64_FORMAT"] send data size:%d, %p", audio_stream.channel_mask, audio_stream.data_size, player->audio_decoded_cb_user_param); +#endif player->audio_decoded_cb(&audio_stream, player->audio_decoded_cb_user_param); MMPLAYER_FLEAVE(); @@ -2378,8 +2407,6 @@ __mmplayer_audio_stream_decoded_render_cb(GstElement *object, GstBuffer *buffer, const gchar *pcm_format = NULL; gint channel = 0; gint rate = 0; - gint depth = 0; - gint endianness = 0; guint64 channel_mask = 0; void *a_data = NULL; gint a_size = 0; @@ -2396,13 +2423,12 @@ __mmplayer_audio_stream_decoded_render_cb(GstElement *object, GstBuffer *buffer, GstCaps *caps = gst_pad_get_current_caps(pad); GstStructure *structure = gst_caps_get_structure(caps, 0); - - /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */ +#ifdef __DEBUG__ + MMPLAYER_LOG_GST_CAPS_TYPE(caps); +#endif pcm_format = gst_structure_get_string(structure, "format"); gst_structure_get_int(structure, "rate", &rate); gst_structure_get_int(structure, "channels", &channel); - gst_structure_get_int(structure, "depth", &depth); - gst_structure_get_int(structure, "endianness", &endianness); gst_structure_get(structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL); gst_caps_unref(GST_CAPS(caps)); @@ -2413,7 +2439,9 @@ __mmplayer_audio_stream_decoded_render_cb(GstElement *object, GstBuffer *buffer, mmplayer_audio_stream_buff_t *tmp = (mmplayer_audio_stream_buff_t *)l->data; if (tmp) { if (channel_mask == tmp->channel_mask) { - /* LOGD("[%"G_GUINT64_FORMAT"] total: %d, data: %d, buffer: %d", channel_mask, tmp->data_size, a_size, tmp->buff_size); */ +#ifdef __DEBUG__ + LOGD("[%"G_GUINT64_FORMAT"] total: %d, data: %d, buffer: %d", channel_mask, tmp->data_size, a_size, tmp->buff_size); +#endif if (tmp->data_size + a_size < tmp->buff_size) { memcpy(tmp->pcm_data + tmp->data_size, a_data, a_size); tmp->data_size += a_size; @@ -2451,8 +2479,6 @@ __mmplayer_audio_stream_decoded_render_cb(GstElement *object, GstBuffer *buffer, } a_buffer->bitrate = rate; a_buffer->channel = channel; - a_buffer->depth = depth; - a_buffer->is_little_endian = (endianness == 1234 ? true : false); a_buffer->channel_mask = channel_mask; a_buffer->data_size = a_size; a_buffer->pcm_format = _mmplayer_convert_audio_pcm_str_to_media_format_mime(pcm_format); @@ -2467,7 +2493,9 @@ __mmplayer_audio_stream_decoded_render_cb(GstElement *object, GstBuffer *buffer, goto DONE; } memcpy(a_buffer->pcm_data, a_data, a_size); - /* LOGD("new [%"G_GUINT64_FORMAT"] total:%d buff:%d", channel_mask, a_buffer->data_size, a_buffer->buff_size); */ +#ifdef __DEBUG__ + LOGD("new [%"G_GUINT64_FORMAT"] total:%d buff:%d", channel_mask, a_buffer->data_size, a_buffer->buff_size); +#endif player->audio_stream_buff_list = g_list_append(player->audio_stream_buff_list, a_buffer); } else { /* If sync is TRUE, send data directly. */ @@ -2531,8 +2559,6 @@ __mmplayer_gst_audio_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpoin audiobin[MMPLAYER_A_SINK].gst = sink; } - gst_element_set_state(sink, GST_STATE_PAUSED); - gst_element_set_state(queue, GST_STATE_PAUSED); _mmplayer_add_signal_connection(player, G_OBJECT(sink), @@ -2541,7 +2567,17 @@ __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"); + goto ERROR; + } + + if (gst_element_sync_state_with_parent(sink) == GST_STATE_CHANGE_FAILURE) { + LOGE("failed to sync state"); + goto ERROR; + } MMPLAYER_FLEAVE(); return; @@ -2565,9 +2601,25 @@ ERROR: } void +__mmplayer_gst_audio_deinterleave_no_more_pads(GstElement* object, gpointer data) +{ + mmplayer_t *player = (mmplayer_t *)data; + + MMPLAYER_FENTER(); + MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin); + + player->no_more_pad = TRUE; + _mmplayer_pipeline_complete(NULL, player); + + MMPLAYER_FLEAVE(); + return; +} + +void __mmplayer_gst_set_pulsesink_property(mmplayer_t *player) { #define MAX_PROPS_LEN 128 + mmplayer_gst_element_t *audiobin = NULL; gint latency_mode = 0; gchar *stream_type = NULL; gchar *latency = NULL; @@ -2582,37 +2634,48 @@ __mmplayer_gst_set_pulsesink_property(mmplayer_t *player) MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->audiobin); + audiobin = player->pipeline->audiobin; + + g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "volume", player->sound.volume, NULL); + if (player->sound.mute) { + LOGD("mute enabled"); + g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "mute", player->sound.mute, NULL); + } + mm_attrs_get_int_by_name(player->attrs, "sound_stream_index", &stream_id); mm_attrs_get_string_by_name(player->attrs, "sound_stream_type", &stream_type); - if (!stream_type) { - LOGE("stream_type is null."); - } else { - snprintf(stream_props, sizeof(stream_props) - 1, "props,media.role=%s, media.parent_id=%d", - stream_type, stream_id); - props = gst_structure_from_string(stream_props, NULL); - g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL); - LOGI("stream_type[%s], stream_id[%d], result[%s].", stream_type, stream_id, stream_props); - gst_structure_free(props); - } + if (!stream_type) + snprintf(stream_props, sizeof(stream_props) - 1, + "props,application.process.id.origin=%d", player->client_pid); + else + snprintf(stream_props, sizeof(stream_props) - 1, + "props,media.role=%s, media.parent_id=%d, application.process.id.origin=%d", + stream_type, stream_id, player->client_pid); + + props = gst_structure_from_string(stream_props, NULL); + g_object_set(audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL); + LOGI("props result[%s].", stream_props); + gst_structure_free(props); mm_attrs_get_int_by_name(player->attrs, "sound_latency_mode", &latency_mode); switch (latency_mode) { case AUDIO_LATENCY_MODE_LOW: - latency = g_strndup("low", 3); + latency = g_strdup("low"); break; case AUDIO_LATENCY_MODE_MID: - latency = g_strndup("mid", 3); + latency = g_strdup("mid"); break; case AUDIO_LATENCY_MODE_HIGH: - latency = g_strndup("high", 4); + latency = g_strdup("high"); + break; + default: + latency = g_strdup("mid"); break; }; - g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, - "latency", latency, - NULL); + g_object_set(audiobin[MMPLAYER_A_SINK].gst, "latency", latency, NULL); LOGD("audiosink property - latency=%s", latency); @@ -2621,18 +2684,23 @@ __mmplayer_gst_set_pulsesink_property(mmplayer_t *player) MMPLAYER_FLEAVE(); } -void +int __mmplayer_gst_set_openalsink_property(mmplayer_t *player) { mmplayer_gst_element_t *audiobin = NULL; MMPLAYER_FENTER(); - MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->audiobin); + MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && + player->pipeline->audiobin, MM_ERROR_PLAYER_NOT_INITIALIZED); audiobin = player->pipeline->audiobin; g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "source-ambisonics-type", 1, NULL); - sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info); + if (sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info)) { + LOGE("failed to create media stream info"); + return MM_ERROR_PLAYER_INTERNAL; + } + g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "stream-info", stream_info, NULL); if (player->video360_yaw_radians <= M_PI && @@ -2649,6 +2717,7 @@ __mmplayer_gst_set_openalsink_property(mmplayer_t *player) } MMPLAYER_FLEAVE(); + return MM_ERROR_NONE; } static int @@ -2714,13 +2783,15 @@ __mmplayer_gst_make_audio_playback_sink(mmplayer_t *player, GList **bucket) /* resampler */ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER, player->ini.audioresampler_element, "audio resampler", *bucket, player); - /* for logical volume control */ - MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", *bucket, player); - g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL); + if (g_strrstr(player->ini.audiosink_element, "openalsink")) { + /* currently, only openalsink uses volume element */ + MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", *bucket, player); + g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL); - if (player->sound.mute) { - LOGD("mute enabled"); - g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL); + if (player->sound.mute) { + LOGD("mute enabled"); + g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL); + } } mm_attrs_get_int_by_name(player->attrs, "content_audio_channels", &channels); @@ -2784,10 +2855,12 @@ __mmplayer_gst_make_audio_playback_sink(mmplayer_t *player, GList **bucket) g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE, NULL); } - if (g_strrstr(player->ini.audiosink_element, "pulsesink")) + if (g_strrstr(player->ini.audiosink_element, "pulsesink")) { __mmplayer_gst_set_pulsesink_property(player); - else if (g_strrstr(player->ini.audiosink_element, "openalsink")) - __mmplayer_gst_set_openalsink_property(player); + } else if (g_strrstr(player->ini.audiosink_element, "openalsink")) { + if (__mmplayer_gst_set_openalsink_property(player) != MM_ERROR_NONE) + goto ERROR; + } /* qos on */ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL); /* qos on */ @@ -2798,7 +2871,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; @@ -2884,9 +2957,9 @@ __mmplayer_gst_make_audio_extract_sink(mmplayer_t *player, GList **bucket) /* 2. decide the extract pcm format */ mm_attrs_multiple_get(player->attrs, NULL, - "pcm_audioformat", &dst_format, &dst_len, - "pcm_extraction_samplerate", &dst_samplerate, - "pcm_extraction_channels", &dst_channels, + MM_PLAYER_PCM_EXT_FORMAT, &dst_format, &dst_len, + MM_PLAYER_PCM_EXT_SAMPLERATE, &dst_samplerate, + MM_PLAYER_PCM_EXT_CHANNELS, &dst_channels, NULL); LOGD("required extract pcm format - format: %s(%d), samplerate : %d, channel: %d", @@ -2936,8 +3009,11 @@ __mmplayer_gst_make_audio_extract_sink(mmplayer_t *player, GList **bucket) /* audiosink will be added after getting signal for each channel */ _mmplayer_add_signal_connection(player, G_OBJECT(audiobin[MMPLAYER_A_EXTRACT_DEINTERLEAVE].gst), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added", G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), (gpointer)player); + _mmplayer_add_signal_connection(player, G_OBJECT(audiobin[MMPLAYER_A_EXTRACT_DEINTERLEAVE].gst), + 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)) @@ -2951,7 +3027,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(); @@ -2982,7 +3058,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; } @@ -3113,7 +3189,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)); @@ -3161,27 +3237,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; @@ -3197,6 +3273,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) { @@ -3237,18 +3314,21 @@ __mmplayer_video_stream_get_bo(mmplayer_t *player, int size) } /* update video num buffers */ - player->video_num_buffers = idx; - if (idx == player->ini.num_of_video_bo) - player->video_extra_num_buffers = player->ini.num_of_video_bo/2; + LOGD("video_num_buffers : %d", idx); + mm_player_set_attribute((MMHandleType)player, NULL, + MM_PLAYER_VIDEO_BUFFER_TOTAL_SIZE, idx, + MM_PLAYER_VIDEO_BUFFER_EXTRA_SIZE, MAX(DEFAULT_NUM_OF_V_OUT_BUFFER, (idx / 2)), + NULL); if (idx == 0) { MMPLAYER_VIDEO_BO_UNLOCK(player); return NULL; } - - LOGD("Num of video buffers(%d/%d)", player->video_num_buffers, player->video_extra_num_buffers); } + 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)) { @@ -3260,20 +3340,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 @@ -3321,7 +3401,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 && @@ -3511,22 +3591,24 @@ __mmplayer_gst_set_videosink_property(mmplayer_t *player, MMDisplaySurfaceType s return MM_ERROR_PLAYER_INTERNAL; } - LOGD("surface type %d, videosink factory name is %s", surface_type, factory_name); if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) { bool use_tbm = (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical)); - if (!use_tbm) { - /* support shard memory with S/W codec on HawkP */ - if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) { - g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, - "use-tbm", use_tbm, NULL); - } + if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) { + g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, + "use-tbm", use_tbm, NULL); } + + if (_mmplayer_update_video_overlay_param(player, "update_all_param") != MM_ERROR_NONE) + return MM_ERROR_PLAYER_INTERNAL; + + LOGI("videosink factory name is %s use-tbm : %d", factory_name, use_tbm); + } else { g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sync", TRUE, "max-lateness", FAKE_SINK_MAX_LATENESS, NULL); } - mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless); + mm_attrs_get_int_by_name(attrs, MM_PLAYER_GAPLESS_MODE, &gapless); if (gapless > 0) { LOGD("disable last-sample"); g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "enable-last-sample", FALSE, NULL); @@ -3553,9 +3635,6 @@ __mmplayer_gst_set_videosink_property(mmplayer_t *player, MMDisplaySurfaceType s (gpointer)player); } - if (_mmplayer_update_video_param(player, "update_all_param") != MM_ERROR_NONE) - return MM_ERROR_PLAYER_INTERNAL; - if (videobin[MMPLAYER_V_SINK].gst) { GstPad *sink_pad = NULL; sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink"); @@ -3615,7 +3694,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)) { @@ -3664,7 +3743,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)); @@ -3699,13 +3778,14 @@ __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 */ LOGD("adding created elements to bin"); if (!_mmplayer_gst_element_add_bucket_to_bin(GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket)) { LOGE("failed to add elements"); + g_list_free(element_bucket); goto ERROR; } @@ -3717,6 +3797,7 @@ __mmplayer_gst_create_plain_text_elements(mmplayer_t *player) LOGD("Linking elements in the bucket by added order."); if (_mmplayer_gst_element_link_bucket(element_bucket) == -1) { LOGE("failed to link elements"); + g_list_free(element_bucket); goto ERROR; } @@ -3751,7 +3832,6 @@ __mmplayer_gst_create_plain_text_elements(mmplayer_t *player) return MM_ERROR_NONE; ERROR: - g_list_free(element_bucket); if (!player->play_subtitle && textbin[MMPLAYER_T_FAKE_SINK].gst) { LOGE("remove textbin sink from sink list"); @@ -3838,11 +3918,11 @@ 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)); - MMPLAYER_FREEIF(player->pipeline->textbin); + MMPLAYER_FREEIF(textbin); player->pipeline->textbin = NULL; MMPLAYER_FLEAVE(); @@ -3960,7 +4040,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; @@ -4011,7 +4091,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; @@ -4136,7 +4216,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"); @@ -4179,8 +4259,6 @@ __mmplayer_gst_create_pipeline(mmplayer_t *player) } player->pipeline = (mmplayer_pipeline_info_t *)g_malloc0(sizeof(mmplayer_pipeline_info_t)); - if (player->pipeline == NULL) - goto INIT_ERROR; /* create mainbin */ mainbin = (mmplayer_gst_element_t *)g_try_malloc0(sizeof(mmplayer_gst_element_t) * MMPLAYER_M_NUM); @@ -4199,17 +4277,21 @@ __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"); 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"); @@ -4225,6 +4307,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; } @@ -4258,13 +4341,14 @@ __mmplayer_gst_destroy_pipeline(mmplayer_t *player) MMPLAYER_FREEIF(player->type); player->no_more_pad = FALSE; player->num_dynamic_pad = 0; - player->demux_pad_index = 0; MMPLAYER_SUBTITLE_INFO_LOCK(player); player->subtitle_language_list = NULL; MMPLAYER_SUBTITLE_INFO_UNLOCK(player); + MMPLAYER_RECONFIGURE_LOCK(player); __mmplayer_reset_gapless_state(player); + MMPLAYER_RECONFIGURE_UNLOCK(player); if (player->streamer) { _mm_player_streaming_initialize(player->streamer, FALSE); @@ -4311,10 +4395,6 @@ __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); @@ -4328,6 +4408,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; @@ -4418,7 +4503,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; } @@ -4502,103 +4587,65 @@ _mmplayer_parse_profile(const char *uri, void *param, mmplayer_parse_profile_t * return ret; } -static gboolean -__mmplayer_can_do_interrupt(mmplayer_t *player) +static int +__resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res, + void *user_data) { - if (!player || !player->pipeline || !player->attrs) { - LOGW("not initialized"); - goto FAILED; - } + mmplayer_t *player = NULL; + MMMessageParamType msg = {0, }; + gint64 pos = 0; + mmplayer_resource_type_e res_idx = MMPLAYER_RESOURCE_TYPE_MAX; - if (player->audio_decoded_cb) { - LOGW("not support in pcm extraction mode"); - goto FAILED; - } + MMPLAYER_FENTER(); - /* 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; + if (!user_data) { + LOGE("user_data is null"); + return TRUE; } - /* 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"); + player = (mmplayer_t *)user_data; - /* 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; + if (!player->pipeline || !player->attrs) { + LOGW("not initialized"); + return TRUE; } -FAILED: /* with CMD UNLOCKED */ - return FALSE; - -INTERRUPT: /* with CMD LOCKED, released at mrp_resource_release_cb() */ - return TRUE; -} + LOGD("cmd lock player, cmd state : %d", player->cmd); + MMPLAYER_CMD_LOCK(player); + LOGD("cmd locked player"); -static int -__resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res, - void *user_data) -{ - mmplayer_t *player = NULL; + 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; + } - MMPLAYER_FENTER(); + player->interrupted_by_resource = TRUE; - if (user_data == NULL) { - LOGE("- user_data is null"); - return FALSE; - } - player = (mmplayer_t *)user_data; + MMPLAYER_POST_MSG(player, MM_MESSAGE_INTERRUPT_STARTED, NULL); - /* do something to release resource here. - * player stop and interrupt forwarding */ - if (!__mmplayer_can_do_interrupt(player)) { - LOGW("no need to interrupt, so leave"); + /* get last play position */ + if (_mmplayer_gst_get_position(player, &pos) == MM_ERROR_NONE) { + msg.union_type = MM_MSG_UNION_TIME; + msg.time.elapsed = pos; + MMPLAYER_POST_MSG(player, MM_MESSAGE_PLAY_POSITION, &msg); } else { - MMMessageParamType msg = {0, }; - gint64 pos = 0; + LOGW("failed to get play position."); + } - player->interrupted_by_resource = TRUE; + LOGD("video resource conflict so, resource will be freed by unrealizing"); + if (_mmplayer_unrealize((MMHandleType)player) != MM_ERROR_NONE) + LOGE("failed to unrealize"); - /* get last play position */ - if (_mmplayer_gst_get_position(player, &pos) != MM_ERROR_NONE) { - LOGW("failed to get play position."); - } else { - msg.union_type = MM_MSG_UNION_TIME; - msg.time.elapsed = pos; - MMPLAYER_POST_MSG(player, MM_MESSAGE_PLAY_POSITION, &msg); - } - LOGD("video resource conflict so, resource will be freed by unrealizing"); - if (_mmplayer_unrealize((MMHandleType)player)) - LOGW("failed to unrealize"); + MMPLAYER_CMD_UNLOCK(player); - /* 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++) { + player->hw_resource[res_idx] = NULL; } - if (res == player->video_overlay_resource) - player->video_overlay_resource = FALSE; - else - player->video_decoder_resource = FALSE; - MMPLAYER_FLEAVE(); - - return FALSE; + return TRUE; /* release all the resources */ } static void @@ -4678,15 +4725,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; } @@ -4695,9 +4742,6 @@ _mmplayer_create_player(MMHandleType handle) g_mutex_init(&player->video_bo_mutex); g_cond_init(&player->video_bo_cond); - /* create media stream callback mutex */ - g_mutex_init(&player->media_stream_cb_lock); - /* create subtitle info lock and cond */ g_mutex_init(&player->subtitle_info_mutex); g_cond_init(&player->subtitle_info_cond); @@ -4711,8 +4755,6 @@ _mmplayer_create_player(MMHandleType handle) player->play_subtitle = FALSE; player->has_closed_caption = FALSE; - player->video_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER; - player->video_extra_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER; player->pending_resume = FALSE; if (player->ini.dump_element_keyword[0][0] == '\0') player->ini.set_dump_element_flag = FALSE; @@ -4860,7 +4902,9 @@ __mmplayer_init_gstreamer(mmplayer_t *player) } /* release */ for (i = 0; i < arg_count; i++) { - //LOGD("release - argv[%d] : %s", i, argv2[i]); +#ifdef __DEBUG__ + LOGD("release - argv[%d] : %s", i, argv2[i]); +#endif MMPLAYER_FREEIF(argv2[i]); } @@ -4956,7 +5000,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); @@ -4965,17 +5009,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 */ @@ -4984,9 +5028,6 @@ _mmplayer_destroy(MMHandleType handle) __mmplayer_release_dump_list(player->dump_list); - /* release miscellaneous information */ - __mmplayer_release_misc(player); - /* release miscellaneous information. these info needs to be released after pipeline is destroyed. */ __mmplayer_release_misc_post(player); @@ -4994,6 +5035,11 @@ _mmplayer_destroy(MMHandleType handle) /* release attributes */ _mmplayer_deconstruct_attribute(handle); + if (player->uri_info.uri_list) { + g_list_free_full(player->uri_info.uri_list, (GDestroyNotify)g_free); + player->uri_info.uri_list = NULL; + } + /* release lock */ g_mutex_clear(&player->fsink_lock); @@ -5004,9 +5050,6 @@ _mmplayer_destroy(MMHandleType handle) g_mutex_clear(&player->video_bo_mutex); g_cond_clear(&player->video_bo_cond); - /* release media stream callback lock */ - g_mutex_clear(&player->media_stream_cb_lock); - MMPLAYER_FLEAVE(); return MM_ERROR_NONE; @@ -5016,10 +5059,10 @@ int _mmplayer_realize(MMHandleType hplayer) { mmplayer_t *player = (mmplayer_t *)hplayer; + int ret = MM_ERROR_NONE; char *uri = NULL; void *param = NULL; MMHandleType attrs = 0; - int ret = MM_ERROR_NONE; MMPLAYER_FENTER(); @@ -5072,7 +5115,6 @@ _mmplayer_realize(MMHandleType hplayer) player->is_subtitle_off = FALSE; /* set the subtitle ON default */ player->video360_metadata.is_spherical = -1; player->is_openal_plugin_used = FALSE; - player->demux_pad_index = 0; player->subtitle_language_list = NULL; player->is_subtitle_force_drop = FALSE; @@ -5085,8 +5127,9 @@ _mmplayer_realize(MMHandleType hplayer) player->streamer = _mm_player_streaming_create(); _mm_player_streaming_initialize(player->streamer, TRUE); - mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_PREBUFFER_MS, &prebuffer_ms); - mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_REBUFFER_MS, &rebuffer_ms); + mm_attrs_multiple_get(player->attrs, NULL, + MM_PLAYER_PREBUFFER_MS, &prebuffer_ms, + MM_PLAYER_REBUFFER_MS, &rebuffer_ms, NULL); if (prebuffer_ms > 0) { prebuffer_ms = MAX(prebuffer_ms, 1000); @@ -5120,12 +5163,15 @@ _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(); 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); @@ -5140,36 +5186,15 @@ _mmplayer_unrealize(MMHandleType hplayer) /* unrealize pipeline */ ret = __mmplayer_gst_unrealize(player); - /* set asm stop if success */ - if (MM_ERROR_NONE == ret) { - if (!player->interrupted_by_resource) { - if (player->video_decoder_resource != NULL) { - ret = mm_resource_manager_mark_for_release(player->resource_manager, - player->video_decoder_resource); - if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) - LOGE("failed to mark decoder resource for release, ret(0x%x)", ret); - else - player->video_decoder_resource = NULL; - } - - if (player->video_overlay_resource != NULL) { - ret = mm_resource_manager_mark_for_release(player->resource_manager, - player->video_overlay_resource); - if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) - LOGE("failed to mark overlay resource for release, ret(0x%x)", ret); - else - player->video_overlay_resource = NULL; - } + 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); + } - ret = mm_resource_manager_commit(player->resource_manager); - if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) - LOGE("failed to commit resource releases, ret(0x%x)", ret); - } - } else - LOGE("failed and don't change asm state to stop"); + player->interrupted_by_resource = FALSE; MMPLAYER_FLEAVE(); - return ret; } @@ -5216,10 +5241,8 @@ __mmplayer_gst_set_volume_property(mmplayer_t *player, const char *prop_name) return MM_ERROR_NONE; } - if (player->build_audio_offload) { - LOGD("offload pipeline"); + if (player->build_audio_offload || g_strrstr(player->ini.audiosink_element, "pulsesink")) volume_elem_id = MMPLAYER_A_SINK; - } vol_element = player->pipeline->audiobin[volume_elem_id].gst; if (!vol_element) { @@ -5328,24 +5351,6 @@ _mmplayer_get_mute(MMHandleType hplayer, bool *mute) } int -_mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param) -{ - mmplayer_t *player = (mmplayer_t *)hplayer; - - MMPLAYER_FENTER(); - - MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); - - player->video_stream_changed_cb = callback; - player->video_stream_changed_cb_user_param = user_param; - LOGD("Handle value is %p : %p", player, player->video_stream_changed_cb); - - MMPLAYER_FLEAVE(); - - return MM_ERROR_NONE; -} - -int _mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param) { mmplayer_t *player = (mmplayer_t *)hplayer; @@ -5516,28 +5521,32 @@ __mmplayer_handle_missed_plugin(mmplayer_t *player) return MM_ERROR_NONE; } -static void -__mmplayer_check_pipeline(mmplayer_t *player) +static void __mmplayer_check_pipeline_reconfigure_state(mmplayer_t *player) { GstState element_state = GST_STATE_VOID_PENDING; GstState element_pending_state = GST_STATE_VOID_PENDING; - gint timeout = 0; - int ret = MM_ERROR_NONE; + GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE; + gint timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player); - if (!player->gapless.reconfigure) - return; + MMPLAYER_RETURN_IF_FAIL(player && player->pipeline); - LOGW("pipeline is under construction."); + MMPLAYER_RECONFIGURE_LOCK(player); + if (!player->gapless.reconfigure) { + MMPLAYER_RECONFIGURE_UNLOCK(player); + return; + } - MMPLAYER_PLAYBACK_LOCK(player); - MMPLAYER_PLAYBACK_UNLOCK(player); + LOGI("reconfigure is under process"); + MMPLAYER_RECONFIGURE_WAIT(player); + MMPLAYER_RECONFIGURE_UNLOCK(player); + LOGI("reconfigure is completed."); - timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player); + result = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, + &element_state, &element_pending_state, timeout * GST_SECOND); + if (result == GST_STATE_CHANGE_FAILURE) + LOGW("failed to get pipeline state in %d sec", timeout); - /* wait for state transition */ - ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND); - if (ret == GST_STATE_CHANGE_FAILURE) - LOGE("failed to change pipeline state within %d sec", timeout); + return; } /* NOTE : it should be able to call 'stop' anytime*/ @@ -5554,9 +5563,11 @@ _mmplayer_stop(MMHandleType hplayer) /* check current state */ MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_STOP); - /* check pipline building state */ - __mmplayer_check_pipeline(player); + /* need to wait till the rebuilding pipeline is completed */ + __mmplayer_check_pipeline_reconfigure_state(player); + MMPLAYER_RECONFIGURE_LOCK(player); __mmplayer_reset_gapless_state(player); + MMPLAYER_RECONFIGURE_UNLOCK(player); /* NOTE : application should not wait for EOS after calling STOP */ _mmplayer_cancel_eos_timer(player); @@ -5590,14 +5601,14 @@ _mmplayer_pause(MMHandleType hplayer) /* check current state */ MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_PAUSE); - /* check pipline building state */ - __mmplayer_check_pipeline(player); + /* 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")); @@ -5640,18 +5651,19 @@ _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 (MM_ERROR_NONE != _mmplayer_update_video_param(player, "display_rotation")) + if (_mmplayer_update_video_overlay_param(player, "display_rotation") != MM_ERROR_NONE) LOGE("failed to update display_rotation"); } MMPLAYER_FLEAVE(); - - return ret; + return MM_ERROR_NONE; } /* in case of streaming, pause could take long time.*/ @@ -5668,11 +5680,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; @@ -5798,8 +5823,8 @@ _mmplayer_set_position(MMHandleType hplayer, gint64 position) MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); - /* check pipline building state */ - __mmplayer_check_pipeline(player); + /* check pipeline reconfigure state */ + __mmplayer_check_pipeline_reconfigure_state(player); ret = _mmplayer_gst_set_position(player, position, FALSE); @@ -5838,7 +5863,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; @@ -5880,8 +5905,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; @@ -5894,10 +5919,11 @@ __mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps) /* set stream information */ gst_structure_get_int(caps_structure, "rate", &samplerate); - mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate); - gst_structure_get_int(caps_structure, "channels", &channels); - mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels); + + mm_player_set_attribute((MMHandleType)player, NULL, + "content_audio_samplerate", samplerate, + "content_audio_channels", channels, NULL); LOGD("audio samplerate : %d channels : %d", samplerate, channels); } @@ -5950,13 +5976,20 @@ _mmplayer_typefind_have_type(GstElement *tf, guint probability, GstCaps *caps, gpointer data) { mmplayer_t *player = (mmplayer_t *)data; - GstPad *pad = NULL; MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(player && tf && caps); /* store type string */ + if (player->type_caps) { + gst_caps_unref(player->type_caps); + player->type_caps = NULL; + } + + player->type_caps = gst_caps_copy(caps); + MMPLAYER_LOG_GST_CAPS_TYPE(player->type_caps); + MMPLAYER_FREEIF(player->type); player->type = gst_caps_to_string(caps); if (player->type) @@ -5982,27 +6015,27 @@ _mmplayer_typefind_have_type(GstElement *tf, guint probability, __mmplayer_update_content_type_info(player); - pad = gst_element_get_static_pad(tf, "src"); - if (!pad) { - LOGE("fail to get typefind src pad."); - return; - } + if (!player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst) { + GstPad *pad = NULL; - if (!_mmplayer_gst_create_decoder(player, pad, caps)) { - gboolean async = FALSE; - LOGE("failed to autoplug %s", player->type); + pad = gst_element_get_static_pad(tf, "src"); + if (!pad) { + LOGE("fail to get typefind src pad."); + return; + } - mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async); + if (!_mmplayer_gst_create_decoder(player, pad, caps)) { + gboolean async = FALSE; + LOGE("failed to autoplug %s", player->type); - if (async && player->msg_posted == FALSE) - __mmplayer_handle_missed_plugin(player); + mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async); + if (async && player->msg_posted == FALSE) + __mmplayer_handle_missed_plugin(player); + } + gst_object_unref(GST_OBJECT(pad)); } - - gst_object_unref(GST_OBJECT(pad)); - MMPLAYER_FLEAVE(); - return; } @@ -6027,20 +6060,24 @@ _mmplayer_gst_make_decodebin(mmplayer_t *player) /* no-more-pad pad handling signal */ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads", - G_CALLBACK(__mmplayer_gst_decode_no_more_pads), (gpointer)player); + G_CALLBACK(_mmplayer_gst_decode_no_more_pads), (gpointer)player); _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed", - G_CALLBACK(__mmplayer_gst_decode_pad_removed), (gpointer)player); + G_CALLBACK(_mmplayer_gst_decode_pad_removed), (gpointer)player); /* This signal is emitted when a pad for which there is no further possible decoding is added to the decodebin.*/ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type", - G_CALLBACK(__mmplayer_gst_decode_unknown_type), (gpointer)player); + G_CALLBACK(_mmplayer_gst_decode_unknown_type), (gpointer)player); /* This signal is emitted whenever decodebin finds a new stream. It is emitted before looking for any elements that can handle that stream.*/ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue", - G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), (gpointer)player); + G_CALLBACK(_mmplayer_gst_decode_autoplug_continue), (gpointer)player); + + if (player->need_video_dec_sorting || player->need_audio_dec_sorting) + _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort", + G_CALLBACK(_mmplayer_gst_decode_autoplug_sort), (gpointer)player); /* This signal is emitted whenever decodebin finds a new stream. It is emitted before looking for any elements that can handle that stream.*/ @@ -6049,7 +6086,7 @@ _mmplayer_gst_make_decodebin(mmplayer_t *player) /* This signal is emitted once decodebin has finished decoding all the data.*/ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained", - G_CALLBACK(__mmplayer_gst_decode_drained), (gpointer)player); + G_CALLBACK(_mmplayer_gst_decode_drained), (gpointer)player); /* This signal is emitted when a element is added to the bin.*/ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added", @@ -6317,8 +6354,8 @@ DONE: return MM_ERROR_NONE; } -static void -__mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) +void +_mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) { mmplayer_t *player = (mmplayer_t *)data; @@ -6329,7 +6366,7 @@ __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) /* remove fakesink. */ if (!_mmplayer_gst_remove_fakesink(player, &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK])) { - /* NOTE : __mmplayer_pipeline_complete() can be called several time. because + /* NOTE : _mmplayer_pipeline_complete() can be called several time. because * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various * source element are not same. To overcome this situation, this function will called * several places and several times. Therefore, this is not an error case. @@ -6339,8 +6376,7 @@ __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) LOGD("[handle: %p] pipeline has completely constructed", player); - if ((player->ini.async_start) && - (player->msg_posted == FALSE) && + if ((player->msg_posted == FALSE) && (player->cmd >= MMPLAYER_COMMAND_START)) __mmplayer_handle_missed_plugin(player); @@ -6405,16 +6441,15 @@ __mmplayer_get_next_uri(mmplayer_t *player) break; } - if (uri_idx == num_of_list) { + if (!uri || uri_idx == num_of_list) { LOGE("failed to find next uri"); return FALSE; } player->uri_info.uri_idx = uri_idx; - mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri); - - if (mm_attrs_commit_all(player->attrs)) { - LOGE("failed to commit"); + if (mm_player_set_attribute((MMHandleType)player, NULL, + "profile_uri", uri, strlen(uri), NULL) != MM_ERROR_NONE) { + LOGE("failed to set attribute"); return FALSE; } @@ -6440,6 +6475,11 @@ __mmplayer_verify_gapless_play_path(mmplayer_t *player) LOGD("checking for gapless play option"); + if (player->build_audio_offload) { + LOGE("offload path is not supportable."); + goto ERROR; + } + if (player->pipeline->textbin) { LOGE("subtitle path is enabled. gapless play is not supported."); goto ERROR; @@ -6451,7 +6491,10 @@ __mmplayer_verify_gapless_play_path(mmplayer_t *player) goto ERROR; } - mm_attrs_get_int_by_name(attrs, "content_video_found", &video); + mm_attrs_multiple_get(player->attrs, NULL, + "content_video_found", &video, + "profile_play_count", &count, + MM_PLAYER_GAPLESS_MODE, &gapless, NULL); /* gapless playback is not supported in case of video at TV profile. */ profile_tv = __mmplayer_check_profile(); @@ -6460,12 +6503,6 @@ __mmplayer_verify_gapless_play_path(mmplayer_t *player) goto ERROR; } - if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE) - LOGE("failed to get play count"); - - if (mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless) != MM_ERROR_NONE) - LOGE("failed to get gapless mode"); - /* check repeat count in case of audio */ if (!gapless && (video || (count != REPEAT_COUNT_INFINITE && count < REPEAT_COUNT_MIN))) { @@ -6483,11 +6520,7 @@ __mmplayer_verify_gapless_play_path(mmplayer_t *player) /* decrease play count */ /* we succeeded to rewind. update play count and then wait for next EOS */ count--; - mm_attrs_set_int_by_name(attrs, "profile_play_count", count); - /* commit attribute */ - if (mm_attrs_commit_all(attrs)) - LOGE("failed to commit attribute"); - + mm_player_set_attribute((MMHandleType)player, NULL, "profile_play_count", count, NULL); } else if (count != REPEAT_COUNT_INFINITE) { LOGD("there is no next uri and no repeat"); goto ERROR; @@ -6507,10 +6540,96 @@ 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) { - mmplayer_selector_t *selector = &player->selector[type]; + mmplayer_track_t *selector = &player->track[type]; mmplayer_gst_element_t *sinkbin = NULL; main_element_id_e selectorId = MMPLAYER_M_NUM; main_element_id_e sinkId = MMPLAYER_M_NUM; @@ -6581,11 +6700,12 @@ __mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type) LOGD("selector release"); /* release and unref requests pad from the selector */ - for (n = 0; n < selector->channels->len; n++) { - GstPad *sinkpad = g_ptr_array_index(selector->channels, n); + for (n = 0; n < selector->streams->len; n++) { + GstPad *sinkpad = g_ptr_array_index(selector->streams, n); gst_element_release_request_pad((player->pipeline->mainbin[selectorId].gst), sinkpad); } - g_ptr_array_set_size(selector->channels, 0); + + g_ptr_array_set_size(selector->streams, 0); gst_element_set_state(player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL); gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst); @@ -6603,11 +6723,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); @@ -6619,9 +6748,7 @@ __mmplayer_deactivate_old_path(mmplayer_t *player) player->streamer = NULL; } - MMPLAYER_PLAYBACK_LOCK(player); MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player); - MMPLAYER_FLEAVE(); return; @@ -6648,10 +6775,11 @@ _mmplayer_set_uri(MMHandleType hplayer, const char *uri) MMPLAYER_FENTER(); MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + MMPLAYER_RETURN_VAL_IF_FAIL(uri, MM_ERROR_INVALID_ARGUMENT); - mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri); - if (mm_attrs_commit_all(player->attrs)) { - LOGE("failed to commit the original uri."); + if (mm_player_set_attribute(hplayer, NULL, + "profile_uri", uri, strlen(uri), NULL) != MM_ERROR_NONE) { + LOGE("failed to set attribute"); result = MM_ERROR_PLAYER_INTERNAL; } else { if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE) @@ -6685,9 +6813,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 { @@ -6735,7 +6863,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; @@ -6750,8 +6878,8 @@ _mmplayer_get_next_uri(MMHandleType hplayer, char **uri) return MM_ERROR_NONE; } -static void -__mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad, +void +_mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad, GstCaps *caps, gpointer data) { mmplayer_t *player = (mmplayer_t *)data; @@ -6772,9 +6900,9 @@ __mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad, __mmplayer_check_not_supported_codec(player, klass, mime); } -static gboolean -__mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, - GstCaps *caps, gpointer data) +gboolean +_mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, + GstCaps *caps, gpointer data) { mmplayer_t *player = (mmplayer_t *)data; const char *mime = NULL; @@ -6801,15 +6929,10 @@ __mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, caps_str = gst_caps_to_string(caps); /* set it directly because not sent by TAG */ if (g_strrstr(caps_str, "mobile-xmf")) - mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf"); + mm_player_set_attribute((MMHandleType)player, NULL, + "content_audio_codec", "mobile-xmf", strlen("mobile-xmf"), NULL); + MMPLAYER_FREEIF(caps_str); - } else if (g_str_has_prefix(mime, "video") && !player->ini.video_playback_supported) { - MMMessageParamType msg_param; - memset(&msg_param, 0, sizeof(MMMessageParamType)); - msg_param.code = MM_ERROR_NOT_SUPPORT_API; - MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param); - LOGD("video file is not supported on this device"); - ret = FALSE; } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) { LOGD("already video linked"); ret = FALSE; @@ -6823,7 +6946,7 @@ __mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, static gboolean __mmplayer_is_audio_offload_device_type(mmplayer_t *player) { - gboolean ret = TRUE; + gboolean ret = FALSE; GDBusConnection *conn = NULL; GError *err = NULL; GVariant *result = NULL; @@ -6833,9 +6956,8 @@ __mmplayer_is_audio_offload_device_type(mmplayer_t *player) conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); if (!conn || err) { - LOGE("failed g_bus_get_sync() (%s)", err ? err->message : NULL); + LOGE("failed g_bus_get_sync() (%s)", (err ? err->message : "null")); g_error_free(err); - ret = FALSE; goto DONE; } @@ -6851,9 +6973,8 @@ __mmplayer_is_audio_offload_device_type(mmplayer_t *player) NULL, &err); if (!result || err) { - LOGE("failed g_dbus_connection_call_sync() (%s)", err ? err->message : NULL); + LOGE("failed g_dbus_connection_call_sync() (%s)", (err ? err->message : "null")); g_error_free(err); - ret = FALSE; goto DONE; } @@ -6861,10 +6982,8 @@ __mmplayer_is_audio_offload_device_type(mmplayer_t *player) g_variant_get(result, "(&s&s)", &dbus_device_type, &dbus_ret); LOGI("g_dbus_connection_call_sync() success (%s, %s)", dbus_device_type, dbus_ret); - if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) { - ret = FALSE; + if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) goto DONE; - } /* the device type is listed in ini file among audio-jack, bt-a2dp, usb-audio, builtin-speaker */ for (idx = 0; player->ini.audio_offload_device_type[idx][0] != '\0'; idx++) { @@ -6876,11 +6995,11 @@ __mmplayer_is_audio_offload_device_type(mmplayer_t *player) } LOGD("audio offload is not supportable"); - ret = FALSE; DONE: g_variant_unref(result); - g_object_unref(conn); + if (conn) + g_object_unref(conn); return ret; } @@ -6905,9 +7024,7 @@ static void __mmplayer_rebuild_audio_pipeline(mmplayer_t *player) _mmplayer_set_position((MMHandleType)player, position); /* async not to be blocked in streaming case */ - mm_attrs_set_int_by_name(player->attrs, "profile_prepare_async", TRUE); - if (mm_attrs_commit_all(player->attrs)) - LOGE("failed to commit"); + mm_player_set_attribute((MMHandleType)player, NULL, "profile_prepare_async", TRUE, NULL); _mmplayer_pause((MMHandleType)player); @@ -6972,6 +7089,37 @@ __mmplayer_add_audio_device_connected_cb(mmplayer_t *player) return TRUE; } +int _mmplayer_audio_offload_is_activated(MMHandleType hplayer, bool *activated) +{ + mmplayer_t *player = (mmplayer_t *)hplayer; + + MMPLAYER_FENTER(); + MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + MMPLAYER_RETURN_VAL_IF_FAIL(activated, MM_ERROR_INVALID_ARGUMENT); + + *activated = player->build_audio_offload; + + LOGD("offload activated : %d", (int)*activated); + + MMPLAYER_FLEAVE(); + return MM_ERROR_NONE; +} + +static gboolean +__mmplayer_is_offload_supported_type(mmplayer_t *player) +{ + /* NOTE : + this function need to be updated according to the supported media format + @see player->ini.audio_offload_media_format */ + + if (__mmplayer_is_only_mp3_type(player->type)) { + LOGD("offload supportable media format type"); + return TRUE; + } + + return FALSE; +} + static gboolean __mmplayer_can_build_audio_offload_path(mmplayer_t *player) { @@ -6982,7 +7130,7 @@ __mmplayer_can_build_audio_offload_path(mmplayer_t *player) MMPLAYER_RETURN_VAL_IF_FAIL(player && player->attrs, FALSE); LOGD("current stream : %s, sink: %s", player->type, player->ini.audio_offload_sink_element); - if (!__mmplayer_is_only_mp3_type(player->type)) + if (!__mmplayer_is_offload_supported_type(player)) goto DONE; if (!strcmp(player->ini.audio_offload_sink_element, "")) { @@ -7002,6 +7150,12 @@ __mmplayer_can_build_audio_offload_path(mmplayer_t *player) } gst_object_unref(factory); + if (_mmplayer_acquire_hw_resource(player, + MMPLAYER_RESOURCE_TYPE_AUDIO_OFFLOAD) != MM_ERROR_NONE) { + LOGE("failed to acquire audio offload decoder resource"); + goto DONE; + } + if (!__mmplayer_add_audio_device_connected_cb(player)) goto DONE; @@ -7012,6 +7166,9 @@ __mmplayer_can_build_audio_offload_path(mmplayer_t *player) ret = TRUE; DONE: + if (!ret) + __mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_AUDIO_OFFLOAD); + MMPLAYER_FLEAVE(); return ret; } @@ -7020,8 +7177,6 @@ static GstAutoplugSelectResult __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps, char *factory_name) { GstAutoplugSelectResult ret = GST_AUTOPLUG_SELECT_TRY; - int idx = 0; - int codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT; int audio_offload = 0; if ((g_strrstr(klass, "Codec/Decoder/Audio"))) { @@ -7039,31 +7194,13 @@ __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps goto DONE; } - mm_attrs_get_int_by_name(player->attrs, "audio_codec_type", &codec_type); - - LOGD("audio codec type: %d", codec_type); - if (codec_type == MM_PLAYER_CODEC_TYPE_HW) { - /* sw codec will be skipped */ - for (idx = 0; player->ini.audiocodec_element_sw[idx][0] != '\0'; idx++) { - if (strstr(factory_name, player->ini.audiocodec_element_sw[idx])) { - LOGW("skipping sw acodec:[%s] by codec type", factory_name); - ret = GST_AUTOPLUG_SELECT_SKIP; - goto DONE; - } - } - } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) { - /* hw codec will be skipped */ - if (strcmp(player->ini.audiocodec_element_hw, "") && - g_strrstr(factory_name, player->ini.audiocodec_element_hw)) { - LOGW("skipping hw acodec:[%s] by codec type", factory_name); - ret = GST_AUTOPLUG_SELECT_SKIP; - goto DONE; - } - } + /* FIXME: If HW audio decoder is selected, related resource have to be acquired here. + And need to consider the multi-track audio content. + There is no HW audio decoder in public. */ /* 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; @@ -7072,65 +7209,156 @@ __mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps } else if (g_strrstr(klass, "Codec/Decoder/Video")) { - mm_attrs_get_int_by_name(player->attrs, "video_codec_type", &codec_type); + if ((strlen(player->ini.videocodec_element_hw) > 0) && + (g_strrstr(factory_name, player->ini.videocodec_element_hw))) { - LOGD("video codec type: %d", codec_type); - if (codec_type == MM_PLAYER_CODEC_TYPE_HW) { - /* sw codec is skipped */ - for (idx = 0; player->ini.videocodec_element_sw[idx][0] != '\0'; idx++) { - if (strstr(factory_name, player->ini.videocodec_element_sw[idx])) { - LOGW("skipping sw vcodec:[%s] by codec type", factory_name); - ret = GST_AUTOPLUG_SELECT_SKIP; - goto DONE; - } + /* mark video decoder for acquire */ + if (player->hw_resource[MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER] != NULL) { + LOGW("video decoder resource is already acquired, skip it."); + ret = GST_AUTOPLUG_SELECT_SKIP; + goto DONE; } - } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) { - /* hw codec is skipped */ - if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) { - LOGW("skipping hw vcodec:[%s] by codec type", factory_name); + + 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; } + player->interrupted_by_resource = FALSE; } - if ((strlen(player->ini.videocodec_element_hw) > 0) && - (g_strrstr(factory_name, player->ini.videocodec_element_hw))) { + /* update codec info */ + player->not_supported_codec &= MISSING_PLUGIN_AUDIO; + player->can_support_codec |= FOUND_PLUGIN_VIDEO; + player->videodec_linked = 1; + } - /* mark video decoder for acquire */ - if (player->video_decoder_resource == NULL) { - if (mm_resource_manager_mark_for_acquire(player->resource_manager, - MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER, - MM_RESOURCE_MANAGER_RES_VOLUME_FULL, - &player->video_decoder_resource) - != MM_RESOURCE_MANAGER_ERROR_NONE) { - LOGE("could not mark video_decoder resource for acquire"); - ret = GST_AUTOPLUG_SELECT_SKIP; - goto DONE; - } - } else { - LOGW("video decoder resource is already acquired, skip it."); - ret = GST_AUTOPLUG_SELECT_SKIP; - goto DONE; +DONE: + return ret; +} + +GValueArray * +_mmplayer_gst_decode_autoplug_sort(GstElement *bin, + GstPad *pad, GstCaps *caps, GValueArray *factories, gpointer data) +{ +#define DEFAULT_IDX 0xFFFF +#define MIN_FACTORY_NUM 2 + mmplayer_t *player = (mmplayer_t *)data; + GValueArray *new_factories = NULL; + GValue val = { 0, }; + GstElementFactory *factory = NULL; + const gchar *klass = NULL; + gchar *factory_name = NULL; + guint hw_dec_idx = DEFAULT_IDX; + guint first_sw_dec_idx = DEFAULT_IDX; + guint last_sw_dec_idx = DEFAULT_IDX; + guint new_pos = DEFAULT_IDX; + guint rm_pos = DEFAULT_IDX; + int audio_codec_type; + int video_codec_type; + mmplayer_codec_type_e codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT; + + if (factories->n_values < MIN_FACTORY_NUM) + return NULL; + + mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_VIDEO_CODEC_TYPE, &video_codec_type); + mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, &audio_codec_type); + +#ifdef __DEBUG__ + LOGD("num of factory : %d, codec type %d, %d", factories->n_values, video_codec_type, audio_codec_type); +#endif + for (int i = 0 ; i < factories->n_values ; i++) { + gchar *hw_dec_info = NULL; + gchar (*sw_dec_info)[PLAYER_INI_MAX_STRLEN] = {NULL, }; + + factory = g_value_get_object(g_value_array_get_nth(factories, i)); + if (!factory) { + LOGW("failed to get factory object"); + continue; + } + klass = gst_element_factory_get_klass(factory); + factory_name = GST_OBJECT_NAME(factory); + +#ifdef __DEBUG__ + LOGD("Klass [%s] Factory [%s]", klass, factory_name); +#endif + if (g_strrstr(klass, "Codec/Decoder/Audio")) { + if (!player->need_audio_dec_sorting) { + LOGD("sorting is not required"); + return NULL; } + codec_type = audio_codec_type; + hw_dec_info = player->ini.audiocodec_element_hw; + sw_dec_info = player->ini.audiocodec_element_sw; + } else if (g_strrstr(klass, "Codec/Decoder/Video")) { + if (!player->need_video_dec_sorting) { + LOGD("sorting is not required"); + return NULL; + } + codec_type = video_codec_type; + hw_dec_info = player->ini.videocodec_element_hw; + sw_dec_info = player->ini.videocodec_element_sw; + } else { + continue; + } - player->interrupted_by_resource = FALSE; - /* acquire resources for video playing */ - if (mm_resource_manager_commit(player->resource_manager) - != MM_RESOURCE_MANAGER_ERROR_NONE) { - LOGE("could not acquire resources for video decoding"); - ret = GST_AUTOPLUG_SELECT_SKIP; - goto DONE; + if (g_strrstr(factory_name, hw_dec_info)) { + hw_dec_idx = i; + } else { + for (int j = 0; sw_dec_info[j][0] != '\0'; j++) { + if (strstr(factory_name, sw_dec_info[j])) { + last_sw_dec_idx = i; + if (first_sw_dec_idx == DEFAULT_IDX) { + first_sw_dec_idx = i; + } + } } + + if (first_sw_dec_idx == DEFAULT_IDX) + LOGW("unknown codec %s", factory_name); } + } - /* update codec info */ - player->not_supported_codec &= MISSING_PLUGIN_AUDIO; - player->can_support_codec |= FOUND_PLUGIN_VIDEO; - player->videodec_linked = 1; + if (hw_dec_idx == DEFAULT_IDX || first_sw_dec_idx == DEFAULT_IDX) + return NULL; + + if (codec_type == MM_PLAYER_CODEC_TYPE_HW) { + if (hw_dec_idx < first_sw_dec_idx) + return NULL; + new_pos = first_sw_dec_idx; + rm_pos = hw_dec_idx + 1; + } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) { + if (last_sw_dec_idx < hw_dec_idx) + return NULL; + new_pos = last_sw_dec_idx + 1; + rm_pos = hw_dec_idx; + } else { + return NULL; } -DONE: - return ret; + /* change position - insert H/W decoder according to the new position */ + factory = g_value_get_object(g_value_array_get_nth(factories, hw_dec_idx)); + if (!factory) { + LOGW("failed to get factory object"); + return NULL; + } + new_factories = g_value_array_copy(factories); + g_value_init (&val, G_TYPE_OBJECT); + g_value_set_object (&val, factory); + g_value_array_insert(new_factories, new_pos, &val); + g_value_unset (&val); + g_value_array_remove(new_factories, rm_pos); /* remove previous H/W element */ + + for (int i = 0 ; i < new_factories->n_values ; i++) { + factory = g_value_get_object(g_value_array_get_nth(new_factories, i)); + if (factory) + LOGD("[Re-arranged] Klass [%s] Factory [%s]", + gst_element_factory_get_klass(factory), GST_OBJECT_NAME (factory)); + else + LOGE("[Re-arranged] failed to get factory object"); + } + + return new_factories; } gint @@ -7160,7 +7388,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; @@ -7263,32 +7491,96 @@ DONE: return result; } -static void -__mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad, +void +_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; + + 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 to NULL"); return; } - gchar *caps_str = NULL; - caps_str = gst_caps_to_string(caps); + 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 to NULL"); + return; + } - LOGD("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem)); + if (!gst_bin_remove(GST_BIN_CAST(mainbin[MMPLAYER_M_PIPE].gst), mainbin[MMPLAYER_M_V_CONCAT].gst)) { + LOGE("failed to remove video concat"); + } - MMPLAYER_FREEIF(caps_str); - gst_caps_unref(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(mainbin[MMPLAYER_M_V_CONCAT].gst)); + mainbin[MMPLAYER_M_V_CONCAT].gst = NULL; + mainbin[MMPLAYER_M_V_CONCAT].id = 0; + + gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst)); + 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(); } -static void -__mmplayer_gst_decode_drained(GstElement *bin, gpointer data) +void +_mmplayer_gst_about_to_finish(GstElement *bin, gpointer data) +{ + mmplayer_t *player = (mmplayer_t *)data; + + MMPLAYER_FENTER(); + MMPLAYER_RETURN_IF_FAIL(player); + + LOGD("got about to finish signal"); + + if (!MMPLAYER_CMD_TRYLOCK(player)) { + LOGW("Fail to get cmd lock"); + return; + } + + if (!__mmplayer_verify_gapless_play_path(player)) { + LOGD("decoding is finished."); + MMPLAYER_CMD_UNLOCK(player); + return; + } + + _mmplayer_set_reconfigure_state(player, TRUE); + MMPLAYER_CMD_UNLOCK(player); + + MMPLAYER_POST_MSG(player, MM_MESSAGE_FLUSH_BUFFER, NULL); + __mmplayer_deactivate_old_path(player); + + MMPLAYER_FLEAVE(); +} + +void +_mmplayer_gst_decode_drained(GstElement *bin, gpointer data) { mmplayer_t *player = (mmplayer_t *)data; GstIterator *iter = NULL; @@ -7300,22 +7592,21 @@ __mmplayer_gst_decode_drained(GstElement *bin, gpointer data) MMPLAYER_FENTER(); MMPLAYER_RETURN_IF_FAIL(player); - LOGD("__mmplayer_gst_decode_drained"); + LOGD("got drained signal"); if (!MMPLAYER_CMD_TRYLOCK(player)) { LOGW("Fail to get cmd lock"); return; } - if (!player->gapless.reconfigure && /* If it is already checked, skip verify. */ - !__mmplayer_verify_gapless_play_path(player)) { + if (!__mmplayer_verify_gapless_play_path(player)) { LOGD("decoding is finished."); - __mmplayer_reset_gapless_state(player); MMPLAYER_CMD_UNLOCK(player); return; } - player->gapless.reconfigure = TRUE; + _mmplayer_set_reconfigure_state(player, TRUE); + MMPLAYER_CMD_UNLOCK(player); /* check decodebin src pads whether they received EOS or not */ iter = gst_element_iterate_src_pads(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst); @@ -7345,7 +7636,6 @@ __mmplayer_gst_decode_drained(GstElement *bin, gpointer data) if (!is_all_drained) { LOGD("Wait util the all pads get EOS."); - MMPLAYER_CMD_UNLOCK(player); MMPLAYER_FLEAVE(); return; } @@ -7354,9 +7644,8 @@ __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_CMD_UNLOCK(player); MMPLAYER_FLEAVE(); } @@ -7380,6 +7669,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")) { @@ -7395,9 +7694,14 @@ _mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data) "max-video-height", player->adaptive_info.limit.height, NULL); } else if (g_strrstr(klass, "Demuxer")) { - //LOGD("plugged element is demuxer. take it"); +#ifdef __DEBUG__ + 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; + } 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; } if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux")) { @@ -7421,6 +7725,12 @@ _mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data) } } else if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) { player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element; + } else if (g_strrstr(factory_name, "omxdec_h264")) { + GstElement *video_parse = player->pipeline->mainbin[MMPLAYER_M_V_PARSE].gst; + if (video_parse && (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"); + } } if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) && @@ -7452,20 +7762,6 @@ __mmplayer_release_misc(mmplayer_t *player) MMPLAYER_RETURN_IF_FAIL(player); - player->video_decoded_cb = NULL; - player->video_decoded_cb_user_param = NULL; - player->video_stream_prerolled = false; - - player->audio_decoded_cb = NULL; - player->audio_decoded_cb_user_param = NULL; - player->audio_extract_opt = MM_PLAYER_AUDIO_EXTRACT_DEFAULT; - - player->video_stream_changed_cb = NULL; - player->video_stream_changed_cb_user_param = NULL; - - player->audio_stream_changed_cb = NULL; - player->audio_stream_changed_cb_user_param = NULL; - player->sent_bos = FALSE; player->playback_rate = DEFAULT_PLAYBACK_RATE; @@ -7505,17 +7801,6 @@ __mmplayer_release_misc(mmplayer_t *player) player->maximum_bitrate[i] = 0; } - MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player); - - /* remove media stream cb(appsrc cb) */ - for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++) { - player->media_stream_buffer_status_cb[i] = NULL; - player->media_stream_seek_data_cb[i] = NULL; - player->buffer_cb_user_param[i] = NULL; - player->seek_cb_user_param[i] = NULL; - } - MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player); - /* free memory related to audio effect */ MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin); @@ -7553,45 +7838,45 @@ __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. */ - MMPLAYER_RETURN_IF_FAIL(player); - mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0); + player->video_decoded_cb = NULL; + player->video_decoded_cb_user_param = NULL; + player->video_stream_prerolled = false; + + player->audio_decoded_cb = NULL; + player->audio_decoded_cb_user_param = NULL; + player->audio_extract_opt = MM_PLAYER_AUDIO_EXTRACT_DEFAULT; + + 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, 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) { + 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 (player->attrs) { - mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri); - LOGD("restore original uri = %s", original_uri); - - if (mm_attrs_commit_all(player->attrs)) - LOGE("failed to commit the original uri."); - } + if (!original_uri) + LOGW("failed to get original uri info"); - 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); - player->uri_info.uri_list = NULL; + mm_player_set_attribute((MMHandleType)player, NULL, "profile_uri", + original_uri, (original_uri) ? strlen(original_uri) : (0), NULL); + MMPLAYER_FREEIF(original_uri); } /* clear the audio stream buffer list */ @@ -7654,14 +7939,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(); } @@ -7750,7 +8038,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); } @@ -7767,22 +8055,20 @@ __mmplayer_release_signal_connection(mmplayer_t *player, mmplayer_signal_type_e } int -_mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay) +_mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, int wl_surface_id) { mmplayer_t *player = 0; int prev_display_surface_type = 0; - void *prev_display_overlay = NULL; MMPLAYER_FENTER(); MMPLAYER_RETURN_VAL_IF_FAIL(handle, MM_ERROR_COMMON_INVALID_ARGUMENT); - MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT); player = MM_PLAYER_CAST(handle); /* check video sinkbin is created */ - if (__mmplayer_video_param_check_video_sink_bin(player) == MM_ERROR_NONE) { - LOGE("Videosink is already created"); + if (_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_NUM)) { + LOGW("Videosink is already created"); return MM_ERROR_NONE; } @@ -7797,7 +8083,6 @@ _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_typ /* load previous attributes */ if (player->attrs) { mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &prev_display_surface_type); - mm_attrs_get_data_by_name(player->attrs, "display_overlay", &prev_display_overlay); LOGD("[0: Video surface, 4: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type); if (prev_display_surface_type == surface_type) { LOGD("incoming display surface type is same as previous one, do nothing.."); @@ -7812,13 +8097,8 @@ _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_typ /* videobin is not created yet, so we just set attributes related to display surface */ LOGD("store display attribute for given surface type(%d)", surface_type); - mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type); - mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay)); - if (mm_attrs_commit_all(player->attrs)) { - LOGE("failed to commit attribute"); - MMPLAYER_FLEAVE(); - return MM_ERROR_PLAYER_INTERNAL; - } + mm_player_set_attribute(handle, NULL, "display_surface_type", surface_type, + "display_overlay", wl_surface_id, NULL); MMPLAYER_FLEAVE(); return MM_ERROR_NONE; @@ -7936,7 +8216,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; @@ -8001,16 +8281,16 @@ __mmplayer_change_external_subtitle_language(mmplayer_t *player, const char *fil goto EXIT; } - LOGD("old subtitle file path is [%s]", subtitle_uri); - LOGD("new subtitle file path is [%s]", filepath); + SECURE_LOGD("old subtitle file path is [%s]", subtitle_uri); + SECURE_LOGD("new subtitle file path is [%s]", filepath); if (!strcmp(filepath, subtitle_uri)) { - LOGD("No need to swtich subtitle, as input filepath is same as current filepath"); + LOGD("subtitle path is not changed"); goto EXIT; } else { - mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath); - if (mm_attrs_commit_all(player->attrs)) { - LOGE("failed to commit."); + if (mm_player_set_attribute((MMHandleType)player, NULL, + "subtitle_uri", filepath, strlen(filepath), NULL) != MM_ERROR_NONE) { + LOGE("failed to set attribute"); goto EXIT; } } @@ -8087,9 +8367,9 @@ _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char *filepath) if (!player->pipeline) { /* IDLE state */ - mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath); - if (mm_attrs_commit_all(player->attrs)) { - LOGE("failed to commit"); /* subtitle path will not be created */ + if (mm_player_set_attribute(hplayer, NULL, "subtitle_uri", filepath, + (filepath)?(strlen(filepath)):(0), NULL) != MM_ERROR_NONE) { + LOGE("failed to set attribute"); return MM_ERROR_PLAYER_INTERNAL; } } else { @@ -8098,13 +8378,13 @@ _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char *filepath) MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT); if (!__mmplayer_check_subtitle(player)) { - mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath); - if (mm_attrs_commit_all(player->attrs)) { - LOGE("failed to commit"); + if (mm_player_set_attribute(hplayer, NULL, "subtitle_uri", + filepath, strlen(filepath), NULL) != MM_ERROR_NONE) { + LOGE("failed to set attribute"); return MM_ERROR_PLAYER_INTERNAL; } - if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player)) { + if (__mmplayer_gst_create_text_pipeline(player) != MM_ERROR_NONE) { LOGE("fail to create text pipeline"); return MM_ERROR_PLAYER_INTERNAL; } @@ -8131,6 +8411,51 @@ _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char *filepath) } static int +__mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int index) +{ + guint active_idx = 0; + GstStream *stream = NULL; + GList *streams = NULL; + 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 */ + 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)); + 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); + } + } + } + } + + 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); + } + + MMPLAYER_FLEAVE(); + return MM_ERROR_NONE; +} + +static int __mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_type_e type, int index) { int result = MM_ERROR_NONE; @@ -8166,7 +8491,7 @@ __mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_type_e type, i goto EXIT; } - total_track_num = player->selector[type].total_track_num; + total_track_num = player->track[type].total_track_num; if (total_track_num <= 0) { result = MM_ERROR_PLAYER_NO_OP; LOGD("Language list is not available"); @@ -8206,7 +8531,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); @@ -8223,7 +8551,6 @@ _mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type gint current_active_index = 0; GstState current_state = GST_STATE_VOID_PENDING; - GstEvent *event = NULL; gint64 time = 0; MMPLAYER_FENTER(); @@ -8234,13 +8561,13 @@ _mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type if (!player->pipeline) { LOGE("Track %d pre setting -> %d", type, index); - player->selector[type].active_pad_index = index; + player->track[type].active_track_index = index; goto EXIT; } mainbin = player->pipeline->mainbin; - current_active_index = player->selector[type].active_pad_index; + current_active_index = player->track[type].active_track_index; /*If index is same as running index no need to change the pad*/ if (current_active_index == index) @@ -8254,27 +8581,34 @@ _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; } - result = __mmplayer_change_selector_pad(player, type, index); + if (MMPLAYER_USE_DECODEBIN(player)) + result = __mmplayer_change_selector_pad(player, type, index); + else + result = __mmplayer_switch_stream(player, type, index); + if (result != MM_ERROR_NONE) { - LOGE("change selector pad error"); + LOGE("failed to change track"); goto EXIT; } - player->selector[type].active_pad_index = index; + player->track[type].active_track_index = index; - if (current_state == GST_STATE_PLAYING) { - event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME, - (GstSeekFlags)(GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), - GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1); - if (event) { - _mmplayer_gst_send_event_to_sink(player, event); - } else { - result = MM_ERROR_PLAYER_INTERNAL; - goto EXIT; + if (MMPLAYER_USE_DECODEBIN(player)) { + GstEvent *event = NULL; + if (current_state == GST_STATE_PLAYING) { + event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME, + (GstSeekFlags)(GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), + GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1); + if (event) { + _mmplayer_gst_send_event_to_sink(player, event); + } else { + result = MM_ERROR_PLAYER_INTERNAL; + goto EXIT; + } } } @@ -8355,9 +8689,9 @@ __mmplayer_dump_buffer_probe_cb(GstPad *pad, GstPadProbeInfo *info, gpointer u_ MMPLAYER_RETURN_VAL_IF_FAIL(dump_data, GST_PAD_PROBE_PASS); gst_buffer_map(buffer, &probe_info, GST_MAP_READ); - -// LOGD("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer))); - +#ifdef __DEBUG__ + LOGD("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer))); +#endif fwrite(probe_info.data, 1, probe_info.size , dump_data); gst_buffer_unmap(buffer, &probe_info); @@ -8412,7 +8746,9 @@ _mm_player_video_stream_internal_buffer_unref(void *buffer) { MMPLAYER_FENTER(); if (buffer) { - // LOGD("unref internal gst buffer %p", buffer); +#ifdef __DEBUG__ + LOGD("unref internal gst buffer %p", buffer); +#endif gst_buffer_unref((GstBuffer *)buffer); buffer = NULL; } @@ -8440,25 +8776,6 @@ _mmplayer_get_timeout(MMHandleType hplayer, int *timeout) return MM_ERROR_NONE; } -int -_mmplayer_get_num_of_video_out_buffers(MMHandleType hplayer, int *num, int *extra_num) -{ - mmplayer_t *player = (mmplayer_t *)hplayer; - - MMPLAYER_FENTER(); - - MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); - MMPLAYER_RETURN_VAL_IF_FAIL(num && extra_num, MM_ERROR_COMMON_INVALID_ARGUMENT); - - *num = player->video_num_buffers; - *extra_num = player->video_extra_num_buffers; - - LOGD("state %d, num %d(%d)", MMPLAYER_CURRENT_STATE(player), *num, *extra_num); - - MMPLAYER_FLEAVE(); - return MM_ERROR_NONE; -} - static void __mmplayer_initialize_storage_info(mmplayer_t *player, mmplayer_path_type_e path_type) { @@ -8497,7 +8814,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) @@ -8637,61 +8954,71 @@ _mmplayer_get_streaming_buffering_time(MMHandleType hplayer, int *prebuffer_ms, } int -_mmplayer_set_codec_type(MMHandleType hplayer, mmplayer_stream_type_e stream_type, mmplayer_video_codec_type_e codec_type) +_mmplayer_set_codec_type(MMHandleType hplayer, mmplayer_stream_type_e stream_type, mmplayer_codec_type_e codec_type) { #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); - MMHandleType attrs = 0; + 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 */ - 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("update %s codec_type to %d", attr_name, codec_type); + LOGD("default setting: [%s][%s][h:%s][s:%s]", attr_name, default_type, element_hw, element_sw); - attrs = MMPLAYER_GET_ATTRS(player); - mm_attrs_set_int_by_name(attrs, attr_name, codec_type); + 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; + } - if (mm_attrs_commit_all(player->attrs)) { - LOGE("failed to commit codec_type attributes"); - return MM_ERROR_PLAYER_INTERNAL; + 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); + mm_player_set_attribute(hplayer, NULL, attr_name, codec_type, NULL); + MMPLAYER_FLEAVE(); return MM_ERROR_NONE; } @@ -8770,7 +9097,7 @@ _mmplayer_set_video_roi_area(MMHandleType hplayer, double scale_x, double scale_ { mmplayer_t *player = (mmplayer_t *)hplayer; MMHandleType attrs = 0; - void *handle = NULL; + int handle = 0; int ret = MM_ERROR_NONE; MMPLAYER_FENTER(); @@ -8780,7 +9107,7 @@ _mmplayer_set_video_roi_area(MMHandleType hplayer, double scale_x, double scale_ attrs = MMPLAYER_GET_ATTRS(player); MMPLAYER_RETURN_VAL_IF_FAIL(attrs, MM_ERROR_PLAYER_INTERNAL); - mm_attrs_get_data_by_name(attrs, "display_overlay", &handle); + mm_attrs_get_int_by_name(attrs, "display_overlay", &handle); if (!handle) { LOGE("Display handle is NULL, after setting window handle, set video roi area"); return MM_ERROR_PLAYER_INTERNAL; @@ -8792,7 +9119,7 @@ _mmplayer_set_video_roi_area(MMHandleType hplayer, double scale_x, double scale_ player->video_roi.scale_height = scale_height; /* check video sinkbin is created */ - if (__mmplayer_video_param_check_video_sink_bin(player) != MM_ERROR_NONE) + if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_NUM)) return MM_ERROR_NONE; if (!gst_video_overlay_set_video_roi_area( @@ -8830,6 +9157,93 @@ _mmplayer_get_video_roi_area(MMHandleType hplayer, double *scale_x, double *scal return ret; } +int +_mmplayer_set_client_pid(MMHandleType hplayer, int pid) +{ + mmplayer_t *player = (mmplayer_t *)hplayer; + + MMPLAYER_FENTER(); + + MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + player->client_pid = pid; + + LOGD("client pid[%d] %p", pid, player); + + MMPLAYER_FLEAVE(); + + return MM_ERROR_NONE; +} + +int +_mmplayer_is_audio_control_available(MMHandleType hplayer, mmplayer_audio_control_opt_e opt, bool *available) +{ + mmplayer_t *player = (mmplayer_t *)hplayer; + mmplayer_codec_type_e codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT; + enum audio_element_id elem_id = MMPLAYER_A_NUM; + + MMPLAYER_FENTER(); + + MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + MMPLAYER_RETURN_VAL_IF_FAIL(available, MM_ERROR_INVALID_ARGUMENT); + + *available = true; + mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, (int *)&codec_type); + + LOGD("current state %d, codec_type %d", MMPLAYER_CURRENT_STATE(player), codec_type); + + if (codec_type == MM_PLAYER_CODEC_TYPE_SW) + return MM_ERROR_NONE; + + /* in case of audio codec default type is HW */ + switch(opt) { + case MM_PLAYER_AUDIO_CONTROL_OPT_EFFECT: + if (player->ini.support_audio_effect) + return MM_ERROR_NONE; + elem_id = MMPLAYER_A_FILTER; + break; + case MM_PLAYER_AUDIO_CONTROL_OPT_REPLAYGAIN: + if (player->ini.support_replaygain_control) + return MM_ERROR_NONE; + elem_id = MMPLAYER_A_RGVOL; + break; + case MM_PLAYER_AUDIO_CONTROL_OPT_PITCH: + if (player->ini.support_pitch_control) + return MM_ERROR_NONE; + elem_id = MMPLAYER_A_PITCH; + break; + case MM_PLAYER_AUDIO_CONTROL_OPT_PCM_EXPORTING: + if (player->ini.support_audio_effect) + return MM_ERROR_NONE; + break; + /* default case handling is not required */ + } + + if (MMPLAYER_CURRENT_STATE(player) < MM_PLAYER_STATE_READY) { + LOGW("audio control option [%d] is not available", opt); + *available = false; + } else { + /* setting pcm exporting option is allowed before READY state */ + if (opt == MM_PLAYER_AUDIO_CONTROL_OPT_PCM_EXPORTING) + return MM_ERROR_PLAYER_INVALID_STATE; + + /* check whether the audio filter exist or not after READY state, + because the sw codec could be added during auto-plugging in some cases */ + if (!player->pipeline || + !player->pipeline->audiobin || + !player->pipeline->audiobin[elem_id].gst) { + LOGW("there is no audio elem [%d]", elem_id); + *available = false; + } + } + + LOGD("audio control opt %d, available %d", opt, *available); + + MMPLAYER_FLEAVE(); + + return MM_ERROR_NONE; +} + static gboolean __mmplayer_update_duration_value(mmplayer_t *player) { @@ -8904,10 +9318,11 @@ __mmplayer_update_audio_attrs(mmplayer_t *player, MMHandleType attrs) mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate); gst_structure_get_int(p, "rate", &samplerate); - mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate); - gst_structure_get_int(p, "channels", &channels); - mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels); + + mm_player_set_attribute((MMHandleType)player, NULL, + "content_audio_samplerate", samplerate, + "content_audio_channels", channels, NULL); SECURE_LOGD("samplerate : %d channels : %d", samplerate, channels); @@ -8945,17 +9360,17 @@ __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; } p = gst_caps_get_structure(caps_v, 0); gst_structure_get_int(p, "width", &width); - mm_attrs_set_int_by_name(attrs, "content_video_width", width); - gst_structure_get_int(p, "height", &height); - mm_attrs_set_int_by_name(attrs, "content_video_height", height); + + mm_player_set_attribute((MMHandleType)player, NULL, + MM_PLAYER_VIDEO_WIDTH, width, MM_PLAYER_VIDEO_HEIGHT, height, NULL); gst_structure_get_fraction(p, "framerate", &tmpNu, &tmpDe); @@ -8965,7 +9380,8 @@ __mmplayer_update_video_attrs(mmplayer_t *player, MMHandleType attrs) gst_object_unref(pad); if (tmpDe > 0) { - mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe); + mm_player_set_attribute((MMHandleType)player, NULL, + MM_PLAYER_VIDEO_FPS, (tmpNu/tmpDe), NULL); SECURE_LOGD("fps : %d", tmpNu / tmpDe); } @@ -8980,7 +9396,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; @@ -9002,9 +9418,10 @@ __mmplayer_update_bitrate_attrs(mmplayer_t *player, MMHandleType attrs) msec_dur = GST_TIME_AS_MSECONDS(player->duration); if (msec_dur > 0) { bitrate = data_size * 8 * 1000 / msec_dur; - SECURE_LOGD("file size : %"G_GUINT64_FORMAT", video bitrate = %"G_GUINT64_FORMAT, data_size, bitrate); - mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate); - + SECURE_LOGD("file size : %"G_GUINT64_FORMAT + ", video bitrate = %"G_GUINT64_FORMAT, data_size, bitrate); + mm_player_set_attribute((MMHandleType)player, NULL, + MM_PLAYER_VIDEO_BITRATE, (int)bitrate, NULL); ret = TRUE; } else { LOGD("player duration is less than 0"); @@ -9013,7 +9430,8 @@ __mmplayer_update_bitrate_attrs(mmplayer_t *player, MMHandleType attrs) if (MMPLAYER_IS_RTSP_STREAMING(player)) { if (player->total_bitrate) { - mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate); + mm_player_set_attribute((MMHandleType)player, NULL, + MM_PLAYER_VIDEO_BITRATE, player->total_bitrate, NULL); ret = TRUE; } } @@ -9123,11 +9541,12 @@ __mmplayer_set_file_uri(mmplayer_parse_profile_t *data, const char *uri) /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */ if (ret == MM_ERROR_NONE) { - g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", path); if (_mmplayer_is_sdp_file(path)) { LOGD("uri is actually a file but it's sdp file. giving it to rtspsrc"); + g_snprintf(data->uri, MM_MAX_URL_LEN, "rtsp-sdp://%s", path); data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP; } else { + g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", path); data->uri_type = MM_PLAYER_URI_TYPE_FILE; } } else if (ret == MM_ERROR_PLAYER_PERMISSION_DENIED) { @@ -9160,7 +9579,9 @@ __mmplayer_create_stream_from_pad(GstPad *pad) return NULL; } - /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */ +#ifdef __DEBUG__ + MMPLAYER_LOG_GST_CAPS_TYPE(caps); +#endif structure = gst_caps_get_structure(caps, 0); gst_structure_get_int(structure, "width", &width); gst_structure_get_int(structure, "height", &height); @@ -9369,7 +9790,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); @@ -9399,10 +9820,9 @@ __mmplayer_set_playing_state(mmplayer_t *player) else audio_codec = "unknown"; - mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec); - - if (mm_attrs_commit_all(player->attrs)) - LOGE("failed to update attributes"); + if (mm_player_set_attribute((MMHandleType)player, NULL, + "content_audio_codec", audio_codec, strlen(audio_codec), NULL) != MM_ERROR_NONE) + LOGE("failed to set attribute"); LOGD("set audio codec type with caps"); }