basesrc: add dynamic size handling
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Wed, 8 Jun 2011 16:22:03 +0000 (18:22 +0200)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Wed, 8 Jun 2011 18:16:25 +0000 (20:16 +0200)
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
libs/gst/base/gstbasesrc.h

index 59319e2..d4f332c 100644 (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)
@@ -585,6 +588,23 @@ gst_base_src_set_format (GstBaseSrc * src, GstFormat format)
 }
 
 /**
+ * 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
  * @live: (out) (allow-none): if the source is live
@@ -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))
index 2a3caec..87e1c06 100644 (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);