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)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Fri, 8 Apr 2011 17:07:07 +0000 (18:07 +0100)
... 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 9473633f4e9946850741c92a89116d8b65aeb9d3..23ea2b066ddf72b3e4bc5814ba1e1e31814a6aec 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 8df1d88dc6865f3d822e1f491eec1e88670d0e61..b31c8530f0c43b897d3c376e18f9d77d7e1ace02 100644 (file)
@@ -68,16 +68,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:
  *
@@ -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];  
 };