[0.6.127] refactoring about gapless playback 70/187670/3
authorEunhae Choi <eunhae1.choi@samsung.com>
Mon, 27 Aug 2018 10:22:06 +0000 (19:22 +0900)
committerEunhae Choi <eunhae1.choi@samsung.com>
Wed, 29 Aug 2018 04:23:39 +0000 (13:23 +0900)
Change-Id: I0828c0c4c1fac6124dcf0bc5c541ed6d475f7b19

packaging/libmm-player.spec
src/mm_player_priv.c

index 75cb815..9f01b14 100644 (file)
@@ -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
index 90ea951..2e5b177 100644 (file)
@@ -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;
 }