From c040305b8c6dac84e8c7abc96bb19d1bf70ac976 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Wed, 8 Jun 2011 20:14:16 +0200 Subject: [PATCH 1/3] Revert "basesrc: Send an update NEWSEGMENT event downstream if the duration changes" This reverts commit 934faf163caf10ed3d54d81fd7b793069913dffd. Original commit leads to possibly sending newsegment event downstream in pull mode. In push mode, quite some downstream elements are likely to only expect newsegment event following a seek they performed and as such may have their state messed up. --- libs/gst/base/gstbasesrc.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index a8098e7e5f..59319e2567 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -2028,7 +2028,6 @@ gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length) GstBaseSrcClass *bclass; GstFormat format; gint64 stop; - gboolean updated = FALSE; bclass = GST_BASE_SRC_GET_CLASS (src); @@ -2084,33 +2083,10 @@ gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length) /* keep track of current position and update duration. * segment is in bytes, we checked that above. */ GST_OBJECT_LOCK (src); - updated = (src->segment.duration != size); gst_segment_set_duration (&src->segment, GST_FORMAT_BYTES, size); gst_segment_set_last_stop (&src->segment, GST_FORMAT_BYTES, offset); GST_OBJECT_UNLOCK (src); - /* If we updated the duration and doing forward playback, we - * have to update the downstream segments to update the stop - * position */ - if (updated && src->segment.rate >= 0.0) { - gint64 stop; - GstEvent *event; - - /* for deriving a stop position for the playback segment from the seek - * segment, we must take the duration when the stop is not set */ - if ((stop = src->segment.stop) == -1) - stop = src->segment.duration; - - GST_DEBUG_OBJECT (src, "Sending update newsegment from %" G_GINT64_FORMAT - " to %" G_GINT64_FORMAT, src->segment.start, stop); - - event = - gst_event_new_new_segment_full (TRUE, - src->segment.rate, src->segment.applied_rate, src->segment.format, - src->segment.start, stop, src->segment.time); - gst_pad_push_event (src->srcpad, event); - } - return TRUE; /* ERRORS */ From f8168cd75f12d31332e981dcb2bbb8b56af967ec Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Wed, 8 Jun 2011 18:22:03 +0200 Subject: [PATCH 2/3] basesrc: add dynamic size handling This allows subclass to indicate that size reported by src may not be static and should as such be updated regularly, rather than only when really needed. Particular examples are filesrc or fdsrc reading from a file that is still growing (e.g. being downloaded). Fixes #652037. --- libs/gst/base/gstbasesrc.c | 33 +++++++++++++++++++++++++++++++-- libs/gst/base/gstbasesrc.h | 2 ++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index 59319e2567..d4f332ce13 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -234,6 +234,7 @@ struct _GstBaseSrcPrivate GstClockTimeDiff ts_offset; gboolean do_timestamp; + volatile gint dynamic_size; /* stream sequence number */ guint32 seqnum; @@ -323,6 +324,8 @@ static GstFlowReturn gst_base_src_pad_get_range (GstPad * pad, guint64 offset, static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length, GstBuffer ** buf); static gboolean gst_base_src_seekable (GstBaseSrc * src); +static gboolean gst_base_src_update_length (GstBaseSrc * src, guint64 offset, + guint * length); static void gst_base_src_base_init (gpointer g_class) @@ -584,6 +587,23 @@ gst_base_src_set_format (GstBaseSrc * src, GstFormat format) GST_OBJECT_UNLOCK (src); } +/** + * gst_base_src_set_dynamic_size: + * @src: base source instance + * @dynamic: new dynamic size mode + * + * If not @dynamic, size is only updated when needed, such as when trying to + * read past current tracked size. Otherwise, size is checked for upon each + * read. + */ +void +gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic) +{ + g_return_if_fail (GST_IS_BASE_SRC (src)); + + g_atomic_int_set (&src->priv->dynamic_size, dynamic); +} + /** * gst_base_src_query_latency: * @src: the source @@ -932,9 +952,14 @@ gst_base_src_default_query (GstBaseSrc * src, GstQuery * query) { gint64 duration; GstFormat seg_format; + guint length = 0; + + /* may have to refresh duration */ + if (g_atomic_int_get (&src->priv->dynamic_size)) + gst_base_src_update_length (src, 0, &length); - GST_OBJECT_LOCK (src); /* this is the duration as configured by the subclass. */ + GST_OBJECT_LOCK (src); duration = src->segment.duration; seg_format = src->segment.format; GST_OBJECT_UNLOCK (src); @@ -2028,6 +2053,7 @@ gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length) GstBaseSrcClass *bclass; GstFormat format; gint64 stop; + gboolean dynamic; bclass = GST_BASE_SRC_GET_CLASS (src); @@ -2052,11 +2078,14 @@ gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length) ", segment.stop %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset, *length, size, stop, maxsize); + dynamic = g_atomic_int_get (&src->priv->dynamic_size); + GST_DEBUG_OBJECT (src, "dynamic size: %d", dynamic); + /* check size if we have one */ if (maxsize != -1) { /* if we run past the end, check if the file became bigger and * retry. */ - if (G_UNLIKELY (offset + *length >= maxsize)) { + if (G_UNLIKELY (offset + *length >= maxsize || dynamic)) { /* see if length of the file changed */ if (bclass->get_size) if (!bclass->get_size (src, &size)) diff --git a/libs/gst/base/gstbasesrc.h b/libs/gst/base/gstbasesrc.h index 2a3caecdbb..87e1c06f41 100644 --- a/libs/gst/base/gstbasesrc.h +++ b/libs/gst/base/gstbasesrc.h @@ -245,6 +245,8 @@ gboolean gst_base_src_is_live (GstBaseSrc *src); void gst_base_src_set_format (GstBaseSrc *src, GstFormat format); +void gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic); + gboolean gst_base_src_query_latency (GstBaseSrc *src, gboolean * live, GstClockTime * min_latency, GstClockTime * max_latency); From de514c63d1c07110ddf57f28c9a43115530c85e5 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Wed, 8 Jun 2011 18:22:36 +0200 Subject: [PATCH 3/3] filesrc/fdsrc: indicate dynamic size handling to basesrc --- plugins/elements/gstfdsrc.c | 3 +++ plugins/elements/gstfilesrc.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/plugins/elements/gstfdsrc.c b/plugins/elements/gstfdsrc.c index 6d7f0f9cea..3d38c6c59d 100644 --- a/plugins/elements/gstfdsrc.c +++ b/plugins/elements/gstfdsrc.c @@ -275,6 +275,8 @@ gst_fd_src_update_fd (GstFdSrc * src, guint64 size) GST_INFO_OBJECT (src, "marking fd %d as seekable", src->fd); src->seekable_fd = TRUE; + + gst_base_src_set_dynamic_size (GST_BASE_SRC (src), TRUE); } return; @@ -282,6 +284,7 @@ not_seekable: { GST_INFO_OBJECT (src, "marking fd %d as NOT seekable", src->fd); src->seekable_fd = FALSE; + gst_base_src_set_dynamic_size (GST_BASE_SRC (src), FALSE); } } diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c index cc07a72a02..f8dbfe2c4c 100644 --- a/plugins/elements/gstfilesrc.c +++ b/plugins/elements/gstfilesrc.c @@ -1019,6 +1019,8 @@ gst_file_src_start (GstBaseSrc * basesrc) * don't know their length, so seeking isn't useful/meaningful */ src->seekable = src->seekable && src->is_regular; + gst_base_src_set_dynamic_size (basesrc, src->seekable); + return TRUE; /* ERROR */