/* MT-protected (with LOCK) */
GstClockTime min_latency;
GstClockTime max_latency;
+
+ GstAllocator *allocator;
+ GstAllocationParams params;
} GstAudioDecoderContext;
struct _GstAudioDecoderPrivate
GstQuery * query);
static void gst_audio_decoder_reset (GstAudioDecoder * dec, gboolean full);
+static gboolean gst_audio_decoder_decide_allocation_default (GstAudioDecoder *
+ dec, GstQuery * query);
+static gboolean gst_audio_decoder_propose_allocation_default (GstAudioDecoder *
+ dec, GstQuery * query);
+
static GstElementClass *parent_class = NULL;
static void gst_audio_decoder_class_init (GstAudioDecoderClass * klass);
GST_DEBUG_FUNCPTR (gst_audio_decoder_sink_eventfunc);
audiodecoder_class->src_event =
GST_DEBUG_FUNCPTR (gst_audio_decoder_src_eventfunc);
+ audiodecoder_class->propose_allocation =
+ GST_DEBUG_FUNCPTR (gst_audio_decoder_propose_allocation_default);
+ audiodecoder_class->decide_allocation =
+ GST_DEBUG_FUNCPTR (gst_audio_decoder_decide_allocation_default);
}
static void
g_list_foreach (dec->priv->pending_events, (GFunc) gst_event_unref, NULL);
g_list_free (dec->priv->pending_events);
dec->priv->pending_events = NULL;
+
+ if (dec->priv->ctx.allocator)
+ gst_object_unref (dec->priv->ctx.allocator);
+ dec->priv->ctx.allocator = NULL;
}
g_queue_foreach (&dec->priv->frames, (GFunc) gst_buffer_unref, NULL);
gst_audio_decoder_set_output_format (GstAudioDecoder * dec,
const GstAudioInfo * info)
{
+ GstAudioDecoderClass *klass = GST_AUDIO_DECODER_GET_CLASS (dec);
gboolean res = TRUE;
guint old_rate;
GstCaps *caps = NULL;
GstCaps *templ_caps;
+ GstQuery *query = NULL;
+ GstAllocator *allocator;
+ GstAllocationParams params;
GST_DEBUG_OBJECT (dec, "Setting output format");
res = gst_pad_set_caps (dec->srcpad, caps);
gst_caps_unref (caps);
+ if (!res)
+ goto done;
+
+ query = gst_query_new_allocation (caps, TRUE);
+ if (!gst_pad_peer_query (dec->srcpad, query)) {
+ GST_DEBUG_OBJECT (dec, "didn't get downstream ALLOCATION hints");
+ }
+
+ g_assert (klass->decide_allocation != NULL);
+ res = klass->decide_allocation (dec, query);
+
+ GST_DEBUG_OBJECT (dec, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, res,
+ query);
+
+ if (!res)
+ 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, ¶ms);
+ } else {
+ allocator = NULL;
+ gst_allocation_params_init (¶ms);
+ }
+
+ if (dec->priv->ctx.allocator)
+ gst_object_unref (dec->priv->ctx.allocator);
+ dec->priv->ctx.allocator = allocator;
+ dec->priv->ctx.params = params;
done:
+ if (query)
+ gst_query_unref (query);
+
return res;
/* ERRORS */
res = FALSE;
goto done;
}
+no_decide_allocation:
+ {
+ GST_WARNING_OBJECT (dec, "Subclass failed to decide allocation");
+ goto done;
+ }
}
static gboolean
return ret;
}
+static gboolean
+gst_audio_decoder_decide_allocation_default (GstAudioDecoder * dec,
+ GstQuery * query)
+{
+ GstAllocator *allocator = NULL;
+ GstAllocationParams params;
+ gboolean update_allocator;
+
+ /* we got configuration from our peer or the decide_allocation method,
+ * parse them */
+ if (gst_query_get_n_allocation_params (query) > 0) {
+ /* try the allocator */
+ gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms);
+ update_allocator = TRUE;
+ } else {
+ allocator = NULL;
+ gst_allocation_params_init (¶ms);
+ update_allocator = FALSE;
+ }
+
+ if (update_allocator)
+ gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms);
+ else
+ gst_query_add_allocation_param (query, allocator, ¶ms);
+ if (allocator)
+ gst_object_unref (allocator);
+
+ return TRUE;
+}
+
+static gboolean
+gst_audio_decoder_propose_allocation_default (GstAudioDecoder * dec,
+ GstQuery * query)
+{
+ return TRUE;
+}
+
/*
* gst_audio_encoded_audio_convert:
* @fmt: audio format of the encoded audio
gst_tag_list_free (otags);
GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
}
+
+/**
+ * gst_audio_decoder_allocate_output_buffer:
+ * @enc: a #GstAudioDecoder
+ * @size: size of the buffer
+ *
+ * Helper function that allocates a buffer to hold an audio frame
+ * for @dec's current output format.
+ *
+ * Returns: (transfer full): allocated buffer
+ */
+GstBuffer *
+gst_audio_decoder_allocate_output_buffer (GstAudioDecoder * dec, gsize size)
+{
+ GstBuffer *buffer;
+
+ g_return_val_if_fail (size > 0, NULL);
+
+ GST_DEBUG ("alloc src buffer");
+
+ GST_AUDIO_DECODER_STREAM_LOCK (dec);
+
+ buffer =
+ gst_buffer_new_allocate (dec->priv->ctx.allocator, size,
+ &dec->priv->ctx.params);
+
+ GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
+
+ return buffer;
+}
* @close: Optional.
* Called when the element changes to GST_STATE_NULL.
* Allows closing external resources.
+ * @decide_allocation: Optional.
+ * Setup the allocation parameters for allocating output
+ * buffers. The passed in query contains the result of the
+ * downstream allocation query.
+ * @propose_allocation: Optional.
+ * Propose buffer allocation parameters for upstream elements.
*
* Subclasses can override any of the available virtual methods or not, as
* needed. At minimum @handle_frame (and likely @set_format) needs to be
gboolean (*close) (GstAudioDecoder *dec);
+ gboolean (*decide_allocation) (GstAudioDecoder *dec, GstQuery *query);
+
+ gboolean (*propose_allocation) (GstAudioDecoder *dec,
+ GstQuery * query);
+
/*< private >*/
gpointer _gst_reserved[GST_PADDING_LARGE-2];
};
GstFlowReturn gst_audio_decoder_finish_frame (GstAudioDecoder * dec,
GstBuffer * buf, gint frames);
+GstBuffer * gst_audio_decoder_allocate_output_buffer (GstAudioDecoder * decoder,
+ gsize size);
+
/* context parameters */
GstAudioInfo * gst_audio_decoder_get_audio_info (GstAudioDecoder * dec);