mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
rtmpsrc: fix flushing seek
Previously this was broken, because a flushing seek causes unlock() to be called and in the implementation of unlock() we close the socket, so the seek errors out. This patch fixes it by re-connecting before the seek. Unfortunately, a seek does not work properly right after re-connecting, so a small hack is also in place: we read 1 buffer before seeking to allow librtmp to do its processing in RTMP_Read() https://bugzilla.gnome.org/show_bug.cgi?id=785941
This commit is contained in:
parent
74154c258f
commit
f0500ec8b4
1 changed files with 47 additions and 20 deletions
|
@ -88,6 +88,7 @@ static void gst_rtmp_src_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec);
|
GValue * value, GParamSpec * pspec);
|
||||||
static void gst_rtmp_src_finalize (GObject * object);
|
static void gst_rtmp_src_finalize (GObject * object);
|
||||||
|
|
||||||
|
static gboolean gst_rtmp_src_connect (GstRTMPSrc * src);
|
||||||
static gboolean gst_rtmp_src_unlock (GstBaseSrc * src);
|
static gboolean gst_rtmp_src_unlock (GstBaseSrc * src);
|
||||||
static gboolean gst_rtmp_src_stop (GstBaseSrc * src);
|
static gboolean gst_rtmp_src_stop (GstBaseSrc * src);
|
||||||
static gboolean gst_rtmp_src_start (GstBaseSrc * src);
|
static gboolean gst_rtmp_src_start (GstBaseSrc * src);
|
||||||
|
@ -330,6 +331,12 @@ gst_rtmp_src_create (GstPushSrc * pushsrc, GstBuffer ** buffer)
|
||||||
|
|
||||||
g_return_val_if_fail (src->rtmp != NULL, GST_FLOW_ERROR);
|
g_return_val_if_fail (src->rtmp != NULL, GST_FLOW_ERROR);
|
||||||
|
|
||||||
|
if (!RTMP_IsConnected (src->rtmp)) {
|
||||||
|
GST_DEBUG_OBJECT (src, "reconnecting");
|
||||||
|
if (!gst_rtmp_src_connect (src))
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
size = GST_BASE_SRC_CAST (pushsrc)->blocksize;
|
size = GST_BASE_SRC_CAST (pushsrc)->blocksize;
|
||||||
|
|
||||||
GST_DEBUG ("reading from %" G_GUINT64_FORMAT
|
GST_DEBUG ("reading from %" G_GUINT64_FORMAT
|
||||||
|
@ -541,17 +548,24 @@ gst_rtmp_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
src->discont = TRUE;
|
|
||||||
|
|
||||||
/* Initial seek */
|
/* Initial seek */
|
||||||
if (src->cur_offset == 0 && segment->start == 0)
|
if (src->cur_offset == 0 && segment->start == 0)
|
||||||
return TRUE;
|
goto success;
|
||||||
|
|
||||||
if (!src->seekable) {
|
if (!src->seekable) {
|
||||||
GST_LOG_OBJECT (src, "Not a seekable stream");
|
GST_LOG_OBJECT (src, "Not a seekable stream");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we have just disconnected in unlock(), we need to re-connect
|
||||||
|
* and also let librtmp read some data before sending a seek,
|
||||||
|
* otherwise it will stall. Calling create() does both. */
|
||||||
|
if (!RTMP_IsConnected (src->rtmp)) {
|
||||||
|
GstBuffer *buffer = NULL;
|
||||||
|
gst_rtmp_src_create (GST_PUSH_SRC (basesrc), &buffer);
|
||||||
|
gst_buffer_replace (&buffer, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
src->last_timestamp = GST_CLOCK_TIME_NONE;
|
src->last_timestamp = GST_CLOCK_TIME_NONE;
|
||||||
if (!RTMP_SendSeek (src->rtmp, segment->start / GST_MSECOND)) {
|
if (!RTMP_SendSeek (src->rtmp, segment->start / GST_MSECOND)) {
|
||||||
GST_ERROR_OBJECT (src, "Seeking failed");
|
GST_ERROR_OBJECT (src, "Seeking failed");
|
||||||
|
@ -559,12 +573,41 @@ gst_rtmp_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
success:
|
||||||
|
/* This is set here so that the call to create() above doesn't clear it */
|
||||||
|
src->discont = TRUE;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src, "Seek to %" GST_TIME_FORMAT " successfull",
|
GST_DEBUG_OBJECT (src, "Seek to %" GST_TIME_FORMAT " successfull",
|
||||||
GST_TIME_ARGS (segment->start));
|
GST_TIME_ARGS (segment->start));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_rtmp_src_connect (GstRTMPSrc * src)
|
||||||
|
{
|
||||||
|
RTMP_Init (src->rtmp);
|
||||||
|
src->rtmp->Link.timeout = src->timeout;
|
||||||
|
if (!RTMP_SetupURL (src->rtmp, src->uri)) {
|
||||||
|
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
|
||||||
|
("Failed to setup URL '%s'", src->uri));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
src->seekable = !(src->rtmp->Link.lFlags & RTMP_LF_LIVE);
|
||||||
|
GST_INFO_OBJECT (src, "seekable %d", src->seekable);
|
||||||
|
|
||||||
|
/* open if required */
|
||||||
|
if (!RTMP_IsConnected (src->rtmp)) {
|
||||||
|
if (!RTMP_Connect (src->rtmp, NULL)) {
|
||||||
|
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
|
||||||
|
("Could not connect to RTMP stream \"%s\" for reading", src->uri));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* open the file, do stuff necessary to go to PAUSED state */
|
/* open the file, do stuff necessary to go to PAUSED state */
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rtmp_src_start (GstBaseSrc * basesrc)
|
gst_rtmp_src_start (GstBaseSrc * basesrc)
|
||||||
|
@ -588,24 +631,8 @@ gst_rtmp_src_start (GstBaseSrc * basesrc)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTMP_Init (src->rtmp);
|
if (!gst_rtmp_src_connect (src))
|
||||||
src->rtmp->Link.timeout = src->timeout;
|
|
||||||
if (!RTMP_SetupURL (src->rtmp, src->uri)) {
|
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
|
|
||||||
("Failed to setup URL '%s'", src->uri));
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
src->seekable = !(src->rtmp->Link.lFlags & RTMP_LF_LIVE);
|
|
||||||
GST_INFO_OBJECT (src, "seekable %d", src->seekable);
|
|
||||||
|
|
||||||
/* open if required */
|
|
||||||
if (!RTMP_IsConnected (src->rtmp)) {
|
|
||||||
if (!RTMP_Connect (src->rtmp, NULL)) {
|
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
|
|
||||||
("Could not connect to RTMP stream \"%s\" for reading", src->uri));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue