MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
- __mmplayer_gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_nsec); /* to update player->last_position */
+ __mmplayer_gst_get_position(player, &pos_nsec); /* to update player->last_position */
attrs = MMPLAYER_GET_ATTRS(player);
if (!attrs) {
if (count == -1) {
gint ret_value = 0;
- ret_value = __mmplayer_gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
+ ret_value = __mmplayer_gst_set_position(player, 0, TRUE);
if (ret_value != MM_ERROR_NONE)
LOGE("seeking to 0 failed in repeat play");
} else {
LOGD("trying to play from(%"G_GINT64_FORMAT") pending position\n", player->pending_seek.pos);
- ret = __mmplayer_gst_set_position(player, player->pending_seek.format, player->pending_seek.pos, FALSE);
+ ret = __mmplayer_gst_set_position(player, player->pending_seek.pos, FALSE);
if (MM_ERROR_NONE != ret)
LOGE("failed to seek pending postion. just keep staying current position.\n");
int retVal = MM_ERROR_NONE;
LOGD("trying to play from (%"G_GINT64_FORMAT") pending position", player->pending_seek.pos);
- retVal = __mmplayer_gst_set_position(player, player->pending_seek.format, player->pending_seek.pos, TRUE);
+ retVal = __mmplayer_gst_set_position(player, player->pending_seek.pos, TRUE);
if (MM_ERROR_NONE != retVal)
LOGE("failed to seek pending postion. just keep staying current position.");
return NULL;
}
+static int
+__mmplayer_gst_check_duration(mm_player_t* player, gint64 position)
+{
+ gint64 dur_nsec = 0;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+ if (MMPLAYER_IS_MS_BUFF_SRC(player))
+ return MM_ERROR_NONE;
+
+ /* NOTE : duration cannot be zero except live streaming.
+ * Since some element could have some timing problemn with quering duration, try again.
+ */
+ if (player->duration == 0) {
+ if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec)) {
+ /* For RTSP Streaming , duration is not returned in READY state. So seek to the previous position does not work properly.
+ * Added a patch to postpone the actual seek when state changes to PLAY. Sending a fake SEEK_COMPLETED event to finish the current request. */
+ if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
+ (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
+ player->pending_seek.is_pending = TRUE;
+ player->pending_seek.pos = position;
+ player->seek_state = MMPLAYER_SEEK_NONE;
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
+ return MM_ERROR_PLAYER_NO_OP;
+ } else {
+ player->seek_state = MMPLAYER_SEEK_NONE;
+ return MM_ERROR_PLAYER_SEEK;
+ }
+ }
+ player->duration = dur_nsec;
+ }
+
+ if (player->duration > 0 && player->duration < position) {
+ LOGE("invalid pos %"G_GINT64_FORMAT", dur: %"G_GINT64_FORMAT, position, player->duration);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
+}
+
+static gboolean
+__mmplayer_gst_check_seekable(mm_player_t* player)
+{
+ GstQuery *query = NULL;
+ gboolean seekable = FALSE;
+
+ if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
+ return TRUE;
+ }
+
+ query = gst_query_new_seeking(GST_FORMAT_TIME);
+ if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, query)) {
+ gst_query_parse_seeking(query, NULL, &seekable, NULL, NULL);
+ gst_query_unref(query);
+
+ if (!seekable) {
+ LOGW("non-seekable content");
+ player->seek_state = MMPLAYER_SEEK_NONE;
+ return FALSE;
+ }
+ } else {
+ LOGW("failed to get seeking query");
+ gst_query_unref(query); /* keep seeking operation */
+ }
+
+ return TRUE;
+}
+
+
#if 0
#endif
}
int
-__mmplayer_gst_set_position(mm_player_t* player, int format, gint64 position, gboolean internal_called)
+__mmplayer_gst_set_position(mm_player_t* player, gint64 position, gboolean internal_called)
{
- gint64 dur_nsec = 0;
+ int ret = MM_ERROR_NONE;
gint64 pos_nsec = 0;
- gboolean ret = TRUE;
gboolean accurated = FALSE;
GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
&& MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)
goto PENDING;
- if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
- /* check duration */
- /* NOTE : duration cannot be zero except live streaming.
- * Since some element could have some timing problemn with quering duration, try again.
- */
- if (player->duration == 0) {
- if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec)) {
- /* For RTSP Streaming , duration is not returned in READY state. So seek to the previous position does not work properly.
- * Added a patch to postpone the actual seek when state changes to PLAY. Sending a fake SEEK_COMPLETED event to finish the current request. */
- if ((MMPLAYER_IS_RTSP_STREAMING(player)) && (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
- player->pending_seek.is_pending = TRUE;
- player->pending_seek.format = format;
- player->pending_seek.pos = position;
- player->seek_state = MMPLAYER_SEEK_NONE;
- MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
- return MM_ERROR_NONE;
- } else {
- goto SEEK_ERROR;
- }
- }
- player->duration = dur_nsec;
- }
+ ret = __mmplayer_gst_check_duration(player, position);
+ if (ret != MM_ERROR_NONE) {
+ LOGE("failed to check duration 0x%X", ret);
+ return (ret == MM_ERROR_PLAYER_NO_OP) ? (MM_ERROR_NONE) : (ret);
}
- LOGD("playback rate: %f\n", player->playback_rate);
-
- mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
- if (accurated)
- seek_flags |= GST_SEEK_FLAG_ACCURATE;
- else
- seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
- /* do seek */
- switch (format) {
- case MM_PLAYER_POS_FORMAT_TIME:
- {
- if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
- GstQuery *query = NULL;
- gboolean seekable = FALSE;
-
- /* check position is valid or not */
- if (position > player->duration)
- goto INVALID_ARGS;
-
- query = gst_query_new_seeking(GST_FORMAT_TIME);
- if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, query)) {
- gst_query_parse_seeking(query, NULL, &seekable, NULL, NULL);
- gst_query_unref(query);
-
- if (!seekable) {
- LOGW("non-seekable content");
- player->seek_state = MMPLAYER_SEEK_NONE;
- return MM_ERROR_PLAYER_NO_OP;
- }
- } else {
- LOGW("failed to get seeking query");
- gst_query_unref(query); /* keep seeking operation */
- }
-
- LOGD("seeking to(%"G_GINT64_FORMAT") nsec, duration is %"G_GINT64_FORMAT" nsec\n", position, player->duration);
-
- /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
- But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
- This causes problem is position calculation during normal pause resume scenarios also.
- Currently during seek , we are sending the current position to rtspsrc module for position saving for later use. */
- if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
- (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
- if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
- LOGW("getting current position failed in seek\n");
-
- player->last_position = pos_nsec;
- g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
- }
-
- if (player->seek_state != MMPLAYER_SEEK_NONE) {
- LOGD("not completed seek");
- return MM_ERROR_PLAYER_DOING_SEEK;
- }
- }
-
- if (!internal_called)
- player->seek_state = MMPLAYER_SEEK_IN_PROGRESS;
-
- if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked)) {
- gint64 cur_time = 0;
-
- /* get current position */
- gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_time);
-
- /* flush */
- GstEvent *event = gst_event_new_seek(1.0,
- GST_FORMAT_TIME,
- (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
- GST_SEEK_TYPE_SET, cur_time,
- GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
- if (event)
- __mmplayer_gst_send_event_to_sink(player, event);
-
- if (!MMPLAYER_IS_RTSP_STREAMING(player))
- __mmplayer_gst_pause(player, FALSE);
- }
+ if (!__mmplayer_gst_check_seekable(player))
+ return MM_ERROR_PLAYER_NO_OP;
- pos_nsec = position;
+ LOGD("seeking to(%"G_GINT64_FORMAT") nsec, rate: %f, dur: %"G_GINT64_FORMAT" nsec",
+ position, player->playback_rate, player->duration);
- /* rtsp streaming case, there is no sink after READY TO PAUSE state(no preroll state change).
- that's why set position through property. */
- if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
- (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) &&
- (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY) &&
- (!player->videodec_linked) && (!player->audiodec_linked)) {
+ /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
+ But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
+ This causes problem is position calculation during normal pause resume scenarios also.
+ Currently during seek , we are sending the current position to rtspsrc module for position saving for later use. */
+ if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
+ (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
+ if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
+ LOGW("getting current position failed in seek");
- g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "pending-start-position", pos_nsec, NULL);
- LOGD("[%s] set position =%"GST_TIME_FORMAT,
- GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), GST_TIME_ARGS(pos_nsec));
- player->seek_state = MMPLAYER_SEEK_NONE;
- MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
- } else {
- ret = __mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
- GST_FORMAT_TIME, seek_flags,
- GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
- }
+ player->last_position = pos_nsec;
+ g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
+ }
- if (!ret) {
- LOGE("failed to set position.");
- goto SEEK_ERROR;
- }
+ if (player->seek_state != MMPLAYER_SEEK_NONE) {
+ LOGD("not completed seek");
+ return MM_ERROR_PLAYER_DOING_SEEK;
}
- break;
- case MM_PLAYER_POS_FORMAT_PERCENT:
- {
- LOGD("seeking to %"G_GINT64_FORMAT"%%", position);
+ if (!internal_called)
+ player->seek_state = MMPLAYER_SEEK_IN_PROGRESS;
- if (player->seek_state != MMPLAYER_SEEK_NONE) {
- LOGD("not completed seek");
- return MM_ERROR_PLAYER_DOING_SEEK;
- }
+ /* rtsp streaming case, there is no sink after READY TO PAUSE state(no preroll state change).
+ that's why set position through property. */
+ if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
+ (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) &&
+ (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY) &&
+ (!player->videodec_linked) && (!player->audiodec_linked)) {
- if (!internal_called)
- player->seek_state = MMPLAYER_SEEK_IN_PROGRESS;
+ LOGD("[%s] set position =%"GST_TIME_FORMAT,
+ GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), GST_TIME_ARGS(position));
- /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
- pos_nsec = (gint64)((position * player->duration) / 100);
- ret = __mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
+ g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "pending-start-position", position, NULL);
+ player->seek_state = MMPLAYER_SEEK_NONE;
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
+ } else {
+ mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
+ if (accurated)
+ seek_flags |= GST_SEEK_FLAG_ACCURATE;
+ else
+ seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
+
+ if (!__mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
GST_FORMAT_TIME, seek_flags,
- GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
- if (!ret) {
- LOGE("failed to set position. pos[%"G_GINT64_FORMAT"] dur[%"G_GINT64_FORMAT"] ", pos_nsec, player->duration);
+ GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
+ LOGE("failed to set position");
goto SEEK_ERROR;
}
}
- break;
-
- default:
- goto INVALID_ARGS;
- }
/* NOTE : store last seeking point to overcome some bad operation
* (returning zero when getting current position) of some elements
*/
- player->last_position = pos_nsec;
+ player->last_position = position;
/* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
if (player->playback_rate > 1.0)
_mmplayer_set_playspeed((MMHandleType)player, player->playback_rate, FALSE);
- if ((!internal_called) &&
- (player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
+ if ((player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
LOGD("buffering should be reset after seeking");
player->streamer->buffering_state = MM_PLAYER_BUFFERING_ABORT;
player->streamer->buffering_percent = 100; /* after seeking, new per can be non-zero. */
PENDING:
player->pending_seek.is_pending = TRUE;
- player->pending_seek.format = format;
player->pending_seek.pos = position;
- LOGW("player current-state : %s, pending-state : %s, just preserve pending position(%"G_GINT64_FORMAT").\n",
+ LOGW("player current-state : %s, pending-state : %s, just preserve pending position(%"G_GINT64_FORMAT")",
MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)),
MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)),
player->pending_seek.pos);
return MM_ERROR_NONE;
-INVALID_ARGS:
- LOGE("invalid arguments, position: %"G_GINT64_FORMAT" dur : %"G_GINT64_FORMAT" format : %d \n", position, player->duration, format);
- return MM_ERROR_INVALID_ARGUMENT;
-
SEEK_ERROR:
player->seek_state = MMPLAYER_SEEK_NONE;
return MM_ERROR_PLAYER_SEEK;
}
int
-__mmplayer_gst_get_position(mm_player_t* player, int format, gint64* position)
+__mmplayer_gst_get_position(mm_player_t* player, gint64* position)
{
#define TRICKPLAY_OFFSET GST_MSECOND
player->last_position = pos_nsec;
}
- switch (format) {
- case MM_PLAYER_POS_FORMAT_TIME:
- *position = pos_nsec;
- break;
-
- case MM_PLAYER_POS_FORMAT_PERCENT:
- {
- if (player->duration <= 0) {
- LOGD("duration is [%"G_GINT64_FORMAT"], so returning position 0\n", player->duration);
- *position = 0;
- } else {
- LOGD("position is [%"G_GINT64_FORMAT"] nsec , duration is [%"G_GINT64_FORMAT"] nsec", pos_nsec, player->duration);
- *position = (gint64)(pos_nsec * 100 / player->duration);
- }
- break;
- }
- default:
- return MM_ERROR_PLAYER_INTERNAL;
- }
+ *position = pos_nsec;
return MM_ERROR_NONE;
}
if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
/* and rtsp is not ready yet. */
- LOGW("it's only used for http streaming case.\n");
+ LOGW("it's only used for http streaming case");
return MM_ERROR_PLAYER_NO_OP;
}
if (format != MM_PLAYER_POS_FORMAT_PERCENT) {
- LOGW("Time format is not supported yet.\n");
+ LOGW("Time format is not supported yet");
return MM_ERROR_INVALID_ARGUMENT;
}
if (content_size_time <= 0 || content_size_bytes <= 0) {
- LOGW("there is no content size.");
+ LOGW("there is no content size");
return MM_ERROR_NONE;
}
- if (__mmplayer_gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position) != MM_ERROR_NONE) {
- LOGW("fail to get current position.");
+ if (__mmplayer_gst_get_position(player, &position) != MM_ERROR_NONE) {
+ LOGW("fail to get current position");
return MM_ERROR_NONE;
}
*start_pos = CHECK_PERCENT_VALUE(start_per, 0, 100);
*stop_pos = CHECK_PERCENT_VALUE(stop_per, *start_pos, 100);
- LOGD("buffered info: %"G_GINT64_FORMAT" bytes, %d sec, per %lu~%lu\n",
+ LOGD("buffered info: %"G_GINT64_FORMAT" bytes, %d sec, per %lu~%lu",
buffered_total, buffered_sec, *start_pos, *stop_pos);
return MM_ERROR_NONE;