v4l2-compliance: add tests for VIDIOC_G/S_PARM.
authorHans Verkuil <hans.verkuil@cisco.com>
Sat, 28 Apr 2012 17:20:20 +0000 (19:20 +0200)
committerHans Verkuil <hans.verkuil@cisco.com>
Sat, 28 Apr 2012 17:20:20 +0000 (19:20 +0200)
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
utils/v4l2-compliance/v4l2-compliance.cpp
utils/v4l2-compliance/v4l2-compliance.h
utils/v4l2-compliance/v4l2-test-formats.cpp

index f6b8045..3d5ffaf 100644 (file)
@@ -609,19 +609,20 @@ int main(int argc, char **argv)
 
        printf("Format ioctls:\n");
        printf("\ttest VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: %s\n", ok(testEnumFormats(&node)));
+       printf("\ttest VIDIOC_G/S_PARM: %s\n", ok(testParm(&node)));
        printf("\ttest VIDIOC_G_FBUF: %s\n", ok(testFBuf(&node)));
        printf("\ttest VIDIOC_G_FMT: %s\n", ok(testFormats(&node)));
        printf("\ttest VIDIOC_G_SLICED_VBI_CAP: %s\n", ok(testSlicedVBICap(&node)));
 
        /* TODO:
 
-          VIDIOC_CROPCAP, VIDIOC_G/S_CROP
+          VIDIOC_CROPCAP, VIDIOC_G/S_CROP, VIDIOC_G/S_SELECTION
           VIDIOC_S_FBUF/OVERLAY
           VIDIOC_S/TRY_FMT
-          VIDIOC_G/S_PARM
           VIDIOC_(TRY_)ENCODER_CMD
+          VIDIOC_(TRY_)DECODER_CMD
           VIDIOC_G_ENC_INDEX
-          VIDIOC_REQBUFS/QBUF/DQBUF/QUERYBUF
+          VIDIOC_REQBUFS/QBUF/DQBUF/QUERYBUF/CREATE_BUFS/PREPARE_BUFS
           VIDIOC_STREAMON/OFF
 
           */
index 2aa11f3..18a91e4 100644 (file)
@@ -162,6 +162,7 @@ int testCustomTimings(struct node *node);
 
 // Format ioctl tests
 int testEnumFormats(struct node *node);
+int testParm(struct node *node);
 int testFBuf(struct node *node);
 int testFormats(struct node *node);
 int testSlicedVBICap(struct node *node);
index 54e979f..c248850 100644 (file)
@@ -375,8 +375,6 @@ static int testFormatsType(struct node *node, enum v4l2_buf_type type)
        if (ret)
                return fail("expected EINVAL, but got %d when getting format for buftype %d\n", ret, type);
        fail_on_test(fmt.type != type);
-       if (ret)
-               return 0;
        
        switch (type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -542,3 +540,114 @@ int testSlicedVBICap(struct node *node)
                return ret;
        return testSlicedVBICapType(node, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 }
+
+static int testParmStruct(struct node *node, struct v4l2_streamparm &parm)
+{
+       struct v4l2_captureparm *cap = &parm.parm.capture;
+       struct v4l2_outputparm *out = &parm.parm.output;
+       int ret;
+
+       switch (parm.type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+               ret = check_0(cap->reserved, sizeof(cap->reserved));
+               if (ret)
+                       return fail("reserved not zeroed\n");
+               fail_on_test(cap->readbuffers > VIDEO_MAX_FRAME);
+               if (!(node->caps & V4L2_CAP_READWRITE))
+                       fail_on_test(cap->readbuffers);
+               else if (node->caps & V4L2_CAP_STREAMING)
+                       fail_on_test(!cap->readbuffers);
+               fail_on_test(cap->capability & ~V4L2_CAP_TIMEPERFRAME);
+               fail_on_test(cap->capturemode & ~V4L2_MODE_HIGHQUALITY);
+               if (cap->capturemode & V4L2_MODE_HIGHQUALITY)
+                       warn("V4L2_MODE_HIGHQUALITY is poorly defined\n");
+               fail_on_test(cap->extendedmode);
+               if (cap->capability & V4L2_CAP_TIMEPERFRAME)
+                       fail_on_test(cap->timeperframe.numerator == 0 || cap->timeperframe.denominator == 0);
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+               ret = check_0(out->reserved, sizeof(out->reserved));
+               if (ret)
+                       return fail("reserved not zeroed\n");
+               fail_on_test(out->writebuffers > VIDEO_MAX_FRAME);
+               if (!(node->caps & V4L2_CAP_READWRITE))
+                       fail_on_test(out->writebuffers);
+               else if (node->caps & V4L2_CAP_STREAMING)
+                       fail_on_test(!out->writebuffers);
+               fail_on_test(out->capability & ~V4L2_CAP_TIMEPERFRAME);
+               fail_on_test(out->outputmode);
+               fail_on_test(out->extendedmode);
+               if (out->capability & V4L2_CAP_TIMEPERFRAME)
+                       fail_on_test(out->timeperframe.numerator == 0 || out->timeperframe.denominator == 0);
+               break;
+       default:
+               break;
+       }
+       return 0;
+}
+
+static int testParmType(struct node *node, enum v4l2_buf_type type)
+{
+       struct v4l2_streamparm parm;
+       int ret;
+
+       memset(&parm, 0, sizeof(parm));
+       parm.type = type;
+       ret = doioctl(node, VIDIOC_G_PARM, &parm);
+       if (ret == ENOTTY)
+               return ret;
+       if (ret == EINVAL)
+               return ENOTTY;
+       if (ret)
+               return fail("expected EINVAL, but got %d when getting parms for buftype %d\n", ret, type);
+       fail_on_test(parm.type != type);
+       ret = testParmStruct(node, parm);
+       if (ret)
+               return ret;
+
+       memset(&parm, 0, sizeof(parm));
+       parm.type = type;
+       ret = doioctl(node, VIDIOC_S_PARM, &parm);
+       if (ret == ENOTTY)
+               return 0;
+       if (ret)
+               return fail("got error %d when setting parms for buftype %d\n", ret, type);
+       fail_on_test(parm.type != type);
+       return testParmStruct(node, parm);
+}
+
+int testParm(struct node *node)
+{
+       bool supported = false;
+       int type;
+       int ret;
+
+       for (type = 0; type <= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; type++) {
+               ret = testParmType(node, (enum v4l2_buf_type)type);
+
+               if (ret && ret != ENOTTY)
+                       return ret;
+               if (!ret) {
+                       supported = true;
+                       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+                           type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+                           type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+                           type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+                               return fail("G/S_PARM is only allowed for video capture/output\n");
+                       if (!(node->caps & buftype2cap[type]))
+                               return fail("%s cap not set, but G/S_PARM worked\n",
+                                               buftype2s(type).c_str());
+               }
+       }
+
+       ret = testParmType(node, V4L2_BUF_TYPE_PRIVATE);
+       if (ret && ret != ENOTTY)
+               return ret;
+       if (!ret) {
+               supported = true;
+               warn("Buffer type PRIVATE allowed!\n");
+       }
+       return supported ? 0 : ENOTTY;
+}