baseparse: add another hook for subclass prior to pushing buffer
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Fri, 17 Sep 2010 15:21:46 +0000 (17:21 +0200)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Fri, 1 Oct 2010 10:15:48 +0000 (12:15 +0200)
... and allow subclass to perform custom segment clipping, or to
emit tags or messages at this time.

gst/audioparsers/gstbaseparse.c
gst/audioparsers/gstbaseparse.h

index 9473633..23ea2b0 100644 (file)
@@ -1063,6 +1063,7 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
   GstFlowReturn ret = GST_FLOW_OK;
   GstClockTime last_start = GST_CLOCK_TIME_NONE;
   GstClockTime last_stop = GST_CLOCK_TIME_NONE;
+  GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
 
   GST_LOG_OBJECT (parse,
       "processing buffer of size %d with ts %" GST_TIME_FORMAT
@@ -1142,24 +1143,42 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
 
   /* TODO: Add to seek table */
 
-  if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
-      GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
-      GST_BUFFER_TIMESTAMP (buffer) > parse->segment.stop) {
-    GST_LOG_OBJECT (parse, "Dropped frame, after segment");
-    gst_buffer_unref (buffer);
-  } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
-      GST_BUFFER_DURATION_IS_VALID (buffer) &&
-      GST_CLOCK_TIME_IS_VALID (parse->segment.start) &&
-      GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer)
-      < parse->segment.start) {
-    /* FIXME: subclass needs way to override the start as downstream might
-     * need frames before for proper decoding */
-    GST_LOG_OBJECT (parse, "Dropped frame, before segment");
+  if (klass->pre_push_buffer)
+    ret = klass->pre_push_buffer (parse, buffer);
+  else
+    ret = GST_BASE_PARSE_FLOW_CLIP;
+
+  if (ret == GST_BASE_PARSE_FLOW_CLIP) {
+    if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
+        GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
+        GST_BUFFER_TIMESTAMP (buffer) > parse->segment.stop) {
+      GST_LOG_OBJECT (parse, "Dropped frame, after segment");
+      ret = GST_FLOW_UNEXPECTED;
+    } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
+        GST_BUFFER_DURATION_IS_VALID (buffer) &&
+        GST_CLOCK_TIME_IS_VALID (parse->segment.start) &&
+        GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer)
+        < parse->segment.start) {
+      GST_LOG_OBJECT (parse, "Dropped frame, before segment");
+      ret = GST_BASE_PARSE_FLOW_DROPPED;
+    } else {
+      ret = GST_FLOW_OK;
+    }
+  }
+
+  if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
+    GST_LOG_OBJECT (parse, "frame (%d bytes) dropped",
+        GST_BUFFER_SIZE (buffer));
     gst_buffer_unref (buffer);
-  } else {
+    ret = GST_FLOW_OK;
+  } else if (ret == GST_FLOW_OK) {
     ret = gst_pad_push (parse->srcpad, buffer);
-    GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %d",
-        GST_BUFFER_SIZE (buffer), ret);
+    GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %s",
+        GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret));
+  } else {
+    gst_buffer_unref (buffer);
+    GST_LOG_OBJECT (parse, "frame (%d bytes) not pushed: %s",
+        GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret));
   }
 
   /* Update current running segment position */
index 8df1d88..b31c853 100644 (file)
@@ -69,16 +69,37 @@ G_BEGIN_DECLS
 #define GST_BASE_PARSE_SINK_PAD(obj)   (GST_BASE_PARSE_CAST (obj)->sinkpad)
 
 /**
+ * GST_BASE_PARSE_SEGMENT:
+ * @obj: base parse instance
+ *
+ * Gives the segment of the element.
+ *
+ * Since: 0.10.x
+ */
+#define GST_BASE_PARSE_SEGMENT(obj)     (GST_BASE_PARSE_CAST (obj)->segment)
+
+/**
  * GST_BASE_PARSE_FLOW_DROPPED:
  *
  * A #GstFlowReturn that can be returned from parse_frame to
- * indicate that no output buffer was generated.
+ * indicate that no output buffer was generated, or from pre_push_buffer to
+ * to forego pushing buffer.
  *
  * Since: 0.10.x
  */
 #define GST_BASE_PARSE_FLOW_DROPPED   GST_FLOW_CUSTOM_SUCCESS
 
 /**
+ * GST_BASE_PARSE_FLOW_CLIP:
+ *
+ * A #GstFlowReturn that can be returned from pre_push_buffer to
+ * indicate that regular segment clipping should be performed.
+ *
+ * Since: 0.10.x
+ */
+#define GST_BASE_PARSE_FLOW_CLIP      GST_FLOW_CUSTOM_SUCCESS_1
+
+/**
  * GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME:
  *
  * A #GstBufferFlag that can be set to have this buffer not counted as frame,
@@ -186,6 +207,13 @@ struct _GstBaseParse {
  *                      this returns -1, it is assumed that this frame should
  *                      be skipped in bitrate calculation.
  *
+ * @pre_push_buffer: Optional.
+ *                   Called just prior to pushing a frame (after any pending
+ *                   events have been sent) to give subclass a chance to perform
+ *                   additional actions at this time (e.g. tag sending) or to
+ *                   decide whether this buffer should be dropped or no
+ *                   (e.g. custom segment clipping).
+ *
  * Subclasses can override any of the available virtual methods or not, as
  * needed. At minimum @check_valid_frame and @parse_frame needs to be
  * overridden.
@@ -233,6 +261,9 @@ struct _GstBaseParseClass {
   gint          (*get_frame_overhead) (GstBaseParse *parse,
                                        GstBuffer *buf);
 
+  GstFlowReturn (*pre_push_buffer)    (GstBaseParse *parse,
+                                       GstBuffer *buf);
+
   /*< private >*/
   gpointer       _gst_reserved[GST_PADDING_LARGE];  
 };