From a7286563ee1fb0d3d2b3c24952288a8e493875da Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Tue, 15 Apr 2014 15:07:23 -0400 Subject: [PATCH] v4l2: Add initial support for alignment and cropping --- sys/v4l2/gstv4l2bufferpool.c | 17 +++ sys/v4l2/gstv4l2bufferpool.h | 3 + sys/v4l2/gstv4l2object.c | 340 ++++++++++++++++++++++++------------------- sys/v4l2/gstv4l2object.h | 7 +- sys/v4l2/gstv4l2videodec.h | 2 - 5 files changed, 213 insertions(+), 156 deletions(-) diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c index 5e669c9..f209345 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 7a7f8c7..9d654c1 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 4399563..96f212f 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 d61a274..e0edf10 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 98aaa40..2ea3e83 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 -- 2.7.4