baseparse: introduce a baseparse frame to serve as context
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Mon, 10 Jan 2011 14:34:48 +0000 (15:34 +0100)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Fri, 8 Apr 2011 17:07:14 +0000 (18:07 +0100)
... and adjust subclass parsers accordingly

gst/audioparsers/gstaacparse.c
gst/audioparsers/gstac3parse.c
gst/audioparsers/gstamrparse.c
gst/audioparsers/gstbaseparse.c
gst/audioparsers/gstbaseparse.h
gst/audioparsers/gstdcaparse.c
gst/audioparsers/gstflacparse.c
gst/audioparsers/gstmpegaudioparse.c

index 4dd2dc7..140f5e4 100644 (file)
@@ -77,10 +77,10 @@ static gboolean gst_aacparse_sink_setcaps (GstBaseParse * parse,
     GstCaps * caps);
 
 gboolean gst_aacparse_check_valid_frame (GstBaseParse * parse,
-    GstBuffer * buffer, guint * size, gint * skipsize);
+    GstBaseParseFrame * frame, guint * size, gint * skipsize);
 
 GstFlowReturn gst_aacparse_parse_frame (GstBaseParse * parse,
-    GstBuffer * buffer);
+    GstBaseParseFrame * frame);
 
 gboolean gst_aacparse_convert (GstBaseParse * parse,
     GstFormat src_format,
@@ -147,8 +147,6 @@ gst_aacparse_class_init (GstAacParseClass * klass)
   parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_aacparse_parse_frame);
   parse_class->check_valid_frame =
       GST_DEBUG_FUNCPTR (gst_aacparse_check_valid_frame);
-  parse_class->get_frame_overhead =
-      GST_DEBUG_FUNCPTR (gst_aacparse_get_frame_overhead);
 }
 
 
@@ -330,8 +328,8 @@ gst_aacparse_adts_get_frame_len (const guint8 * data)
  */
 static gboolean
 gst_aacparse_check_adts_frame (GstAacParse * aacparse,
-    const guint8 * data,
-    const guint avail, guint * framesize, guint * needed_data)
+    const guint8 * data, const guint avail, gboolean drain,
+    guint * framesize, guint * needed_data)
 {
   if (G_UNLIKELY (avail < 2))
     return FALSE;
@@ -340,7 +338,7 @@ gst_aacparse_check_adts_frame (GstAacParse * aacparse,
     *framesize = gst_aacparse_adts_get_frame_len (data);
 
     /* In EOS mode this is enough. No need to examine the data further */
-    if (gst_base_parse_get_drain (GST_BASE_PARSE (aacparse))) {
+    if (drain) {
       return TRUE;
     }
 
@@ -408,7 +406,8 @@ gst_aacparse_parse_adts_header (GstAacParse * aacparse, const guint8 * data,
  */
 static gboolean
 gst_aacparse_detect_stream (GstAacParse * aacparse,
-    const guint8 * data, const guint avail, guint * framesize, gint * skipsize)
+    const guint8 * data, const guint avail, gboolean drain,
+    guint * framesize, gint * skipsize)
 {
   gboolean found = FALSE;
   guint need_data = 0;
@@ -444,7 +443,7 @@ gst_aacparse_detect_stream (GstAacParse * aacparse,
     return FALSE;
   }
 
-  if (gst_aacparse_check_adts_frame (aacparse, data, avail,
+  if (gst_aacparse_check_adts_frame (aacparse, data, avail, drain,
           framesize, &need_data)) {
     gint rate, channels;
 
@@ -568,17 +567,19 @@ gst_aacparse_detect_stream (GstAacParse * aacparse,
  */
 gboolean
 gst_aacparse_check_valid_frame (GstBaseParse * parse,
-    GstBuffer * buffer, guint * framesize, gint * skipsize)
+    GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
 {
   const guint8 *data;
   GstAacParse *aacparse;
   gboolean ret = FALSE;
   gboolean sync;
+  GstBuffer *buffer;
 
   aacparse = GST_AACPARSE (parse);
+  buffer = frame->buffer;
   data = GST_BUFFER_DATA (buffer);
 
-  sync = gst_base_parse_get_sync (parse);
+  sync = GST_BASE_PARSE_FRAME_SYNC (frame);
 
   if (aacparse->header_type == DSPAAC_HEADER_ADIF ||
       aacparse->header_type == DSPAAC_HEADER_NONE) {
@@ -589,13 +590,14 @@ gst_aacparse_check_valid_frame (GstBaseParse * parse,
   } else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || sync == FALSE) {
 
     ret = gst_aacparse_detect_stream (aacparse, data, GST_BUFFER_SIZE (buffer),
-        framesize, skipsize);
+        GST_BASE_PARSE_FRAME_DRAIN (frame), framesize, skipsize);
 
   } else if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
     guint needed_data = 1024;
 
     ret = gst_aacparse_check_adts_frame (aacparse, data,
-        GST_BUFFER_SIZE (buffer), framesize, &needed_data);
+        GST_BUFFER_SIZE (buffer), GST_BASE_PARSE_FRAME_DRAIN (frame),
+        framesize, &needed_data);
 
     if (!ret) {
       GST_DEBUG ("buffer didn't contain valid frame");
@@ -619,21 +621,39 @@ gst_aacparse_check_valid_frame (GstBaseParse * parse,
  *
  * Implementation of "parse_frame" vmethod in #GstBaseParse class.
  *
+ * Also determines frame overhead.
+ * ADTS streams have a 7 byte header in each frame. MP4 and ADIF streams don't have
+ * a per-frame header.
+ *
+ * We're making a couple of simplifying assumptions:
+ *
+ * 1. We count Program Configuration Elements rather than searching for them
+ *    in the streams to discount them - the overhead is negligible.
+ *
+ * 2. We ignore CRC. This has a worst-case impact of (num_raw_blocks + 1)*16
+ *    bits, which should still not be significant enough to warrant the
+ *    additional parsing through the headers
+ *
  * Returns: GST_FLOW_OK if frame was successfully parsed and can be pushed
  *          forward. Otherwise appropriate error is returned.
  */
 GstFlowReturn
-gst_aacparse_parse_frame (GstBaseParse * parse, GstBuffer * buffer)
+gst_aacparse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
   GstAacParse *aacparse;
+  GstBuffer *buffer;
   GstFlowReturn ret = GST_FLOW_OK;
   gint rate, channels;
 
   aacparse = GST_AACPARSE (parse);
+  buffer = frame->buffer;
 
   if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS))
     return ret;
 
+  /* see above */
+  frame->overhead = 7;
+
   gst_aacparse_parse_adts_header (aacparse, GST_BUFFER_DATA (buffer),
       &rate, &channels, NULL, NULL);
   GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
@@ -692,33 +712,3 @@ gst_aacparse_stop (GstBaseParse * parse)
   GST_DEBUG ("stop");
   return TRUE;
 }
-
-
-/**
- * gst_aacparse_get_frame_overhead:
- * @parse: #GstBaseParse.
- * @buffer: #GstBuffer.
- *
- * Implementation of "get_frame_overhead" vmethod in #GstBaseParse class. ADTS
- * streams have a 7 byte header in each frame. MP4 and ADIF streams don't have
- * a per-frame header.
- *
- * We're making a couple of simplifying assumptions:
- *
- * 1. We count Program Configuration Elements rather than searching for them
- *    in the streams to discount them - the overhead is negligible.
- *
- * 2. We ignore CRC. This has a worst-case impact of (num_raw_blocks + 1)*16
- *    bits, which should still not be significant enough to warrant the
- *    additional parsing through the headers
- */
-gint
-gst_aacparse_get_frame_overhead (GstBaseParse * parse, GstBuffer * buffer)
-{
-  GstAacParse *aacparse = GST_AACPARSE (parse);
-
-  if (aacparse->header_type == DSPAAC_HEADER_ADTS)
-    return 7;
-  else
-    return 0;
-}
index 7e3a8b4..0c7fba3 100644 (file)
@@ -160,9 +160,9 @@ static void gst_ac3_parse_finalize (GObject * object);
 static gboolean gst_ac3_parse_start (GstBaseParse * parse);
 static gboolean gst_ac3_parse_stop (GstBaseParse * parse);
 static gboolean gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
-    GstBuffer * buffer, guint * size, gint * skipsize);
+    GstBaseParseFrame * frame, guint * size, gint * skipsize);
 static GstFlowReturn gst_ac3_parse_parse_frame (GstBaseParse * parse,
-    GstBuffer * buf);
+    GstBaseParseFrame * frame);
 
 GST_BOILERPLATE (GstAc3Parse, gst_ac3_parse, GstBaseParse, GST_TYPE_BASE_PARSE);
 
@@ -384,11 +384,12 @@ gst_ac3_parse_frame_header (GstAc3Parse * parse, GstBuffer * buf,
 }
 
 static gboolean
-gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
-    guint * framesize, gint * skipsize)
+gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
+    GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
 {
-  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
   GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
+  GstBuffer *buf = frame->buffer;
+  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
   gint off;
   gboolean sync, drain;
 
@@ -421,8 +422,8 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
 
   GST_LOG_OBJECT (parse, "got frame");
 
-  sync = gst_base_parse_get_sync (parse);
-  drain = gst_base_parse_get_drain (parse);
+  sync = GST_BASE_PARSE_FRAME_SYNC (frame);
+  drain = GST_BASE_PARSE_FRAME_DRAIN (frame);
 
   if (!sync && !drain) {
     guint16 word = 0;
@@ -451,9 +452,10 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
 }
 
 static GstFlowReturn
-gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf)
+gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
   GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
+  GstBuffer *buf = frame->buffer;
   guint fsize, rate, chans, blocks, sid;
   gboolean eac;
 
@@ -465,7 +467,7 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf)
 
   if (G_UNLIKELY (sid)) {
     GST_LOG_OBJECT (parse, "sid: %d", sid);
-    GST_BUFFER_FLAG_SET (buf, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME);
+    frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NO_FRAME;
   }
 
   if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans
index a182e76..191a029 100644 (file)
@@ -78,10 +78,10 @@ static gboolean gst_amrparse_sink_setcaps (GstBaseParse * parse,
     GstCaps * caps);
 
 gboolean gst_amrparse_check_valid_frame (GstBaseParse * parse,
-    GstBuffer * buffer, guint * framesize, gint * skipsize);
+    GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
 
 GstFlowReturn gst_amrparse_parse_frame (GstBaseParse * parse,
-    GstBuffer * buffer);
+    GstBaseParseFrame * frame);
 
 #define _do_init(bla) \
     GST_DEBUG_CATEGORY_INIT (gst_amrparse_debug, "amrparse", 0, \
@@ -267,13 +267,15 @@ gst_amrparse_parse_header (GstAmrParse * amrparse,
  */
 gboolean
 gst_amrparse_check_valid_frame (GstBaseParse * parse,
-    GstBuffer * buffer, guint * framesize, gint * skipsize)
+    GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
 {
+  GstBuffer *buffer;
   const guint8 *data;
   gint fsize, mode, dsize;
   GstAmrParse *amrparse;
 
   amrparse = GST_AMRPARSE (parse);
+  buffer = frame->buffer;
   data = GST_BUFFER_DATA (buffer);
   dsize = GST_BUFFER_SIZE (buffer);
 
@@ -305,8 +307,8 @@ gst_amrparse_check_valid_frame (GstBaseParse * parse,
      *       to contain a valid header as well (and there is enough data to
      *       perform this check)
      */
-    if (gst_base_parse_get_sync (parse) || gst_base_parse_get_drain (parse) ||
-        (dsize >= fsize && (data[fsize] & 0x83) == 0)) {
+    if (GST_BASE_PARSE_FRAME_SYNC (frame) || GST_BASE_PARSE_FRAME_DRAIN (frame)
+        || (dsize >= fsize && (data[fsize] & 0x83) == 0)) {
       *framesize = fsize;
       return TRUE;
     }
@@ -327,9 +329,8 @@ gst_amrparse_check_valid_frame (GstBaseParse * parse,
  * Returns: #GstFlowReturn defining the parsing status.
  */
 GstFlowReturn
-gst_amrparse_parse_frame (GstBaseParse * parse, GstBuffer * buffer)
+gst_amrparse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
-  gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
   return GST_FLOW_OK;
 }
 
index 8f7a5d5..9189846 100644 (file)
@@ -352,10 +352,9 @@ static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer);
 static void gst_base_parse_loop (GstPad * pad);
 
 static gboolean gst_base_parse_check_frame (GstBaseParse * parse,
-    GstBuffer * buffer, guint * framesize, gint * skipsize);
-
+    GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
 static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse,
-    GstBuffer * buffer);
+    GstBaseParseFrame * frame);
 
 static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse,
     GstEvent * event);
@@ -504,6 +503,49 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
   GST_DEBUG_OBJECT (parse, "init ok");
 }
 
+/**
+ * gst_base_parse_frame_init:
+ * @parse: #GstBaseParse.
+ * @fmt: #GstBaseParseFrame.
+ *
+ * Sets a #GstBaseParseFrame to initial state.  Currently this means
+ * all fields are zero-ed.
+ */
+void
+gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame)
+{
+  memset (frame, 0, sizeof (*frame));
+}
+
+/* clear == frame no longer to be used following this */
+static void
+gst_base_parse_frame_clear (GstBaseParse * parse, GstBaseParseFrame * frame)
+{
+  /* limited for now */
+  if (frame->buffer) {
+    gst_buffer_unref (frame->buffer);
+    frame->buffer = NULL;
+  }
+}
+
+static inline void
+gst_base_parse_frame_update (GstBaseParse * parse, GstBaseParseFrame * frame,
+    GstBuffer * buf)
+{
+  gst_buffer_replace (&frame->buffer, buf);
+  if (parse->priv->drain) {
+    frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DRAIN;
+  } else {
+    frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_DRAIN);
+  }
+  /* losing sync is pretty much a discont (and vice versa), no ? */
+  if (!parse->priv->discont) {
+    frame->flags |= GST_BASE_PARSE_FRAME_FLAG_SYNC;
+  } else {
+    frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_SYNC);
+  }
+}
+
 static void
 gst_base_parse_reset (GstBaseParse * parse)
 {
@@ -587,9 +629,9 @@ gst_base_parse_reset (GstBaseParse * parse)
  */
 static gboolean
 gst_base_parse_check_frame (GstBaseParse * parse,
-    GstBuffer * buffer, guint * framesize, gint * skipsize)
+    GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
 {
-  *framesize = GST_BUFFER_SIZE (buffer);
+  *framesize = GST_BUFFER_SIZE (frame->buffer);
   *skipsize = 0;
   return TRUE;
 }
@@ -603,8 +645,10 @@ gst_base_parse_check_frame (GstBaseParse * parse,
  * Default callback for parse_frame.
  */
 static GstFlowReturn
-gst_base_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer)
+gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
+  GstBuffer *buffer = frame->buffer;
+
   if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
       GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts)) {
     GST_BUFFER_TIMESTAMP (buffer) = parse->priv->next_ts;
@@ -1114,23 +1158,22 @@ gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min,
  * running average bitrate of the stream so far.
  */
 static void
-gst_base_parse_update_bitrates (GstBaseParse * parse, GstBuffer * buffer)
+gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
   /* Only update the tag on a 10 kbps delta */
   static const gint update_threshold = 10000;
 
   GstBaseParseClass *klass;
   guint64 data_len, frame_dur;
-  gint overhead = 0, frame_bitrate, old_avg_bitrate;
+  gint overhead, frame_bitrate, old_avg_bitrate;
   gboolean update_min = FALSE, update_avg = FALSE, update_max = FALSE;
+  GstBuffer *buffer = frame->buffer;
 
   klass = GST_BASE_PARSE_GET_CLASS (parse);
 
-  if (klass->get_frame_overhead) {
-    overhead = klass->get_frame_overhead (parse, buffer);
-    if (overhead == -1)
-      return;
-  }
+  overhead = frame->overhead;
+  if (overhead == -1)
+    return;
 
   data_len = GST_BUFFER_SIZE (buffer) - overhead;
   parse->priv->data_bytecount += data_len;
@@ -1391,11 +1434,16 @@ gst_base_parse_check_media (GstBaseParse * parse)
  * Returns: #GstFlowReturn
  */
 static GstFlowReturn
-gst_base_parse_handle_and_push_buffer (GstBaseParse * parse,
-    GstBaseParseClass * klass, GstBuffer * buffer)
+gst_base_parse_handle_and_push_frame (GstBaseParse * parse,
+    GstBaseParseClass * klass, GstBaseParseFrame * frame)
 {
   GstFlowReturn ret;
   gint64 offset;
+  GstBuffer *buffer;
+
+  g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
+
+  buffer = frame->buffer;
 
   if (parse->priv->discont) {
     GST_DEBUG_OBJECT (parse, "marking DISCONT");
@@ -1417,7 +1465,11 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse,
 
   /* store offset as it might get overwritten */
   offset = GST_BUFFER_OFFSET (buffer);
-  ret = klass->parse_frame (parse, buffer);
+  ret = klass->parse_frame (parse, frame);
+  /* sync */
+  buffer = frame->buffer;
+  /* subclass must play nice */
+  g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
 
   /* check initial frame to determine if subclass/format can provide ts.
    * If so, that allows and enables extra seek and duration determining options */
@@ -1446,7 +1498,7 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse,
   }
 
   /* re-use default handler to add missing metadata as-much-as-possible */
-  gst_base_parse_parse_frame (parse, buffer);
+  gst_base_parse_parse_frame (parse, frame);
   if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
       GST_BUFFER_DURATION_IS_VALID (buffer)) {
     parse->priv->next_ts =
@@ -1468,34 +1520,40 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse,
    * frames to decide on the format and queues them internally */
   /* convert internal flow to OK and mark discont for the next buffer. */
   if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
-    gst_buffer_unref (buffer);
+    gst_base_parse_frame_clear (parse, frame);
     return GST_FLOW_OK;
   } else if (ret != GST_FLOW_OK) {
     return ret;
   }
 
-  return gst_base_parse_push_buffer (parse, buffer);
+  return gst_base_parse_push_frame (parse, frame);
 }
 
 /**
- * gst_base_parse_push_buffer:
+ * gst_base_parse_push_frame:
  * @parse: #GstBaseParse.
- * @buffer: #GstBuffer.
+ * @frame: #GstBaseParseFrame.
  *
- * Pushes the buffer downstream, sends any pending events and
+ * Pushes the frame downstream, sends any pending events and
  * does some timestamp and segment handling.
  *
- * This must be called with srcpad STREAM_LOCK held.
+ * This must be called with sinkpad STREAM_LOCK held.
  *
  * Returns: #GstFlowReturn
  */
 GstFlowReturn
-gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
+gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
   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);
+  GstBuffer *buffer;
+
+  g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
+  g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR);
+
+  buffer = frame->buffer;
 
   GST_LOG_OBJECT (parse,
       "processing buffer of size %d with ts %" GST_TIME_FORMAT
@@ -1505,13 +1563,12 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
 
   /* update stats */
   parse->priv->bytecount += GST_BUFFER_SIZE (buffer);
-  if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME)) {
+  if (G_LIKELY (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME))) {
     parse->priv->framecount++;
     if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
       parse->priv->acc_duration += GST_BUFFER_DURATION (buffer);
     }
   }
-  GST_BUFFER_FLAG_UNSET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME);
   if (parse->priv->update_interval &&
       (parse->priv->framecount % parse->priv->update_interval) == 0)
     gst_base_parse_update_duration (parse);
@@ -1525,8 +1582,6 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
   /* should have caps by now */
   g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR);
 
-  gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
-
   /* segment adjustment magic; only if we are running the whole show */
   if (!parse->priv->passthrough && parse->segment.rate > 0.0 &&
       (parse->priv->pad_mode == GST_ACTIVATE_PULL ||
@@ -1615,7 +1670,7 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
 
   /* update bitrates and optionally post corresponding tags
    * (following newsegment) */
-  gst_base_parse_update_bitrates (parse, buffer);
+  gst_base_parse_update_bitrates (parse, frame);
 
   if (G_UNLIKELY (parse->priv->pending_events)) {
     GList *l;
@@ -1627,15 +1682,26 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
     parse->priv->pending_events = NULL;
   }
 
-  if (klass->pre_push_buffer)
-    ret = klass->pre_push_buffer (parse, buffer);
-  else
-    ret = GST_BASE_PARSE_FLOW_CLIP;
+  if (klass->pre_push_frame) {
+    ret = klass->pre_push_frame (parse, frame);
+  } else {
+    frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
+  }
+
+  /* take final ownership of frame buffer */
+  buffer = frame->buffer;
+  frame->buffer = NULL;
+
+  /* subclass must play nice */
+  g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
+
+  /* decorate */
+  gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
 
   parse->priv->seen_keyframe |= parse->priv->is_video &&
       !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
 
-  if (ret == GST_BASE_PARSE_FLOW_CLIP) {
+  if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_CLIP) {
     if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
         GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
         GST_BUFFER_TIMESTAMP (buffer) >
@@ -1693,6 +1759,8 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
       parse->segment.last_stop < last_stop)
     gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop);
 
+  gst_base_parse_frame_clear (parse, frame);
+
   return ret;
 }
 
@@ -1879,16 +1947,19 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
   const guint8 *data;
   guint old_min_size = 0, min_size, av;
   GstClockTime timestamp;
+  GstBaseParseFrame _frame = { 0, };
+  GstBaseParseFrame *frame;
 
   parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad));
   bclass = GST_BASE_PARSE_GET_CLASS (parse);
+  frame = &_frame;
 
   if (G_LIKELY (buffer)) {
     GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT,
         GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer));
     if (G_UNLIKELY (parse->priv->passthrough)) {
-      buffer = gst_buffer_make_metadata_writable (buffer);
-      return gst_base_parse_push_buffer (parse, buffer);
+      frame->buffer = gst_buffer_make_metadata_writable (buffer);
+      return gst_base_parse_push_frame (parse, frame);
     }
     /* upstream feeding us in reverse playback;
      * gather each fragment, then process it in single run */
@@ -1906,6 +1977,8 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
   /* Parse and push as many frames as possible */
   /* Stop either when adapter is empty or we are flushing */
   while (!parse->priv->flushing) {
+    gboolean res;
+
     tmpbuf = gst_buffer_new ();
 
     old_min_size = 0;
@@ -1949,7 +2022,10 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
       }
 
       skip = -1;
-      if (bclass->check_valid_frame (parse, tmpbuf, &fsize, &skip)) {
+      gst_base_parse_frame_update (parse, frame, tmpbuf);
+      res = bclass->check_valid_frame (parse, frame, &fsize, &skip);
+      gst_buffer_replace (&frame->buffer, NULL);
+      if (res) {
         if (gst_adapter_available (parse->adapter) < fsize) {
           GST_DEBUG_OBJECT (parse,
               "found valid frame but not enough data available (only %d bytes)",
@@ -2031,7 +2107,8 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
       parse->priv->prev_ts = parse->priv->next_ts = timestamp;
     }
 
-    ret = gst_base_parse_handle_and_push_buffer (parse, bclass, outbuf);
+    frame->buffer = outbuf;
+    ret = gst_base_parse_handle_and_push_frame (parse, bclass, frame);
     GST_PAD_STREAM_UNLOCK (parse->srcpad);
 
     if (ret != GST_FLOW_OK) {
@@ -2195,19 +2272,20 @@ exit:
  * ajusts sync, drain and offset going along */
 static GstFlowReturn
 gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
-    GstBuffer ** buf, gboolean full)
+    GstBaseParseFrame * frame, gboolean full)
 {
   GstBuffer *buffer, *outbuf;
   GstFlowReturn ret = GST_FLOW_OK;
   guint fsize = 0, min_size, old_min_size = 0;
   gint skip = 0;
 
-  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
+  g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
 
   GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT
       " (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset);
 
   while (TRUE) {
+    gboolean res;
 
     min_size = MAX (parse->priv->min_frame_size, fsize);
     /* loop safety check */
@@ -2230,7 +2308,10 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
       parse->priv->drain = TRUE;
 
     skip = -1;
-    if (klass->check_valid_frame (parse, buffer, &fsize, &skip)) {
+    gst_base_parse_frame_update (parse, frame, buffer);
+    res = klass->check_valid_frame (parse, frame, &fsize, &skip);
+    gst_buffer_replace (&frame->buffer, NULL);
+    if (res) {
       parse->priv->drain = FALSE;
       GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip);
       break;
@@ -2289,7 +2370,7 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
 
   parse->priv->offset += fsize;
 
-  *buf = outbuf;
+  frame->buffer = outbuf;
 
 done:
   return ret;
@@ -2315,8 +2396,8 @@ gst_base_parse_loop (GstPad * pad)
 {
   GstBaseParse *parse;
   GstBaseParseClass *klass;
-  GstBuffer *outbuf;
   GstFlowReturn ret = GST_FLOW_OK;
+  GstBaseParseFrame frame = { 0, };
 
   parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
   klass = GST_BASE_PARSE_GET_CLASS (parse);
@@ -2333,12 +2414,12 @@ gst_base_parse_loop (GstPad * pad)
     }
   }
 
-  ret = gst_base_parse_scan_frame (parse, klass, &outbuf, TRUE);
+  ret = gst_base_parse_scan_frame (parse, klass, &frame, TRUE);
   if (ret != GST_FLOW_OK)
     goto done;
 
-  /* This always unrefs the outbuf, even if error occurs */
-  ret = gst_base_parse_handle_and_push_buffer (parse, klass, outbuf);
+  /* This always cleans up frame, even if error occurs */
+  ret = gst_base_parse_handle_and_push_frame (parse, klass, &frame);
 
   /* eat expected eos signalling past segment in reverse playback */
   if (parse->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED &&
@@ -2708,48 +2789,6 @@ gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
       lead_out, parse->priv->lead_out_ts / GST_MSECOND);
 }
 
-/**
- * gst_base_parse_get_sync:
- * @parse: the #GstBaseParse to query
- *
- * Returns: TRUE if parser is considered 'in sync'.  That is, frames have been
- * continuously successfully parsed and pushed.
- */
-gboolean
-gst_base_parse_get_sync (GstBaseParse * parse)
-{
-  gboolean ret;
-
-  g_return_val_if_fail (parse != NULL, FALSE);
-
-  /* losing sync is pretty much a discont (and vice versa), no ? */
-  ret = !parse->priv->discont;
-
-  GST_DEBUG_OBJECT (parse, "sync: %d", ret);
-  return ret;
-}
-
-/**
- * gst_base_parse_get_drain:
- * @parse: the #GstBaseParse to query
- *
- * Returns: TRUE if parser is currently 'draining'.  That is, leftover data
- * (e.g. in FLUSH or EOS situation) is being parsed.
- */
-gboolean
-gst_base_parse_get_drain (GstBaseParse * parse)
-{
-  gboolean ret;
-
-  g_return_val_if_fail (parse != NULL, FALSE);
-
-  /* losing sync is pretty much a discont (and vice versa), no ? */
-  ret = parse->priv->drain;
-
-  GST_DEBUG_OBJECT (parse, "drain: %d", ret);
-  return ret;
-}
-
 static gboolean
 gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format,
     GstClockTime * duration)
@@ -2941,6 +2980,7 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos,
   gboolean orig_drain, orig_discont;
   GstFlowReturn ret = GST_FLOW_OK;
   GstBuffer *buf = NULL;
+  GstBaseParseFrame frame = { 0, };
 
   g_return_val_if_fail (GST_FLOW_ERROR, pos != NULL);
   g_return_val_if_fail (GST_FLOW_ERROR, time != NULL);
@@ -2961,10 +3001,11 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos,
 
   /* jump elsewhere and locate next frame */
   parse->priv->offset = *pos;
-  ret = gst_base_parse_scan_frame (parse, klass, &buf, FALSE);
+  ret = gst_base_parse_scan_frame (parse, klass, &frame, FALSE);
   if (ret != GST_FLOW_OK)
     goto done;
 
+  buf = frame.buffer;
   GST_LOG_OBJECT (parse,
       "peek parsing frame at offset %" G_GUINT64_FORMAT
       " (%#" G_GINT64_MODIFIER "x) of size %d",
@@ -2972,12 +3013,13 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos,
 
   /* get offset first, subclass parsing might dump other stuff in there */
   *pos = GST_BUFFER_OFFSET (buf);
-  ret = klass->parse_frame (parse, buf);
+  ret = klass->parse_frame (parse, &frame);
+  buf = frame.buffer;
 
   /* but it should provide proper time */
   *time = GST_BUFFER_TIMESTAMP (buf);
   *duration = GST_BUFFER_DURATION (buf);
-  gst_buffer_unref (buf);
+  gst_base_parse_frame_clear (parse, &frame);
 
   GST_LOG_OBJECT (parse,
       "frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT,
index 5a4b674..d5d4415 100644 (file)
@@ -90,25 +90,78 @@ G_BEGIN_DECLS
 #define GST_BASE_PARSE_FLOW_DROPPED   GST_FLOW_CUSTOM_SUCCESS
 
 /**
- * GST_BASE_PARSE_FLOW_CLIP:
+ * GstBaseParseFrameFlags:
+ * @GST_BASE_PARSE_FRAME_FLAG_NONE: no flag
+ * @GST_BASE_PARSE_FRAME_FLAG_SYNC: indicates if parsing is 'in sync'
+ * @GST_BASE_PARSE_FRAME_FLAG_DRAIN: indicates if parser is 'draining'.
+ *   That is, leftover data (e.g. in FLUSH or EOS situation) is being parsed.
+ * @GST_BASE_PARSE_FRAME_FLAG_NO_FRAME: set to indicate this buffer should not be
+ *   counted as frame, e.g. if this frame is dependent on a previous one.
+ *   As it is not counted as a frame, bitrate increases but frame to time
+ *   conversions are maintained.
+ * @GST_BASE_PARSE_FRAME_FLAG_CLIP: @pre_push_buffer can set this to indicate
+ *    that regular segment clipping can still be performed (as opposed to
+ *    any custom one having been done).
  *
- * A #GstFlowReturn that can be returned from pre_push_buffer to
- * indicate that regular segment clipping should be performed.
+ * Flags to be used in a #GstBaseParseFrame.
  *
  * Since: 0.10.x
  */
-#define GST_BASE_PARSE_FLOW_CLIP      GST_FLOW_CUSTOM_SUCCESS_1
+typedef enum {
+  GST_BASE_PARSE_FRAME_FLAG_NONE         = 0,
+  GST_BASE_PARSE_FRAME_FLAG_SYNC         = (1 << 0),
+  GST_BASE_PARSE_FRAME_FLAG_DRAIN        = (1 << 1),
+  GST_BASE_PARSE_FRAME_FLAG_NO_FRAME     = (1 << 2),
+  GST_BASE_PARSE_FRAME_FLAG_CLIP         = (1 << 3)
+} GstBaseParseFrameFlags;
 
 /**
- * GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME:
+ * GstBaseParseFrame:
+ * @buffer: data to check for valid frame or parsed frame.
+ *   Subclass is allowed to replace this buffer.
+ * @overhead: subclass can set this to indicates the metadata overhead
+ *   for the given frame, which is then used to enable more accurate bitrate
+ *   computations. If this is -1, it is assumed that this frame should be
+ *   skipped in bitrate calculation.
+ * @flags: a combination of input and output #GstBaseParseFrameFlags that
+ *  convey additional context to subclass or allow subclass to tune
+ *  subsequent #GstBaseParse actions.
  *
- * A #GstBufferFlag that can be set to have this buffer not counted as frame,
- * e.g. if this frame is dependent on a previous one.  As it is not counted as
- * a frame, bitrate increases but frame to time conversions are maintained.
+ * Frame (context) data passed to each frame parsing virtual methods.  In
+ * addition to providing the data to be checked for a valid frame or an already
+ * identified frame, it conveys additional metadata or control information
+ * from and to the subclass w.r.t. the particular frame in question (rather
+ * than global parameters).  Some of these may apply to each parsing stage, others
+ * only to some a particular one.  These parameters are effectively zeroed at start
+ * of each frame's processing, i.e. parsing virtual method invocation sequence.
  *
  * Since: 0.10.x
  */
-#define GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME     GST_BUFFER_FLAG_LAST
+typedef struct {
+  GstBuffer       *buffer;
+  guint           flags;
+  gint            overhead;
+} GstBaseParseFrame;
+
+/**
+ * GST_BASE_PARSE_FRAME_SYNC:
+ * @frame: base parse frame instance
+ *
+ * Obtains current sync status indicated in frame.
+ *
+ * Since: 0.10.x
+ */
+#define GST_BASE_PARSE_FRAME_SYNC(frame)     (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_SYNC))
+
+/**
+ * GST_BASE_PARSE_FRAME_DRAIN:
+ * @frame: base parse frame instance
+ *
+ * Obtains current drain status indicated in frame.
+ *
+ * Since: 0.10.x
+ */
+#define GST_BASE_PARSE_FRAME_DRAIN(frame)    (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_DRAIN))
 
 
 /**
@@ -118,6 +171,8 @@ G_BEGIN_DECLS
  * GST_BASE_PARSE_SEEK_TABLE: Additional metadata provides more accurate seeking.
  *
  * Indicates what level (of quality) of seeking is possible.
+ *
+ * Since: 0.10.x
  */
 typedef enum _GstBaseParseSeekable {
   GST_BASE_PARSE_SEEK_NONE,
@@ -221,12 +276,15 @@ struct _GstBaseParseClass {
                                        GstCaps *caps);
 
   gboolean      (*check_valid_frame)  (GstBaseParse *parse,
-                                       GstBuffer *buffer,
+                                       GstBaseParseFrame *frame,
                                        guint *framesize,
                                        gint *skipsize);
 
   GstFlowReturn (*parse_frame)        (GstBaseParse *parse,
-                                       GstBuffer *buffer);
+                                       GstBaseParseFrame *frame);
+
+  GstFlowReturn (*pre_push_frame)     (GstBaseParse *parse,
+                                       GstBaseParseFrame *frame);
 
   gboolean      (*convert)            (GstBaseParse * parse,
                                        GstFormat src_format,
@@ -240,21 +298,16 @@ struct _GstBaseParseClass {
   gboolean      (*src_event)          (GstBaseParse *parse,
                                        GstEvent *event);
 
-  gint          (*get_frame_overhead) (GstBaseParse *parse,
-                                       GstBuffer *buf);
-
-  GstFlowReturn (*pre_push_buffer)    (GstBaseParse *parse,
-                                       GstBuffer *buf);
-
   /*< private >*/
-  gpointer       _gst_reserved[GST_PADDING_LARGE];  
+  gpointer       _gst_reserved[GST_PADDING_LARGE];
 };
 
 GType           gst_base_parse_get_type         (void);
 
+void gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame);
 
-GstFlowReturn gst_base_parse_push_buffer (GstBaseParse *parse,
-                                          GstBuffer *buffer);
+GstFlowReturn gst_base_parse_push_frame (GstBaseParse *parse,
+                                          GstBaseParseFrame *frame);
 
 void gst_base_parse_set_duration (GstBaseParse *parse,
                                   GstFormat fmt, gint64 duration, gint interval);
@@ -262,17 +315,13 @@ void gst_base_parse_set_duration (GstBaseParse *parse,
 void gst_base_parse_set_seek (GstBaseParse * parse,
                               GstBaseParseSeekable seek, guint bitrate);
 
-void gst_base_parse_set_min_frame_size (GstBaseParse *parse,
-                                        guint min_size);
+void gst_base_parse_set_min_frame_size (GstBaseParse *parse, guint min_size);
+
 void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough);
 
 void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
                                      guint fps_den, guint lead_in, guint lead_out);
 
-gboolean gst_base_parse_get_sync (GstBaseParse * parse);
-
-gboolean gst_base_parse_get_drain (GstBaseParse * parse);
-
 gboolean gst_base_parse_convert_default (GstBaseParse * parse,
                                          GstFormat src_format, gint64 src_value,
                                          GstFormat dest_format, gint64 * dest_value);
index 4573d3b..8ef6acd 100644 (file)
@@ -70,9 +70,9 @@ static void gst_dca_parse_finalize (GObject * object);
 static gboolean gst_dca_parse_start (GstBaseParse * parse);
 static gboolean gst_dca_parse_stop (GstBaseParse * parse);
 static gboolean gst_dca_parse_check_valid_frame (GstBaseParse * parse,
-    GstBuffer * buffer, guint * size, gint * skipsize);
+    GstBaseParseFrame * frame, guint * size, gint * skipsize);
 static GstFlowReturn gst_dca_parse_parse_frame (GstBaseParse * parse,
-    GstBuffer * buf);
+    GstBaseParseFrame * frame);
 
 GST_BOILERPLATE (GstDcaParse, gst_dca_parse, GstBaseParse, GST_TYPE_BASE_PARSE);
 
@@ -289,11 +289,12 @@ gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader,
 }
 
 static gboolean
-gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
-    guint * framesize, gint * skipsize)
+gst_dca_parse_check_valid_frame (GstBaseParse * parse,
+    GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
 {
-  GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
   GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
+  GstBuffer *buf = frame->buffer;
+  GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
   gboolean parser_draining;
   gboolean parser_in_sync;
   guint32 sync = 0;
@@ -303,7 +304,7 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
   if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 16))
     return FALSE;
 
-  parser_in_sync = gst_base_parse_get_sync (parse);
+  parser_in_sync = GST_BASE_PARSE_FRAME_SYNC (frame);
 
   if (G_LIKELY (parser_in_sync && dcaparse->last_sync != 0)) {
     off = gst_byte_reader_masked_scan_uint32 (&r, 0xffffffff,
@@ -343,7 +344,7 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
 
   dcaparse->last_sync = sync;
 
-  parser_draining = gst_base_parse_get_drain (parse);
+  parser_draining = GST_BASE_PARSE_FRAME_DRAIN (frame);
 
   if (!parser_in_sync && !parser_draining) {
     /* check for second frame to be sure */
@@ -377,10 +378,11 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
 }
 
 static GstFlowReturn
-gst_dca_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf)
+gst_dca_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
-  GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
   GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
+  GstBuffer *buf = frame->buffer;
+  GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
   guint size, rate, chans, samples;
 
   if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans,
index 378caf4..f991095 100644 (file)
@@ -193,13 +193,11 @@ static void gst_flac_parse_get_property (GObject * object, guint prop_id,
 static gboolean gst_flac_parse_start (GstBaseParse * parse);
 static gboolean gst_flac_parse_stop (GstBaseParse * parse);
 static gboolean gst_flac_parse_check_valid_frame (GstBaseParse * parse,
-    GstBuffer * buffer, guint * framesize, gint * skipsize);
+    GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
 static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse,
-    GstBuffer * buffer);
-static gint gst_flac_parse_get_frame_overhead (GstBaseParse * parse,
-    GstBuffer * buffer);
-static GstFlowReturn gst_flac_parse_pre_push_buffer (GstBaseParse * parse,
-    GstBuffer * buf);
+    GstBaseParseFrame * frame);
+static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse,
+    GstBaseParseFrame * frame);
 
 GST_BOILERPLATE (GstFlacParse, gst_flac_parse, GstBaseParse,
     GST_TYPE_BASE_PARSE);
@@ -244,10 +242,8 @@ gst_flac_parse_class_init (GstFlacParseClass * klass)
   baseparse_class->check_valid_frame =
       GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame);
   baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame);
-  baseparse_class->get_frame_overhead =
-      GST_DEBUG_FUNCPTR (gst_flac_parse_get_frame_overhead);
-  baseparse_class->pre_push_buffer =
-      GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_buffer);
+  baseparse_class->pre_push_frame =
+      GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
 }
 
 static void
@@ -563,15 +559,17 @@ need_more_data:
 }
 
 static gboolean
-gst_flac_parse_frame_is_valid (GstFlacParse * flacparse, GstBuffer * buffer,
-    guint * ret)
+gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
+    GstBaseParseFrame * frame, guint * ret)
 {
+  GstBuffer *buffer;
   const guint8 *data;
   guint max, size, remaining;
   guint i, search_start, search_end;
   FrameHeaderCheckReturn header_ret;
   guint16 block_size;
 
+  buffer = frame->buffer;
   data = GST_BUFFER_DATA (buffer);
   size = GST_BUFFER_SIZE (buffer);
 
@@ -621,7 +619,7 @@ gst_flac_parse_frame_is_valid (GstFlacParse * flacparse, GstBuffer * buffer,
   }
 
   /* For the last frame output everything to the end */
-  if (G_UNLIKELY (gst_base_parse_get_drain (GST_BASE_PARSE (flacparse)))) {
+  if (G_UNLIKELY (GST_BASE_PARSE_FRAME_DRAIN (frame))) {
     if (flacparse->check_frame_checksums) {
       guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
       guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
@@ -648,9 +646,10 @@ need_more:
 
 static gboolean
 gst_flac_parse_check_valid_frame (GstBaseParse * parse,
-    GstBuffer * buffer, guint * framesize, gint * skipsize)
+    GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
 {
   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
+  GstBuffer *buffer = frame->buffer;
   const guint8 *data = GST_BUFFER_DATA (buffer);
 
   if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4))
@@ -689,13 +688,13 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse,
       flacparse->sample_number = 0;
 
       GST_DEBUG_OBJECT (flacparse, "Found sync code");
-      ret = gst_flac_parse_frame_is_valid (flacparse, buffer, &next);
+      ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
       if (ret) {
         *framesize = next;
         return TRUE;
       } else {
         /* If we're at EOS and the frame was not valid, drop it! */
-        if (G_UNLIKELY (gst_base_parse_get_drain (parse))) {
+        if (G_UNLIKELY (GST_BASE_PARSE_FRAME_DRAIN (frame))) {
           GST_WARNING_OBJECT (flacparse, "EOS");
           return FALSE;
         }
@@ -1044,6 +1043,7 @@ push_headers:
   while (flacparse->headers) {
     GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
     GstFlowReturn ret;
+    GstBaseParseFrame frame;
 
     flacparse->headers =
         g_list_delete_link (flacparse->headers, flacparse->headers);
@@ -1051,7 +1051,11 @@ push_headers:
     gst_buffer_set_caps (buf,
         GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse))));
 
-    ret = gst_base_parse_push_buffer (GST_BASE_PARSE (flacparse), buf);
+    /* init, set and give away frame */
+    gst_base_parse_frame_init (GST_BASE_PARSE (flacparse), &frame);
+    frame.buffer = buf;
+    frame.overhead = -1;
+    ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
     if (ret != GST_FLOW_OK) {
       res = FALSE;
       break;
@@ -1175,9 +1179,10 @@ gst_flac_parse_generate_headers (GstFlacParse * flacparse)
 }
 
 static GstFlowReturn
-gst_flac_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer)
+gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
+  GstBuffer *buffer = frame->buffer;
   const guint8 *data = GST_BUFFER_DATA (buffer);
 
   if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
@@ -1312,6 +1317,11 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer)
     GST_BUFFER_DURATION (buffer) =
         GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
 
+    /* To simplify, we just assume that it's a fixed size header and ignore
+     * subframe headers. The first could lead us to being off by 88 bits and
+     * the second even less, so the total inaccuracy is negligible. */
+    frame->overhead = 7;
+
     /* Minimal size of a frame header */
     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
             flacparse->min_framesize));
@@ -1324,22 +1334,8 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer)
   }
 }
 
-static gint
-gst_flac_parse_get_frame_overhead (GstBaseParse * parse, GstBuffer * buffer)
-{
-  GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
-
-  if (flacparse->state != GST_FLAC_PARSE_STATE_DATA)
-    return -1;
-  else
-    /* To simplify, we just assume that it's a fixed size header and ignore
-     * subframe headers. The first could lead us to being off by 88 bits and
-     * the second even less, so the total inaccuracy is negligible. */
-    return 7;
-}
-
 static GstFlowReturn
-gst_flac_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf)
+gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
 
@@ -1349,5 +1345,7 @@ gst_flac_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf)
     flacparse->tags = NULL;
   }
 
-  return GST_BASE_PARSE_FLOW_CLIP;
+  frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
+
+  return GST_FLOW_OK;
 }
index 889efec..d95f8ae 100644 (file)
@@ -82,11 +82,11 @@ static void gst_mpeg_audio_parse_finalize (GObject * object);
 static gboolean gst_mpeg_audio_parse_start (GstBaseParse * parse);
 static gboolean gst_mpeg_audio_parse_stop (GstBaseParse * parse);
 static gboolean gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
-    GstBuffer * buffer, guint * size, gint * skipsize);
+    GstBaseParseFrame * frame, guint * size, gint * skipsize);
 static GstFlowReturn gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
-    GstBuffer * buf);
-static GstFlowReturn gst_mpeg_audio_parse_pre_push_buffer (GstBaseParse * parse,
-    GstBuffer * buf);
+    GstBaseParseFrame * frame);
+static GstFlowReturn gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse,
+    GstBaseParseFrame * frame);
 static gboolean gst_mpeg_audio_parse_convert (GstBaseParse * parse,
     GstFormat src_format, gint64 src_value,
     GstFormat dest_format, gint64 * dest_value);
@@ -164,8 +164,8 @@ gst_mpeg_audio_parse_class_init (GstMpegAudioParseClass * klass)
       GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_check_valid_frame);
   parse_class->parse_frame =
       GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_parse_frame);
-  parse_class->pre_push_buffer =
-      GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_pre_push_buffer);
+  parse_class->pre_push_frame =
+      GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_pre_push_frame);
   parse_class->convert = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_convert);
 
   /* register tags */
@@ -470,11 +470,12 @@ gst_mpeg_audio_parse_head_check (GstMpegAudioParse * mp3parse,
 }
 
 static gboolean
-gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
-    guint * framesize, gint * skipsize)
+gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
+    GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
 {
-  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
   GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
+  GstBuffer *buf = frame->buffer;
+  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
   gint off, bpf;
   gboolean sync, drain, valid, caps_change;
   guint32 header;
@@ -519,8 +520,8 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
   else
     caps_change = FALSE;
 
-  sync = gst_base_parse_get_sync (parse);
-  drain = gst_base_parse_get_drain (parse);
+  sync = GST_BASE_PARSE_FRAME_SYNC (frame);
+  drain = GST_BASE_PARSE_FRAME_DRAIN (frame);
 
   if (!drain && (!sync || caps_change)) {
     if (!gst_mp3parse_validate_extended (mp3parse, buf, header, bpf, drain,
@@ -900,9 +901,11 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
 }
 
 static GstFlowReturn
-gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf)
+gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
+    GstBaseParseFrame * frame)
 {
   GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
+  GstBuffer *buf = frame->buffer;
   guint bitrate, layer, rate, channels, version, mode, crc;
 
   g_return_val_if_fail (GST_BUFFER_SIZE (buf) >= 4, GST_FLOW_ERROR);
@@ -1122,7 +1125,8 @@ gst_mpeg_audio_parse_convert (GstBaseParse * parse, GstFormat src_format,
 }
 
 static GstFlowReturn
-gst_mpeg_audio_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf)
+gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse,
+    GstBaseParseFrame * frame)
 {
   GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
   GstTagList *taglist;
@@ -1188,5 +1192,7 @@ gst_mpeg_audio_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf)
   }
 
   /* usual clipping applies */
-  return GST_BASE_PARSE_FLOW_CLIP;
+  frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
+
+  return GST_FLOW_OK;
 }