v4l2-compliance: improve tests when TRY/S_FMT returns EINVAL.
authorHans Verkuil <hans.verkuil@cisco.com>
Mon, 11 Mar 2013 20:45:14 +0000 (21:45 +0100)
committerHans Verkuil <hans.verkuil@cisco.com>
Mon, 11 Mar 2013 20:45:14 +0000 (21:45 +0100)
If a wrong pixelformat is specified, then TRY/S_FMT can return EINVAL.
However, part of the test sequence was skipped in that case, which led
to missed errors.

Now get a valid pixelformat and put that in and try again. That way all
other tests are executed as well.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
utils/v4l2-compliance/v4l2-test-formats.cpp

index 4e26020..3c70a69 100644 (file)
@@ -565,14 +565,47 @@ int testTryFormats(struct node *node)
                }
                ret = doioctl(node, VIDIOC_TRY_FMT, &fmt);
                if (ret == EINVAL) {
-                       warn("TRY_FMT cannot handle an invalid pixelformat. This may or may not be a problem.\n"
-                            "See http://www.mail-archive.com/linux-media@vger.kernel.org/msg56550.html for more information.\n");
-               } else {
-                       ret = testFormatsType(node, ret, type, fmt);
-                       if (ret)
-                               return fail("%s is valid, but TRY_FMT failed to return a format\n",
-                                               buftype2s(type).c_str());
+                       __u32 pixelformat;
+                       bool is_mplane = false;
+
+                       /* In case of failure obtain a valid pixelformat and insert
+                        * that in the next attempt to call TRY_FMT. */
+                       doioctl(node, VIDIOC_G_FMT, &fmt);
+
+                       switch (type) {
+                       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+                               pixelformat = fmt.fmt.pix.pixelformat;
+                               break;
+                       case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+                       case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+                               pixelformat = fmt.fmt.pix_mp.pixelformat;
+                               is_mplane = true;
+                               break;
+                       default:
+                               /* for other formats returning EINVAL is certainly wrong */
+                               return fail("TRY_FMT cannot handle an invalid format\n");
+                       }
+                       warn("TRY_FMT cannot handle an invalid pixelformat.\n");
+                       warn("This may or may not be a problem. For more information see:\n");
+                       warn("http://www.mail-archive.com/linux-media@vger.kernel.org/msg56550.html\n");
+
+                       /* Now try again, but pass a valid pixelformat. */
+                       memset(&fmt, 0xff, sizeof(fmt));
+                       fmt.type = type;
+                       fmt.fmt.pix.field = V4L2_FIELD_ANY;
+                       if (is_mplane)
+                               fmt.fmt.pix_mp.pixelformat = pixelformat;
+                       else
+                               fmt.fmt.pix.pixelformat = pixelformat;
+                       ret = doioctl(node, VIDIOC_TRY_FMT, &fmt);
+                       if (ret == EINVAL)
+                               return fail("TRY_FMT cannot handle an invalid format\n");
                }
+               ret = testFormatsType(node, ret, type, fmt);
+               if (ret)
+                       return fail("%s is valid, but TRY_FMT failed to return a format\n",
+                                       buftype2s(type).c_str());
        }
 
        memset(&fmt, 0, sizeof(fmt));
@@ -723,14 +756,47 @@ int testSetFormats(struct node *node)
                fmt_set.fmt.pix.field = V4L2_FIELD_ANY;
                ret = doioctl(node, VIDIOC_S_FMT, &fmt_set);
                if (ret == EINVAL) {
-                       warn("S_FMT cannot handle an invalid pixelformat. This may or may not be a problem.\n"
-                            "See http://www.mail-archive.com/linux-media@vger.kernel.org/msg56550.html for more information.\n");
-               } else {
-                       ret = testFormatsType(node, ret, type, fmt_set);
-                       if (ret)
-                               return fail("%s is valid, but no S_FMT was implemented\n",
-                                               buftype2s(type).c_str());
+                       __u32 pixelformat;
+                       bool is_mplane = false;
+
+                       /* In case of failure obtain a valid pixelformat and insert
+                        * that in the next attempt to call TRY_FMT. */
+                       doioctl(node, VIDIOC_G_FMT, &fmt_set);
+
+                       switch (type) {
+                       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+                               pixelformat = fmt_set.fmt.pix.pixelformat;
+                               break;
+                       case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+                       case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+                               pixelformat = fmt_set.fmt.pix_mp.pixelformat;
+                               is_mplane = true;
+                               break;
+                       default:
+                               /* for other formats returning EINVAL is certainly wrong */
+                               return fail("TRY_FMT cannot handle an invalid format\n");
+                       }
+                       warn("S_FMT cannot handle an invalid pixelformat.\n");
+                       warn("This may or may not be a problem. For more information see:\n");
+                       warn("http://www.mail-archive.com/linux-media@vger.kernel.org/msg56550.html\n");
+
+                       /* Now try again, but pass a valid pixelformat. */
+                       memset(&fmt_set, 0xff, sizeof(fmt_set));
+                       fmt_set.type = type;
+                       fmt_set.fmt.pix.field = V4L2_FIELD_ANY;
+                       if (is_mplane)
+                               fmt_set.fmt.pix_mp.pixelformat = pixelformat;
+                       else
+                               fmt_set.fmt.pix.pixelformat = pixelformat;
+                       ret = doioctl(node, VIDIOC_S_FMT, &fmt_set);
+                       if (ret == EINVAL)
+                               return fail("S_FMT cannot handle an invalid format\n");
                }
+               ret = testFormatsType(node, ret, type, fmt_set);
+               if (ret)
+                       return fail("%s is valid, but no S_FMT was implemented\n",
+                                       buftype2s(type).c_str());
 
                fmt_set = fmt;
                ret = doioctl(node, VIDIOC_S_FMT, &fmt_set);