summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Dufresne <nicolas.dufresne@collabora.com>2014-04-15 15:07:23 -0400
committerNicolas Dufresne <nicolas.dufresne@collabora.com>2014-05-08 15:56:35 -0400
commita7286563ee1fb0d3d2b3c24952288a8e493875da (patch)
tree121e49f9132e7b0626321989e656fd48c00f9ad7
parent70e7868f18db93dfe3b8798c402e44f4a67cd89c (diff)
v4l2: Add initial support for alignment and cropping
-rw-r--r--sys/v4l2/gstv4l2bufferpool.c17
-rw-r--r--sys/v4l2/gstv4l2bufferpool.h3
-rw-r--r--sys/v4l2/gstv4l2object.c340
-rw-r--r--sys/v4l2/gstv4l2object.h7
-rw-r--r--sys/v4l2/gstv4l2videodec.h2
5 files changed, 213 insertions, 156 deletions
diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 5e669c905..f2093457d 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -141,11 +141,13 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
GstV4l2Meta *meta;
GstV4l2Object *obj;
GstVideoInfo *info;
+ GstVideoAlignment *align;
guint index;
gint i;
obj = pool->obj;
info = &obj->info;
+ align = &obj->align;
switch (obj->mode) {
case GST_V4L2_IO_RW:
@@ -339,6 +341,15 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
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;
+ }
break;
}
case GST_V4L2_IO_USERPTR:
@@ -1666,3 +1677,9 @@ start_failed:
return FALSE;
}
}
+
+void
+gst_v4l2_buffer_pool_add_crop_meta (GstV4l2BufferPool * bpool, gboolean add)
+{
+ bpool->add_cropmeta = add;
+}
diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h
index 7a7f8c733..9d654c104 100644
--- a/sys/v4l2/gstv4l2bufferpool.h
+++ b/sys/v4l2/gstv4l2bufferpool.h
@@ -54,6 +54,7 @@ struct _GstV4l2BufferPool
GstAllocationParams params;
guint size;
gboolean add_videometa;
+ gboolean add_cropmeta;
gboolean can_alloc; /* if extra buffers can be allocated */
guint num_buffers; /* number of buffers we use */
@@ -110,6 +111,8 @@ GstFlowReturn gst_v4l2_buffer_pool_process (GstV4l2BufferPool * bpool, Gst
gboolean gst_v4l2_buffer_pool_flush (GstV4l2BufferPool * pool);
+void gst_v4l2_buffer_pool_add_crop_meta (GstV4l2BufferPool * bpool, gboolean add);
+
G_END_DECLS
#endif /*__GST_V4L2_BUFFER_POOL_H__ */
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 439956309..96f212f0b 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -2255,7 +2255,7 @@ no_supported_capture_method:
static void
gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
struct v4l2_fmtdesc *fmtdesc, struct v4l2_format *format,
- GstVideoInfo * info)
+ GstVideoInfo * info, GstVideoAlignment * align)
{
const GstVideoFormatInfo *finfo = info->finfo;
gint i;
@@ -2302,7 +2302,25 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
GST_DEBUG_OBJECT (v4l2object->element, "Got sizeimage %u",
v4l2object->sizeimage);
+ /* To avoid copies, we need crop_meta if top or left padding is set */
+ v4l2object->need_crop_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" */
+ if (GST_VIDEO_INFO_PLANE_STRIDE (info, 0) != v4l2object->bytesperline[0])
+ 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->fmtdesc = fmtdesc;
/* if we have a framerate pre-calculate duration */
@@ -2324,12 +2342,20 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps)
guint32 pixelformat;
struct v4l2_fmtdesc *fmtdesc;
GstVideoInfo info;
+ GstVideoAlignment align;
gint width, height, fps_n, fps_d;
+ gint n_v4l_planes;
gint i = 0;
+ gboolean is_mplane, format_changed;
GST_V4L2_CHECK_OPEN (v4l2object);
GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);
+ is_mplane = V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type);
+
+ gst_video_info_init (&info);
+ gst_video_alignment_reset (&align);
+
if (!gst_v4l2_object_get_caps_info (v4l2object, caps, &fmtdesc, &info))
goto invalid_caps;
@@ -2339,9 +2365,11 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps)
fps_n = GST_VIDEO_INFO_FPS_N (&info);
fps_d = GST_VIDEO_INFO_FPS_D (&info);
- /* get bytesperline for each plane */
- for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&info); i++)
- v4l2object->bytesperline[i] = GST_VIDEO_INFO_PLANE_STRIDE (&info, i);
+ /* if encoded format (GST_VIDEO_INFO_N_PLANES return 0)
+ * or if contiguous is prefered */
+ n_v4l_planes = GST_VIDEO_INFO_N_PLANES (&info);
+ if (!n_v4l_planes || !v4l2object->prefered_non_contiguous)
+ n_v4l_planes = 1;
if (GST_VIDEO_INFO_IS_INTERLACED (&info)) {
GST_DEBUG_OBJECT (v4l2object->element, "interlaced video");
@@ -2356,22 +2384,19 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps)
GST_DEBUG_OBJECT (v4l2object->element, "Desired format %dx%d, format "
"%" GST_FOURCC_FORMAT " stride: %d", width, height,
- GST_FOURCC_ARGS (pixelformat), v4l2object->bytesperline[0]);
+ GST_FOURCC_ARGS (pixelformat), GST_VIDEO_INFO_PLANE_STRIDE (&info, 0));
memset (&format, 0x00, sizeof (struct v4l2_format));
format.type = v4l2object->type;
- if (!v4l2object->no_initial_format) {
+ if (v4l2object->no_initial_format) {
+ format_changed = TRUE;
+ } else {
if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0)
goto get_fmt_failed;
- }
- if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type)) {
- GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
- "%" GST_FOURCC_FORMAT " colorspace %d, nb planes %d",
- format.fmt.pix_mp.width, format.fmt.pix_mp.height,
- GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
- format.fmt.pix_mp.colorspace, format.fmt.pix_mp.num_planes);
+ /* Note that four first fields are the same between v4l2_pix_format and
+ * v4l2_pix_format_mplane, so we don't need to duplicate he checks */
/* If no size in caps, use configured size */
if (width == 0 && height == 0) {
@@ -2379,133 +2404,108 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps)
height = format.fmt.pix_mp.height;
}
- if (format.type != v4l2object->type ||
+ format_changed = format.type != v4l2object->type ||
format.fmt.pix_mp.width != width ||
format.fmt.pix_mp.height != height ||
format.fmt.pix_mp.pixelformat != pixelformat ||
- format.fmt.pix_mp.field != field) {
- /* even in v4l2 multiplanar mode we can work in contiguous mode
- * if the device supports it */
- gint n_v4l_planes = GST_VIDEO_INFO_N_PLANES (&info);
-
- /* if encoded format (GST_VIDEO_INFO_N_PLANES return 0)
- * or if contiguous is prefered */
- if (!n_v4l_planes || !v4l2object->prefered_non_contiguous)
- n_v4l_planes = 1;
-
- /* something different, set the format */
- GST_DEBUG_OBJECT (v4l2object->element, "Setting format to %dx%d, format "
- "%" GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat));
-
- format.type = v4l2object->type;
- format.fmt.pix_mp.pixelformat = pixelformat;
- format.fmt.pix_mp.width = width;
- format.fmt.pix_mp.height = height;
- format.fmt.pix_mp.field = field;
- format.fmt.pix_mp.num_planes = n_v4l_planes;
- /* try to ask our prefered stride but it's not a failure
- * if not accepted */
- for (i = 0; i < format.fmt.pix_mp.num_planes; i++)
- format.fmt.pix_mp.plane_fmt[i].bytesperline =
- v4l2object->bytesperline[i];
-
- if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED) {
- format.fmt.pix_mp.plane_fmt[0].sizeimage = ENCODED_BUFFER_SIZE;
- }
-
- if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0)
- goto set_fmt_failed;
-
- GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
- "%" GST_FOURCC_FORMAT ", nb planes %d", format.fmt.pix.width,
- format.fmt.pix_mp.height,
- GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
- format.fmt.pix_mp.num_planes);
+ format.fmt.pix_mp.field != field;
+ }
#ifndef GST_DISABLE_GST_DEBUG
- for (i = 0; i < format.fmt.pix_mp.num_planes; i++)
- GST_DEBUG_OBJECT (v4l2object->element, " stride %d",
- format.fmt.pix_mp.plane_fmt[i].bytesperline);
-#endif
-
- if (format.fmt.pix_mp.pixelformat != pixelformat)
- goto invalid_pixelformat;
-
- /* we set the dimensions just in case but don't validate them afterwards
- * For some codecs the dimensions are *not* in the bitstream, IIRC VC1
- * in ASF mode for example. */
- if (info.finfo->format != GST_VIDEO_FORMAT_ENCODED) {
- if (format.fmt.pix_mp.width != width
- || format.fmt.pix_mp.height != height)
- goto invalid_dimensions;
- }
-
- if (format.fmt.pix_mp.num_planes != n_v4l_planes)
- goto invalid_planes;
- }
+ if (is_mplane) {
+ GST_DEBUG_OBJECT (v4l2object->element, "Current size is %dx%d, format "
+ "%" GST_FOURCC_FORMAT " colorspace %d, nb planes %d",
+ format.fmt.pix_mp.width, format.fmt.pix_mp.height,
+ GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
+ format.fmt.pix_mp.colorspace, format.fmt.pix_mp.num_planes);
- /* figure out the frame layout */
- v4l2object->n_v4l2_planes = format.fmt.pix_mp.num_planes;
- v4l2object->sizeimage = 0;
- for (i = 0; i < format.fmt.pix_mp.num_planes; i++) {
- v4l2object->bytesperline[i] = format.fmt.pix_mp.plane_fmt[i].bytesperline;
- v4l2object->sizeimage += format.fmt.pix_mp.plane_fmt[i].sizeimage;
- }
+ for (i = 0; i < format.fmt.pix_mp.num_planes; i++)
+ GST_DEBUG_OBJECT (v4l2object->element, " stride %d",
+ format.fmt.pix_mp.plane_fmt[i].bytesperline);
} else {
- GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
- "%" GST_FOURCC_FORMAT " bytesperline %d, colorspace %d",
+ GST_DEBUG_OBJECT (v4l2object->element, "Current size is %dx%d, format "
+ "%" GST_FOURCC_FORMAT " stride %d, colorspace %d",
format.fmt.pix.width, format.fmt.pix.height,
GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
format.fmt.pix.bytesperline, format.fmt.pix.colorspace);
+ }
+#endif
- /* If no size in caps, use configured size */
- if (width == 0 && height == 0) {
- width = format.fmt.pix_mp.width;
- height = format.fmt.pix_mp.height;
- }
+ /* If nothing changed, we are done */
+ if (!format_changed)
+ goto done;
- if (format.type != v4l2object->type ||
- format.fmt.pix.width != width ||
- format.fmt.pix.height != height ||
- format.fmt.pix.pixelformat != pixelformat ||
- format.fmt.pix.field != field) {
- /* something different, set the format */
- GST_DEBUG_OBJECT (v4l2object->element, "Setting format to %dx%d, format "
- "%" GST_FOURCC_FORMAT " bytesperline %d", width, height,
- GST_FOURCC_ARGS (pixelformat), v4l2object->bytesperline[0]);
-
- format.type = v4l2object->type;
- format.fmt.pix.width = width;
- format.fmt.pix.height = height;
- format.fmt.pix.pixelformat = pixelformat;
- format.fmt.pix.field = field;
- /* try to ask our prefered stride */
- format.fmt.pix.bytesperline = v4l2object->bytesperline[0];
-
- if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED) {
- format.fmt.pix.sizeimage = ENCODED_BUFFER_SIZE;
- }
+ /* something different, set the format */
+ GST_DEBUG_OBJECT (v4l2object->element, "Setting format to %dx%d, format "
+ "%" GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat));
+
+ if (is_mplane) {
+ format.type = v4l2object->type;
+ format.fmt.pix_mp.pixelformat = pixelformat;
+ format.fmt.pix_mp.width = width;
+ format.fmt.pix_mp.height = height;
+ format.fmt.pix_mp.field = field;
+ format.fmt.pix_mp.num_planes = n_v4l_planes;
+
+ /* try to ask our prefered stride but it's not a failure
+ * if not accepted */
+ for (i = 0; i < format.fmt.pix_mp.num_planes; i++)
+ format.fmt.pix_mp.plane_fmt[i].bytesperline =
+ GST_VIDEO_INFO_PLANE_STRIDE (&info, i);
+
+ if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED)
+ format.fmt.pix_mp.plane_fmt[0].sizeimage = ENCODED_BUFFER_SIZE;
+ } else {
+ format.type = v4l2object->type;
+ format.fmt.pix.width = width;
+ format.fmt.pix.height = height;
+ format.fmt.pix.pixelformat = pixelformat;
+ format.fmt.pix.field = field;
+ /* try to ask our prefered stride */
+ format.fmt.pix.bytesperline = GST_VIDEO_INFO_PLANE_STRIDE (&info, 0);
- if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0)
- goto set_fmt_failed;
+ if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED)
+ format.fmt.pix.sizeimage = ENCODED_BUFFER_SIZE;
+ }
- GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
- "%" GST_FOURCC_FORMAT " stride %d", format.fmt.pix.width,
- format.fmt.pix.height, GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
- format.fmt.pix.bytesperline);
+ if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0)
+ goto set_fmt_failed;
- /* we set the dimensions just in case but don't validate them afterwards
- * For some codecs the dimensions are *not* in the bitstream, IIRC VC1
- * in ASF mode for example. */
- if (info.finfo->format != GST_VIDEO_FORMAT_ENCODED) {
- if (format.fmt.pix.width != width || format.fmt.pix.height != height)
- goto invalid_dimensions;
- }
+ GST_DEBUG_OBJECT (v4l2object->element, "Got format to %dx%d, format "
+ "%" GST_FOURCC_FORMAT ", nb planes %d", format.fmt.pix.width,
+ format.fmt.pix_mp.height,
+ GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
+ is_mplane ? format.fmt.pix_mp.num_planes : 1);
- if (format.fmt.pix.pixelformat != pixelformat)
- goto invalid_pixelformat;
- }
+#ifndef GST_DISABLE_GST_DEBUG
+ if (is_mplane) {
+ for (i = 0; i < format.fmt.pix_mp.num_planes; i++)
+ GST_DEBUG_OBJECT (v4l2object->element, " stride %d",
+ format.fmt.pix_mp.plane_fmt[i].bytesperline);
}
+#endif
+
+ if (format.fmt.pix.pixelformat != pixelformat)
+ goto invalid_pixelformat;
+
+ /* Only negotiate size with raw data.
+ * For some codecs the dimensions are *not* in the bitstream, IIRC VC1
+ * in ASF mode for example, there is also not reason for a driver to
+ * change the size. */
+ if (info.finfo->format != GST_VIDEO_FORMAT_ENCODED) {
+ /* We can crop larger images */
+ if (format.fmt.pix.width < width || format.fmt.pix.height < height)
+ goto invalid_dimensions;
+
+ /* Note, this will be adjusted if upstream has non-centered cropping. */
+ align.padding_top = 0;
+ align.padding_bottom = format.fmt.pix.height - height;
+ align.padding_left = 0;
+ align.padding_right = format.fmt.pix.width - width;
+ }
+
+ if (is_mplane && format.fmt.pix_mp.num_planes != n_v4l_planes)
+ goto invalid_planes;
/* Is there a reason we require the caller to always specify a framerate? */
GST_DEBUG_OBJECT (v4l2object->element, "Desired framerate: %u/%u", fps_n,
@@ -2562,9 +2562,9 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps)
}
done:
- gst_v4l2_object_save_format (v4l2object, fmtdesc, &format, &info);
+ gst_v4l2_object_save_format (v4l2object, fmtdesc, &format, &info, &align);
- /* now configure ther pools */
+ /* now configure the pool */
if (!gst_v4l2_object_setup_pool (v4l2object, caps))
goto pool_failed;
@@ -2660,28 +2660,24 @@ pool_failed:
* gst_v4l2_object_acquire_format:
* @v4l2object the object
* @info a GstVideoInfo to be filled
- * @align a GstVideoAlignment to be filled
*
- * Setup the format base on the currently configured format. This is useful in
- * decoder or encoder elements where the output format is dictated by the
- * input.
* Acquire the driver choosen format. This is useful in decoder or encoder elements where
* the output format is choosen by the HW.
*
* Returns: %TRUE on success, %FALSE on failure.
*/
gboolean
-gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info,
- GstVideoAlignment * align)
+gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
{
struct v4l2_fmtdesc *fmtdesc;
struct v4l2_format fmt;
struct v4l2_crop crop;
GstVideoFormat format;
guint width, height;
+ GstVideoAlignment align;
gst_video_info_init (info);
- gst_video_alignment_reset (align);
+ gst_video_alignment_reset (&align);
memset (&fmt, 0x00, sizeof (struct v4l2_format));
fmt.type = v4l2object->type;
@@ -2709,10 +2705,10 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info,
memset (&crop, 0, sizeof (struct v4l2_crop));
crop.type = v4l2object->type;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CROP, &crop) >= 0) {
- align->padding_left = crop.c.left;
- align->padding_top = crop.c.top;
- align->padding_right = width - crop.c.width - crop.c.left;
- align->padding_bottom = height - crop.c.height - crop.c.top;
+ align.padding_left = crop.c.left;
+ align.padding_top = crop.c.top;
+ align.padding_right = width - crop.c.width - crop.c.left;
+ align.padding_bottom = height - crop.c.height - crop.c.top;
width = crop.c.width;
height = crop.c.height;
}
@@ -2733,7 +2729,7 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info,
goto unsupported_field;
}
- gst_v4l2_object_save_format (v4l2object, fmtdesc, &fmt, info);
+ gst_v4l2_object_save_format (v4l2object, fmtdesc, &fmt, info, &align);
/* Shall we setup the pool ? */
@@ -2838,6 +2834,8 @@ gst_v4l2_object_copy (GstV4l2Object * v4l2object, GstBuffer * dest,
GST_DEBUG_OBJECT (v4l2object->element, "copy video frame");
+ /* FIXME This won't work if cropping apply */
+
/* we have raw video, use videoframe copy to get strides right */
if (!gst_video_frame_map (&src_frame, &v4l2object->info, src, GST_MAP_READ))
goto invalid_buffer;
@@ -2932,6 +2930,8 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
GstBufferPool *pool;
guint size, min, max;
gboolean update;
+ gboolean has_video_meta, has_crop_meta;
+ gboolean can_use_own_pool;
struct v4l2_control ctl = { 0, };
GST_DEBUG_OBJECT (obj->element, "decide allocation");
@@ -2981,16 +2981,19 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
if (max != 0 && max < min)
max = min;
+ 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_use_own_pool = ((has_crop_meta || !obj->need_crop_meta) &&
+ (has_video_meta || !obj->need_video_meta));
+
/* select a pool */
switch (obj->mode) {
case GST_V4L2_IO_RW:
- if (pool == NULL) {
- /* no downstream pool, use our own then */
- GST_DEBUG_OBJECT (obj->element,
- "read/write mode: no downstream pool, using our own");
- pool = GST_BUFFER_POOL_CAST (obj->pool);
- size = obj->sizeimage;
- } else {
+ if (pool) {
/* in READ/WRITE mode, prefer a downstream pool because our own pool
* doesn't help much, we have to write to it as well */
GST_DEBUG_OBJECT (obj->element,
@@ -2999,19 +3002,33 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
* other size than what the hardware gives us but for downstream pools
* we can try */
size = MAX (size, obj->sizeimage);
+ } else if (can_use_own_pool) {
+ /* no downstream pool, use our own then */
+ GST_DEBUG_OBJECT (obj->element,
+ "read/write mode: no downstream pool, using our own");
+ pool = obj->pool;
+ size = obj->sizeimage;
}
break;
case GST_V4L2_IO_MMAP:
case GST_V4L2_IO_USERPTR:
case GST_V4L2_IO_DMABUF:
/* in streaming mode, prefer our own pool */
- if (pool)
- gst_object_unref (pool);
- pool = GST_BUFFER_POOL_CAST (obj->pool);
- size = obj->sizeimage;
- max = 0;
- GST_DEBUG_OBJECT (obj->element,
- "streaming mode: using our own pool %" GST_PTR_FORMAT, pool);
+ /* Check if we can use it ... */
+ if (can_use_own_pool) {
+ if (pool)
+ gst_object_unref (pool);
+ pool = obj->pool;
+ size = obj->sizeimage;
+ max = 0;
+ GST_DEBUG_OBJECT (obj->element,
+ "streaming mode: using our own pool %" GST_PTR_FORMAT, pool);
+ } else if (pool) {
+ GST_DEBUG_OBJECT (obj->element,
+ "streaming mode: copying to downstream pool %" GST_PTR_FORMAT,
+ pool);
+ size = MAX (size, obj->sizeimage);
+ }
break;
case GST_V4L2_IO_AUTO:
default:
@@ -3028,7 +3045,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
gst_buffer_pool_config_set_params (config, caps, size, min, max);
/* if downstream supports video metadata, add this to the pool config */
- if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) {
+ if (has_video_meta) {
GST_DEBUG_OBJECT (pool, "activate Video Meta");
gst_buffer_pool_config_add_option (config,
GST_BUFFER_POOL_OPTION_VIDEO_META);
@@ -3037,6 +3054,25 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
gst_buffer_pool_set_config (pool, config);
}
+ /* Our pool may be incompatible, though we'll need the metadata in order to
+ * copy to a downstream compatible buffer */
+ if (pool != obj->pool && obj->need_video_meta) {
+ GstStructure *config;
+ GstCaps *caps;
+
+ config = gst_buffer_pool_get_config (obj->pool);
+ gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL);
+ gst_buffer_pool_config_set_params (config, caps, obj->sizeimage, min, 0);
+ gst_buffer_pool_config_add_option (config,
+ GST_BUFFER_POOL_OPTION_VIDEO_META);
+
+ gst_buffer_pool_set_config (obj->pool, config);
+ }
+
+ if (obj->need_crop_meta)
+ gst_v4l2_buffer_pool_add_crop_meta (GST_V4L2_BUFFER_POOL (obj->pool),
+ obj->need_crop_meta);
+
if (update)
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
else
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index d61a274c8..e0edf1090 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -97,6 +97,10 @@ struct _GstV4l2Object {
/* the current format */
struct v4l2_fmtdesc *fmtdesc;
GstVideoInfo info;
+ GstVideoAlignment align;
+
+ gboolean need_video_meta;
+ gboolean need_crop_meta;
/* only used if the device supports MPLANE
* nb planes is meaning of v4l2 planes
@@ -254,8 +258,7 @@ GstCaps * gst_v4l2_object_get_caps (GstV4l2Object * v4l2object,
GstCaps * filter);
gboolean gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object,
- GstVideoInfo * info,
- GstVideoAlignment * align);
+ GstVideoInfo * info);
gboolean gst_v4l2_object_decide_allocation (GstV4l2Object * v4l2object,
GstQuery * query);
diff --git a/sys/v4l2/gstv4l2videodec.h b/sys/v4l2/gstv4l2videodec.h
index 98aaa4044..2ea3e83f0 100644
--- a/sys/v4l2/gstv4l2videodec.h
+++ b/sys/v4l2/gstv4l2videodec.h
@@ -65,8 +65,6 @@ struct _GstV4l2VideoDec
gboolean active;
gboolean processing;
GstFlowReturn output_flow;
-
- GstVideoAlignment align;
};
struct _GstV4l2VideoDecClass