aggregator: remove duplicated code fragment
[platform/upstream/gstreamer.git] / libs / gst / base / gstaggregator.c
index 1a95fc9..33752e1 100644 (file)
@@ -221,6 +221,8 @@ struct _GstAggregatorPadPrivate
   GstClockTime time_level;
   GstSegment head_segment;      /* segment before the queue */
 
+  gboolean negotiated;
+
   gboolean eos;
 
   GMutex lock;
@@ -308,6 +310,12 @@ struct _GstAggregatorPrivate
   GstAggregatorStartTimeSelection start_time_selection;
   GstClockTime start_time;
 
+  /* protected by the object lock */
+  GstQuery *allocation_query;
+  GstAllocator *allocator;
+  GstBufferPool *pool;
+  GstAllocationParams allocation_params;
+
   /* properties */
   gint64 latency;               /* protected by both src_lock and all pad locks */
 };
@@ -348,6 +356,8 @@ static GstFlowReturn gst_aggregator_pad_chain_internal (GstAggregator * self,
  *
  * This method guarantees that @func will be called only once for each
  * sink pad.
+ *
+ * Returns: %FALSE if there are no sinkpads or if @func returned %FALSE
  */
 gboolean
 gst_aggregator_iterate_sinkpads (GstAggregator * self,
@@ -743,6 +753,7 @@ static gboolean
 check_events (GstAggregator * self, GstAggregatorPad * pad, gpointer user_data)
 {
   GstEvent *event = NULL;
+  GstQuery *query = NULL;
   GstAggregatorClass *klass = NULL;
   gboolean *processed_event = user_data;
 
@@ -755,19 +766,51 @@ check_events (GstAggregator * self, GstAggregatorPad * pad, gpointer user_data)
       pad->priv->eos = TRUE;
     }
     if (pad->priv->clipped_buffer == NULL &&
-        GST_IS_EVENT (g_queue_peek_tail (&pad->priv->buffers))) {
-      event = g_queue_pop_tail (&pad->priv->buffers);
-      PAD_BROADCAST_EVENT (pad);
+        !GST_IS_BUFFER (g_queue_peek_tail (&pad->priv->buffers))) {
+      if (GST_IS_EVENT (g_queue_peek_tail (&pad->priv->buffers)))
+        event = gst_event_ref (g_queue_peek_tail (&pad->priv->buffers));
+      if (GST_IS_QUERY (g_queue_peek_tail (&pad->priv->buffers)))
+        query = g_queue_peek_tail (&pad->priv->buffers);
     }
     PAD_UNLOCK (pad);
-    if (event) {
+    if (event || query) {
+      gboolean ret;
+
       if (processed_event)
         *processed_event = TRUE;
       if (klass == NULL)
         klass = GST_AGGREGATOR_GET_CLASS (self);
 
-      GST_LOG_OBJECT (pad, "Processing %" GST_PTR_FORMAT, event);
-      klass->sink_event (self, pad, event);
+      if (event) {
+        GST_LOG_OBJECT (pad, "Processing %" GST_PTR_FORMAT, event);
+        gst_event_ref (event);
+        ret = klass->sink_event (self, pad, event);
+
+        PAD_LOCK (pad);
+        if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS)
+          pad->priv->negotiated = ret;
+        if (g_queue_peek_tail (&pad->priv->buffers) == event)
+          gst_event_unref (g_queue_pop_tail (&pad->priv->buffers));
+        gst_event_unref (event);
+      }
+
+      if (query) {
+        GST_LOG_OBJECT (pad, "Processing %" GST_PTR_FORMAT, query);
+        ret = klass->sink_query (self, pad, query);
+
+        PAD_LOCK (pad);
+        if (g_queue_peek_tail (&pad->priv->buffers) == query) {
+          GstStructure *s;
+
+          s = gst_query_writable_structure (query);
+          gst_structure_set (s, "gst-aggregator-retval", G_TYPE_BOOLEAN, ret,
+              NULL);
+          g_queue_pop_tail (&pad->priv->buffers);
+        }
+      }
+
+      PAD_BROADCAST_EVENT (pad);
+      PAD_UNLOCK (pad);
     }
   } while (event != NULL);
 
@@ -797,7 +840,8 @@ gst_aggregator_pad_set_flushing (GstAggregatorPad * aggpad,
         GST_EVENT_TYPE (item->data) == GST_EVENT_EOS ||
         GST_EVENT_TYPE (item->data) == GST_EVENT_SEGMENT ||
         !GST_EVENT_IS_STICKY (item->data)) {
-      gst_mini_object_unref (item->data);
+      if (!GST_IS_QUERY (item->data))
+        gst_mini_object_unref (item->data);
       g_queue_delete_link (&aggpad->priv->buffers, item);
     }
     item = next;
@@ -809,6 +853,232 @@ gst_aggregator_pad_set_flushing (GstAggregatorPad * aggpad,
   PAD_UNLOCK (aggpad);
 }
 
+static GstFlowReturn
+gst_aggregator_default_update_src_caps (GstAggregator * agg, GstCaps * caps,
+    GstCaps ** ret)
+{
+  *ret = gst_caps_ref (caps);
+
+  return GST_FLOW_OK;
+}
+
+static GstCaps *
+gst_aggregator_default_fixate_src_caps (GstAggregator * agg, GstCaps * caps)
+{
+  caps = gst_caps_fixate (caps);
+
+  return caps;
+}
+
+static gboolean
+gst_aggregator_default_negotiated_src_caps (GstAggregator * agg, GstCaps * caps)
+{
+  return TRUE;
+}
+
+
+/* takes ownership of the pool, allocator and query */
+static gboolean
+gst_aggregator_set_allocation (GstAggregator * self,
+    GstBufferPool * pool, GstAllocator * allocator,
+    GstAllocationParams * params, GstQuery * query)
+{
+  GstAllocator *oldalloc;
+  GstBufferPool *oldpool;
+  GstQuery *oldquery;
+
+  GST_DEBUG ("storing allocation query");
+
+  GST_OBJECT_LOCK (self);
+  oldpool = self->priv->pool;
+  self->priv->pool = pool;
+
+  oldalloc = self->priv->allocator;
+  self->priv->allocator = allocator;
+
+  oldquery = self->priv->allocation_query;
+  self->priv->allocation_query = query;
+
+  if (params)
+    self->priv->allocation_params = *params;
+  else
+    gst_allocation_params_init (&self->priv->allocation_params);
+  GST_OBJECT_UNLOCK (self);
+
+  if (oldpool) {
+    GST_DEBUG_OBJECT (self, "deactivating old pool %p", oldpool);
+    gst_buffer_pool_set_active (oldpool, FALSE);
+    gst_object_unref (oldpool);
+  }
+  if (oldalloc) {
+    gst_object_unref (oldalloc);
+  }
+  if (oldquery) {
+    gst_query_unref (oldquery);
+  }
+  return TRUE;
+}
+
+
+static gboolean
+gst_aggregator_decide_allocation (GstAggregator * self, GstQuery * query)
+{
+  GstAggregatorClass *aggclass = GST_AGGREGATOR_GET_CLASS (self);
+
+  if (aggclass->decide_allocation)
+    if (!aggclass->decide_allocation (self, query))
+      return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+gst_aggregator_do_allocation (GstAggregator * self, GstCaps * caps)
+{
+  GstQuery *query;
+  gboolean result = TRUE;
+  GstBufferPool *pool = NULL;
+  GstAllocator *allocator;
+  GstAllocationParams params;
+
+  /* find a pool for the negotiated caps now */
+  GST_DEBUG_OBJECT (self, "doing allocation query");
+  query = gst_query_new_allocation (caps, TRUE);
+  if (!gst_pad_peer_query (self->srcpad, query)) {
+    /* not a problem, just debug a little */
+    GST_DEBUG_OBJECT (self, "peer ALLOCATION query failed");
+  }
+
+  GST_DEBUG_OBJECT (self, "calling decide_allocation");
+  result = gst_aggregator_decide_allocation (self, query);
+
+  GST_DEBUG_OBJECT (self, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result,
+      query);
+
+  if (!result)
+    goto no_decide_allocation;
+
+  /* we got configuration from our peer or the decide_allocation method,
+   * parse them */
+  if (gst_query_get_n_allocation_params (query) > 0) {
+    gst_query_parse_nth_allocation_param (query, 0, &allocator, &params);
+  } else {
+    allocator = NULL;
+    gst_allocation_params_init (&params);
+  }
+
+  if (gst_query_get_n_allocation_pools (query) > 0)
+    gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
+
+  /* now store */
+  result =
+      gst_aggregator_set_allocation (self, pool, allocator, &params, query);
+
+  return result;
+
+  /* Errors */
+no_decide_allocation:
+  {
+    GST_WARNING_OBJECT (self, "Failed to decide allocation");
+    gst_query_unref (query);
+
+    return result;
+  }
+
+}
+
+/* WITH SRC_LOCK held */
+static GstFlowReturn
+gst_aggregator_update_src_caps (GstAggregator * self)
+{
+  GstAggregatorClass *agg_klass = GST_AGGREGATOR_GET_CLASS (self);
+  GstCaps *downstream_caps, *template_caps, *caps = NULL;
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  template_caps = gst_pad_get_pad_template_caps (self->srcpad);
+  downstream_caps = gst_pad_peer_query_caps (self->srcpad, template_caps);
+
+  if (gst_caps_is_empty (downstream_caps)) {
+    GST_INFO_OBJECT (self, "Downstream caps (%"
+        GST_PTR_FORMAT ") not compatible with pad template caps (%"
+        GST_PTR_FORMAT ")", downstream_caps, template_caps);
+    ret = GST_FLOW_NOT_NEGOTIATED;
+    goto done;
+  }
+
+  g_assert (agg_klass->update_src_caps);
+  GST_DEBUG_OBJECT (self, "updating caps from %" GST_PTR_FORMAT,
+      downstream_caps);
+  ret = agg_klass->update_src_caps (self, downstream_caps, &caps);
+  if (ret < GST_FLOW_OK) {
+    GST_WARNING_OBJECT (self, "Subclass failed to update provided caps");
+    goto done;
+  }
+  if ((caps == NULL || gst_caps_is_empty (caps)) && ret >= GST_FLOW_OK) {
+    ret = GST_FLOW_NOT_NEGOTIATED;
+    goto done;
+  }
+  GST_DEBUG_OBJECT (self, "               to %" GST_PTR_FORMAT, caps);
+
+#ifdef GST_ENABLE_EXTRA_CHECKS
+  if (!gst_caps_is_subset (caps, template_caps)) {
+    GstCaps *intersection;
+
+    GST_ERROR_OBJECT (self,
+        "update_src_caps returned caps %" GST_PTR_FORMAT
+        " which are not a real subset of the template caps %"
+        GST_PTR_FORMAT, caps, template_caps);
+    g_warning ("%s: update_src_caps returned caps which are not a real "
+        "subset of the filter caps", GST_ELEMENT_NAME (self));
+
+    intersection =
+        gst_caps_intersect_full (template_caps, caps, GST_CAPS_INTERSECT_FIRST);
+    gst_caps_unref (caps);
+    caps = intersection;
+  }
+#endif
+
+  if (gst_caps_is_any (caps)) {
+    goto done;
+  }
+
+  if (!gst_caps_is_fixed (caps)) {
+    g_assert (agg_klass->fixate_src_caps);
+
+    GST_DEBUG_OBJECT (self, "fixate caps from %" GST_PTR_FORMAT, caps);
+    if (!(caps = agg_klass->fixate_src_caps (self, caps))) {
+      GST_WARNING_OBJECT (self, "Subclass failed to fixate provided caps");
+      ret = GST_FLOW_NOT_NEGOTIATED;
+      goto done;
+    }
+    GST_DEBUG_OBJECT (self, "             to %" GST_PTR_FORMAT, caps);
+  }
+
+  if (agg_klass->negotiated_src_caps) {
+    if (!agg_klass->negotiated_src_caps (self, caps)) {
+      GST_WARNING_OBJECT (self, "Subclass failed to accept negotiated caps");
+      ret = GST_FLOW_NOT_NEGOTIATED;
+      goto done;
+    }
+  }
+
+  gst_aggregator_set_src_caps (self, caps);
+
+  if (!gst_aggregator_do_allocation (self, caps)) {
+    GST_WARNING_OBJECT (self, "Allocation negotiation failed");
+    ret = GST_FLOW_NOT_NEGOTIATED;
+  }
+
+done:
+  gst_caps_unref (downstream_caps);
+  gst_caps_unref (template_caps);
+
+  if (caps)
+    gst_caps_unref (caps);
+
+  return ret;
+}
+
 static void
 gst_aggregator_aggregate_func (GstAggregator * self)
 {
@@ -823,7 +1093,7 @@ gst_aggregator_aggregate_func (GstAggregator * self)
 
   GST_LOG_OBJECT (self, "Checking aggregate");
   while (priv->send_eos && priv->running) {
-    GstFlowReturn flow_return;
+    GstFlowReturn flow_return = GST_FLOW_OK;
     gboolean processed_event = FALSE;
 
     gst_aggregator_iterate_sinkpads (self, check_events, NULL);
@@ -835,8 +1105,19 @@ gst_aggregator_aggregate_func (GstAggregator * self)
     if (processed_event)
       continue;
 
-    GST_TRACE_OBJECT (self, "Actually aggregating!");
-    flow_return = klass->aggregate (self, timeout);
+    if (gst_pad_check_reconfigure (GST_AGGREGATOR_SRC_PAD (self))) {
+      flow_return = gst_aggregator_update_src_caps (self);
+      if (flow_return != GST_FLOW_OK)
+        gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self));
+    }
+
+    if (timeout || flow_return >= GST_FLOW_OK) {
+      GST_TRACE_OBJECT (self, "Actually aggregating!");
+      flow_return = klass->aggregate (self, timeout);
+    }
+
+    if (flow_return == GST_AGGREGATOR_FLOW_NEED_DATA)
+      continue;
 
     GST_OBJECT_LOCK (self);
     if (flow_return == GST_FLOW_FLUSHING && priv->flush_seeking) {
@@ -888,6 +1169,8 @@ gst_aggregator_start (GstAggregator * self)
   self->priv->send_eos = TRUE;
   self->priv->srccaps = NULL;
 
+  gst_aggregator_set_allocation (self, NULL, NULL, NULL, NULL);
+
   klass = GST_AGGREGATOR_GET_CLASS (self);
 
   if (klass->start)
@@ -1142,6 +1425,10 @@ gst_aggregator_default_sink_event (GstAggregator * self,
       PAD_LOCK (aggpad);
       GST_OBJECT_LOCK (aggpad);
       gst_event_copy_segment (event, &aggpad->segment);
+      /* We've got a new segment, tail_position is now meaningless
+       * and may interfere with the time_level calculation
+       */
+      aggpad->priv->tail_position = GST_CLOCK_TIME_NONE;
       update_time_level (aggpad, FALSE);
       GST_OBJECT_UNLOCK (aggpad);
       PAD_UNLOCK (aggpad);
@@ -1234,6 +1521,12 @@ gst_aggregator_stop_pad (GstAggregator * self, GstAggregatorPad * pad,
 {
   gst_aggregator_pad_flush (pad, self);
 
+  PAD_LOCK (pad);
+  pad->priv->flow_return = GST_FLOW_FLUSHING;
+  pad->priv->negotiated = FALSE;
+  PAD_BROADCAST_EVENT (pad);
+  PAD_UNLOCK (pad);
+
   return TRUE;
 }
 
@@ -1262,6 +1555,8 @@ gst_aggregator_stop (GstAggregator * agg)
     gst_tag_list_unref (agg->priv->tags);
   agg->priv->tags = NULL;
 
+  gst_aggregator_set_allocation (agg, NULL, NULL, NULL, NULL);
+
   return result;
 }
 
@@ -1339,10 +1634,12 @@ gst_aggregator_default_create_new_pad (GstAggregator * self,
   gint serial = 0;
   gchar *name = NULL;
 
-  if (templ->direction != GST_PAD_SINK ||
-      g_strcmp0 (templ->name_template, "sink_%u") != 0)
+  if (templ->direction != GST_PAD_SINK)
     goto not_sink;
 
+  if (templ->presence != GST_PAD_REQUEST)
+    goto not_request;
+
   GST_OBJECT_LOCK (self);
   if (req_name == NULL || strlen (req_name) < 6
       || !g_str_has_prefix (req_name, "sink_")) {
@@ -1367,7 +1664,12 @@ gst_aggregator_default_create_new_pad (GstAggregator * self,
   /* errors */
 not_sink:
   {
-    GST_WARNING_OBJECT (self, "request new pad that is not a SINK pad\n");
+    GST_WARNING_OBJECT (self, "request new pad that is not a SINK pad");
+    return NULL;
+  }
+not_request:
+  {
+    GST_WARNING_OBJECT (self, "request new pad that is not a REQUEST pad");
     return NULL;
   }
 }
@@ -1390,7 +1692,6 @@ gst_aggregator_request_new_pad (GstElement * element,
   }
 
   GST_DEBUG_OBJECT (element, "Adding pad %s", GST_PAD_NAME (agg_pad));
-  self->priv->has_peer_latency = FALSE;
 
   if (priv->running)
     gst_pad_set_active (GST_PAD (agg_pad), TRUE);
@@ -1825,6 +2126,45 @@ gst_aggregator_default_sink_query (GstAggregator * self,
 {
   GstPad *pad = GST_PAD (aggpad);
 
+  if (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION) {
+    GstQuery *decide_query = NULL;
+    GstAggregatorClass *agg_class;
+    gboolean ret;
+
+    GST_OBJECT_LOCK (self);
+    PAD_LOCK (aggpad);
+    if (G_UNLIKELY (!aggpad->priv->negotiated)) {
+      GST_DEBUG_OBJECT (self,
+          "not negotiated yet, can't answer ALLOCATION query");
+      PAD_UNLOCK (aggpad);
+      GST_OBJECT_UNLOCK (self);
+
+      return FALSE;
+    }
+
+    if ((decide_query = self->priv->allocation_query))
+      gst_query_ref (decide_query);
+    PAD_UNLOCK (aggpad);
+    GST_OBJECT_UNLOCK (self);
+
+    GST_DEBUG_OBJECT (self,
+        "calling propose allocation with query %" GST_PTR_FORMAT, decide_query);
+
+    agg_class = GST_AGGREGATOR_GET_CLASS (self);
+
+    /* pass the query to the propose_allocation vmethod if any */
+    if (agg_class->propose_allocation)
+      ret = agg_class->propose_allocation (self, aggpad, decide_query, query);
+    else
+      ret = FALSE;
+
+    if (decide_query)
+      gst_query_unref (decide_query);
+
+    GST_DEBUG_OBJECT (self, "ALLOCATION ret %d, %" GST_PTR_FORMAT, ret, query);
+    return ret;
+  }
+
   return gst_pad_query_default (pad, GST_OBJECT (self), query);
 }
 
@@ -1980,6 +2320,9 @@ gst_aggregator_class_init (GstAggregatorClass * klass)
   klass->src_query = gst_aggregator_default_src_query;
 
   klass->create_new_pad = gst_aggregator_default_create_new_pad;
+  klass->update_src_caps = gst_aggregator_default_update_src_caps;
+  klass->fixate_src_caps = gst_aggregator_default_fixate_src_caps;
+  klass->negotiated_src_caps = gst_aggregator_default_negotiated_src_caps;
 
   gstelement_class->request_new_pad =
       GST_DEBUG_FUNCPTR (gst_aggregator_request_new_pad);
@@ -2165,12 +2508,16 @@ gst_aggregator_pad_chain_internal (GstAggregator * self,
 
   buf_pts = GST_BUFFER_PTS (buffer);
 
-  aggpad->priv->first_buffer = FALSE;
-
   for (;;) {
     SRC_LOCK (self);
     GST_OBJECT_LOCK (self);
     PAD_LOCK (aggpad);
+
+    if (aggpad->priv->first_buffer) {
+      self->priv->has_peer_latency = FALSE;
+      aggpad->priv->first_buffer = FALSE;
+    }
+
     if (gst_aggregator_pad_has_space (self, aggpad)
         && aggpad->priv->flow_return == GST_FLOW_OK) {
       if (head)
@@ -2285,31 +2632,53 @@ static gboolean
 gst_aggregator_pad_query_func (GstPad * pad, GstObject * parent,
     GstQuery * query)
 {
+  GstAggregator *self = GST_AGGREGATOR (parent);
   GstAggregatorPad *aggpad = GST_AGGREGATOR_PAD (pad);
   GstAggregatorClass *klass = GST_AGGREGATOR_GET_CLASS (parent);
 
   if (GST_QUERY_IS_SERIALIZED (query)) {
+    GstStructure *s;
+    gboolean ret = FALSE;
+
+    SRC_LOCK (self);
     PAD_LOCK (aggpad);
 
+    if (aggpad->priv->flow_return != GST_FLOW_OK) {
+      SRC_UNLOCK (self);
+      goto flushing;
+    }
+
+    g_queue_push_head (&aggpad->priv->buffers, query);
+    SRC_BROADCAST (self);
+    SRC_UNLOCK (self);
+
     while (!gst_aggregator_pad_queue_is_empty (aggpad)
         && aggpad->priv->flow_return == GST_FLOW_OK) {
       GST_DEBUG_OBJECT (aggpad, "Waiting for buffer to be consumed");
       PAD_WAIT_EVENT (aggpad);
     }
 
+    s = gst_query_writable_structure (query);
+    if (gst_structure_get_boolean (s, "gst-aggregator-retval", &ret))
+      gst_structure_remove_field (s, "gst-aggregator-retval");
+    else
+      g_queue_remove (&aggpad->priv->buffers, query);
+
     if (aggpad->priv->flow_return != GST_FLOW_OK)
       goto flushing;
 
     PAD_UNLOCK (aggpad);
+
+    return ret;
   }
 
-  return klass->sink_query (GST_AGGREGATOR (parent),
-      GST_AGGREGATOR_PAD (pad), query);
+  return klass->sink_query (self, aggpad, query);
 
 flushing:
   GST_DEBUG_OBJECT (aggpad, "Pad is %s, dropping query",
       gst_flow_get_name (aggpad->priv->flow_return));
   PAD_UNLOCK (aggpad);
+
   return FALSE;
 }
 
@@ -2341,8 +2710,7 @@ gst_aggregator_pad_event_func (GstPad * pad, GstObject * parent,
       GST_OBJECT_UNLOCK (aggpad);
     }
 
-    if (!gst_aggregator_pad_queue_is_empty (aggpad) &&
-        GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) {
+    if (GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) {
       GST_DEBUG_OBJECT (aggpad, "Store event in queue: %" GST_PTR_FORMAT,
           event);
       g_queue_push_head (&aggpad->priv->buffers, event);
@@ -2354,12 +2722,10 @@ gst_aggregator_pad_event_func (GstPad * pad, GstObject * parent,
   }
 
   if (event) {
-    gboolean is_caps = (GST_EVENT_TYPE (event) == GST_EVENT_CAPS);
-
     if (!klass->sink_event (self, aggpad, event)) {
       /* Copied from GstPad to convert boolean to a GstFlowReturn in
        * the event handling func */
-      ret = is_caps ? GST_FLOW_NOT_NEGOTIATED : GST_FLOW_ERROR;
+      ret = GST_FLOW_ERROR;
     }
   }
 
@@ -2467,6 +2833,7 @@ gst_aggregator_pad_init (GstAggregatorPad * pad)
   g_mutex_init (&pad->priv->lock);
 
   gst_aggregator_pad_reset_unlocked (pad);
+  pad->priv->negotiated = FALSE;
 }
 
 /* Must be called with the PAD_LOCK held */
@@ -2487,7 +2854,7 @@ static void
 gst_aggregator_pad_clip_buffer_unlocked (GstAggregatorPad * pad)
 {
   GstAggregator *self = NULL;
-  GstAggregatorClass *aggclass;
+  GstAggregatorClass *aggclass = NULL;
   GstBuffer *buffer = NULL;
 
   while (pad->priv->clipped_buffer == NULL &&
@@ -2693,3 +3060,53 @@ gst_aggregator_set_latency (GstAggregator * self,
         gst_message_new_latency (GST_OBJECT_CAST (self)));
   }
 }
+
+/**
+ * gst_aggregator_get_buffer_pool:
+ * @self: a #GstAggregator
+ *
+ * Returns: (transfer full): the instance of the #GstBufferPool used
+ * by @trans; free it after use it
+ */
+GstBufferPool *
+gst_aggregator_get_buffer_pool (GstAggregator * self)
+{
+  GstBufferPool *pool;
+
+  g_return_val_if_fail (GST_IS_AGGREGATOR (self), NULL);
+
+  GST_OBJECT_LOCK (self);
+  pool = self->priv->pool;
+  if (pool)
+    gst_object_ref (pool);
+  GST_OBJECT_UNLOCK (self);
+
+  return pool;
+}
+
+/**
+ * gst_aggregator_get_allocator:
+ * @self: a #GstAggregator
+ * @allocator: (out) (allow-none) (transfer full): the #GstAllocator
+ * used
+ * @params: (out) (allow-none) (transfer full): the
+ * #GstAllocationParams of @allocator
+ *
+ * Lets #GstAggregator sub-classes get the memory @allocator
+ * acquired by the base class and its @params.
+ *
+ * Unref the @allocator after use it.
+ */
+void
+gst_aggregator_get_allocator (GstAggregator * self,
+    GstAllocator ** allocator, GstAllocationParams * params)
+{
+  g_return_if_fail (GST_IS_AGGREGATOR (self));
+
+  if (allocator)
+    *allocator = self->priv->allocator ?
+        gst_object_ref (self->priv->allocator) : NULL;
+
+  if (params)
+    *params = self->priv->allocation_params;
+}