diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c index 488ae2eccb..5cc174b2b3 100644 --- a/sys/v4l2/gstv4l2bufferpool.c +++ b/sys/v4l2/gstv4l2bufferpool.c @@ -353,11 +353,9 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer, GstBuffer *newbuf = NULL; GstV4l2Object *obj; GstVideoInfo *info; - GstVideoAlignment *align; obj = pool->obj; info = &obj->info; - align = &obj->align; switch (obj->mode) { case GST_V4L2_IO_RW: @@ -394,71 +392,11 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer, } /* add metadata to raw video buffers */ - if (pool->add_videometa && info->finfo) { - const GstVideoFormatInfo *finfo = info->finfo; - gsize offset[GST_VIDEO_MAX_PLANES]; - gint width, height, n_gst_planes, offs, i, stride[GST_VIDEO_MAX_PLANES]; - - width = GST_VIDEO_INFO_WIDTH (info); - height = GST_VIDEO_INFO_HEIGHT (info); - - /* n_gst_planes is the number of planes - * (RGB: 1, YUY2: 1, NV12: 2, I420: 3) - * It's greater or equal than the number of v4l2 planes. */ - n_gst_planes = GST_VIDEO_INFO_N_PLANES (info); - - /* the basic are common between MPLANE mode and non MPLANE mode - * except a special case inside the loop at the end - */ - offs = 0; - for (i = 0; i < n_gst_planes; i++) { - GST_DEBUG_OBJECT (pool, "adding video meta, bytesperline %d", - obj->bytesperline[i]); - - offset[i] = offs; - - if (GST_VIDEO_FORMAT_INFO_IS_TILED (finfo)) { - guint x_tiles, y_tiles, ws, hs, tile_height; - - ws = GST_VIDEO_FORMAT_INFO_TILE_WS (finfo); - hs = GST_VIDEO_FORMAT_INFO_TILE_HS (finfo); - tile_height = 1 << hs; - - x_tiles = obj->bytesperline[i] >> ws; - y_tiles = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (finfo, i, - GST_ROUND_UP_N (height, tile_height) >> hs); - stride[i] = GST_VIDEO_TILE_MAKE_STRIDE (x_tiles, y_tiles); - } else { - stride[i] = obj->bytesperline[i]; - } - - /* when using multiplanar mode and if there is more then one v4l - * plane for each gst plane - */ - if (V4L2_TYPE_IS_MULTIPLANAR (obj->type) && group->n_mem > 1) - /* non_contiguous case here so we have to make sure that gst goes to the - * next plane (using default gstvideometa.c::default_map). - * And the next plane is after length bytes of the previous one from - * the gst buffer point of view. */ - offs += gst_memory_get_sizes (group->mem[i], NULL, NULL); - else - offs += obj->bytesperline[i] * - GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (finfo, i, height); - } - + if (pool->add_videometa) gst_buffer_add_video_meta_full (newbuf, GST_VIDEO_FRAME_FLAG_NONE, - GST_VIDEO_INFO_FORMAT (info), width, height, n_gst_planes, - offset, stride); - } - - if (pool->add_cropmeta) { - GstVideoCropMeta *crop; - crop = gst_buffer_add_video_crop_meta (newbuf); - crop->x = align->padding_left; - crop->y = align->padding_top; - crop->width = info->width; - crop->width = info->height; - } + GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info), + GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info), + info->offset, info->stride); *buffer = newbuf; @@ -489,10 +427,6 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config) gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); - pool->add_cropmeta = - gst_buffer_pool_config_has_option (config, - GST_V4L2_BUFFER_POOL_OPTION_CROP_META); - /* parse the config and keep around */ if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers)) @@ -564,13 +498,6 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config) GST_BUFFER_POOL_OPTION_VIDEO_META); } - if (!pool->add_cropmeta && obj->need_crop_meta) { - GST_INFO_OBJECT (pool, "adding needed crop meta"); - updated = TRUE; - gst_buffer_pool_config_add_option (config, - GST_V4L2_BUFFER_POOL_OPTION_CROP_META); - } - if (updated) gst_buffer_pool_config_set_params (config, caps, size, min_buffers, max_buffers); @@ -1474,7 +1401,7 @@ gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps) gst_object_ref (obj->element); config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool)); - gst_buffer_pool_config_set_params (config, caps, obj->sizeimage, 0, 0); + gst_buffer_pool_config_set_params (config, caps, obj->info.size, 0, 0); /* This will simply set a default config, but will not configure the pool * because min and max are not valid */ gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pool), config); @@ -1498,7 +1425,7 @@ gst_v4l2_do_read (GstV4l2BufferPool * pool, GstBuffer * buf) GstMapInfo map; gint toread; - toread = obj->sizeimage; + toread = obj->info.size; GST_LOG_OBJECT (pool, "reading %d bytes into buffer %p", toread, buf); diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h index b0f96b5a22..d2126553c7 100644 --- a/sys/v4l2/gstv4l2bufferpool.h +++ b/sys/v4l2/gstv4l2bufferpool.h @@ -44,8 +44,6 @@ G_BEGIN_DECLS #define GST_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_BUFFER_POOL, GstV4l2BufferPool)) #define GST_V4L2_BUFFER_POOL_CAST(obj) ((GstV4l2BufferPool*)(obj)) -#define GST_V4L2_BUFFER_POOL_OPTION_CROP_META "GstV4l2BufferPoolOptionCropMeta" - struct _GstV4l2BufferPool { GstBufferPool parent; @@ -59,8 +57,7 @@ struct _GstV4l2BufferPool GstBufferPool *other_pool; guint size; - gboolean add_videometa; - gboolean add_cropmeta; + gboolean add_videometa; /* set if video meta should be added */ guint num_buffers; /* number of buffers we use */ guint num_queued; /* number of buffers queued in the driver */ diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index 9d80467a76..d12c3b033c 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -2245,32 +2245,68 @@ no_supported_capture_method: } static void -gst_v4l2_object_extrapolate_stride (GstV4l2Object * v4l2object, - struct v4l2_format *format, const GstVideoFormatInfo * finfo, guint stride) +gst_v4l2_object_set_stride (GstVideoInfo * info, GstVideoAlignment * align, + gint plane, gint stride) { - gint i; + const GstVideoFormatInfo *finfo = info->finfo; + + if (GST_VIDEO_FORMAT_INFO_IS_TILED (finfo)) { + gint x_tiles, y_tiles, ws, hs, tile_height, padded_height; + + + ws = GST_VIDEO_FORMAT_INFO_TILE_WS (finfo); + hs = GST_VIDEO_FORMAT_INFO_TILE_HS (finfo); + tile_height = 1 << hs; + + padded_height = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (finfo, plane, + info->height + align->padding_top + align->padding_bottom); + padded_height = GST_ROUND_UP_N (padded_height, tile_height); + + x_tiles = stride >> ws; + y_tiles = padded_height >> hs; + info->stride[plane] = GST_VIDEO_TILE_MAKE_STRIDE (x_tiles, y_tiles); + } else { + info->stride[plane] = stride; + } +} + +static void +gst_v4l2_object_extrapolate_info (GstV4l2Object * v4l2object, + GstVideoInfo * info, GstVideoAlignment * align, gint stride) +{ + const GstVideoFormatInfo *finfo = info->finfo; + gint i, estride, padded_height; + gsize offs = 0; g_return_if_fail (v4l2object->n_v4l2_planes == 1); - /* figure out the frame layout */ + padded_height = info->height + align->padding_top + align->padding_bottom; + for (i = 0; i < finfo->n_planes; i++) { switch (finfo->format) { case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV12_64Z32: case GST_VIDEO_FORMAT_NV21: case GST_VIDEO_FORMAT_NV16: case GST_VIDEO_FORMAT_NV24: - v4l2object->bytesperline[i] = (i == 0 ? 1 : 2) * + estride = (i == 0 ? 1 : 2) * GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (finfo, i, stride); break; default: - v4l2object->bytesperline[i] = - GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (finfo, i, stride); + estride = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (finfo, i, stride); break; } + gst_v4l2_object_set_stride (info, align, i, estride); + + info->offset[i] = offs; + offs += stride * + GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (finfo, i, padded_height); + GST_DEBUG_OBJECT (v4l2object->element, - "Extrapolated stride for plane %d from %d to %d", i, stride, - v4l2object->bytesperline[i]); + "Extrapolated for plane %d with base stride %d: " + "stride %d, offset %" G_GSIZE_FORMAT, i, stride, info->stride[i], + info->offset[i]); } } @@ -2280,60 +2316,114 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object, GstVideoInfo * info, GstVideoAlignment * align) { const GstVideoFormatInfo *finfo = info->finfo; - guint stride; - gint i; + gboolean standard_stride = TRUE; + gint stride, padded_width, padded_height, i; + if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_ENCODED) { + v4l2object->n_v4l2_planes = 1; + info->size = format->fmt.pix.sizeimage; + goto store_info; + } + + /* adjust right padding */ + if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type)) + stride = format->fmt.pix_mp.plane_fmt[0].bytesperline; + else + stride = format->fmt.pix.bytesperline; + + padded_width = stride / GST_VIDEO_FORMAT_INFO_PSTRIDE (finfo, 0); + + if (padded_width < format->fmt.pix.width) + GST_WARNING_OBJECT (v4l2object->element, + "Driver bug detected, stride is too small for the width"); + + align->padding_right = padded_width - info->width - align->padding_left; + + /* adjust bottom padding */ + padded_height = format->fmt.pix.height; + + if (GST_VIDEO_FORMAT_INFO_IS_TILED (finfo)) { + guint hs, tile_height; + + hs = GST_VIDEO_FORMAT_INFO_TILE_HS (finfo); + tile_height = 1 << hs; + + padded_height = GST_ROUND_UP_N (padded_height, tile_height); + } + + align->padding_bottom = padded_height - info->height - align->padding_top; + + /* setup the strides and offset */ if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type)) { + struct v4l2_pix_format_mplane *pix_mp = &format->fmt.pix_mp; + /* figure out the frame layout */ - v4l2object->n_v4l2_planes = MAX (1, format->fmt.pix_mp.num_planes); - v4l2object->sizeimage = 0; + v4l2object->n_v4l2_planes = MAX (1, pix_mp->num_planes); + info->size = 0; for (i = 0; i < v4l2object->n_v4l2_planes; i++) { - v4l2object->bytesperline[i] = - format->fmt.pix_mp.plane_fmt[i].bytesperline; - v4l2object->sizeimage += format->fmt.pix_mp.plane_fmt[i].sizeimage; + stride = pix_mp->plane_fmt[i].bytesperline; + + if (info->stride[i] != stride) + standard_stride = FALSE; + + gst_v4l2_object_set_stride (info, align, i, stride); + info->offset[i] = info->size; + info->size += pix_mp->plane_fmt[i].sizeimage; } /* Extrapolate stride if planar format are being set in 1 v4l2 plane */ if (v4l2object->n_v4l2_planes < finfo->n_planes) { stride = format->fmt.pix_mp.plane_fmt[0].bytesperline; - gst_v4l2_object_extrapolate_stride (v4l2object, format, finfo, stride); + gst_v4l2_object_extrapolate_info (v4l2object, info, align, stride); } } else { /* only one plane in non-MPLANE mode */ v4l2object->n_v4l2_planes = 1; - v4l2object->sizeimage = format->fmt.pix.sizeimage; + info->size = format->fmt.pix.sizeimage; stride = format->fmt.pix.bytesperline; - gst_v4l2_object_extrapolate_stride (v4l2object, format, finfo, stride); + + if (info->stride[0] != stride) + standard_stride = FALSE; + + gst_v4l2_object_extrapolate_info (v4l2object, info, align, stride); } - GST_DEBUG_OBJECT (v4l2object->element, "Got sizeimage %u", - v4l2object->sizeimage); + /* adjust the offset to take into account left and top */ + if (GST_VIDEO_FORMAT_INFO_IS_TILED (finfo)) { + if ((align->padding_left + align->padding_top) > 0) + GST_WARNING_OBJECT (v4l2object->element, + "Left and top padding is not permitted for tiled formats"); + } else { + for (i = 0; i < finfo->n_planes; i++) { + gint vedge, hedge; - /* To avoid copies, we need crop_meta if top or left padding is set */ - v4l2object->need_crop_meta = + /* FIXME we assume plane as component as this is true for all supported + * format we support. */ + + hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (finfo, i, align->padding_left); + vedge = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (finfo, i, align->padding_top); + + info->offset[i] += (vedge * info->stride[i]) + + (hedge * GST_VIDEO_INFO_COMP_PSTRIDE (info, i)); + } + } + +store_info: + GST_DEBUG_OBJECT (v4l2object->element, "Got sizeimage %" G_GSIZE_FORMAT, + info->size); + + /* to avoid copies we need video meta if top or left padding */ + v4l2object->need_video_meta = ((align->padding_top + align->padding_left) != 0); - /* ... or video meta if bottom or right padding is set */ - v4l2object->need_video_meta = (v4l2object->need_crop_meta || - ((align->padding_bottom + align->padding_right) != 0)); - - /* ... or also video meta if stride is non "standard" */ - for (i = 0; i < v4l2object->n_v4l2_planes; i++) { - gint stride = GST_VIDEO_INFO_PLANE_STRIDE (info, i); - - if (GST_VIDEO_FORMAT_INFO_IS_TILED (info->finfo)) - stride = GST_VIDEO_TILE_X_TILES (stride) << - GST_VIDEO_FORMAT_INFO_TILE_WS (info->finfo); - - if (stride != v4l2object->bytesperline[i]) - v4l2object->need_video_meta = TRUE; - } + /* ... or if stride is non "standard" */ + if (!standard_stride) + v4l2object->need_video_meta = TRUE; /* ... or also video meta if we use multiple, non-contiguous, planes */ if (v4l2object->n_v4l2_planes > 1) v4l2object->need_video_meta = TRUE; - gst_video_info_align (info, align); v4l2object->info = *info; v4l2object->align = *align; v4l2object->format = *format; @@ -2622,11 +2712,9 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps) } done: + /* add boolean return, so we can fail on drivers bugs */ gst_v4l2_object_save_format (v4l2object, fmtdesc, &format, &info, &align); - if (v4l2object->sizeimage < GST_VIDEO_INFO_SIZE (&info)) - goto short_allocation; - /* now configure the pool */ if (!gst_v4l2_object_setup_pool (v4l2object, caps)) goto pool_failed; @@ -2711,14 +2799,6 @@ set_parm_failed: GST_ERROR_SYSTEM); goto done; } -short_allocation: - { - GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS, - (_("Video device provided a image size that is too short.")), - ("Expected at least %" G_GSIZE_FORMAT " but got %u", info.size, - v4l2object->sizeimage)); - return FALSE; - } pool_failed: { /* setup_pool already send the error */ @@ -2801,9 +2881,6 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info) gst_v4l2_object_save_format (v4l2object, fmtdesc, &fmt, info, &align); - if (v4l2object->sizeimage < GST_VIDEO_INFO_SIZE (info)) - goto short_allocation; - /* Shall we setup the pool ? */ return TRUE; @@ -2837,14 +2914,6 @@ unsupported_format: GST_FOURCC_ARGS (fmt.fmt.pix.pixelformat))); return FALSE; } -short_allocation: - { - GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS, - (_("Video device provided a image size that is too short.")), - ("Expected at least %" G_GSIZE_FORMAT " but got %u", info->size, - v4l2object->sizeimage)); - return FALSE; - } } gboolean @@ -2995,7 +3064,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query) GstStructure *config; guint size, min, max, own_min = 0; gboolean update; - gboolean has_video_meta, has_crop_meta; + gboolean has_video_meta; gboolean can_share_own_pool, pushing_from_our_pool = FALSE; struct v4l2_control ctl = { 0, }; @@ -3026,12 +3095,8 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query) has_video_meta = gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); - has_crop_meta = - gst_query_find_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, - NULL); - can_share_own_pool = ((has_crop_meta || !obj->need_crop_meta) && - (has_video_meta || !obj->need_video_meta)); + can_share_own_pool = (has_video_meta || !obj->need_video_meta); /* select a pool */ switch (obj->mode) { @@ -3044,13 +3109,13 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query) /* use the bigest size, when we use our own pool we can't really do any * other size than what the hardware gives us but for downstream pools * we can try */ - size = MAX (size, obj->sizeimage); + size = MAX (size, obj->info.size); } else if (can_share_own_pool) { /* no downstream pool, use our own then */ GST_DEBUG_OBJECT (obj->element, "read/write mode: no downstream pool, using our own"); pool = gst_object_ref (obj->pool); - size = obj->sizeimage; + size = obj->info.size; pushing_from_our_pool = TRUE; } break; @@ -3066,7 +3131,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query) other_pool = pool; gst_object_unref (pool); pool = gst_object_ref (obj->pool); - size = obj->sizeimage; + size = obj->info.size; break; case GST_V4L2_IO_MMAP: @@ -3077,7 +3142,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query) if (pool) gst_object_unref (pool); pool = gst_object_ref (obj->pool); - size = obj->sizeimage; + size = obj->info.size; GST_DEBUG_OBJECT (obj->element, "streaming mode: using our own pool %" GST_PTR_FORMAT, pool); pushing_from_our_pool = TRUE; @@ -3088,7 +3153,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query) } else { GST_DEBUG_OBJECT (obj->element, "streaming mode: no usable pool, copying to generic pool"); - size = MAX (size, obj->sizeimage); + size = MAX (size, obj->info.size); } break; case GST_V4L2_IO_AUTO: @@ -3152,12 +3217,6 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query) GST_BUFFER_POOL_OPTION_VIDEO_META); } - if (obj->need_crop_meta) { - GST_DEBUG_OBJECT (obj->element, "activate VideoCrop Meta"); - gst_buffer_pool_config_add_option (config, - GST_V4L2_BUFFER_POOL_OPTION_CROP_META); - } - gst_buffer_pool_config_set_params (config, caps, size, own_min, 0); GST_DEBUG_OBJECT (obj->element, "setting own pool config to %" @@ -3256,7 +3315,7 @@ gst_v4l2_object_propose_allocation (GstV4l2Object * obj, GstQuery * query) gboolean need_pool; /* Set defaults allocation parameters */ - size = obj->sizeimage; + size = obj->info.size; min = GST_V4L2_MIN_BUFFERS; max = VIDEO_MAX_FRAME; diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h index ff96dc0193..a85f3e837e 100644 --- a/sys/v4l2/gstv4l2object.h +++ b/sys/v4l2/gstv4l2object.h @@ -102,7 +102,6 @@ struct _GstV4l2Object { /* Features */ gboolean need_video_meta; - gboolean need_crop_meta; gboolean has_alpha_component; /* only used if the device supports MPLANE @@ -111,8 +110,7 @@ struct _GstV4l2Object { */ gint n_v4l2_planes; - guint32 bytesperline[GST_VIDEO_MAX_PLANES]; - guint32 sizeimage; + /* We cache the frame duration if known */ GstClockTime duration; /* if the MPLANE device support both contiguous and non contiguous diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index a830e2a19d..12a30df2c5 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -622,7 +622,7 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf) GstClockTime delay; ret = GST_BASE_SRC_CLASS (parent_class)->alloc (GST_BASE_SRC (src), 0, - obj->sizeimage, buf); + obj->info.size, buf); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto alloc_failed; diff --git a/sys/v4l2/gstv4l2transform.c b/sys/v4l2/gstv4l2transform.c index 34df50987c..6928a392be 100644 --- a/sys/v4l2/gstv4l2transform.c +++ b/sys/v4l2/gstv4l2transform.c @@ -463,7 +463,7 @@ gst_v4l2_transform_prepare_output_buffer (GstBaseTransform * trans, if (!gst_buffer_pool_is_active (pool)) { GstStructure *config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, self->incaps, - self->v4l2output->sizeimage, 2, 2); + self->v4l2output->info.size, 2, 2); /* There is no reason to refuse this config */ if (!gst_buffer_pool_set_config (pool, config)) diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c index 12ab1789c4..2b3aa9d83a 100644 --- a/sys/v4l2/gstv4l2videodec.c +++ b/sys/v4l2/gstv4l2videodec.c @@ -471,7 +471,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder, if (!gst_buffer_pool_is_active (pool)) { GstStructure *config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, self->input_state->caps, - self->v4l2output->sizeimage, 2, 2); + self->v4l2output->info.size, 2, 2); /* There is no reason to refuse this config */ if (!gst_buffer_pool_set_config (pool, config))