videoaggregator: Move aggregated_frame and the pad buffer into the private struct
authorSebastian Dröge <sebastian@centricular.com>
Sat, 5 May 2018 13:49:17 +0000 (15:49 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Sat, 5 May 2018 14:32:19 +0000 (16:32 +0200)
The aggregated_frame is now called prepared_frame and passed to the
prepare_frame and cleanup_frame virtual methods directly. For the
currently queued buffer there is a method on the video aggregator pad
now.

ext/gl/gstglmixer.c
ext/gl/gstglstereomix.c
ext/gl/gstglvideomixer.c
ext/iqa/iqa.c
gst-libs/gst/video/gstvideoaggregator.c
gst-libs/gst/video/gstvideoaggregator.h
gst/compositor/compositor.c

index 327da54..a7d2240 100644 (file)
@@ -39,9 +39,10 @@ static void gst_gl_mixer_pad_get_property (GObject * object, guint prop_id,
 static void gst_gl_mixer_pad_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static gboolean gst_gl_mixer_pad_prepare_frame (GstVideoAggregatorPad * vpad,
-    GstVideoAggregator * vagg);
+    GstVideoAggregator * vagg, GstBuffer * buffer,
+    GstVideoFrame * prepared_frame);
 static void gst_gl_mixer_pad_clean_frame (GstVideoAggregatorPad * vpad,
-    GstVideoAggregator * vagg);
+    GstVideoAggregator * vagg, GstVideoFrame * prepared_frame);
 
 enum
 {
@@ -101,54 +102,45 @@ gst_gl_mixer_pad_set_property (GObject * object, guint prop_id,
 
 static gboolean
 gst_gl_mixer_pad_prepare_frame (GstVideoAggregatorPad * vpad,
-    GstVideoAggregator * vagg)
+    GstVideoAggregator * vagg, GstBuffer * buffer,
+    GstVideoFrame * prepared_frame)
 {
   GstGLMixerPad *pad = GST_GL_MIXER_PAD (vpad);
   GstGLMixer *mix = GST_GL_MIXER (vagg);
+  GstVideoInfo gl_info;
+  GstGLSyncMeta *sync_meta;
 
   pad->current_texture = 0;
-  vpad->aggregated_frame = NULL;
-
-  if (vpad->buffer != NULL) {
-    GstVideoInfo gl_info;
-    GstVideoFrame aggregated_frame;
-    GstGLSyncMeta *sync_meta;
-
-    gst_video_info_set_format (&gl_info,
-        GST_VIDEO_FORMAT_RGBA,
-        GST_VIDEO_INFO_WIDTH (&vpad->info),
-        GST_VIDEO_INFO_HEIGHT (&vpad->info));
-
-    sync_meta = gst_buffer_get_gl_sync_meta (vpad->buffer);
-    if (sync_meta)
-      gst_gl_sync_meta_wait (sync_meta, GST_GL_BASE_MIXER (mix)->context);
-
-    if (!gst_video_frame_map (&aggregated_frame, &gl_info, vpad->buffer,
-            GST_MAP_READ | GST_MAP_GL)) {
-      GST_ERROR_OBJECT (pad, "Failed to map input frame");
-      return FALSE;
-    }
 
-    pad->current_texture = *(guint *) aggregated_frame.data[0];
+  gst_video_info_set_format (&gl_info,
+      GST_VIDEO_FORMAT_RGBA,
+      GST_VIDEO_INFO_WIDTH (&vpad->info), GST_VIDEO_INFO_HEIGHT (&vpad->info));
+
+  sync_meta = gst_buffer_get_gl_sync_meta (buffer);
+  if (sync_meta)
+    gst_gl_sync_meta_wait (sync_meta, GST_GL_BASE_MIXER (mix)->context);
 
-    vpad->aggregated_frame = g_slice_new0 (GstVideoFrame);
-    *vpad->aggregated_frame = aggregated_frame;
+  if (!gst_video_frame_map (prepared_frame, &gl_info, buffer,
+          GST_MAP_READ | GST_MAP_GL)) {
+    GST_ERROR_OBJECT (pad, "Failed to map input frame");
+    return FALSE;
   }
 
+  pad->current_texture = *(guint *) prepared_frame->data[0];
+
   return TRUE;
 }
 
 static void
 gst_gl_mixer_pad_clean_frame (GstVideoAggregatorPad * vpad,
-    GstVideoAggregator * vagg)
+    GstVideoAggregator * vagg, GstVideoFrame * prepared_frame)
 {
   GstGLMixerPad *pad = GST_GL_MIXER_PAD (vpad);
 
   pad->current_texture = 0;
-  if (vpad->aggregated_frame) {
-    gst_video_frame_unmap (vpad->aggregated_frame);
-    g_slice_free (GstVideoFrame, vpad->aggregated_frame);
-    vpad->aggregated_frame = NULL;
+  if (prepared_frame->buffer) {
+    gst_video_frame_unmap (prepared_frame);
+    memset (prepared_frame, 0, sizeof (GstVideoFrame));
   }
 }
 
index 4d72dfa..e9037be 100644 (file)
@@ -88,7 +88,7 @@ G_DEFINE_TYPE_WITH_CODE (GstGLStereoMix, gst_gl_stereo_mix, GST_TYPE_GL_MIXER,
 
 static GstCaps *_update_caps (GstVideoAggregator * vagg, GstCaps * caps);
 static gboolean _negotiated_caps (GstAggregator * aggregator, GstCaps * caps);
-gboolean gst_gl_stereo_mix_make_output (GstGLStereoMix * mix);
+static gboolean gst_gl_stereo_mix_make_output (GstGLStereoMix * mix);
 static gboolean gst_gl_stereo_mix_process_frames (GstGLStereoMix * mixer);
 
 #define DEFAULT_DOWNMIX GST_GL_STEREO_DOWNMIX_ANAGLYPH_GREEN_MAGENTA_DUBOIS
@@ -301,7 +301,7 @@ gst_gl_stereo_mix_get_output_buffer (GstVideoAggregator * videoaggregator,
   return ret;
 }
 
-gboolean
+static gboolean
 gst_gl_stereo_mix_make_output (GstGLStereoMix * mix)
 {
   GList *walk;
@@ -316,11 +316,12 @@ gst_gl_stereo_mix_make_output (GstGLStereoMix * mix)
   while (walk) {
     GstVideoAggregatorPad *vaggpad = walk->data;
     GstGLStereoMixPad *pad = walk->data;
+    GstBuffer *buffer = gst_video_aggregator_pad_get_current_buffer (vaggpad);
 
     GST_LOG_OBJECT (mix, "Checking pad %" GST_PTR_FORMAT, vaggpad);
 
-    if (vaggpad->buffer != NULL) {
-      pad->current_buffer = vaggpad->buffer;
+    if (buffer != NULL) {
+      pad->current_buffer = buffer;
 
       GST_DEBUG_OBJECT (pad, "Got buffer %" GST_PTR_FORMAT,
           pad->current_buffer);
index 26a42d6..3879dbb 100644 (file)
@@ -1583,9 +1583,10 @@ gst_gl_video_mixer_callback (gpointer stuff)
     {
       GstVideoAffineTransformationMeta *af_meta;
       gfloat matrix[16];
+      GstBuffer *buffer =
+          gst_video_aggregator_pad_get_current_buffer (vagg_pad);
 
-      af_meta =
-          gst_buffer_get_video_affine_transformation_meta (vagg_pad->buffer);
+      af_meta = gst_buffer_get_video_affine_transformation_meta (buffer);
       gst_gl_get_affine_transformation_meta_as_ndc_ext (af_meta, matrix);
       gst_gl_shader_set_uniform_matrix_4fv (video_mixer->shader,
           "u_transformation", 1, FALSE, matrix);
index 2500adc..8c3e4a6 100644 (file)
@@ -264,14 +264,16 @@ gst_iqa_aggregate_frames (GstVideoAggregator * vagg, GstBuffer * outbuf)
   GST_OBJECT_LOCK (vagg);
   for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) {
     GstVideoAggregatorPad *pad = l->data;
+    GstVideoFrame *prepared_frame =
+        gst_video_aggregator_pad_get_prepared_frame (pad);
 
-    if (pad->aggregated_frame != NULL) {
+    if (prepared_frame != NULL) {
       if (!ref_frame) {
-        ref_frame = pad->aggregated_frame;
+        ref_frame = prepared_frame;
       } else {
         gboolean res;
         gchar *padname = gst_pad_get_name (pad);
-        GstVideoFrame *cmp_frame = pad->aggregated_frame;
+        GstVideoFrame *cmp_frame = prepared_frame;
 
         res = compare_frames (self, ref_frame, cmp_frame, outbuf, msg_structure,
             padname);
index 4c267fd..cdbf260 100644 (file)
@@ -65,6 +65,9 @@ enum
 
 struct _GstVideoAggregatorPadPrivate
 {
+  GstBuffer *buffer;
+  GstVideoFrame prepared_frame;
+
   /* properties */
   guint zorder;
   gboolean repeat_after_eos;
@@ -146,7 +149,7 @@ _flush_pad (GstAggregatorPad * aggpad, GstAggregator * aggregator)
   GstVideoAggregatorPad *pad = GST_VIDEO_AGGREGATOR_PAD (aggpad);
 
   gst_video_aggregator_reset_qos (vagg);
-  gst_buffer_replace (&pad->buffer, NULL);
+  gst_buffer_replace (&pad->priv->buffer, NULL);
   pad->priv->start_time = -1;
   pad->priv->end_time = -1;
 
@@ -259,28 +262,26 @@ gst_video_aggregator_pad_finalize (GObject * o)
 
 static gboolean
 gst_video_aggregator_pad_prepare_frame (GstVideoAggregatorPad * pad,
-    GstVideoAggregator * vagg)
+    GstVideoAggregator * vagg, GstBuffer * buffer,
+    GstVideoFrame * prepared_frame)
 {
-  guint outsize;
-  GstVideoFrame *converted_frame;
-  GstBuffer *converted_buf = NULL;
-  GstVideoFrame *frame;
-  static GstAllocationParams params = { 0, 15, 0, 0, };
+  GstVideoFrame frame;
 
-  if (!pad->buffer)
+  if (!pad->priv->buffer)
     return TRUE;
 
-  frame = g_slice_new0 (GstVideoFrame);
-
-  if (!gst_video_frame_map (frame, &pad->info, pad->buffer, GST_MAP_READ)) {
+  if (!gst_video_frame_map (&frame, &pad->info, pad->priv->buffer,
+          GST_MAP_READ)) {
     GST_WARNING_OBJECT (vagg, "Could not map input buffer");
     return FALSE;
   }
 
   if (pad->priv->convert) {
+    GstVideoFrame converted_frame;
+    GstBuffer *converted_buf = NULL;
+    static GstAllocationParams params = { 0, 15, 0, 0, };
     gint converted_size;
-
-    converted_frame = g_slice_new0 (GstVideoFrame);
+    guint outsize;
 
     /* We wait until here to set the conversion infos, in case vagg->info changed */
     converted_size = pad->priv->conversion_info.size;
@@ -288,37 +289,32 @@ gst_video_aggregator_pad_prepare_frame (GstVideoAggregatorPad * pad,
     converted_size = converted_size > outsize ? converted_size : outsize;
     converted_buf = gst_buffer_new_allocate (NULL, converted_size, &params);
 
-    if (!gst_video_frame_map (converted_frame, &(pad->priv->conversion_info),
+    if (!gst_video_frame_map (&converted_frame, &(pad->priv->conversion_info),
             converted_buf, GST_MAP_READWRITE)) {
       GST_WARNING_OBJECT (vagg, "Could not map converted frame");
 
-      g_slice_free (GstVideoFrame, converted_frame);
-      gst_video_frame_unmap (frame);
-      g_slice_free (GstVideoFrame, frame);
+      gst_video_frame_unmap (&frame);
       return FALSE;
     }
 
-    gst_video_converter_frame (pad->priv->convert, frame, converted_frame);
+    gst_video_converter_frame (pad->priv->convert, &frame, &converted_frame);
     pad->priv->converted_buffer = converted_buf;
-    gst_video_frame_unmap (frame);
-    g_slice_free (GstVideoFrame, frame);
+    gst_video_frame_unmap (&frame);
+    *prepared_frame = converted_frame;
   } else {
-    converted_frame = frame;
+    *prepared_frame = frame;
   }
 
-  pad->aggregated_frame = converted_frame;
-
   return TRUE;
 }
 
 static void
 gst_video_aggregator_pad_clean_frame (GstVideoAggregatorPad * pad,
-    GstVideoAggregator * vagg)
+    GstVideoAggregator * vagg, GstVideoFrame * prepared_frame)
 {
-  if (pad->aggregated_frame) {
-    gst_video_frame_unmap (pad->aggregated_frame);
-    g_slice_free (GstVideoFrame, pad->aggregated_frame);
-    pad->aggregated_frame = NULL;
+  if (prepared_frame->buffer) {
+    gst_video_frame_unmap (prepared_frame);
+    memset (prepared_frame, 0, sizeof (GstVideoFrame));
   }
 
   if (pad->priv->converted_buffer) {
@@ -368,11 +364,77 @@ gst_video_aggregator_pad_init (GstVideoAggregatorPad * vaggpad)
   vaggpad->priv->zorder = DEFAULT_PAD_ZORDER;
   vaggpad->priv->repeat_after_eos = DEFAULT_PAD_REPEAT_AFTER_EOS;
   vaggpad->priv->converted_buffer = NULL;
-  vaggpad->aggregated_frame = NULL;
+  memset (&vaggpad->priv->prepared_frame, 0, sizeof (GstVideoFrame));
 
   vaggpad->priv->convert = NULL;
 }
 
+/**
+ * gst_video_aggregator_pad_has_current_buffer:
+ * @pad: a #GstVideoAggregatorPad
+ *
+ * Checks if the pad currently has a buffer queued that is going to be used
+ * for the current output frame.
+ *
+ * This must only be called from the aggregate_frames() virtual method,
+ * or from the prepare_frame() virtual method of the aggregator pads.
+ *
+ * Returns: %TRUE if the pad has currently a buffer queued
+ */
+gboolean
+gst_video_aggregator_pad_has_current_buffer (GstVideoAggregatorPad * pad)
+{
+  g_return_val_if_fail (GST_IS_VIDEO_AGGREGATOR_PAD (pad), FALSE);
+
+  return pad->priv->buffer != NULL;
+}
+
+/**
+ * gst_video_aggregator_pad_has_current_buffer:
+ * @pad: a #GstVideoAggregatorPad
+ *
+ * Returns the currently queued buffer that is going to be used
+ * for the current output frame.
+ *
+ * This must only be called from the aggregate_frames() virtual method,
+ * or from the prepare_frame() virtual method of the aggregator pads.
+ *
+ * The return value is only valid until aggregate_frames() or prepare_frames()
+ * returns.
+ *
+ * Returns: (transfer none): The currently queued buffer
+ */
+GstBuffer *
+gst_video_aggregator_pad_get_current_buffer (GstVideoAggregatorPad * pad)
+{
+  g_return_val_if_fail (GST_IS_VIDEO_AGGREGATOR_PAD (pad), NULL);
+
+  return pad->priv->buffer;
+}
+
+/**
+ * gst_video_aggregator_pad_get_prepared_frame:
+ * @pad: a #GstVideoAggregatorPad
+ *
+ * Returns the currently prepared video frame that has to be aggregated into
+ * the current output frame.
+ *
+ * This must only be called from the aggregate_frames() virtual method,
+ * or from the prepare_frame() virtual method of the aggregator pads.
+ *
+ * The return value is only valid until aggregate_frames() or prepare_frames()
+ * returns.
+ *
+ * Returns: (transfer none): The currently prepared video frame
+ */
+GstVideoFrame *
+gst_video_aggregator_pad_get_prepared_frame (GstVideoAggregatorPad * pad)
+{
+  g_return_val_if_fail (GST_IS_VIDEO_AGGREGATOR_PAD (pad), NULL);
+
+  return pad->priv->prepared_frame.buffer ? &pad->priv->prepared_frame : NULL;
+}
+
 /**************************************
  * GstVideoAggregator implementation  *
  **************************************/
@@ -1017,7 +1079,7 @@ gst_video_aggregator_reset (GstVideoAggregator * vagg)
   for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) {
     GstVideoAggregatorPad *p = l->data;
 
-    gst_buffer_replace (&p->buffer, NULL);
+    gst_buffer_replace (&p->priv->buffer, NULL);
     p->priv->start_time = -1;
     p->priv->end_time = -1;
 
@@ -1038,7 +1100,7 @@ gst_video_aggregator_fill_queues (GstVideoAggregator * vagg,
   gboolean need_reconfigure = FALSE;
   GstSegment *agg_segment = &GST_AGGREGATOR_PAD (agg->srcpad)->segment;
 
-  /* get a set of buffers into pad->buffer that are within output_start_running_time
+  /* get a set of buffers into pad->priv->buffer that are within output_start_running_time
    * and output_end_running_time taking into account finished and unresponsive pads */
 
   GST_OBJECT_LOCK (vagg);
@@ -1078,7 +1140,7 @@ gst_video_aggregator_fill_queues (GstVideoAggregator * vagg,
             gst_segment_to_running_time (&segment, GST_FORMAT_TIME, start_time);
 
         if (start_time >= output_end_running_time) {
-          if (pad->buffer) {
+          if (pad->priv->buffer) {
             GST_DEBUG_OBJECT (pad, "buffer duration is -1, start_time >= "
                 "output_end_running_time. Keeping previous buffer");
           } else {
@@ -1090,7 +1152,7 @@ gst_video_aggregator_fill_queues (GstVideoAggregator * vagg,
         } else if (start_time < output_start_running_time) {
           GST_DEBUG_OBJECT (pad, "buffer duration is -1, start_time < "
               "output_start_running_time.  Discarding old buffer");
-          gst_buffer_replace (&pad->buffer, buf);
+          gst_buffer_replace (&pad->priv->buffer, buf);
           if (pad->priv->pending_vinfo.finfo) {
             pad->info = pad->priv->pending_vinfo;
             need_reconfigure = TRUE;
@@ -1103,7 +1165,7 @@ gst_video_aggregator_fill_queues (GstVideoAggregator * vagg,
         }
         gst_buffer_unref (buf);
         buf = gst_aggregator_pad_pop_buffer (bpad);
-        gst_buffer_replace (&pad->buffer, buf);
+        gst_buffer_replace (&pad->priv->buffer, buf);
         if (pad->priv->pending_vinfo.finfo) {
           pad->info = pad->priv->pending_vinfo;
           need_reconfigure = TRUE;
@@ -1168,7 +1230,7 @@ gst_video_aggregator_fill_queues (GstVideoAggregator * vagg,
         GST_DEBUG_OBJECT (pad,
             "Taking new buffer with start time %" GST_TIME_FORMAT,
             GST_TIME_ARGS (start_time));
-        gst_buffer_replace (&pad->buffer, buf);
+        gst_buffer_replace (&pad->priv->buffer, buf);
         if (pad->priv->pending_vinfo.finfo) {
           pad->info = pad->priv->pending_vinfo;
           need_reconfigure = TRUE;
@@ -1186,7 +1248,7 @@ gst_video_aggregator_fill_queues (GstVideoAggregator * vagg,
         gst_buffer_unref (buf);
         eos = FALSE;
       } else {
-        gst_buffer_replace (&pad->buffer, buf);
+        gst_buffer_replace (&pad->priv->buffer, buf);
         if (pad->priv->pending_vinfo.finfo) {
           pad->info = pad->priv->pending_vinfo;
           need_reconfigure = TRUE;
@@ -1218,13 +1280,13 @@ gst_video_aggregator_fill_queues (GstVideoAggregator * vagg,
             GST_DEBUG ("I just need more data");
             need_more_data = TRUE;
           } else {
-            gst_buffer_replace (&pad->buffer, NULL);
+            gst_buffer_replace (&pad->priv->buffer, NULL);
           }
         } else if (is_eos) {
           eos = FALSE;
         }
       } else if (is_eos) {
-        gst_buffer_replace (&pad->buffer, NULL);
+        gst_buffer_replace (&pad->priv->buffer, NULL);
       }
     }
   }
@@ -1249,10 +1311,10 @@ sync_pad_values (GstElement * vagg, GstPad * pad, gpointer user_data)
   GstClockTime timestamp;
   gint64 stream_time;
 
-  if (vpad->buffer == NULL)
+  if (vpad->priv->buffer == NULL)
     return TRUE;
 
-  timestamp = GST_BUFFER_TIMESTAMP (vpad->buffer);
+  timestamp = GST_BUFFER_TIMESTAMP (vpad->priv->buffer);
   GST_OBJECT_LOCK (bpad);
   stream_time = gst_segment_to_stream_time (&bpad->segment, GST_FORMAT_TIME,
       timestamp);
@@ -1272,10 +1334,13 @@ prepare_frames (GstElement * agg, GstPad * pad, gpointer user_data)
   GstVideoAggregatorPadClass *vaggpad_class =
       GST_VIDEO_AGGREGATOR_PAD_GET_CLASS (pad);
 
-  if (vpad->buffer == NULL || !vaggpad_class->prepare_frame)
+  memset (&vpad->priv->prepared_frame, 0, sizeof (GstVideoFrame));
+
+  if (vpad->priv->buffer == NULL || !vaggpad_class->prepare_frame)
     return TRUE;
 
-  return vaggpad_class->prepare_frame (vpad, GST_VIDEO_AGGREGATOR_CAST (agg));
+  return vaggpad_class->prepare_frame (vpad, GST_VIDEO_AGGREGATOR_CAST (agg),
+      vpad->priv->buffer, &vpad->priv->prepared_frame);
 }
 
 static gboolean
@@ -1287,7 +1352,9 @@ clean_pad (GstElement * agg, GstPad * pad, gpointer user_data)
       GST_VIDEO_AGGREGATOR_PAD_GET_CLASS (pad);
 
   if (vaggpad_class->clean_frame)
-    vaggpad_class->clean_frame (vpad, vagg);
+    vaggpad_class->clean_frame (vpad, vagg, &vpad->priv->prepared_frame);
+
+  memset (&vpad->priv->prepared_frame, 0, sizeof (GstVideoFrame));
 
   return TRUE;
 }
@@ -1749,11 +1816,11 @@ gst_video_aggregator_flush (GstAggregator * agg)
 
     /* Convert to the output segment rate */
     if (ABS (agg_segment->rate) != abs_rate) {
-      if (ABS (agg_segment->rate) != 1.0 && p->buffer) {
+      if (ABS (agg_segment->rate) != 1.0 && p->priv->buffer) {
         p->priv->start_time /= ABS (agg_segment->rate);
         p->priv->end_time /= ABS (agg_segment->rate);
       }
-      if (abs_rate != 1.0 && p->buffer) {
+      if (abs_rate != 1.0 && p->priv->buffer) {
         p->priv->start_time *= abs_rate;
         p->priv->end_time *= abs_rate;
       }
@@ -1879,7 +1946,7 @@ gst_video_aggregator_release_pad (GstElement * element, GstPad * pad)
   if (last_pad)
     gst_video_aggregator_reset (vagg);
 
-  gst_buffer_replace (&vaggpad->buffer, NULL);
+  gst_buffer_replace (&vaggpad->priv->buffer, NULL);
 
   GST_ELEMENT_CLASS (gst_video_aggregator_parent_class)->release_pad
       (GST_ELEMENT (vagg), pad);
index 471b4c9..af1e026 100644 (file)
@@ -71,9 +71,6 @@ struct _GstVideoAggregatorPad
   /* read-only, with OBJECT_LOCK */
   GstVideoInfo info;
 
-  GstBuffer *buffer;
-  GstVideoFrame *aggregated_frame;
-
   /* Subclasses can force an alpha channel in the (input thus output)
    * colorspace format */
   gboolean needs_alpha;
@@ -102,10 +99,13 @@ struct _GstVideoAggregatorPadClass
                                                GstVideoInfo          * wanted_info);
 
   gboolean           (*prepare_frame)         (GstVideoAggregatorPad * pad,
-                                               GstVideoAggregator    * videoaggregator);
+                                               GstVideoAggregator    * videoaggregator,
+                                               GstBuffer             * buffer,
+                                               GstVideoFrame         * prepared_frame);
 
   void               (*clean_frame)           (GstVideoAggregatorPad * pad,
-                                               GstVideoAggregator    * videoaggregator);
+                                               GstVideoAggregator    * videoaggregator,
+                                               GstVideoFrame         * prepared_frame);
 
   gpointer          _gst_reserved[GST_PADDING_LARGE];
 };
@@ -113,6 +113,15 @@ struct _GstVideoAggregatorPadClass
 GST_VIDEO_BAD_API
 GType gst_video_aggregator_pad_get_type   (void);
 
+GST_VIDEO_BAD_API
+gboolean gst_video_aggregator_pad_has_current_buffer (GstVideoAggregatorPad *pad);
+
+GST_VIDEO_BAD_API
+GstBuffer * gst_video_aggregator_pad_get_current_buffer (GstVideoAggregatorPad *pad);
+
+GST_VIDEO_BAD_API
+GstVideoFrame * gst_video_aggregator_pad_get_prepared_frame (GstVideoAggregatorPad *pad);
+
 #define GST_TYPE_VIDEO_AGGREGATOR (gst_video_aggregator_get_type())
 #define GST_VIDEO_AGGREGATOR(obj) \
         (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_AGGREGATOR, GstVideoAggregator))
index 66cf36c..f5c83fe 100644 (file)
@@ -376,14 +376,13 @@ clamp_rectangle (gint x, gint y, gint w, gint h, gint outer_width,
 
 static gboolean
 gst_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad,
-    GstVideoAggregator * vagg)
+    GstVideoAggregator * vagg, GstBuffer * buffer,
+    GstVideoFrame * prepared_frame)
 {
   GstCompositor *comp = GST_COMPOSITOR (vagg);
   GstCompositorPad *cpad = GST_COMPOSITOR_PAD (pad);
   guint outsize;
-  GstVideoFrame *converted_frame;
-  GstBuffer *converted_buf = NULL;
-  GstVideoFrame *frame;
+  GstVideoFrame frame;
   static GstAllocationParams params = { 0, 15, 0, 0, };
   gint width, height;
   gboolean frame_obscured = FALSE;
@@ -392,9 +391,6 @@ gst_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad,
    * Due to the clamping, this is different from the frame width/height above. */
   GstVideoRectangle frame_rect;
 
-  if (!pad->buffer)
-    return TRUE;
-
   /* There's three types of width/height here:
    * 1. GST_VIDEO_FRAME_WIDTH/HEIGHT:
    *     The frame width/height (same as pad->info.height/width;
@@ -476,7 +472,6 @@ gst_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad,
 
   if (cpad->alpha == 0.0) {
     GST_DEBUG_OBJECT (vagg, "Pad has alpha 0.0, not converting frame");
-    converted_frame = NULL;
     goto done;
   }
 
@@ -486,7 +481,6 @@ gst_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad,
   if (frame_rect.w == 0 || frame_rect.h == 0) {
     GST_DEBUG_OBJECT (vagg, "Resulting frame is zero-width or zero-height "
         "(w: %i, h: %i), skipping", frame_rect.w, frame_rect.h);
-    converted_frame = NULL;
     goto done;
   }
 
@@ -523,9 +517,9 @@ gst_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad,
 
     /* Check if there's a buffer to be aggregated, ensure it can't have an alpha
      * channel, then check opacity and frame boundaries */
-    if (pad2->buffer && cpad2->alpha == 1.0 &&
-        !GST_VIDEO_INFO_HAS_ALPHA (&pad2->info) &&
-        is_rectangle_contained (frame_rect, frame2_rect)) {
+    if (gst_video_aggregator_pad_has_current_buffer (pad2)
+        && cpad2->alpha == 1.0 && !GST_VIDEO_INFO_HAS_ALPHA (&pad2->info)
+        && is_rectangle_contained (frame_rect, frame2_rect)) {
       frame_obscured = TRUE;
       GST_DEBUG_OBJECT (pad, "%ix%i@(%i,%i) obscured by %s %ix%i@(%i,%i) "
           "in output of size %ix%i; skipping frame", frame_rect.w, frame_rect.h,
@@ -538,22 +532,18 @@ gst_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad,
   }
   GST_OBJECT_UNLOCK (vagg);
 
-  if (frame_obscured) {
-    converted_frame = NULL;
+  if (frame_obscured)
     goto done;
-  }
 
-  frame = g_slice_new0 (GstVideoFrame);
-
-  if (!gst_video_frame_map (frame, &pad->info, pad->buffer, GST_MAP_READ)) {
+  if (!gst_video_frame_map (&frame, &pad->info, buffer, GST_MAP_READ)) {
     GST_WARNING_OBJECT (vagg, "Could not map input buffer");
     return FALSE;
   }
 
   if (cpad->convert) {
     gint converted_size;
-
-    converted_frame = g_slice_new0 (GstVideoFrame);
+    GstVideoFrame converted_frame;
+    GstBuffer *converted_buf = NULL;
 
     /* We wait until here to set the conversion infos, in case vagg->info changed */
     converted_size = GST_VIDEO_INFO_SIZE (&cpad->conversion_info);
@@ -561,40 +551,36 @@ gst_compositor_pad_prepare_frame (GstVideoAggregatorPad * pad,
     converted_size = converted_size > outsize ? converted_size : outsize;
     converted_buf = gst_buffer_new_allocate (NULL, converted_size, &params);
 
-    if (!gst_video_frame_map (converted_frame, &(cpad->conversion_info),
+    if (!gst_video_frame_map (&converted_frame, &(cpad->conversion_info),
             converted_buf, GST_MAP_READWRITE)) {
       GST_WARNING_OBJECT (vagg, "Could not map converted frame");
 
-      g_slice_free (GstVideoFrame, converted_frame);
-      gst_video_frame_unmap (frame);
-      g_slice_free (GstVideoFrame, frame);
+      gst_video_frame_unmap (&frame);
       return FALSE;
     }
 
-    gst_video_converter_frame (cpad->convert, frame, converted_frame);
+    gst_video_converter_frame (cpad->convert, &frame, &converted_frame);
     cpad->converted_buffer = converted_buf;
-    gst_video_frame_unmap (frame);
-    g_slice_free (GstVideoFrame, frame);
+    gst_video_frame_unmap (&frame);
+    *prepared_frame = converted_frame;
   } else {
-    converted_frame = frame;
+    *prepared_frame = frame;
   }
 
 done:
-  pad->aggregated_frame = converted_frame;
 
   return TRUE;
 }
 
 static void
 gst_compositor_pad_clean_frame (GstVideoAggregatorPad * pad,
-    GstVideoAggregator * vagg)
+    GstVideoAggregator * vagg, GstVideoFrame * prepared_frame)
 {
   GstCompositorPad *cpad = GST_COMPOSITOR_PAD (pad);
 
-  if (pad->aggregated_frame) {
-    gst_video_frame_unmap (pad->aggregated_frame);
-    g_slice_free (GstVideoFrame, pad->aggregated_frame);
-    pad->aggregated_frame = NULL;
+  if (prepared_frame->buffer) {
+    gst_video_frame_unmap (prepared_frame);
+    memset (prepared_frame, 0, sizeof (GstVideoFrame));
   }
 
   if (cpad->converted_buffer) {
@@ -1065,44 +1051,50 @@ gst_compositor_crossfade_frames (GstCompositor * self, GstVideoFrame * outframe)
   for (l = GST_ELEMENT (self)->sinkpads; l; l = l->next) {
     GstVideoAggregatorPad *pad = l->data;
     GstCompositorPad *compo_pad = GST_COMPOSITOR_PAD (pad);
+    GstVideoFrame *prepared_frame =
+        gst_video_aggregator_pad_get_prepared_frame (pad);
 
-    if (compo_pad->crossfade >= 0.0f && pad->aggregated_frame) {
+    if (compo_pad->crossfade >= 0.0f && prepared_frame) {
       gfloat alpha = compo_pad->crossfade * compo_pad->alpha;
       GstVideoAggregatorPad *npad = l->next ? l->next->data : NULL;
-      GstVideoFrame *nframe;
+      GstVideoFrame *next_prepared_frame;
+      GstVideoFrame nframe;
+
+      next_prepared_frame =
+          npad ? gst_video_aggregator_pad_get_prepared_frame (npad) : NULL;
 
       if (!all_crossfading) {
-        nframe = g_slice_new0 (GstVideoFrame);
-        gst_compositor_fill_transparent (self, outframe, nframe);
+        gst_compositor_fill_transparent (self, outframe, &nframe);
       } else {
-        nframe = outframe;
+        nframe = *outframe;
       }
 
-      self->overlay (pad->aggregated_frame,
+      self->overlay (prepared_frame,
           compo_pad->crossfaded ? 0 : compo_pad->xpos,
           compo_pad->crossfaded ? 0 : compo_pad->ypos,
-          alpha, nframe, COMPOSITOR_BLEND_MODE_ADDITIVE);
+          alpha, &nframe, COMPOSITOR_BLEND_MODE_ADDITIVE);
 
-      if (npad && npad->aggregated_frame) {
+      if (npad && next_prepared_frame) {
         GstCompositorPad *next_compo_pad = GST_COMPOSITOR_PAD (npad);
 
         alpha = (1.0 - compo_pad->crossfade) * next_compo_pad->alpha;
-        self->overlay (npad->aggregated_frame, next_compo_pad->xpos,
-            next_compo_pad->ypos, alpha, nframe,
+        self->overlay (next_prepared_frame, next_compo_pad->xpos,
+            next_compo_pad->ypos, alpha, &nframe,
             COMPOSITOR_BLEND_MODE_ADDITIVE);
 
         /* Replace frame with current frame */
-        gst_compositor_pad_clean_frame (npad, vagg);
-        npad->aggregated_frame = !all_crossfading ? nframe : NULL;
+        gst_compositor_pad_clean_frame (npad, vagg, next_prepared_frame);
+        if (!all_crossfading)
+          *next_prepared_frame = nframe;
         next_compo_pad->crossfaded = TRUE;
 
         /* Frame is now consumed, clean it up */
-        gst_compositor_pad_clean_frame (pad, vagg);
-        pad->aggregated_frame = NULL;
+        gst_compositor_pad_clean_frame (pad, vagg, prepared_frame);
       } else {
         GST_LOG_OBJECT (self, "Simply fading out as no following pad found");
-        gst_compositor_pad_clean_frame (pad, vagg);
-        pad->aggregated_frame = !all_crossfading ? nframe : NULL;
+        gst_compositor_pad_clean_frame (pad, vagg, prepared_frame);
+        if (!all_crossfading)
+          *prepared_frame = nframe;
         compo_pad->crossfaded = TRUE;
       }
     }
@@ -1156,9 +1148,11 @@ gst_compositor_aggregate_frames (GstVideoAggregator * vagg, GstBuffer * outbuf)
     for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) {
       GstVideoAggregatorPad *pad = l->data;
       GstCompositorPad *compo_pad = GST_COMPOSITOR_PAD (pad);
+      GstVideoFrame *prepared_frame =
+          gst_video_aggregator_pad_get_prepared_frame (pad);
 
-      if (pad->aggregated_frame != NULL) {
-        composite (pad->aggregated_frame,
+      if (prepared_frame != NULL) {
+        composite (prepared_frame,
             compo_pad->crossfaded ? 0 : compo_pad->xpos,
             compo_pad->crossfaded ? 0 : compo_pad->ypos, compo_pad->alpha,
             outframe, COMPOSITOR_BLEND_MODE_NORMAL);