修改 gstrtspsrc.c
参考加粗字体
1.
<pre name="code" class="cpp">gst_rtspsrc_loop_send_cmd (GstRTSPSrc * src, gint cmd, gint mask)
{
gint old;
gboolean flushed = FALSE;
/* start new request */
gst_rtspsrc_loop_start_cmd (src, cmd);
GST_DEBUG_OBJECT (src, "sending cmd %s", cmd_to_string (cmd));
GST_OBJECT_LOCK (src);
old = src->pending_cmd;
if (old == CMD_RECONNECT) {
GST_DEBUG_OBJECT (src, "ignore, we were reconnecting");
cmd = CMD_RECONNECT;
}
<strong><strong> // vvv ----- Patch----
else if (old == CMD_CLOSE) {
/* our CMD_CLOSE might have interrutped CMD_LOOP. gst_rtspsrc_loop
* will send a CMD_WAIT which would cancel our pending CMD_CLOSE (if
* still pending). We just avoid it here by making sure CMD_CLOSE is
* * still the pending command. */
GST_DEBUG_OBJECT (src, "ignore, we were closing");
}
//if (old != CMD_WAIT) {
else if (old != CMD_WAIT) {
// ^^^ ---- Patch ---</strong></strong>
src->pending_cmd = CMD_WAIT;
GST_OBJECT_UNLOCK (src);
/* cancel previous request */
GST_DEBUG_OBJECT (src, "cancel previous request %s", cmd_to_string (old));
gst_rtspsrc_loop_cancel_cmd (src, old);
GST_OBJECT_LOCK (src);
}
2.
gst_rtspsrc_change_state (GstElement * element, GstStateChange transition)
{
GstRTSPSrc *rtspsrc;
GstStateChangeReturn ret;
rtspsrc = GST_RTSPSRC (element);
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
if (!gst_rtspsrc_start (rtspsrc))
goto start_failed;
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
/* init some state */
rtspsrc->cur_protocols = rtspsrc->protocols;
/* first attempt, don't ignore timeouts */
rtspsrc->ignore_timeout = FALSE;
rtspsrc->open_error = FALSE;
gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_OPEN, 0);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
set_manager_buffer_mode (rtspsrc);
/* fall-through */
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
/* unblock the tcp tasks and make the loop waiting */
if (gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_WAIT, CMD_LOOP)) {
/* make sure it is waiting before we send PAUSE or PLAY below */
GST_RTSP_STREAM_LOCK (rtspsrc);
GST_RTSP_STREAM_UNLOCK (rtspsrc);
}
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
break;
default:
break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
if (ret == GST_STATE_CHANGE_FAILURE)
goto done;
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
ret = GST_STATE_CHANGE_SUCCESS;
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
ret = GST_STATE_CHANGE_NO_PREROLL;
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_PLAY, 0);
ret = GST_STATE_CHANGE_SUCCESS;
break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
/* send pause request and keep the idle task around */
gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_PAUSE, CMD_LOOP);
ret = GST_STATE_CHANGE_NO_PREROLL;
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
<strong> <strong>// vvv ----patch
// gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_CLOSE, CMD_PAUSE);
gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_CLOSE, CMD_ALL);
/* make sure teardown request is not interrupted by stop below */
GST_RTSP_STREAM_LOCK (rtspsrc);
GST_RTSP_STREAM_UNLOCK (rtspsrc);
// ^^^ ---- patch</strong></strong>
ret = GST_STATE_CHANGE_SUCCESS;
break;