pad-monitor: output timestamps should be in range of received ones
authorThiago Santos <thiago.sousa.santos@collabora.com>
Wed, 17 Jul 2013 14:31:38 +0000 (11:31 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.com>
Wed, 17 Jul 2013 14:49:39 +0000 (11:49 -0300)
Checks if the timestamps of pushed buffers are in the range of the
received buffer timestamps;

validate/gst/qa/gst-qa-pad-monitor.c
validate/gst/qa/gst-qa-pad-monitor.h

index 5ac0600d5e767adbb89285c41b78523d04582fe6..0efe7e0b7ef4a96a2b9c4c77d85dadef0d334e54 100644 (file)
@@ -211,6 +211,116 @@ gst_qa_pad_monitor_new (GstPad * pad, GstQaRunner * runner,
   return monitor;
 }
 
+static gboolean
+gst_qa_pad_monitor_timestamp_is_in_received_range (GstQaPadMonitor * monitor,
+    GstClockTime ts)
+{
+  return !GST_CLOCK_TIME_IS_VALID (monitor->timestamp_range_start) ||
+      !GST_CLOCK_TIME_IS_VALID (monitor->timestamp_range_end) ||
+      (monitor->timestamp_range_start <= ts
+      && ts <= monitor->timestamp_range_end);
+}
+
+/* Iterates over internal links (sinkpads) to check that this buffer has
+ * a timestamp that is in the range of the lastly received buffers */
+static void
+gst_qa_pad_monitor_check_buffer_timestamp_in_received_range (GstQaPadMonitor *
+    monitor, GstBuffer * buffer)
+{
+  GstClockTime ts;
+  GstClockTime ts_end;
+  GstIterator *iter;
+  gboolean has_one = FALSE;
+  gboolean found = FALSE;
+  gboolean done;
+  GstPad *otherpad;
+  GstQaPadMonitor *othermonitor;
+
+  if (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))
+      || !GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
+    GST_DEBUG_OBJECT (monitor,
+        "Can't check buffer timestamps range as "
+        "buffer has no valid timestamp/duration");
+    return;
+  }
+  ts = GST_BUFFER_TIMESTAMP (buffer);
+  ts_end = ts + GST_BUFFER_DURATION (buffer);
+
+  iter = gst_pad_iterate_internal_links (GST_QA_PAD_MONITOR_GET_PAD (monitor));
+  done = FALSE;
+  while (!done) {
+    switch (gst_iterator_next (iter, (gpointer *) & otherpad)) {
+      case GST_ITERATOR_OK:
+        GST_DEBUG_OBJECT (monitor, "Checking pad %s:%s input timestamps",
+            GST_DEBUG_PAD_NAME (otherpad));
+        othermonitor = g_object_get_data ((GObject *) otherpad, "qa-monitor");
+        if (gst_qa_pad_monitor_timestamp_is_in_received_range (othermonitor, ts)
+            && gst_qa_pad_monitor_timestamp_is_in_received_range (othermonitor,
+                ts_end)) {
+          done = TRUE;
+          found = TRUE;
+        }
+        gst_object_unref (otherpad);
+        has_one = TRUE;
+        break;
+      case GST_ITERATOR_RESYNC:
+        gst_iterator_resync (iter);
+        has_one = FALSE;
+        found = FALSE;
+        break;
+      case GST_ITERATOR_ERROR:
+        GST_WARNING_OBJECT (monitor, "Internal links pad iteration error");
+        done = TRUE;
+        break;
+      case GST_ITERATOR_DONE:
+        done = TRUE;
+        break;
+    }
+  }
+  gst_iterator_free (iter);
+
+  if (!has_one) {
+    GST_DEBUG_OBJECT (monitor, "Skipping timestamp in range check as no "
+        "internal linked pad was found");
+  }
+  if (!found) {
+    GST_QA_MONITOR_REPORT_WARNING (monitor, BUFFER, TIMESTAMP,
+        "Timestamp is out of range of received input");
+  }
+}
+
+static void
+gst_qa_pad_monitor_notify_buffer_pushed (GstQaPadMonitor * monitor)
+{
+  GstIterator *iter;
+  gboolean done;
+  GstPad *otherpad;
+  GstQaPadMonitor *othermonitor;
+
+  iter = gst_pad_iterate_internal_links (GST_QA_PAD_MONITOR_GET_PAD (monitor));
+  done = FALSE;
+  while (!done) {
+    switch (gst_iterator_next (iter, (gpointer *) & otherpad)) {
+      case GST_ITERATOR_OK:
+        othermonitor = g_object_get_data ((GObject *) otherpad, "qa-monitor");
+        othermonitor->buffer_pushed = TRUE;
+        gst_object_unref (otherpad);
+        break;
+      case GST_ITERATOR_RESYNC:
+        gst_iterator_resync (iter);
+        break;
+      case GST_ITERATOR_ERROR:
+        GST_WARNING_OBJECT (monitor, "Internal links pad iteration error");
+        done = TRUE;
+        break;
+      case GST_ITERATOR_DONE:
+        done = TRUE;
+        break;
+    }
+  }
+  gst_iterator_free (iter);
+}
+
 static void
 gst_qa_pad_monitor_check_first_buffer (GstQaPadMonitor * pad_monitor,
     GstBuffer * buffer)
@@ -239,6 +349,18 @@ gst_qa_pad_monitor_update_buffer_data (GstQaPadMonitor * pad_monitor,
 {
   pad_monitor->current_timestamp = GST_BUFFER_TIMESTAMP (buffer);
   pad_monitor->current_duration = GST_BUFFER_DURATION (buffer);
+  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)) &&
+      GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
+    if (pad_monitor->buffer_pushed) {
+      pad_monitor->timestamp_range_start = GST_BUFFER_TIMESTAMP (buffer);
+    }
+    pad_monitor->timestamp_range_end = GST_BUFFER_TIMESTAMP (buffer) +
+        GST_BUFFER_DURATION (buffer);
+  } else {
+    pad_monitor->timestamp_range_start = GST_CLOCK_TIME_NONE;
+    pad_monitor->timestamp_range_end = GST_CLOCK_TIME_NONE;
+  }
+  pad_monitor->buffer_pushed = FALSE;
 }
 
 
@@ -538,6 +660,9 @@ gst_qa_pad_monitor_buffer_probe (GstPad * pad, GstBuffer * buffer,
   gst_qa_pad_monitor_check_first_buffer (monitor, buffer);
   gst_qa_pad_monitor_update_buffer_data (monitor, buffer);
 
+  gst_qa_pad_monitor_check_buffer_timestamp_in_received_range (monitor, buffer);
+  gst_qa_pad_monitor_notify_buffer_pushed (monitor);
+
   /* TODO should we assume that a pad-monitor should always have an
    * element-monitor as a parent? */
   if (G_LIKELY (GST_QA_MONITOR_GET_PARENT (monitor))) {
index e64ce58ffb9833a40eef27e0f2136b2cb89d403b..07474c4d382490339114aaa9ed3833bdb33d4df2 100644 (file)
@@ -83,6 +83,18 @@ struct _GstQaPadMonitor {
   GstSegment segment;
   GstClockTime current_timestamp;
   GstClockTime current_duration;
+
+  /* Stores the current timestamp range of data
+   * in this pad by using TIMESTAMP and TIMESTAMP+DURATION from
+   * incomming buffers.
+   *
+   * If the internally linked pads haven't pushed a buffer, it will
+   * update the end to the new TIMESTAMP+DURATION, in case a buffer
+   * was pushed, the start is also updated to be TIMESTMAP.
+   */
+  GstClockTime timestamp_range_start;
+  GstClockTime timestamp_range_end;
+  gboolean buffer_pushed;
 };
 
 /**