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.
This commit is contained in:
Mark Nauwelaerts 2011-06-08 18:22:03 +02:00
parent c040305b8c
commit f8168cd75f
2 changed files with 33 additions and 2 deletions

View file

@ -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))

View file

@ -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);