Skip to content

Commit

Permalink
ServiceMP3: Optimize GStreamer start sequence
Browse files Browse the repository at this point in the history
On start set PLAYING state and check return value of the change state.
On stop make sure that last change state was sucessfull, it prevents deadlock on fast channel zap.
When unpause is called make sure that we are in paused state before change state.
Move evStart event in NULL to READY state and update EPG on READY to PAUSED state.

Note: The get state on stop might block forever, so use 5 seconds timeout.
Note:  The m_state change to running when pipeline is prerolled, on ready to paused state.
  • Loading branch information
athoik committed Nov 28, 2015
1 parent 708ec16 commit 7b64e9f
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 60 deletions.
113 changes: 55 additions & 58 deletions lib/service/servicemp3.cpp
Expand Up @@ -418,7 +418,6 @@ eServiceMP3::eServiceMP3(eServiceReference ref):
m_cuesheet_loaded = false; /* cuesheet CVR */
#if GST_VERSION_MAJOR >= 1
m_use_chapter_entries = false; /* TOC chapter support CVR */
m_user_paused = false; /* CVR */
m_last_seek_pos = 0; /* CVR last seek position */
#endif
m_extra_headers = "";
Expand Down Expand Up @@ -666,8 +665,7 @@ eServiceMP3::~eServiceMP3()
gst_object_unref(bus);
}

if (m_state == stRunning)
stop();
stop();

if (m_stream_tags)
gst_tag_list_free(m_stream_tags);
Expand Down Expand Up @@ -748,19 +746,28 @@ RESULT eServiceMP3::start()
{
ASSERT(m_state == stIdle);

m_state = stRunning;
if (m_gst_playbin)
{
eDebug("[eServiceMP3] starting pipeline");
#if GST_VERSION_MAJOR < 1
gst_element_set_state (m_gst_playbin, GST_STATE_PLAYING);
#else
gst_element_set_state (m_gst_playbin, GST_STATE_PAUSED);
#endif
updateEpgCacheNowNext();
}
GstStateChangeReturn ret;
ret = gst_element_set_state (m_gst_playbin, GST_STATE_PLAYING);

m_event(this, evStart);
switch(ret)
{
case GST_STATE_CHANGE_FAILURE:
eDebug("[eServiceMP3] failed to start pipeline");
stop();
break;
case GST_STATE_CHANGE_SUCCESS:
m_is_live = false;
break;
case GST_STATE_CHANGE_NO_PREROLL:
m_is_live = true;
break;
default:
break;
}
}

return 0;
}
Expand All @@ -774,14 +781,25 @@ void eServiceMP3::sourceTimeout()

RESULT eServiceMP3::stop()
{
ASSERT(m_state != stIdle);

if (m_state == stStopped)
if (!m_gst_playbin || m_state == stStopped)
return -1;

eDebug("[eServiceMP3] stop %s", m_ref.path.c_str());
gst_element_set_state(m_gst_playbin, GST_STATE_NULL);
m_state = stStopped;

GstStateChangeReturn ret;
GstState state, pending;
/* make sure that last state change was successfull */
ret = gst_element_get_state(m_gst_playbin, &state, &pending, 5 * GST_SECOND);
eDebug("[eServiceMP3] stop state:%s pending:%s ret:%s",
gst_element_state_get_name(state),
gst_element_state_get_name(pending),
gst_element_state_change_return_get_name(ret));

ret = gst_element_set_state(m_gst_playbin, GST_STATE_NULL);
if (ret != GST_STATE_CHANGE_SUCCESS)
eDebug("[eServiceMP3] stop GST_STATE_NULL failure");

saveCuesheet();
m_nownext_timer->stop();
if (m_streamingsrc_timeout)
Expand Down Expand Up @@ -821,6 +839,7 @@ RESULT eServiceMP3::pause()
if (!m_gst_playbin || m_state != stRunning)
return -1;

eDebug("[eServiceMP3] pause");
trickSeek(0.0);

return 0;
Expand All @@ -831,6 +850,14 @@ RESULT eServiceMP3::unpause()
if (!m_gst_playbin || m_state != stRunning)
return -1;

/* no need to unpase if we are not paused already */
if (m_currentTrickRatio == 1.0 && !m_paused)
{
eDebug("[eServiceMP3] trickSeek no need to unpause!");
return 0;
}

eDebug("[eServiceMP3] unpause");
trickSeek(1.0);

return 0;
Expand All @@ -845,10 +872,7 @@ RESULT eServiceMP3::seek(ePtr<iSeekableService> &ptr)

RESULT eServiceMP3::getLength(pts_t &pts)
{
if (!m_gst_playbin)
return -1;

if (m_state != stRunning)
if (!m_gst_playbin || m_state != stRunning)
return -1;

GstFormat fmt = GST_FORMAT_TIME;
Expand Down Expand Up @@ -884,19 +908,11 @@ RESULT eServiceMP3::seekToImpl(pts_t to)
return -1;
}

#if GST_VERSION_MAJOR < 1
if (m_paused)
{
m_seek_paused = true;
gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING);
}
#else
if (m_user_paused)
{
m_seek_paused = true;
gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING);
}
#endif

return 0;
}
Expand Down Expand Up @@ -1045,9 +1061,7 @@ RESULT eServiceMP3::getPlayPosition(pts_t &pts)
gint64 pos;
pts = 0;

if (!m_gst_playbin)
return -1;
if (m_state != stRunning)
if (!m_gst_playbin || m_state != stRunning)
return -1;

if (audioSink || videoSink)
Expand Down Expand Up @@ -1084,9 +1098,7 @@ RESULT eServiceMP3::isCurrentlySeekable()
{
int ret = 3; /* just assume that seeking and fast/slow winding are possible */

if (!m_gst_playbin)
return 0;
if (m_state != stRunning)
if (!m_gst_playbin || m_state != stRunning)
return 0;

return ret;
Expand Down Expand Up @@ -1650,17 +1662,11 @@ void eServiceMP3::gstBusCall(GstMessage *msg)
{
case GST_STATE_CHANGE_NULL_TO_READY:
{
#if GST_VERSION_MAJOR >= 1
/* CVR basic init done , now playbin must go to pause until mediasettings are done */
if(m_gst_playbin)
{
gst_element_set_state(m_gst_playbin, GST_STATE_PAUSED);
m_paused = true;
}
#endif
m_event(this, evStart);
} break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
{
m_state = stRunning;
#if GST_VERSION_MAJOR >= 1
GValue result = { 0, };
#endif
Expand Down Expand Up @@ -1725,20 +1731,22 @@ void eServiceMP3::gstBusCall(GstMessage *msg)
#endif
gst_iterator_free(children);

m_is_live = (gst_element_get_state(m_gst_playbin, NULL, NULL, 0LL) == GST_STATE_CHANGE_NO_PREROLL);
/* if we are in preroll already do not check again the state */
if (!m_is_live)
{
m_is_live = (gst_element_get_state(m_gst_playbin, NULL, NULL, 0LL) == GST_STATE_CHANGE_NO_PREROLL);
}

setAC3Delay(ac3_delay);
setPCMDelay(pcm_delay);
if(!m_cuesheet_loaded) /* cuesheet CVR */
loadCuesheet();
updateEpgCacheNowNext();
} break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
{
if ( m_sourceinfo.is_streaming && m_streamingsrc_timeout )
m_streamingsrc_timeout->stop();
#if GST_VERSION_MAJOR >= 1
m_user_paused = false;
#endif
m_paused = false;
if (m_seek_paused)
{
Expand All @@ -1750,9 +1758,6 @@ void eServiceMP3::gstBusCall(GstMessage *msg)
} break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
{
#if GST_VERSION_MAJOR >= 1
m_user_paused = true;
#endif
m_paused = true;
} break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
Expand Down Expand Up @@ -2025,14 +2030,6 @@ void eServiceMP3::gstBusCall(GstMessage *msg)
if (m_errorInfo.missing_codec.find("video/") == 0 || (m_errorInfo.missing_codec.find("audio/") == 0 && m_audioStreams.empty()))
m_event((iPlayableService*)this, evUser+12);
}
#if GST_VERSION_MAJOR >= 1
/* CVR now all audio,video and subsettings are done playbin may go to playing */
if(m_paused && !m_user_paused)
{
gst_element_set_state (m_gst_playbin, GST_STATE_PLAYING);
m_paused = false;
}
#endif
break;
}
case GST_MESSAGE_ELEMENT:
Expand Down Expand Up @@ -2097,7 +2094,7 @@ void eServiceMP3::gstBusCall(GstMessage *msg)
break;
}
case GST_MESSAGE_BUFFERING:
if (m_state == stRunning && m_sourceinfo.is_streaming)
if (m_sourceinfo.is_streaming)
{
GstBufferingMode mode;
gst_message_parse_buffering(msg, &(m_bufferInfo.bufferPercent));
Expand Down
2 changes: 0 additions & 2 deletions lib/service/servicemp3.h
Expand Up @@ -306,8 +306,6 @@ class eServiceMP3: public iPlayableService, public iPauseableService,
/* servicemMP3 chapter TOC support CVR */
#if GST_VERSION_MAJOR >= 1
bool m_use_chapter_entries;
/* CVR needed for user requested media pause */
bool m_user_paused;
/* last used seek position gst-1 only */
gint64 m_last_seek_pos;
#endif
Expand Down

0 comments on commit 7b64e9f

Please sign in to comment.