cv4l2video4linux

How to get list of supported frame size and frame interval of webcam device using video4linux api?


I'm trying to use V4L2 api to enumertate supported frame size and frame rate of webcam device. I try to do it with the following code without success. The ioctl function always returns -1.

#include <stdio.h>
#include <fcntl.h>
#include "linux/videodev2.h"
int main(int argc, char **argv) {
    int fd = open("/dev/video0", O_RDWR);
    struct v4l2_frmivalenum frmsize;
    memset(&frmsize, 0, sizeof (struct v4l2_frmsizeenum));
    ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS , &frmsize);
    printf("%u \n", frmsize.he);
    return 0;
}

Solution

  • You should set the in parameter before ioctl VIDIOC_ENUM_FRAMESIZES to get frame sizes :

    Table A.34. struct v4l2_frmivalenum
    __u32   index               IN: Index of the given frame interval in the enumeration.
    __u32   pixel_format        IN: Pixel format for which the frame intervals are enumerated.
    __u32   width               IN: Frame width for which the frame intervals are enumerated.
    __u32   height              IN: Frame height for which the frame intervals are enumerated.
    

    and ioctl VIDIOC_ENUM_FRAMEINTERVALS to get frame intervals :

    Table A.31. struct v4l2_frmsizeenum
    __u32   index               IN: Index of the given frame size in the enumeration.
    __u32   pixel_format        IN: Pixel format for which the frame sizes are enumerated.
    

    Then an implementation that enumerates frame sizes and frame intervals could be :

    #include <stdio.h>
    #include <string.h>
    #include <fcntl.h>
    #include "linux/videodev2.h"
    void printFrameInterval(int fd, unsigned int fmt, unsigned int width, unsigned int height)
    {
        struct v4l2_frmivalenum frmival;
        memset(&frmival,0,sizeof(frmival));
        frmival.pixel_format = fmt;
        frmival.width = width;
        frmival.height = height;
        while (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) == 0) 
        {
            if (frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) 
                printf("[%dx%d] %f fps\n", width, height, 1.0*frmival.discrete.denominator/frmival.discrete.numerator);
            else
                printf("[%dx%d] [%f,%f] fps\n", width, height, 1.0*frmival.stepwise.max.denominator/frmival.stepwise.max.numerator, 1.0*frmival.stepwise.min.denominator/frmival.stepwise.min.numerator);
            frmival.index++;    
        }
    }
    
    int main(int argc, char **argv) {
        unsigned int width=0, height=0;;
        int fd = open("/dev/video0", O_RDWR);
        struct v4l2_frmsizeenum frmsize;
        memset(&frmsize,0,sizeof(frmsize));
        frmsize.pixel_format = V4L2_PIX_FMT_JPEG;
        while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) == 0)
        {
            if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) 
            {
                printFrameInterval(fd, frmsize.pixel_format, frmsize.discrete.width, frmsize.discrete.height);
            }
            else
            {
                for (width=frmsize.stepwise.min_width; width< frmsize.stepwise.max_width; width+=frmsize.stepwise.step_width)
                    for (height=frmsize.stepwise.min_height; height< frmsize.stepwise.max_height; height+=frmsize.stepwise.step_height)
                        printFrameInterval(fd, frmsize.pixel_format, width, height);
    
            }
            frmsize.index++;
        }
        return 0;
    }