baseparse: use only upstream duration if it provides one
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Fri, 29 Oct 2010 12:08:58 +0000 (14:08 +0200)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Fri, 29 Oct 2010 12:11:47 +0000 (14:11 +0200)
gst/audioparsers/gstbaseparse.c

index fbbe30a..bfdcc13 100644 (file)
@@ -258,6 +258,7 @@ struct _GstBaseParsePrivate
   gboolean own_index;
   /* seek table entries only maintained if upstream is BYTE seekable */
   gboolean upstream_seekable;
+  gboolean upstream_has_duration;
   /* minimum distance between two index entries */
   GstClockTimeDiff idx_interval;
   /* ts and offset of last entry added */
@@ -529,6 +530,7 @@ gst_base_parse_reset (GstBaseParse * parse)
   parse->priv->index_last_ts = 0;
   parse->priv->index_last_offset = 0;
   parse->priv->upstream_seekable = FALSE;
+  parse->priv->upstream_has_duration = FALSE;
   parse->priv->idx_interval = 0;
   parse->priv->exact_position = TRUE;
 
@@ -1298,6 +1300,24 @@ done:
   parse->priv->idx_interval = idx_interval * GST_MSECOND;
 }
 
+/* some misc checks on upstream */
+static void
+gst_base_parse_check_upstream (GstBaseParse * parse)
+{
+  GstFormat fmt = GST_FORMAT_TIME;
+  gint64 stop;
+
+  if (gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop))
+    if (GST_CLOCK_TIME_IS_VALID (stop) && stop) {
+      /* upstream has one, accept it also, and no further updates */
+      gst_base_parse_set_duration (parse, GST_FORMAT_TIME, stop, 0);
+      parse->priv->upstream_has_duration = TRUE;
+    }
+
+  GST_DEBUG_OBJECT (parse, "upstream_has_duration: %d",
+      parse->priv->upstream_has_duration);
+}
+
 /**
  * gst_base_parse_handle_and_push_buffer:
  * @parse: #GstBaseParse.
@@ -1323,6 +1343,12 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse,
     parse->priv->discont = FALSE;
   }
 
+  /* some one-time start-up */
+  if (G_UNLIKELY (!parse->priv->framecount)) {
+    gst_base_parse_check_seekability (parse);
+    gst_base_parse_check_upstream (parse);
+  }
+
   GST_LOG_OBJECT (parse,
       "parsing frame at offset %" G_GUINT64_FORMAT
       " (%#" G_GINT64_MODIFIER "x) of size %d",
@@ -1383,11 +1409,6 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
 
-  /* some one-time start-up */
-  if (G_UNLIKELY (!parse->priv->framecount)) {
-    gst_base_parse_check_seekability (parse);
-  }
-
   /* update stats */
   parse->priv->bytecount += GST_BUFFER_SIZE (buffer);
   if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME)) {
@@ -2386,6 +2407,11 @@ gst_base_parse_set_duration (GstBaseParse * parse,
   g_return_if_fail (parse != NULL);
 
   GST_BASE_PARSE_LOCK (parse);
+  if (parse->priv->upstream_has_duration) {
+    GST_DEBUG_OBJECT (parse, "using upstream duration; discarding update");
+    goto exit;
+  }
+
   if (duration != parse->priv->duration) {
     GstMessage *m;
 
@@ -2405,6 +2431,7 @@ gst_base_parse_set_duration (GstBaseParse * parse,
   }
   GST_DEBUG_OBJECT (parse, "set update interval: %d", interval);
   parse->priv->update_interval = interval;
+exit:
   GST_BASE_PARSE_UNLOCK (parse);
 }