v4l2: Fix support for left and top padding

In the current implementation, we support for most pixel format left
and top padding by changing the offset in the video meta. Though, to
align driver bytesused to the offset, we recalculate the offset, which
removed the modification we did before.

Instead, save the plane size, and truncate the driver reported bytesused
to the expected size, which ensures that the offsets still match. This
should also fix issues were the buffer size ended up bigger then the
pool size due to driver introduced padding.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4920>
This commit is contained in:
Nicolas Dufresne 2023-06-22 10:10:43 -04:00 committed by GStreamer Marge Bot
parent b18bd5ec2b
commit 170dcd58db
3 changed files with 16 additions and 18 deletions

View file

@ -1240,8 +1240,7 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
GstV4l2Object *obj = pool->obj; GstV4l2Object *obj = pool->obj;
GstClockTime timestamp; GstClockTime timestamp;
GstV4l2MemoryGroup *group; GstV4l2MemoryGroup *group;
GstVideoMeta *vmeta; const GstVideoInfo *info = &obj->info;
gsize size;
gint i; gint i;
gint old_buffer_state; gint old_buffer_state;
@ -1292,9 +1291,9 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
timestamp = GST_TIMEVAL_TO_TIME (group->buffer.timestamp); timestamp = GST_TIMEVAL_TO_TIME (group->buffer.timestamp);
size = 0;
vmeta = gst_buffer_get_video_meta (outbuf);
for (i = 0; i < group->n_mem; i++) { for (i = 0; i < group->n_mem; i++) {
const GstVideoFormatInfo *finfo = info->finfo;
GST_LOG_OBJECT (pool, GST_LOG_OBJECT (pool,
"dequeued buffer %p seq:%d (ix=%d), mem %p used %d, plane=%d, flags %08x, ts %" "dequeued buffer %p seq:%d (ix=%d), mem %p used %d, plane=%d, flags %08x, ts %"
GST_TIME_FORMAT ", pool-queued=%d, buffer=%p, previous-state=%i", GST_TIME_FORMAT ", pool-queued=%d, buffer=%p, previous-state=%i",
@ -1302,10 +1301,15 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
group->planes[i].bytesused, i, group->buffer.flags, group->planes[i].bytesused, i, group->buffer.flags,
GST_TIME_ARGS (timestamp), pool->num_queued, outbuf, old_buffer_state); GST_TIME_ARGS (timestamp), pool->num_queued, outbuf, old_buffer_state);
if (vmeta) { /* Ensure our offset matches the expected plane size, or image size if
vmeta->offset[i] = size; * there is only one memory */
size += gst_memory_get_sizes (group->mem[i], NULL, NULL); if (group->n_mem == 1) {
gst_memory_resize (group->mem[0], 0, info->size + info->offset[0]);
break;
} }
if (!GST_VIDEO_FORMAT_INFO_IS_TILED (finfo))
gst_memory_resize (group->mem[i], 0, obj->plane_size[i]);
} }
/* Ignore timestamp and field for OUTPUT device */ /* Ignore timestamp and field for OUTPUT device */

View file

@ -3576,18 +3576,11 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
if ((align->padding_left + align->padding_top) > 0) if ((align->padding_left + align->padding_top) > 0)
GST_WARNING_OBJECT (v4l2object->dbg_obj, GST_WARNING_OBJECT (v4l2object->dbg_obj,
"Left and top padding is not permitted for tiled formats"); "Left and top padding is not permitted for tiled formats");
memset (v4l2object->plane_size, 0,
sizeof (v4l2object->plane_size[0] * GST_VIDEO_MAX_PLANES));
} else { } else {
for (i = 0; i < finfo->n_planes; i++) { if (!gst_video_info_align_full (info, align, v4l2object->plane_size)) {
gint vedge, hedge; GST_WARNING_OBJECT (v4l2object->dbg_obj, "Failed to align video info");
/* 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));
} }
} }

View file

@ -148,6 +148,7 @@ struct _GstV4l2Object {
GstVideoInfo info; GstVideoInfo info;
GstVideoAlignment align; GstVideoAlignment align;
GstVideoTransferFunction transfer; GstVideoTransferFunction transfer;
gsize plane_size[GST_VIDEO_MAX_PLANES];
/* Features */ /* Features */
gboolean need_video_meta; gboolean need_video_meta;