v4l2codecs: Add support for multi planar buffers

V4L2 have some pixel formats that produces 2 dmabuf, this add
support for these format.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1567>
This commit is contained in:
Nicolas Dufresne 2022-01-19 15:53:05 -05:00 committed by GStreamer Marge Bot
parent e2b2ff26c9
commit 3005dbc55a

View file

@ -102,12 +102,21 @@ gst_v4l2_format_to_video_info (struct v4l2_format *fmt, GstVideoInfo * out_info)
struct v4l2_pix_format *pix = &fmt->fmt.pix;
gint plane;
gsize offset = 0;
gboolean extrapolate = FALSE;
if (!entry)
return FALSE;
if (entry->num_planes != 1) {
GST_FIXME ("Multi allocation formats are not supported yet");
/* validate the entry against the format */
if (V4L2_TYPE_IS_MULTIPLANAR (fmt->type)) {
if (entry->num_planes != pix_mp->num_planes) {
GST_ERROR ("Miss-matched number of planes in internal entry "
"(%i != %i)", entry->num_planes, pix_mp->num_planes);
return FALSE;
}
} else if (entry->num_planes != 1) {
GST_ERROR ("Miss-matched number of planes in internal entry "
"(must be 1 for non-multiplanar, got %i)", entry->num_planes);
return FALSE;
}
@ -116,28 +125,52 @@ gst_v4l2_format_to_video_info (struct v4l2_format *fmt, GstVideoInfo * out_info)
return FALSE;
if (V4L2_TYPE_IS_MULTIPLANAR (fmt->type)) {
/* TODO: We don't support multi-allocation yet */
g_return_val_if_fail (pix_mp->num_planes == 1, FALSE);
out_info->size = pix_mp->plane_fmt[0].sizeimage;
out_info->size = 0;
for (plane = 0; plane < pix_mp->num_planes; plane++)
out_info->size += pix_mp->plane_fmt[plane].sizeimage;
} else {
out_info->size = pix->sizeimage;
}
/*
* When single allocation formats are used for planar formats we need to
* extrapolate the per-plane stride. Do this check once to prevent
* complex inner loop.
*/
if (entry->num_planes == 1 && out_info->finfo->n_planes != entry->num_planes)
extrapolate = TRUE;
for (plane = 0; plane < GST_VIDEO_INFO_N_PLANES (out_info); plane++) {
gint stride;
if (V4L2_TYPE_IS_MULTIPLANAR (fmt->type))
stride = gst_video_format_info_extrapolate_stride (out_info->finfo, plane,
pix_mp->plane_fmt[0].bytesperline);
else
stride = gst_video_format_info_extrapolate_stride (out_info->finfo, plane,
pix->bytesperline);
if (V4L2_TYPE_IS_MULTIPLANAR (fmt->type)) {
if (extrapolate)
stride = gst_video_format_info_extrapolate_stride (out_info->finfo,
plane, pix_mp->plane_fmt[0].bytesperline);
else
stride = pix_mp->plane_fmt[plane].bytesperline;
} else {
if (extrapolate)
stride = gst_video_format_info_extrapolate_stride (out_info->finfo,
plane, pix->bytesperline);
else
stride = pix->bytesperline;
}
set_stride (out_info, plane, stride);
out_info->offset[plane] = offset;
offset += stride * GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (out_info->finfo,
plane, pix_mp->height);
if ((V4L2_TYPE_IS_MULTIPLANAR (fmt->type) && !extrapolate))
offset += pix_mp->plane_fmt[plane].sizeimage;
else
offset += stride * GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (out_info->finfo,
plane, pix_mp->height);
}
/* Check that the extrapolation didn't overflow the reported sizeimage */
if (extrapolate && offset > out_info->size) {
GST_ERROR ("Extrapolated plane offset overflow the image size.");
return FALSE;
}
return TRUE;