baseparse: simplify and improve frame state handling
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Wed, 15 Feb 2012 16:11:54 +0000 (17:11 +0100)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Wed, 15 Feb 2012 16:11:54 +0000 (17:11 +0100)
Use a frame flag to signal to subclass it should reset any retained
state w.r.t. frame parsing since the frame being passed is 'new',
i.e. not related to previously passed and processed data.

libs/gst/base/gstbaseparse.c
libs/gst/base/gstbaseparse.h

index e7d9425..e5576ad 100644 (file)
@@ -323,10 +323,10 @@ struct _GstBaseParsePrivate
   /* Newsegment event to be sent after SEEK */
   GstEvent *pending_segment;
 
-  /* frame previously passed to subclass (might be re-used) */
-  GstBaseParseFrame *prev_frame;
-  /* offset corresponding to above frame */
+  /* offset of last parsed frame/data */
   gint64 prev_offset;
+  /* force a new frame, regardless of offset */
+  gboolean new_frame;
   /* whether we are merely scanning for a frame */
   gboolean scanning;
   /* ... and resulting frame, if any */
@@ -762,11 +762,7 @@ gst_base_parse_reset (GstBaseParse * parse)
   if (parse->priv->adapter)
     gst_adapter_clear (parse->priv->adapter);
 
-  /* we know it is not alloc'ed, but maybe other stuff to free, some day ... */
-  if (parse->priv->prev_frame) {
-    gst_base_parse_frame_free (parse->priv->prev_frame);
-    parse->priv->prev_frame = NULL;
-  }
+  parse->priv->new_frame = TRUE;
 
   g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL);
   g_list_free (parse->priv->detect_buffers);
@@ -1082,10 +1078,7 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
       parse->priv->flushing = FALSE;
       parse->priv->discont = TRUE;
       parse->priv->last_ts = GST_CLOCK_TIME_NONE;
-      if (parse->priv->prev_frame) {
-        gst_base_parse_frame_free (parse->priv->prev_frame);
-        parse->priv->prev_frame = NULL;
-      }
+      parse->priv->new_frame = TRUE;
       break;
 
     case GST_EVENT_EOS:
@@ -1725,23 +1718,18 @@ gst_base_parse_prepare_frame (GstBaseParse * parse, GstBuffer * buffer)
 
   GST_BUFFER_OFFSET (buffer) = parse->priv->offset;
 
-  if (parse->priv->prev_frame) {
-    if (parse->priv->prev_offset == parse->priv->offset) {
-      frame = parse->priv->prev_frame;
-    } else {
-      gst_base_parse_frame_free (parse->priv->prev_frame);
-    }
-    parse->priv->prev_frame = NULL;
-  }
-
-  if (!frame) {
-    frame = gst_base_parse_frame_new (buffer, 0, 0);
-  }
+  frame = gst_base_parse_frame_new (buffer, 0, 0);
 
   /* also ensure to update state flags */
   gst_base_parse_frame_update (parse, frame, buffer);
   gst_buffer_unref (buffer);
 
+  if (parse->priv->prev_offset != parse->priv->offset || parse->priv->new_frame) {
+    GST_LOG_OBJECT (parse, "marking as new frame");
+    parse->priv->new_frame = FALSE;
+    frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME;
+  }
+
   frame->offset = parse->priv->prev_offset = parse->priv->offset;
 
   /* use default handler to provide initial (upstream) metadata */
@@ -1750,15 +1738,6 @@ gst_base_parse_prepare_frame (GstBaseParse * parse, GstBuffer * buffer)
   return frame;
 }
 
-static void
-gst_base_parse_unprepare_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
-{
-  g_assert (parse->priv->prev_frame == NULL);
-
-  parse->priv->prev_frame = frame;
-  gst_base_parse_frame_update (parse, frame, NULL);
-}
-
 /* Wraps buffer in a frame and dispatches to subclass.
  * Also manages data skipping and offset handling (including adapter flushing).
  * Takes ownership of @buffer */
@@ -1790,7 +1769,6 @@ gst_base_parse_handle_buffer (GstBaseParse * parse, GstBuffer * buffer,
 
   frame = gst_base_parse_prepare_frame (parse, buffer);
   ret = klass->handle_frame (parse, frame, skip);
-  gst_base_parse_unprepare_frame (parse, frame);
 
   *flushed = parse->priv->flushed;
 
@@ -1805,14 +1783,6 @@ gst_base_parse_handle_buffer (GstBaseParse * parse, GstBuffer * buffer,
   /* subclass can only do one of these, or semantics are too unclear */
   g_assert (*skip == 0 || *flushed == 0);
 
-  /* if it did something, clear frame state,
-   * though this should also trigger the offset check anyway */
-  if (*skip != 0 || *flushed != 0) {
-    GST_LOG_OBJECT (parse, "clearing prev frame");
-    gst_base_parse_frame_free (parse->priv->prev_frame);
-    parse->priv->prev_frame = NULL;
-  }
-
   /* track skipping */
   if (*skip > 0) {
     GstClockTime timestamp;
@@ -1849,6 +1819,8 @@ exit:
     gst_adapter_clear (parse->priv->adapter);
   }
 
+  gst_base_parse_frame_free (frame);
+
   return ret;
 }
 
index f247127..5bef570 100644 (file)
@@ -93,6 +93,9 @@ G_BEGIN_DECLS
 /**
  * GstBaseParseFrameFlags:
  * @GST_BASE_PARSE_FRAME_FLAG_NONE: no flag
+ * @GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME: set by baseclass if current frame
+ *   is passed for processing to the subclass for the first time
+ *   (and not set on subsequent calls with same data).
  * @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
@@ -112,6 +115,7 @@ G_BEGIN_DECLS
  */
 typedef enum {
   GST_BASE_PARSE_FRAME_FLAG_NONE         = 0,
+  GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME    = (1 << 0),
   GST_BASE_PARSE_FRAME_FLAG_NO_FRAME     = (1 << 0),
   GST_BASE_PARSE_FRAME_FLAG_CLIP         = (1 << 1),
   GST_BASE_PARSE_FRAME_FLAG_DROP         = (1 << 2),