__mmplayer_gst_callback(GstMessage *msg, gpointer data)
{
mm_player_t* player = (mm_player_t*)(data);
- static gboolean async_done = FALSE;
MMPLAYER_RETURN_IF_FAIL(player);
MMPLAYER_RETURN_IF_FAIL(msg && GST_IS_MESSAGE(msg));
gst_message_parse_buffering(msg, &buffer_percent);
- LOGD("force resume -last posted %d %%, new per %d %%",
+ LOGD("interrupted buffering -last posted %d %%, new per %d %%",
player->streamer->buffering_percent, buffer_percent);
- if (player->streamer->buffering_percent > buffer_percent) {
+ if (player->streamer->buffering_percent > buffer_percent || buffer_percent <= 0) {
player->streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
player->streamer->buffering_req.is_pre_buffering = FALSE;
- LOGD("force resume - need to enter the buffering mode again - %d %%", buffer_percent);
+ LOGD("interrupted buffering - need to enter the buffering mode again - %d %%", buffer_percent);
} else {
- LOGD("force resume - ignored the remained buffering msg!");
+ LOGD("interrupted buffering - ignored the remained buffering msg!");
MMPLAYER_CMD_UNLOCK(player);
break;
}
if (MMPLAYER_IS_RTSP_STREAMING(player) &&
(player->streamer->buffering_percent >= MAX_BUFFER_PERCENT)) {
- if (player->doing_seek) {
+ if (player->seek_state == MMPLAYER_SEEK_IN_PROGRESS) {
if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
- player->doing_seek = FALSE;
+ player->seek_state = MMPLAYER_SEEK_NONE;
MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
} else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
- async_done = TRUE;
+ /* Considering the async state trasition in case of RTSP.
+ After getting state change gst msg, seek cmpleted msg will be posted. */
+ player->seek_state = MMPLAYER_SEEK_COMPLETED;
}
}
}
player->gapless.stream_changed = FALSE;
}
- if (player->doing_seek && async_done) {
- player->doing_seek = FALSE;
- async_done = FALSE;
+ if (player->seek_state == MMPLAYER_SEEK_COMPLETED) {
+ player->seek_state = MMPLAYER_SEEK_NONE;
MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
}
}
case GST_MESSAGE_ASYNC_DONE:
{
+ MMPlayerGstElement *mainbin;
+
+ if (!(player->pipeline && player->pipeline->mainbin)) {
+ LOGE("player pipeline handle is null");
+ break;
+ }
+
+ mainbin = player->pipeline->mainbin;
+
LOGD("GST_MESSAGE_ASYNC_DONE : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
/* we only handle messages from pipeline */
- if (msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst)
+ if (msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst)
break;
- if (player->doing_seek) {
+ if (player->seek_state == MMPLAYER_SEEK_IN_PROGRESS) {
if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
- player->doing_seek = FALSE;
+ player->seek_state = MMPLAYER_SEEK_NONE;
MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
} else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
+ if (mainbin[MMPLAYER_M_AUTOPLUG].gst) {
+ LOGD("sync %s state(%s) with parent state(%s)",
+ GST_ELEMENT_NAME(mainbin[MMPLAYER_M_AUTOPLUG].gst),
+ gst_element_state_get_name(GST_STATE(mainbin[MMPLAYER_M_AUTOPLUG].gst)),
+ gst_element_state_get_name(GST_STATE(mainbin[MMPLAYER_M_PIPE].gst)));
+
+ /* In case of streaming, pause is required before finishing seeking by buffering.
+ After completing the seek(during buffering), the player and sink elems has paused state but others in playing state.
+ Because the buffering state is controlled according to the state transition for force resume,
+ the decodebin state should be paused as player state. */
+ gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_AUTOPLUG].gst);
+ }
+
if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
(player->streamer) &&
(player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
__mmplayer_handle_buffering_message(player);
}
- async_done = TRUE;
+ player->seek_state = MMPLAYER_SEEK_COMPLETED;
}
}
}
G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
}
-
/* check autoplug element is OK */
if (!element) {
LOGE("can not create element(%d)\n", elemId);
player->pending_seek.is_pending = TRUE;
player->pending_seek.format = format;
player->pending_seek.pos = position;
- player->doing_seek = FALSE;
+ player->seek_state = MMPLAYER_SEEK_NONE;
MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
return MM_ERROR_NONE;
} else {
if (!seekable) {
LOGW("non-seekable content");
- player->doing_seek = FALSE;
+ player->seek_state = MMPLAYER_SEEK_NONE;
return MM_ERROR_PLAYER_NO_OP;
}
} else {
g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
}
- if (player->doing_seek) {
+ if (player->seek_state != MMPLAYER_SEEK_NONE) {
LOGD("not completed seek");
return MM_ERROR_PLAYER_DOING_SEEK;
}
}
if (!internal_called)
- player->doing_seek = TRUE;
+ player->seek_state = MMPLAYER_SEEK_IN_PROGRESS;
if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked)) {
gint64 cur_time = 0;
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->doing_seek = FALSE;
+ player->seek_state = MMPLAYER_SEEK_NONE;
MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
} else {
ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
{
LOGD("seeking to %"G_GINT64_FORMAT"%%", position);
- if (player->doing_seek) {
+ if (player->seek_state != MMPLAYER_SEEK_NONE) {
LOGD("not completed seek");
return MM_ERROR_PLAYER_DOING_SEEK;
}
if (!internal_called)
- player->doing_seek = TRUE;
+ player->seek_state = MMPLAYER_SEEK_IN_PROGRESS;
/* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
pos_nsec = (gint64)((position * player->duration) / 100);
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)) {
+ 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. */
+ }
+
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
return MM_ERROR_INVALID_ARGUMENT;
SEEK_ERROR:
- player->doing_seek = FALSE;
+ player->seek_state = MMPLAYER_SEEK_NONE;
return MM_ERROR_PLAYER_SEEK;
}
}
/* check if seeking */
- if (player->doing_seek) {
+ if (player->seek_state != MMPLAYER_SEEK_NONE) {
MMMessageParamType msg_param;
memset(&msg_param, 0, sizeof(MMMessageParamType));
msg_param.code = MM_ERROR_PLAYER_SEEK;
- player->doing_seek = FALSE;
+ player->seek_state = MMPLAYER_SEEK_NONE;
MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
goto FAILED;
}
__mmplayer_unrealize_streaming_ext(player);
/* reset */
- player->doing_seek = FALSE;
+ player->seek_state = MMPLAYER_SEEK_NONE;
/* stop pipeline */
ret = __gst_stop(player);
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- /* Changing back sync mode rtspsrc to async */
if ((MMPLAYER_IS_RTSP_STREAMING(player))) {
+ if (player->is_external_subtitle_added_now) { /* after setting external subtitle, seeking and buffering is in progress. */
+ player->pending_resume = TRUE; /* will be resumed after finishing the buffering. */
+ return ret;
+ }
+
+ /* Changing back sync mode rtspsrc to async */
LOGD("async resume for rtsp case");
async = TRUE;
}
/* check current state */
MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_RESUME);
+ ret = __gst_resume(player, async);
+ if (ret != MM_ERROR_NONE)
+ LOGE("failed to resume player.\n");
+
if ((player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
LOGD("force resume even during buffering");
player->streamer->buffering_state = MM_PLAYER_BUFFERING_ABORT;
}
- ret = __gst_resume(player, async);
-
- if (ret != MM_ERROR_NONE)
- LOGE("failed to resume player.\n");
-
MMPLAYER_FLEAVE();
return ret;
player->has_many_types = FALSE;
player->no_more_pad = FALSE;
player->not_found_demuxer = 0;
- player->doing_seek = FALSE;
+ player->seek_state = MMPLAYER_SEEK_NONE;
player->max_audio_channels = 0;
player->is_subtitle_force_drop = FALSE;
player->play_subtitle = FALSE;
player->sent_bos = FALSE;
player->playback_rate = DEFAULT_PLAYBACK_RATE;
- player->doing_seek = FALSE;
+ player->seek_state = MMPLAYER_SEEK_NONE;
player->total_bitrate = 0;
player->total_maximum_bitrate = 0;
if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
LOGD("RTSP seek completed, after pause state..\n");
- player->doing_seek = FALSE;
+ player->seek_state = MMPLAYER_SEEK_NONE;
MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
}
return MM_ERROR_PLAYER_INTERNAL;
}
- if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING) {
+ if (player->seek_state == MMPLAYER_SEEK_NONE && previous_state == MM_PLAYER_STATE_PLAYING) {
LOGW("trying to block pad(video)");
// if (!gst_pad_set_blocked(src_pad_dec, TRUE))
gst_pad_add_probe(src_pad_dec, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
LOGW("pad is blocked(video)");
} else {
/* no data flows, so no need to do pad_block */
- if (player->doing_seek)
- LOGW("not completed seek(%d), do nothing", player->doing_seek);
+ if (player->seek_state != MMPLAYER_SEEK_NONE)
+ LOGW("not completed seek(%d), do nothing", player->seek_state);
LOGD("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
}
} else
LOGW("failed to get clock, maybe it is the time before first playing");
- if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING) {
+ if (player->seek_state == MMPLAYER_SEEK_NONE && previous_state == MM_PLAYER_STATE_PLAYING) {
/* change state of videobin to PAUSED */
LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
#endif
LOGW("pad is unblocked(video)");
} else {
- if (player->doing_seek)
- LOGW("not completed seek(%d)", player->doing_seek);
+ if (player->seek_state != MMPLAYER_SEEK_NONE)
+ LOGW("not completed seek(%d)", player->seek_state);
/* change state of videobin to PAUSED */
LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
/* LOGD("in(us) : %"G_GINT64_FORMAT", %"G_GINT64_FORMAT", %"G_GINT64_FORMAT", %"G_GINT64_FORMAT", %"G_GINT64_FORMAT,
clock, clock_delta, video_time, media_clock, audio_time); */
- if ((video_time < 0) || (player->doing_seek)) {
+ if ((video_time < 0) || (player->seek_state != MMPLAYER_SEEK_NONE)) {
LOGD("skip setting master clock. %lld", video_time);
goto EXIT;
}