basetransform: make new copy_metadata vmethod
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 21 Jul 2011 15:29:13 +0000 (17:29 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Thu, 21 Jul 2011 15:29:13 +0000 (17:29 +0200)
Make a new copy_metadata vmethod and move the code to copy the timestamps, flags
and offsets into a default implementation. This will allow us to give the
subclasses a chance to override the copy method.

libs/gst/base/gstbasetransform.c
libs/gst/base/gstbasetransform.h

index 1419cff..0dafab9 100644 (file)
@@ -328,6 +328,8 @@ static const GstQueryType *gst_base_transform_query_type (GstPad * pad);
 
 static GstFlowReturn default_prepare_output_buffer (GstBaseTransform * trans,
     GstBuffer * inbuf, GstBuffer ** outbuf);
+static gboolean default_copy_metadata (GstBaseTransform * trans,
+    GstBuffer * inbuf, GstBuffer * outbuf);
 
 /* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
 
@@ -375,6 +377,7 @@ gst_base_transform_class_init (GstBaseTransformClass * klass)
       GST_DEBUG_FUNCPTR (gst_base_transform_acceptcaps_default);
   klass->prepare_output_buffer =
       GST_DEBUG_FUNCPTR (default_prepare_output_buffer);
+  klass->copy_metadata = GST_DEBUG_FUNCPTR (default_copy_metadata);
 }
 
 static void
@@ -1379,9 +1382,6 @@ default_prepare_output_buffer (GstBaseTransform * trans,
     GST_DEBUG_OBJECT (trans, "passthrough: reusing input buffer");
     *outbuf = gst_buffer_ref (inbuf);
   } else {
-    gboolean copymeta;
-    guint mask;
-
     /* we can't reuse the input buffer */
     if (priv->pool) {
       GST_DEBUG_OBJECT (trans, "using pool alloc");
@@ -1428,45 +1428,6 @@ default_prepare_output_buffer (GstBaseTransform * trans,
       *outbuf =
           gst_buffer_new_allocate (priv->allocator, outsize, priv->alignment);
     }
-
-    /* now copy the metadata */
-    mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS |
-        GST_BUFFER_FLAG_DELTA_UNIT | GST_BUFFER_FLAG_DISCONT |
-        GST_BUFFER_FLAG_GAP | GST_BUFFER_FLAG_MEDIA1 |
-        GST_BUFFER_FLAG_MEDIA2 | GST_BUFFER_FLAG_MEDIA3;
-
-    /* see if the flags and timestamps match */
-    copymeta =
-        (GST_MINI_OBJECT_FLAGS (*outbuf) & mask) !=
-        (GST_MINI_OBJECT_FLAGS (inbuf) & mask);
-    copymeta |=
-        GST_BUFFER_TIMESTAMP (*outbuf) != GST_BUFFER_TIMESTAMP (inbuf) ||
-        GST_BUFFER_DURATION (*outbuf) != GST_BUFFER_DURATION (inbuf) ||
-        GST_BUFFER_OFFSET (*outbuf) != GST_BUFFER_OFFSET (inbuf) ||
-        GST_BUFFER_OFFSET_END (*outbuf) != GST_BUFFER_OFFSET_END (inbuf);
-    /* we need to modify the metadata when the element is not gap aware,
-     * passthrough is not used and the gap flag is set */
-    copymeta |= !priv->gap_aware && !trans->passthrough
-        && (GST_MINI_OBJECT_FLAGS (*outbuf) & GST_BUFFER_FLAG_GAP);
-
-    if (copymeta) {
-      GST_DEBUG_OBJECT (trans, "copying metadata");
-
-      if (!gst_buffer_is_writable (*outbuf)) {
-        /* this should not happen, buffers allocated from a pool or with
-         * new_allocate should always be writable. */
-        GST_WARNING_OBJECT (trans, "buffer %p not writable", *outbuf);
-        *outbuf = gst_buffer_make_writable (*outbuf);
-      }
-
-      /* when we get here, the metadata should be writable */
-      gst_buffer_copy_into (*outbuf, inbuf,
-          GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
-
-      /* clear the GAP flag when the subclass does not understand it */
-      if (!priv->gap_aware)
-        GST_BUFFER_FLAG_UNSET (*outbuf, GST_BUFFER_FLAG_GAP);
-    }
   }
   return ret;
 
@@ -1478,6 +1439,62 @@ unknown_size:
   }
 }
 
+static gboolean
+default_copy_metadata (GstBaseTransform * trans,
+    GstBuffer * inbuf, GstBuffer * outbuf)
+{
+  GstBaseTransformPrivate *priv;
+  gboolean copymeta;
+  guint mask;
+
+  priv = trans->priv;
+
+  /* now copy the metadata */
+  mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS |
+      GST_BUFFER_FLAG_DELTA_UNIT | GST_BUFFER_FLAG_DISCONT |
+      GST_BUFFER_FLAG_GAP | GST_BUFFER_FLAG_MEDIA1 |
+      GST_BUFFER_FLAG_MEDIA2 | GST_BUFFER_FLAG_MEDIA3;
+
+  /* see if the flags and timestamps match */
+  copymeta =
+      (GST_MINI_OBJECT_FLAGS (outbuf) & mask) !=
+      (GST_MINI_OBJECT_FLAGS (inbuf) & mask);
+  copymeta |=
+      GST_BUFFER_TIMESTAMP (outbuf) != GST_BUFFER_TIMESTAMP (inbuf) ||
+      GST_BUFFER_DURATION (outbuf) != GST_BUFFER_DURATION (inbuf) ||
+      GST_BUFFER_OFFSET (outbuf) != GST_BUFFER_OFFSET (inbuf) ||
+      GST_BUFFER_OFFSET_END (outbuf) != GST_BUFFER_OFFSET_END (inbuf);
+  /* we need to modify the metadata when the element is not gap aware,
+   * passthrough is not used and the gap flag is set */
+  copymeta |= !priv->gap_aware && !trans->passthrough
+      && (GST_MINI_OBJECT_FLAGS (outbuf) & GST_BUFFER_FLAG_GAP);
+
+  if (copymeta) {
+    GST_DEBUG_OBJECT (trans, "copying metadata");
+
+    /* this should not happen, buffers allocated from a pool or with
+     * new_allocate should always be writable. */
+    if (!gst_buffer_is_writable (outbuf))
+      goto not_writable;
+
+    /* when we get here, the metadata should be writable */
+    gst_buffer_copy_into (outbuf, inbuf,
+        GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
+
+    /* clear the GAP flag when the subclass does not understand it */
+    if (!priv->gap_aware)
+      GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_GAP);
+  }
+  return TRUE;
+
+  /* ERRORS */
+not_writable:
+  {
+    GST_WARNING_OBJECT (trans, "buffer %p not writable", outbuf);
+    return FALSE;
+  }
+}
+
 /* Given @caps calcultate the size of one unit.
  *
  * For video caps, this is the size of one frame (and thus one buffer).
@@ -1830,6 +1847,14 @@ no_qos:
         "prepare_output_buffer implementation");
     gst_buffer_unref (*outbuf);
     *outbuf = inbuf;
+  } else {
+    /* copy the metadata */
+    if (bclass->copy_metadata)
+      if (!bclass->copy_metadata (trans, inbuf, *outbuf)) {
+        /* something failed, post a warning */
+        GST_ELEMENT_WARNING (trans, STREAM, NOT_IMPLEMENTED,
+            ("could not copy metadata"), (NULL));
+      }
   }
   GST_DEBUG_OBJECT (trans, "using allocated buffer in %p, out %p", inbuf,
       *outbuf);
index 1dd13ce..090b769 100644 (file)
@@ -181,7 +181,13 @@ struct _GstBaseTransform {
  *                         allocation of output buffers.  Elements that only do
  *                         analysis can return a subbuffer or even just
  *                         increment the reference to the input buffer (if in
- *                         passthrough mode)
+ *                         passthrough mode). The default implementation will
+ *                         use the negotiated allocator or bufferpool and
+ *                         transform_size to allocate an output buffer.
+ * @copy_metadata: Optional.
+ *                 Copy the metadata from the input buffer to the output buffer.
+ *                 The default implementation will copy the flags, timestamps and
+ *                 offsets of the buffer.
  * @before_transform: Optional. Since 0.10.22
  *                    This method is called right before the base class will
  *                    start processing. Dynamic properties or other delayed
@@ -235,7 +241,9 @@ struct _GstBaseTransformClass {
   gboolean      (*src_event)    (GstBaseTransform *trans, GstEvent *event);
 
   GstFlowReturn (*prepare_output_buffer) (GstBaseTransform * trans,
-     GstBuffer *input, GstBuffer **buf);
+     GstBuffer *input, GstBuffer **outbuf);
+
+  gboolean      (*copy_metadata) (GstBaseTransform * trans, GstBuffer *input, GstBuffer *outbuf);
 
   void          (*before_transform)  (GstBaseTransform *trans, GstBuffer *buffer);