Commit 83af6001 authored by Wim Taymans's avatar Wim Taymans
Browse files

query: rework the ALLOCATION query

Separate the bufferpool and allocator hints in the allocation query, some
of the values don't always make sense together.
Keep the bufferpool and its configuration together.
Keep the allocator and its parameters together.
Allow for multiple bufferpool configurations in the query.
parent c8acf02f
......@@ -89,12 +89,6 @@ typedef struct
#define GST_QUERY_STRUCTURE(q) (((GstQueryImpl *)(q))->structure)
/* GstQueryBufferingRange: internal struct for GArray */
typedef struct
{
gint64 start;
gint64 stop;
} GstQueryBufferingRange;
typedef struct
{
......@@ -1277,6 +1271,13 @@ gst_query_parse_buffering_range (GstQuery * query, GstFormat * format,
GST_QUARK (ESTIMATED_TOTAL)));
}
/* GstQueryBufferingRange: internal struct for GArray */
typedef struct
{
gint64 start;
gint64 stop;
} GstQueryBufferingRange;
/**
* gst_query_add_buffering_range:
* @query: a GST_QUERY_BUFFERING type query #GstQuery
......@@ -1484,14 +1485,7 @@ gst_query_new_allocation (GstCaps * caps, gboolean need_pool)
structure = gst_structure_new_id (GST_QUARK (QUERY_ALLOCATION),
GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool,
GST_QUARK (SIZE), G_TYPE_UINT, 0,
GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, 0,
GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, 0,
GST_QUARK (PREFIX), G_TYPE_UINT, 0,
GST_QUARK (PADDING), G_TYPE_UINT, 0,
GST_QUARK (ALIGN), G_TYPE_UINT, 0,
GST_QUARK (POOL), GST_TYPE_BUFFER_POOL, NULL, NULL);
GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL);
query = gst_query_new_custom (GST_QUERY_ALLOCATION, structure);
......@@ -1522,73 +1516,155 @@ gst_query_parse_allocation (GstQuery * query, GstCaps ** caps,
GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL);
}
typedef struct
{
GstBufferPool *pool;
guint size;
guint min_buffers;
guint max_buffers;
} AllocationPool;
static void
allocation_pool_free (AllocationPool * ap)
{
if (ap->pool)
gst_object_unref (ap->pool);
}
/**
* gst_query_set_allocation_params:
* gst_query_add_allocation_pool:
* @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
* @pool: the #GstBufferPool
* @size: the size
* @min_buffers: the min buffers
* @max_buffers: the max buffers
* @prefix: the prefix
* @padding: the padding
* @alignment: the alignment
* @pool: the #GstBufferPool
*
* Set the allocation parameters in @query.
* Set the pool parameters in @query.
*/
void
gst_query_set_allocation_params (GstQuery * query, guint size,
guint min_buffers, guint max_buffers, guint prefix, guint padding,
guint alignment, GstBufferPool * pool)
gst_query_add_allocation_pool (GstQuery * query, GstBufferPool * pool,
guint size, guint min_buffers, guint max_buffers)
{
GArray *array;
GstStructure *structure;
AllocationPool ap;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
g_return_if_fail (gst_query_is_writable (query));
g_return_if_fail (((alignment + 1) & alignment) == 0);
g_return_if_fail (size != 0 || pool == NULL);
g_return_if_fail (size != 0);
structure = GST_QUERY_STRUCTURE (query);
gst_structure_id_set (structure,
GST_QUARK (SIZE), G_TYPE_UINT, size,
GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, min_buffers,
GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, max_buffers,
GST_QUARK (PREFIX), G_TYPE_UINT, prefix,
GST_QUARK (PADDING), G_TYPE_UINT, padding,
GST_QUARK (ALIGN), G_TYPE_UINT, alignment,
GST_QUARK (POOL), GST_TYPE_BUFFER_POOL, pool, NULL);
array = ensure_array (structure, GST_QUARK (POOL),
sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
if ((ap.pool = pool))
gst_object_ref (pool);
ap.size = size;
ap.min_buffers = min_buffers;
ap.max_buffers = max_buffers;
g_array_append_val (array, ap);
}
/**
* gst_query_get_n_allocation_pools:
* @query: a GST_QUERY_ALLOCATION type query #GstQuery
*
* Retrieve the number of values currently stored in the
* pool array of the query's structure.
*
* Returns: the pool array size as a #guint.
*/
guint
gst_query_get_n_allocation_pools (GstQuery * query)
{
GArray *array;
GstStructure *structure;
g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
structure = GST_QUERY_STRUCTURE (query);
array = ensure_array (structure, GST_QUARK (POOL),
sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
return array->len;
}
/**
* gst_query_parse_allocation_params:
* gst_query_parse_nth_allocation_pool:
* @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
* @pool: (out) (allow-none) (transfer none): the #GstBufferPool
* @size: (out) (allow-none): the size
* @min_buffers: (out) (allow-none): the min buffers
* @max_buffers: (out) (allow-none): the max buffers
* @prefix: (out) (allow-none): the prefix
* @padding: (out) (allow-none): the padding
* @alignment: (out) (allow-none): the alignment
* @pool: (out) (allow-none) (transfer full): the #GstBufferPool
*
* Get the allocation parameters in @query.
* Get the pool parameters in @query.
*/
void
gst_query_parse_allocation_params (GstQuery * query, guint * size,
guint * min_buffers, guint * max_buffers, guint * prefix,
guint * padding, guint * alignment, GstBufferPool ** pool)
gst_query_parse_nth_allocation_pool (GstQuery * query, guint index,
GstBufferPool ** pool, guint * size, guint * min_buffers,
guint * max_buffers)
{
GArray *array;
GstStructure *structure;
AllocationPool *ap;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
structure = GST_QUERY_STRUCTURE (query);
gst_structure_id_get (structure,
GST_QUARK (SIZE), G_TYPE_UINT, size,
GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, min_buffers,
GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, max_buffers,
GST_QUARK (PREFIX), G_TYPE_UINT, prefix,
GST_QUARK (PADDING), G_TYPE_UINT, padding,
GST_QUARK (ALIGN), G_TYPE_UINT, alignment,
GST_QUARK (POOL), GST_TYPE_BUFFER_POOL, pool, NULL);
array = ensure_array (structure, GST_QUARK (POOL),
sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
g_return_if_fail (index < array->len);
ap = &g_array_index (array, AllocationPool, index);
if (pool)
if ((*pool = ap->pool))
gst_object_ref (*pool);
if (size)
*size = ap->size;
if (min_buffers)
*min_buffers = ap->min_buffers;
if (max_buffers)
*max_buffers = ap->max_buffers;
}
/**
* gst_query_set_nth_allocation_pool:
* @index: index to modify
* @query: A valid #GstQuery of type GST_QUERY_ALLOCATION.
* @pool: the #GstBufferPool
* @size: the size
* @min_buffers: the min buffers
* @max_buffers: the max buffers
*
* Set the pool parameters in @query.
*/
void
gst_query_set_nth_allocation_pool (GstQuery * query, guint index,
GstBufferPool * pool, guint size, guint min_buffers, guint max_buffers)
{
GArray *array;
GstStructure *structure;
AllocationPool *oldap, ap;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
structure = GST_QUERY_STRUCTURE (query);
array = ensure_array (structure, GST_QUARK (POOL),
sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
g_return_if_fail (index < array->len);
oldap = &g_array_index (array, AllocationPool, index);
allocation_pool_free (oldap);
if ((ap.pool = pool))
gst_object_ref (pool);
ap.size = size;
ap.min_buffers = min_buffers;
ap.max_buffers = max_buffers;
g_array_index (array, AllocationPool, index) = ap;
}
/**
......@@ -1716,37 +1792,59 @@ gst_query_has_allocation_meta (GstQuery * query, GType api)
return FALSE;
}
typedef struct
{
GstAllocator *allocator;
GstAllocationParams params;
} AllocationParam;
static void
allocation_param_free (AllocationParam * ap)
{
if (ap->allocator)
gst_allocator_unref (ap->allocator);
}
/**
* gst_query_add_allocation_memory:
* gst_query_add_allocation_param:
* @query: a GST_QUERY_ALLOCATION type query #GstQuery
* @allocator: the memory allocator
* @params: a #GstAllocationParams
*
* Add @allocator as a supported memory allocator.
* Add @allocator and its @params as a supported memory allocator.
*/
void
gst_query_add_allocation_memory (GstQuery * query, GstAllocator * allocator)
gst_query_add_allocation_param (GstQuery * query, GstAllocator * allocator,
const GstAllocationParams * params)
{
GArray *array;
GstStructure *structure;
AllocationParam ap;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
g_return_if_fail (gst_query_is_writable (query));
g_return_if_fail (allocator != NULL);
g_return_if_fail (allocator != NULL || params != NULL);
structure = GST_QUERY_STRUCTURE (query);
array =
ensure_array (structure, GST_QUARK (ALLOCATOR), sizeof (GstAllocator *),
(GDestroyNotify) gst_allocator_unref);
array = ensure_array (structure, GST_QUARK (ALLOCATOR),
sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
if ((ap.allocator = allocator))
gst_allocator_ref (allocator);
if (params)
ap.params = *params;
else
gst_allocation_params_init (&ap.params);
g_array_append_val (array, allocator);
g_array_append_val (array, ap);
}
/**
* gst_query_get_n_allocation_memories:
* gst_query_get_n_allocation_params:
* @query: a GST_QUERY_ALLOCATION type query #GstQuery
*
* Retrieve the number of values currently stored in the
* allocator array of the query's structure.
* allocator params array of the query's structure.
*
* If no memory allocator is specified, the downstream element can handle
* the default memory allocator.
......@@ -1754,7 +1852,7 @@ gst_query_add_allocation_memory (GstQuery * query, GstAllocator * allocator)
* Returns: the allocator array size as a #guint.
*/
guint
gst_query_get_n_allocation_memories (GstQuery * query)
gst_query_get_n_allocation_params (GstQuery * query)
{
GArray *array;
GstStructure *structure;
......@@ -1762,39 +1860,82 @@ gst_query_get_n_allocation_memories (GstQuery * query)
g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
structure = GST_QUERY_STRUCTURE (query);
array =
ensure_array (structure, GST_QUARK (ALLOCATOR), sizeof (GstAllocator *),
(GDestroyNotify) gst_allocator_unref);
array = ensure_array (structure, GST_QUARK (ALLOCATOR),
sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
return array->len;
}
/**
* gst_query_parse_nth_allocation_memory:
* gst_query_parse_nth_allocation_param:
* @query: a GST_QUERY_ALLOCATION type query #GstQuery
* @index: position in the allocator array to read
* @allocator: (transfer none): variable to hold the result
* @params: parameters for the allocator
*
* Parse an available query and get the alloctor
* Parse an available query and get the alloctor and its params
* at @index of the allocator array.
*/
void
gst_query_parse_nth_allocation_param (GstQuery * query, guint index,
GstAllocator ** allocator, GstAllocationParams * params)
{
GArray *array;
GstStructure *structure;
AllocationParam *ap;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
structure = GST_QUERY_STRUCTURE (query);
array = ensure_array (structure, GST_QUARK (ALLOCATOR),
sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
g_return_if_fail (index < array->len);
ap = &g_array_index (array, AllocationParam, index);
if (allocator)
if ((*allocator = ap->allocator))
gst_allocator_ref (*allocator);
if (params)
*params = ap->params;
}
/**
* gst_query_set_nth_allocation_param:
* @query: a GST_QUERY_ALLOCATION type query #GstQuery
* @index: position in the allocator array to set
* @allocator: (transfer full): new allocator to set
* @params: parameters for the allocator
*
* Returns: (transfer none): the allocator at @index. The allocator remains
* valid for as long as @query is valid.
* Parse an available query and get the alloctor and its params
* at @index of the allocator array.
*/
GstAllocator *
gst_query_parse_nth_allocation_memory (GstQuery * query, guint index)
void
gst_query_set_nth_allocation_param (GstQuery * query, guint index,
GstAllocator * allocator, const GstAllocationParams * params)
{
GArray *array;
GstStructure *structure;
AllocationParam *old, ap;
g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, NULL);
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
structure = GST_QUERY_STRUCTURE (query);
array =
ensure_array (structure, GST_QUARK (ALLOCATOR), sizeof (GstAllocator *),
(GDestroyNotify) gst_allocator_unref);
g_return_val_if_fail (index < array->len, NULL);
array = ensure_array (structure, GST_QUARK (ALLOCATOR),
sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
g_return_if_fail (index < array->len);
old = &g_array_index (array, AllocationParam, index);
allocation_param_free (old);
if ((ap.allocator = allocator))
gst_allocator_ref (allocator);
if (params)
ap.params = *params;
else
gst_allocation_params_init (&ap.params);
return g_array_index (array, GstAllocator *, index);
g_array_index (array, AllocationParam, index) = ap;
}
/**
......
......@@ -393,30 +393,46 @@ gboolean gst_query_parse_nth_buffering_range (GstQuery *query,
gint64 *stop);
/* URI query */
GstQuery * gst_query_new_uri (void) G_GNUC_MALLOC;
void gst_query_parse_uri (GstQuery *query, gchar **uri);
void gst_query_set_uri (GstQuery *query, const gchar *uri);
GstQuery * gst_query_new_uri (void) G_GNUC_MALLOC;
void gst_query_parse_uri (GstQuery *query, gchar **uri);
void gst_query_set_uri (GstQuery *query, const gchar *uri);
/* allocation query */
GstQuery * gst_query_new_allocation (GstCaps *caps, gboolean need_pool) G_GNUC_MALLOC;
void gst_query_parse_allocation (GstQuery *query, GstCaps **caps, gboolean *need_pool);
void gst_query_set_allocation_params (GstQuery *query, guint size, guint min_buffers,
guint max_buffers, guint prefix, guint padding,
guint alignment, GstBufferPool *pool);
void gst_query_parse_allocation_params (GstQuery *query, guint *size, guint *min_buffers,
guint *max_buffers, guint *prefix, guint *padding,
guint *alignment, GstBufferPool **pool);
GstQuery * gst_query_new_allocation (GstCaps *caps, gboolean need_pool) G_GNUC_MALLOC;
void gst_query_parse_allocation (GstQuery *query, GstCaps **caps, gboolean *need_pool);
/* pools */
void gst_query_add_allocation_pool (GstQuery *query, GstBufferPool *pool,
guint size, guint min_buffers,
guint max_buffers);
guint gst_query_get_n_allocation_pools (GstQuery *query);
void gst_query_parse_nth_allocation_pool (GstQuery *query, guint index,
GstBufferPool **pool,
guint *size, guint *min_buffers,
guint *max_buffers);
void gst_query_set_nth_allocation_pool (GstQuery *query, guint index,
GstBufferPool *pool,
guint size, guint min_buffers,
guint max_buffers);
/* allocators */
void gst_query_add_allocation_param (GstQuery *query, GstAllocator *allocator,
const GstAllocationParams *params);
guint gst_query_get_n_allocation_params (GstQuery *query);
void gst_query_parse_nth_allocation_param (GstQuery *query, guint index,
GstAllocator **allocator,
GstAllocationParams *params);
void gst_query_set_nth_allocation_param (GstQuery *query, guint index,
GstAllocator *allocator,
const GstAllocationParams *params);
/* metadata */
void gst_query_add_allocation_meta (GstQuery *query, GType api);
guint gst_query_get_n_allocation_metas (GstQuery *query);
GType gst_query_parse_nth_allocation_meta (GstQuery *query, guint index);
void gst_query_remove_nth_allocation_meta (GstQuery *query, guint index);
gboolean gst_query_has_allocation_meta (GstQuery *query, GType api);
void gst_query_add_allocation_memory (GstQuery *query, GstAllocator *allocator);
guint gst_query_get_n_allocation_memories (GstQuery *query);
GstAllocator * gst_query_parse_nth_allocation_memory (GstQuery *query, guint index);
/* scheduling query */
/**
......
......@@ -559,6 +559,7 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate));
gst_pad_set_activatemode_function (parse->sinkpad,
GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_mode));
GST_PAD_SET_PROXY_ALLOCATION (parse->sinkpad);
gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
GST_DEBUG_OBJECT (parse, "sinkpad created");
......
......@@ -2702,7 +2702,7 @@ null_buffer:
static gboolean
gst_base_src_set_allocation (GstBaseSrc * basesrc, GstBufferPool * pool,
GstAllocator * allocator, guint prefix, guint padding, guint alignment)
GstAllocator * allocator, GstAllocationParams * params)
{
GstAllocator *oldalloc;
GstBufferPool *oldpool;
......@@ -2721,10 +2721,10 @@ gst_base_src_set_allocation (GstBaseSrc * basesrc, GstBufferPool * pool,
oldalloc = priv->allocator;
priv->allocator = allocator;
gst_allocation_params_init (&priv->params);
priv->params.prefix = prefix;
priv->params.padding = padding;
priv->params.align = alignment;
if (params)
priv->params = *params;
else
gst_allocation_params_init (&priv->params);
GST_OBJECT_UNLOCK (basesrc);
if (oldpool) {
......@@ -2775,7 +2775,8 @@ gst_base_src_prepare_allocation (GstBaseSrc * basesrc, GstCaps * caps)
GstQuery *query;
GstBufferPool *pool = NULL;
GstAllocator *allocator = NULL;
guint size, min, max, prefix, padding, alignment;
guint size, min, max;
GstAllocationParams params;
bclass = GST_BASE_SRC_GET_CLASS (basesrc);
......@@ -2793,35 +2794,41 @@ gst_base_src_prepare_allocation (GstBaseSrc * basesrc, GstCaps * caps)
GST_DEBUG_OBJECT (basesrc, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result,
query);
gst_query_parse_allocation_params (query, &size, &min, &max, &prefix,
&padding, &alignment, &pool);
if (size == 0) {
/* no size, we have variable size buffers */
if (gst_query_get_n_allocation_memories (query) > 0) {
if ((allocator = gst_query_parse_nth_allocation_memory (query, 0)))
gst_allocator_ref (allocator);
if (gst_query_get_n_allocation_params (query) > 0) {
/* try the allocator */
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, &size, &min, &max);
if (pool == NULL) {
/* no pool, just parameters, we can make our own */
GST_DEBUG_OBJECT (basesrc, "no pool, making new pool");
pool = gst_buffer_pool_new ();
}
GST_DEBUG_OBJECT (basesrc, "0 size, using allocator %p", allocator);
} else if (pool == NULL) {
/* fixed size, we can use a bufferpool */
GstStructure *config;
} else {
pool = NULL;
size = min = max = 0;
}
/* we did not get a pool, make one ourselves then */
pool = gst_buffer_pool_new ();
GST_DEBUG_OBJECT (basesrc, "no pool, making new pool");
/* now configure */
if (pool) {
GstStructure *config;
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set (config, caps, size, min, max, prefix,
padding, alignment);
gst_buffer_pool_config_set (config, caps, size, min, max, params.prefix,
params.padding, params.align);
gst_buffer_pool_set_config (pool, config);
}
gst_query_unref (query);
result = gst_base_src_set_allocation (basesrc, pool, allocator, &params);
result =
gst_base_src_set_allocation (basesrc, pool, allocator, prefix, padding,
alignment);
gst_query_unref (query);
return result;
......@@ -3178,7 +3185,7 @@ gst_base_src_stop (GstBaseSrc * basesrc)
if (bclass->stop)
result = bclass->stop (basesrc);
gst_base_src_set_allocation (basesrc, NULL, NULL, 0, 0, 0);
gst_base_src_set_allocation (basesrc, NULL, NULL, NULL);
return result;
......
......@@ -742,8 +742,8 @@ done:
/* takes ownership of the pool, allocator and query */
static gboolean
gst_base_transform_set_allocation (GstBaseTransform * trans,
GstBufferPool * pool, GstAllocator * allocator, guint prefix,
guint padding, guint alignment, GstQuery * query)
GstBufferPool * pool, GstAllocator * allocator,
GstAllocationParams * params, GstQuery * query)
{
GstAllocator *oldalloc;
GstBufferPool *oldpool;
......@@ -754,14 +754,17 @@ gst_base_transform_set_allocation (GstBaseTransform * trans,
oldpool = priv->pool;
priv->pool = pool;
priv->pool_active = FALSE;
oldalloc = priv->allocator;
priv->allocator = allocator;
oldquery = priv->query;
priv->query = query;
gst_allocation_params_init (&priv->params);
priv->params.prefix = prefix;
priv->params.padding = padding;
priv->params.align = alignment;
if (params)