Skip to content

Commit

Permalink
HACK: v4l2codecs: Support multi-planar YUV420M format
Browse files Browse the repository at this point in the history
V4L's YUV420M multi-planar format almost equals to YUV420 format of Linux
DRM  and to I420 of GStreamer, but in fact it shouldn't because I420 is
supposed to have 1 memory plane, while YUV420M 3 memory planes. This happens
to work by chance, since neither GStreamer, nor kernel's V4L core handles
properly plane's offsets by assuming that they all zeros always. Nevertheless,
this situation is good enough for us for testing of V4L codecs plugin on
NVIDIA Tegra.

Note that I haven't removed the pitch comparison of decoded frames vs
displayed from gstv4l2codech264dec that is unnecessary for YUV420M. Meaning
that video resolutions that aren't multiple of 16 pixels in width will
require software copying of video buffers, which is extremely slow. The
pitch of YUV420M format isn't equal to pitch of I420, but pitch difference
doesn't matter in a case of separate memory planes. Technically the comparison
could be removed for testing, but will be better to support YUV420M properly.
Testing of 720p videos will work fine since width is multiple of 16, 1080p
won't work well without removal of the comparison.
  • Loading branch information
digetx committed Jan 12, 2022
1 parent 1be6d6c commit b8509bd
Showing 1 changed file with 8 additions and 16 deletions.
24 changes: 8 additions & 16 deletions subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2format.c
Expand Up @@ -36,6 +36,7 @@ static struct FormatEntry format_map[] = {
{V4L2_PIX_FMT_YUYV, 1, GST_VIDEO_FORMAT_YUY2, 8, 422},
{V4L2_PIX_FMT_SUNXI_TILED_NV12, 1, GST_VIDEO_FORMAT_NV12_32L32, 8, 422},
{V4L2_PIX_FMT_NV12_4L4, 1, GST_VIDEO_FORMAT_NV12_4L4, 8, 420},
{V4L2_PIX_FMT_YUV420M, 3, GST_VIDEO_FORMAT_I420, 8, 420},
{0,}
};

Expand Down Expand Up @@ -85,6 +86,7 @@ extrapolate_stride (const GstVideoFormatInfo * finfo, gint plane, gint stride)
case GST_VIDEO_FORMAT_NV21:
case GST_VIDEO_FORMAT_NV24:
case GST_VIDEO_FORMAT_NV61:
case GST_VIDEO_FORMAT_I420:
estride = (plane == 0 ? 1 : 2) *
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (finfo, plane, stride);
break;
Expand Down Expand Up @@ -131,31 +133,21 @@ gst_v4l2_format_to_video_info (struct v4l2_format *fmt, GstVideoInfo * out_info)
if (!entry)
return FALSE;

if (entry->num_planes != 1) {
GST_FIXME ("Multi allocation formats are not supported yet");
return FALSE;
}

if (!gst_video_info_set_format (out_info, entry->gst_fmt,
pix_mp->width, pix_mp->height))
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;
} else {
out_info->size = pix->sizeimage;
}

for (plane = 0; plane < GST_VIDEO_INFO_N_PLANES (out_info); plane++) {
gint stride;

if (V4L2_TYPE_IS_MULTIPLANAR (fmt->type))
if (V4L2_TYPE_IS_MULTIPLANAR (fmt->type)) {
stride = extrapolate_stride (out_info->finfo, plane,
pix_mp->plane_fmt[0].bytesperline);
else
pix_mp->plane_fmt[plane].bytesperline);
out_info->size += pix_mp->plane_fmt[plane].sizeimage;
} else {
stride = extrapolate_stride (out_info->finfo, plane, pix->bytesperline);
out_info->size += pix->sizeimage;
}

set_stride (out_info, plane, stride);
out_info->offset[plane] = offset;
Expand Down

0 comments on commit b8509bd

Please sign in to comment.