summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Parrot <bparrot@ti.com>2019-09-11 12:04:27 -0500
committerTomi Valkeinen <tomi.valkeinen@iki.fi>2019-09-16 09:19:45 +0300
commit339e794dc14740d3628bac988e33e48d20551df4 (patch)
treec0512d2b303cf5e4e2ecaaa9c440306cdfa00290
parenta5545df02b40414c2bf3abc60cf629c5f59d00ec (diff)
videodevice: handle NV12 <-> NM12 translation
V4L2 and DRM differ in their interpretation of YUV420::NV12 V4L2 NV12 is a Y and UV co-located planes in a single plane buffer. DRM NV12 is a Y and UV planes presented as dual plane buffer, which is known as NM12 in V4L2. Since here we have hybrid DRM/V4L2 user space helper functions we need to translate DRM::NV12 to V4L2:NM12 pixel format back and forth to keep the data view consistent. Signed-off-by: Benoit Parrot <bparrot@ti.com>
-rw-r--r--kms++util/src/videodevice.cpp28
1 files changed, 25 insertions, 3 deletions
diff --git a/kms++util/src/videodevice.cpp b/kms++util/src/videodevice.cpp
index cc11357..23f45d4 100644
--- a/kms++util/src/videodevice.cpp
+++ b/kms++util/src/videodevice.cpp
@@ -15,6 +15,18 @@
using namespace std;
using namespace kms;
+/*
+ * V4L2 and DRM differ in their interpretation of YUV420::NV12
+ *
+ * V4L2 NV12 is a Y and UV co-located planes in a single plane buffer.
+ * DRM NV12 is a Y and UV planes presented as dual plane buffer,
+ * which is known as NM12 in V4L2.
+ *
+ * Since here we have hybrid DRM/V4L2 user space helper functions
+ * we need to translate DRM::NV12 to V4L2:NM12 pixel format back
+ * and forth to keep the data view consistent.
+ */
+
/* V4L2 helper funcs */
static vector<PixelFormat> v4l2_get_formats(int fd, uint32_t buf_type)
{
@@ -24,7 +36,11 @@ static vector<PixelFormat> v4l2_get_formats(int fd, uint32_t buf_type)
desc.type = buf_type;
while (ioctl(fd, VIDIOC_ENUM_FMT, &desc) == 0) {
- v.push_back((PixelFormat)desc.pixelformat);
+ if (desc.pixelformat == V4L2_PIX_FMT_NV12M)
+ v.push_back(PixelFormat::NV12);
+ else if (desc.pixelformat != V4L2_PIX_FMT_NV12)
+ v.push_back((PixelFormat)desc.pixelformat);
+
desc.index++;
}
@@ -47,8 +63,14 @@ static void v4l2_set_format(int fd, PixelFormat fmt, uint32_t width, uint32_t he
if (mplane) {
v4l2_pix_format_mplane& mp = v4lfmt.fmt.pix_mp;
+ uint32_t used_fmt;
+
+ if (fmt == PixelFormat::NV12)
+ used_fmt = V4L2_PIX_FMT_NV12M;
+ else
+ used_fmt = (uint32_t)fmt;
- mp.pixelformat = (uint32_t)fmt;
+ mp.pixelformat = used_fmt;
mp.width = width;
mp.height = height;
@@ -65,7 +87,7 @@ static void v4l2_set_format(int fd, PixelFormat fmt, uint32_t width, uint32_t he
r = ioctl(fd, VIDIOC_S_FMT, &v4lfmt);
ASSERT(r == 0);
- ASSERT(mp.pixelformat == (uint32_t)fmt);
+ ASSERT(mp.pixelformat == used_fmt);
ASSERT(mp.width == width);
ASSERT(mp.height == height);