From: Eunhae Choi Date: Mon, 27 Aug 2018 10:22:06 +0000 (+0900) Subject: [0.6.127] refactoring about gapless playback X-Git-Tag: submit/tizen/20180829.053131~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=70700c53d0c488f555608bc91d535bca9be73820;p=platform%2Fcore%2Fmultimedia%2Flibmm-player.git [0.6.127] refactoring about gapless playback Change-Id: I0828c0c4c1fac6124dcf0bc5c541ed6d475f7b19 --- diff --git a/packaging/libmm-player.spec b/packaging/libmm-player.spec index 75cb815..9f01b14 100644 --- a/packaging/libmm-player.spec +++ b/packaging/libmm-player.spec @@ -1,6 +1,6 @@ Name: libmm-player Summary: Multimedia Framework Player Library -Version: 0.6.126 +Version: 0.6.127 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index 90ea951..2e5b177 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -972,6 +972,66 @@ __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer dat return GST_PAD_PROBE_OK; } +static void +__mmplayer_gst_selector_update_start_time(mm_player_t* player, MMPlayerTrackType stream_type) +{ + gint64 stop_running_time = 0; + gint64 position_running_time = 0; + gint64 position = 0; + gint idx = 0; + + 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); */ + continue; + } + + if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].stop)) { + stop_running_time = + gst_segment_to_running_time(&player->gapless.segment[idx], + GST_FORMAT_TIME, player->gapless.segment[idx].stop); + } else if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].duration)) { + stop_running_time = + gst_segment_to_running_time(&player->gapless.segment[idx], + GST_FORMAT_TIME, player->gapless.segment[idx].duration); + } else { + LOGD("duration: %"GST_TIME_FORMAT, GST_TIME_ARGS(player->duration)); + stop_running_time = + gst_segment_to_running_time(&player->gapless.segment[idx], + GST_FORMAT_TIME, player->duration); + } + + position_running_time = + gst_segment_to_running_time(&player->gapless.segment[idx], + GST_FORMAT_TIME, player->gapless.segment[idx].position); + + LOGD("[type:%d] time info %" GST_TIME_FORMAT " , %" + GST_TIME_FORMAT" , %" GST_TIME_FORMAT, + idx, + GST_TIME_ARGS(stop_running_time), + GST_TIME_ARGS(position_running_time), + GST_TIME_ARGS(gst_segment_to_running_time(&player->gapless.segment[idx], + GST_FORMAT_TIME, player->gapless.segment[idx].start))); + + position_running_time = MAX(position_running_time, stop_running_time); + position_running_time -= gst_segment_to_running_time(&player->gapless.segment[idx], + GST_FORMAT_TIME, player->gapless.segment[idx].start); + position_running_time = MAX(0, position_running_time); + position = MAX(position, position_running_time); + } + + if (position != 0) { + LOGD("[%d]GST_EVENT_STREAM_START: start_time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT, + stream_type, GST_TIME_ARGS(player->gapless.start_time[stream_type]), + GST_TIME_ARGS(player->gapless.start_time[stream_type] + position)); + + player->gapless.start_time[stream_type] += position; + } + + return; +} + static GstPadProbeReturn __mmplayer_gst_selector_event_probe(GstPad * pad, GstPadProbeInfo * info, gpointer data) { @@ -983,16 +1043,15 @@ __mmplayer_gst_selector_event_probe(GstPad * pad, GstPadProbeInfo * info, gpoint const gchar* name = NULL; MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_VIDEO; - - if (GST_EVENT_IS_DOWNSTREAM(event)) { - 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) - return ret; - } else if (GST_EVENT_IS_UPSTREAM(event)) { - if (GST_EVENT_TYPE(event) != GST_EVENT_QOS) - return ret; + 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) { + return ret; + } else if (GST_EVENT_IS_UPSTREAM(event) && + GST_EVENT_TYPE(event) != GST_EVENT_QOS) { + return ret; } caps = gst_pad_query_caps(pad, NULL); @@ -1035,59 +1094,7 @@ __mmplayer_gst_selector_event_probe(GstPad * pad, GstPadProbeInfo * info, gpoint } case GST_EVENT_STREAM_START: { - gint64 stop_running_time = 0; - gint64 position_running_time = 0; - gint64 position = 0; - gint idx = 0; - - 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); */ - continue; - } - - if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].stop)) { - stop_running_time = - gst_segment_to_running_time(&player->gapless.segment[idx], - GST_FORMAT_TIME, player->gapless.segment[idx].stop); - } else if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].duration)) { - stop_running_time = - gst_segment_to_running_time(&player->gapless.segment[idx], - GST_FORMAT_TIME, player->gapless.segment[idx].duration); - } else { - LOGD("duration: %"GST_TIME_FORMAT, GST_TIME_ARGS(player->duration)); - stop_running_time = - gst_segment_to_running_time(&player->gapless.segment[idx], - GST_FORMAT_TIME, player->duration); - } - - position_running_time = - gst_segment_to_running_time(&player->gapless.segment[idx], - GST_FORMAT_TIME, player->gapless.segment[idx].position); - - LOGD("[type:%d] time info %" GST_TIME_FORMAT " , %" - GST_TIME_FORMAT" , %" GST_TIME_FORMAT, - idx, - GST_TIME_ARGS(stop_running_time), - GST_TIME_ARGS(position_running_time), - GST_TIME_ARGS(gst_segment_to_running_time(&player->gapless.segment[idx], - GST_FORMAT_TIME, player->gapless.segment[idx].start))); - - position_running_time = MAX(position_running_time, stop_running_time); - position_running_time -= gst_segment_to_running_time(&player->gapless.segment[idx], - GST_FORMAT_TIME, player->gapless.segment[idx].start); - position_running_time = MAX(0, position_running_time); - position = MAX(position, position_running_time); - } - - if (position != 0) { - LOGD("[%d]GST_EVENT_STREAM_START: start_time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT, - stream_type, GST_TIME_ARGS(player->gapless.start_time[stream_type]), - GST_TIME_ARGS(player->gapless.start_time[stream_type] + position)); - - player->gapless.start_time[stream_type] += position; - } + __mmplayer_gst_selector_update_start_time(player, stream_type); break; } case GST_EVENT_FLUSH_STOP: @@ -1105,30 +1112,32 @@ __mmplayer_gst_selector_event_probe(GstPad * pad, GstPadProbeInfo * info, gpoint LOGD("[%d] GST_EVENT_SEGMENT", stream_type); gst_event_copy_segment(event, &segment); - if (segment.format == GST_FORMAT_TIME) { - LOGD("segment base:%" GST_TIME_FORMAT ", offset:%" GST_TIME_FORMAT - ", start:%" GST_TIME_FORMAT ", stop: %" GST_TIME_FORMAT - ", time: %" GST_TIME_FORMAT ", pos: %" GST_TIME_FORMAT ", dur: %" GST_TIME_FORMAT, - GST_TIME_ARGS(segment.base), GST_TIME_ARGS(segment.offset), - GST_TIME_ARGS(segment.start), GST_TIME_ARGS(segment.stop), - GST_TIME_ARGS(segment.time), GST_TIME_ARGS(segment.position), GST_TIME_ARGS(segment.duration)); + if (segment.format != GST_FORMAT_TIME) + break; - /* keep the all the segment ev to cover the seeking */ - gst_segment_copy_into(&segment, &player->gapless.segment[stream_type]); - player->gapless.update_segment[stream_type] = TRUE; + LOGD("segment base:%" GST_TIME_FORMAT ", offset:%" GST_TIME_FORMAT + ", start:%" GST_TIME_FORMAT ", stop: %" GST_TIME_FORMAT + ", time: %" GST_TIME_FORMAT ", pos: %" GST_TIME_FORMAT ", dur: %" GST_TIME_FORMAT, + GST_TIME_ARGS(segment.base), GST_TIME_ARGS(segment.offset), + GST_TIME_ARGS(segment.start), GST_TIME_ARGS(segment.stop), + GST_TIME_ARGS(segment.time), GST_TIME_ARGS(segment.position), GST_TIME_ARGS(segment.duration)); - if (!player->gapless.running) - break; + /* keep the all the segment ev to cover the seeking */ + gst_segment_copy_into(&segment, &player->gapless.segment[stream_type]); + player->gapless.update_segment[stream_type] = TRUE; - player->gapless.segment[stream_type].base = player->gapless.start_time[stream_type]; + if (!player->gapless.running) + break; - LOGD("[%d] new base: %" GST_TIME_FORMAT, stream_type, GST_TIME_ARGS(player->gapless.segment[stream_type].base)); + player->gapless.segment[stream_type].base = player->gapless.start_time[stream_type]; + + LOGD("[%d] new base: %" GST_TIME_FORMAT, stream_type, GST_TIME_ARGS(player->gapless.segment[stream_type].base)); + + tmpev = gst_event_new_segment(&player->gapless.segment[stream_type]); + gst_event_set_seqnum(tmpev, gst_event_get_seqnum(event)); + gst_event_unref(event); + GST_PAD_PROBE_INFO_DATA(info) = tmpev; - tmpev = gst_event_new_segment(&player->gapless.segment[stream_type]); - gst_event_set_seqnum(tmpev, gst_event_get_seqnum(event)); - gst_event_unref(event); - GST_PAD_PROBE_INFO_DATA(info) = tmpev; - } break; } case GST_EVENT_QOS: @@ -7216,23 +7225,98 @@ __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-complete"); } +static int +__mmplayer_check_profile(void) +{ + char *profileName; + static int profile_tv = -1; + + if (__builtin_expect(profile_tv != -1, 1)) + return profile_tv; + + system_info_get_platform_string("http://tizen.org/feature/profile", &profileName); + switch (*profileName) { + case 't': + case 'T': + profile_tv = 1; + break; + default: + profile_tv = 0; + break; + } + free(profileName); + + return profile_tv; +} + static gboolean -__mmplayer_verify_next_play_path(mm_player_t *player) +__mmplayer_get_next_uri(mm_player_t *player) { - MMHandleType attrs = 0; MMPlayerParseProfile profile; - gint uri_idx = 0, check_cnt = 0; + gint uri_idx = 0; + guint num_of_list = 0; char *uri = NULL; + + num_of_list = g_list_length(player->uri_info.uri_list); + uri_idx = player->uri_info.uri_idx; + + LOGD("num of uri list = %d, current uri idx %d", num_of_list, uri_idx); + for (uri_idx++; uri_idx < num_of_list; uri_idx++) { + uri = g_list_nth_data(player->uri_info.uri_list, uri_idx); + if (uri == NULL) { + LOGW("next uri does not exist"); + continue; + } + + if (__mmplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE) { + LOGE("failed to parse profile"); + continue; + } + + if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) && + (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP)) { + LOGW("uri type is not supported(%d)", profile.uri_type); + continue; + } + + LOGD("success to find next uri %d", uri_idx); + break; + } + + if (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 (mmf_attrs_commit(player->attrs)) { + LOGE("failed to commit"); + return FALSE; + } + + SECURE_LOGD("next playback uri: %s", uri); + return TRUE; +} + +static gboolean +__mmplayer_verify_next_play_path(mm_player_t *player) +{ +#define REPEAT_COUNT_INFINITELY -1 +#define REPEAT_COUNT_MIN 2 + + MMHandleType attrs = 0; gint mode = MM_PLAYER_PD_MODE_NONE; gint video = 0; gint count = 0; gint gapless = 0; guint num_of_list = 0; - static int profile_tv = -1; + int profile_tv = -1; MMPLAYER_FENTER(); - LOGD("checking for gapless play"); + LOGD("checking for next play option"); if (player->pipeline->textbin) { LOGE("subtitle path is enabled. gapless play is not supported.\n"); @@ -7247,20 +7331,8 @@ __mmplayer_verify_next_play_path(mm_player_t *player) mm_attrs_get_int_by_name(attrs, "content_video_found", &video); - if (__builtin_expect(profile_tv == -1, 0)) { - char *profileName; - system_info_get_platform_string("http://tizen.org/feature/profile", &profileName); - switch (*profileName) { - case 't': - case 'T': - profile_tv = 1; - break; - default: - profile_tv = 0; - } - free(profileName); - } /* gapless playback is not supported in case of video at TV profile. */ + profile_tv = __mmplayer_check_profile(); if (profile_tv && video) { LOGW("not support video gapless playback"); goto ERROR; @@ -7274,117 +7346,52 @@ __mmplayer_verify_next_play_path(mm_player_t *player) } if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE) - LOGE("can not get play count\n"); + LOGE("failed to get play count"); if (mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless) != MM_ERROR_NONE) - LOGE("can not get gapless mode\n"); - - if (video && !gapless) { - LOGW("not enabled video gapless playback"); - goto ERROR; - } - - if ((count == -1 || count > 1)) /* enable gapless when looping or repeat */ - gapless = 1; + LOGE("failed to get gapless mode"); - if (!gapless) { - LOGW("gapless is disabled\n"); /* FIXME: playlist(without gapless) is not implemented. */ + /* check repeat count in case of audio */ + if (!gapless && + (video || (count != REPEAT_COUNT_INFINITELY && count < REPEAT_COUNT_MIN))) { + LOGW("gapless is disabled"); goto ERROR; } num_of_list = g_list_length(player->uri_info.uri_list); - LOGD("repeat count = %d, num_of_list = %d\n", count, num_of_list); + LOGD("repeat count = %d, num_of_list = %d", count, num_of_list); if (num_of_list == 0) { - if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE) { - LOGE("can not get profile_uri\n"); - goto ERROR; - } + /* audio looping path */ + if (count >= REPEAT_COUNT_MIN) { + /* decrease play count */ + /* we succeeded to rewind. update play count and then wait for next EOS */ + count--; - if (!uri) { - LOGE("uri list is empty.\n"); - goto ERROR; - } - - player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri)); - LOGD("add original path : %s ", uri); - - num_of_list = 1; - uri = NULL; - } - - uri_idx = player->uri_info.uri_idx; - - while (TRUE) { - check_cnt++; + mm_attrs_set_int_by_name(attrs, "profile_play_count", count); - if (check_cnt > num_of_list) { - LOGE("there is no valid uri."); + /* commit attribute */ + if (mmf_attrs_commit(attrs)) + LOGE("failed to commit attribute"); + } else if (count != REPEAT_COUNT_INFINITELY) { + LOGD("there is no next uri and no repeat"); goto ERROR; } - LOGD("uri idx : %d / %d\n", uri_idx, num_of_list); - - if (uri_idx < num_of_list-1) { - uri_idx++; - } else { - if ((count <= 1) && (count != -1)) { - LOGD("no repeat."); - goto ERROR; - } else if (count > 1) { - /* 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 (mmf_attrs_commit(attrs)) - LOGE("failed to commit attribute\n"); - } - - /* count < 0 : repeat continually */ - uri_idx = 0; - } - - uri = g_list_nth_data(player->uri_info.uri_list, uri_idx); - LOGD("uri idx : %d, uri = %s\n", uri_idx, uri); - - if (uri == NULL) { - LOGW("next uri does not exist\n"); - continue; - } - - if (__mmplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE) { - LOGE("failed to parse profile\n"); - continue; - } - - if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) && - (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP)) { - LOGW("uri type is not supported(%d).", profile.uri_type); - continue; + LOGD("looping cnt %d", count); + } else { + /* gapless playback path */ + if (!__mmplayer_get_next_uri(player)) { + LOGE("failed to get next uri"); + goto ERROR; } - - break; } - player->uri_info.uri_idx = uri_idx; - mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri); - - if (mmf_attrs_commit(player->attrs)) { - LOGE("failed to commit.\n"); - goto ERROR; - } - - LOGD("next uri %s(%d)\n", uri, uri_idx); - return TRUE; ERROR: - - LOGE("unable to play next path. EOS will be posted soon.\n"); + LOGE("unable to play next path. EOS will be posted soon"); return FALSE; }