diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index 9f6a3aee23..867b95b6b3 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -224,6 +224,7 @@ struct _GstBaseSrcPrivate GstClockTimeDiff ts_offset; gboolean do_timestamp; + volatile gint dynamic_size; /* stream sequence number */ guint32 seqnum; @@ -311,6 +312,8 @@ 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_negotiate (GstBaseSrc * basesrc); +static gboolean gst_base_src_update_length (GstBaseSrc * src, guint64 offset, + guint * length); static void gst_base_src_class_init (GstBaseSrcClass * klass) @@ -562,6 +565,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 @@ -901,9 +921,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); @@ -1976,14 +2001,14 @@ gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length) GstBaseSrcClass *bclass; GstFormat format; gint64 stop; - GstEvent *event = NULL; + gboolean dynamic; bclass = GST_BASE_SRC_GET_CLASS (src); format = src->segment.format; stop = src->segment.stop; /* get total file size */ - size = (guint64) src->segment.duration; + size = src->segment.duration; /* only operate if we are working with bytes */ if (format != GST_FORMAT_BYTES) @@ -2001,11 +2026,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)) @@ -2032,18 +2060,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); - if (src->segment.duration != size) { - src->segment.duration = size; - event = gst_event_new_segment (&src->segment); - } + src->segment.duration = size; src->segment.position = offset; GST_OBJECT_UNLOCK (src); - /* If we updated the duration, we have to update the downstream - * segments to update the stop position */ - if (event) - gst_pad_push_event (src->srcpad, event); - return TRUE; /* ERRORS */ diff --git a/libs/gst/base/gstbasesrc.h b/libs/gst/base/gstbasesrc.h index 0cb627af99..d4bbd67824 100644 --- a/libs/gst/base/gstbasesrc.h +++ b/libs/gst/base/gstbasesrc.h @@ -221,6 +221,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); diff --git a/plugins/elements/gstfdsrc.c b/plugins/elements/gstfdsrc.c index 9f297ff66f..008232707e 100644 --- a/plugins/elements/gstfdsrc.c +++ b/plugins/elements/gstfdsrc.c @@ -259,6 +259,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; @@ -266,6 +268,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 cb5fdb0df5..b005392c4e 100644 --- a/plugins/elements/gstfilesrc.c +++ b/plugins/elements/gstfilesrc.c @@ -538,6 +538,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 */