Detailed parameter adjustment of camera under V4L2

Posted by satan165 on Sat, 20 Nov 2021 14:26:54 +0100

1, Common parameters of camera (camera)

The path of V4L2 related header files under Linux is / kernel source code directory / include/linux/videodev2.h, and V4L2 related API documents.
White balance (automatic white balance AWB), color temperature, exposure (automatic exposure AE, exposure compensation EV), brightness, contrast, saturation, chroma (hue + saturation), sharpness (also known as sharpness), backlight compensation (also known as backlight compensation), gain, focusing, etc

(Note: the open parameters of different cameras are inconsistent. It is necessary to confirm the adjustable parameters of this camera in advance. The parameters that are not open cannot be adjusted!!!)

Common ioctl commands:

VIDIOC_QUERYCAP     /* Get operations supported by the device */
VIDIOC_G_FMT             /* Gets or sets the supported video formats */
VIDIOC_S_FMT             /* Format captured video */
VIDIOC_REQBUFS       /* Make a request for memory to the driver */
VIDIOC_QUERYBUF    /* Memory requested from driver query */
VIDIOC_QBUF              /* Add free memory to the queue that can capture video */
VIDIOC_DQBUF           /* Pull the captured video memory out of the captured video queue
VIDIOC_STREAMON      /* Open video stream */
VIDIOC_STREAMOFF    /* Turn off video streaming */
VIDIOC_QUERYCTRL    /* Query whether the driver supports this command */
VIDIOC_G_CTRL         /* Gets the current command value */
VIDIOC_S_CTRL         /* Set new command values */
VIDIOC_G_TUNER     /* Get tuner information */
VIDIOC_S_TUNER      /* Set tuner information */
VIDIOC_G_FREQUENCY  /* Get tuner frequency */
VIDIOC_S_FREQUENCY  /* Set tuner frequency */

VIDIOC_QUERYCAP

Parameter control related functions and structures:
Function: ioctl(fd,VIDIOC_QUERYCAP,struct v4l2_streamparm *argp);

Function: query equipment capability

     struct v4l2_capability {
        __u8    driver[16];     /* i.e. "bttv" */
        __u8    card[32];       /* i.e. "Hauppauge WinTV" */
        __u8    bus_info[32];   /* "PCI:" + pci_name(pci_dev) */
        __u32   version;        /* should use KERNEL_VERSION() */
        __u32   capabilities;   /* Device capabilities */
        __u32   reserved[4];
   };
   
    /*Get camera information*/
    struct v4l2_capability cap;
 
    if (ioctl(cam_fd, VIDIOC_QUERYCAP, &cap) < 0)
    {
        perror("get info failed!");
        return -1;
    }
 
    printf("Driver Name:%s\n Card Name:%s\n Bus info:%s\n version:%d\n capabilities:%x\n \n ", cap.driver, cap.card, cap.bus_info,cap.version,cap.capabilities);
             
    if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == V4L2_CAP_VIDEO_CAPTURE)
    {
        printf("Device %s: supports capture.\n",DEV_NAME);
    }
    if ((cap.capabilities & V4L2_CAP_STREAMING) == V4L2_CAP_STREAMING)
    {
        printf("Device %s: supports streaming.\n",DEV_NAME);
    }

VIDIOC_ENUM_FMT

Function: int ioctl(fd, VIDIOC_ENUM_FMT, struct v4l2_fmtdesc *argp);
Function: get the video format supported by the current driver

struct v4l2_fmtdesc
{
__u32 index; // Format sequence number to query, application settings
enum v4l2_buf_type type; // Frame type, application settings
__u32 flags; // Compressed format
__u8 description[32]; // Format name
__u32 pixelformat; // format
__u32 reserved[4]; // retain
};

Chestnuts:

printf("[**********************All supported formats:****************************]\n");
struct v4l2_fmtdesc dis_fmtdesc;
dis_fmtdesc.index=0;
dis_fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
printf("Support format:\n");
while(ioctl(cam_fd,VIDIOC_ENUM_FMT,&dis_fmtdesc)!=-1)
{
     printf("\t%d.%s\n",dis_fmtdesc.index+1,dis_fmtdesc.description);
     dis_fmtdesc.index++;
}
printf("\n");

VIDIOC_QUERYCAP

Function: ioctl(fd,VIDIOC_QUERYCAP,struct v4l2_queryctrl *argp);
Function: used to query some attribute requirements of some parameters (such as maximum and minimum range, default value, etc.)

struct v4l2_queryctrl {
        __u32                id;
        enum v4l2_ctrl_type  type;
        __u8                 name[32];  /* Whatever */
        __s32                minimum;   /* Note signedness */
        __s32                maximum;
        __s32                step;
        __s32                default_value;
        __u32                flags;
        __u32                reserved[2];
};

VIDIOC_G_FMT

Functions: ioctl(fd,VIDIOC_G_FMT,struct v4l2_format *argp); / / VIDIOC_S_FMT
Function: resolution, image acquisition format and related settings

struct v4l2_format {
        enum v4l2_buf_type type;
        union {
                struct v4l2_pix_format          pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
                struct v4l2_pix_format_mplane   pix_mp;  /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
                struct v4l2_window              win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
                struct v4l2_vbi_format          vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
                struct v4l2_sliced_vbi_format   sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
                __u8    raw_data[200];                   /* user-defined */
        } fmt;
};

    printf("[**********************Get current format information:****************************]\n");
    Format.type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if(ioctl(cam_fd,VIDIOC_G_FMT,&Format)==-1)
    {
        perror("ioctl");
        exit(EXIT_FAILURE);
    }
    printf(">>:  %d * %d\n",Format.fmt.pix.width,Format.fmt.pix.height);
    printf("pix.pixelformat:%c%c%c%c\n", \
            Format.fmt.pix.pixelformat & 0xFF,\
            (Format.fmt.pix.pixelformat >> 8) & 0xFF, \
            (Format.fmt.pix.pixelformat >> 16) & 0xFF,\
            (Format.fmt.pix.pixelformat >> 24) & 0xFF);
    printf("\n");

VIDIOC_G_PARM

Functions: ioctl(fd,VIDIOC_G_PARM,struct v4l2_streamparm *argp); / / VIDIOC_S_PARM
Role: stream dependent (e.g. frame rate)

struct v4l2_format {
        enum v4l2_buf_type type;
        union {
                struct v4l2_pix_format          pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
                struct v4l2_pix_format_mplane   pix_mp;  /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
                struct v4l2_window              win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
                struct v4l2_vbi_format          vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
                struct v4l2_sliced_vbi_format   sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
                __u8    raw_data[200];                   /* user-defined */
        } fmt;
};

    printf("[**********************Get current format information:****************************]\n");
    Format.type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if(ioctl(cam_fd,VIDIOC_G_FMT,&Format)==-1)
    {
        perror("ioctl");
        exit(EXIT_FAILURE);
    }
    printf(">>:  %d * %d\n",Format.fmt.pix.width,Format.fmt.pix.height);
    printf("pix.pixelformat:%c%c%c%c\n", \
            Format.fmt.pix.pixelformat & 0xFF,\
            (Format.fmt.pix.pixelformat >> 8) & 0xFF, \
            (Format.fmt.pix.pixelformat >> 16) & 0xFF,\
            (Format.fmt.pix.pixelformat >> 24) & 0xFF);
    printf("\n");

VIDIOC_G_PARM

Functions: ioctl(fd,VIDIOC_G_PARM,struct v4l2_streamparm *argp); / / VIDIOC_S_PARM
Role: stream dependent (e.g. frame rate)

struct v4l2_streamparm {
        enum v4l2_buf_type type;
        union {
                struct v4l2_captureparm capture;
                struct v4l2_outputparm  output;
                __u8    raw_data[200];  /* user-defined */
        } parm;
};

printf("[***********************Get frame rate information**************************]\n");
 
struct v4l2_streamparm Stream_Parm;
 
Stream_Parm.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
if(ioctl(cam_fd,VIDIOC_G_PARM,&Stream_Parm)==-1)
 
{
 
perror("ioctl");
 
exit(EXIT_FAILURE);
 
}
 
printf(">>: Frame rate: %u/%u\n",Stream_Parm.parm.capture.timeperframe.numerator,Stream_Parm.parm.capture.timeperframe.denominator);
 
printf("\n");

VIDIOC_G_CTRL

Functions: ioctl(fd,VIDIOC_G_CTRL,struct v4l2_control*argp); / / VIDIOC_S_CTRL
Function: parameter control (white balance, color temperature, contrast, saturation, sharpness, exposure, etc. are all controlled by this structure)

struct v4l2_control {
        __u32                id;        //ID is the parameter ID to be controlled (for example, the white balance ID is V4L2_CID_AUTO_WHITE_BALANCE)
        __s32                value;  
};

    printf("[**********************Set manual white balance:******************************]\n");
    ctrl.id = V4L2_CID_AUTO_WHITE_BALANCE;
    ctrl.value = V4L2_WHITE_BALANCE_MANUAL ;
    if(ioctl(cam_fd,VIDIOC_G_CTRL,&ctrl)==-1)
    {
        perror("ioctl");
        exit(EXIT_FAILURE);
    }
    printf("\n");    
 
    /*************Set white balance color temperature****************************/
    printf("[****************Set white balance color temperature********************]\n");
    ctrl.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE;
    ctrl.value = 5100;
     if(ioctl(cam_fd,VIDIOC_S_CTRL,&ctrl)==-1)
    {
        perror("ioctl");
        exit(EXIT_FAILURE);
    }
    printf("\n");
 
    printf("[***************Set brightness***************************]\n");
    ctrl.id= V4L2_CID_BRIGHTNESS;
    ctrl.value = 40;
    if(ioctl(cam_fd,VIDIOC_S_CTRL,&ctrl)==-1)
    {
        perror("ioctl");
        exit(EXIT_FAILURE);
    }
    printf("\n");
 
    printf("[***************Set contrast**************************]\n");
    ctrl.id = V4L2_CID_CONTRAST;
    ctrl.value= 45;
    if(ioctl(cam_fd,VIDIOC_S_CTRL,&ctrl)==-1)
    {
        perror("ioctl");
        exit(EXIT_FAILURE);
    }
    sleep(1);
    printf("\n");
 
    printf("[***************Set saturation**************************]\n");
    ctrl.id = V4L2_CID_SATURATION;
    ctrl.value= 60;
    if(ioctl(cam_fd,VIDIOC_S_CTRL,&ctrl)==-1)
    {
        perror("ioctl");
        exit(EXIT_FAILURE);
    }
    printf("\n");
 
    printf("[********************Set chroma**********************]\n");
    ctrl.id = V4L2_CID_HUE;
    ctrl.value = 1;
    if(ioctl(cam_fd,VIDIOC_S_CTRL,&ctrl)==-1)
    {
        perror("ioctl");
        exit(EXIT_FAILURE);
    }
    printf("\n");
 
    printf("[********************Set sharpness**********************]\n");
    ctrl.id = V4L2_CID_SHARPNESS;
    ctrl.value = 4;
    if(ioctl(cam_fd,VIDIOC_S_CTRL,&ctrl)==-1)
    {
        perror("ioctl");
        exit(EXIT_FAILURE);
    }
    printf("\n");
 
    
    printf("[*******************Set backlight compensation******************]\n");
    ctrl.id = V4L2_CID_BACKLIGHT_COMPENSATION;
    ctrl.value = 3;
    if(ioctl(cam_fd,VIDIOC_S_CTRL,&ctrl)==-1)
    {
        perror("ioctl");
        exit(EXIT_FAILURE);
    }
    printf("\n");
 
    printf("[********************Set gamma value**********************]\n");
    ctrl.id = V4L2_CID_GAMMA;
    ctrl.value = 120;
    if(ioctl(cam_fd,VIDIOC_S_CTRL,&ctrl)==-1)
    {
        perror("ioctl");
        exit(EXIT_FAILURE);
    }
    printf("\n");
    


Set exposure value:

  1. First, change the exposure mode to manual exposure.

  2. Set the exposure level or specific exposure value.

Example 1: get the exposure mode and set it to manual exposure mode

int ret;
struct v4l2_control ctrl;
//Get exposure mode
ctrl.id = V4L2_CID_EXPOSURE_AUTO;
ret = ioctl(Handle, VIDIOC_G_CTRL, &ctrl);
 
if (ret < 0) 
{
    printf("Get exposure auto Type failed\n");
 
    return V4L2_UTILS_GET_EXPSURE_AUTO_TYPE_ERR;
}
 
printf("\nGet Exposure Auto Type:[%d]\n", ctrl.value);

//Set the exposure mode to manual mode

ctrl.id = V4L2_CID_EXPOSURE_AUTO; 
ctrl.value = V4L2_EXPOSURE_MANUAL;  //Manual exposure mode
ret = ioctl(Handle, VIDIOC_S_CTRL, &ctrl); 
if (ret < 0) 
{
   printf("Get exposure auto Type failed\n"); 
 
   return V4L2_UTILS_SET_EXPSURE_AUTO_TYPE_ERR; 
 
}

Example 2: after setting to manual mode, obtain and set the exposure level

int ret; 
struct v4l2_control ctrl; 
ctrl.id = V4L2_CID_EXPOSURE;  //The exposure level is obtained, and A20 accepts 9 levels from - 4 to 4
ret = ioctl(Handle, VIDIOC_G_CTRL, &ctrl); 
if (ret < 0) 
{ 
    printf("Get exposure failed (%d)\n", ret); 
    return V4L2_UTILS_GET_EXPSURE_ERR; 
} 
 
printf("\nGet Exposure :[%d]\n", ctrl.value);
 
//Set exposure level
ctrl.id = V4L2_CID_EXPOSURE; 
ctrl.value = -4; 
ret = ioctl(Handle, VIDIOC_S_CTRL, &ctrl); 
if (ret < 0) 
{ 
    printf("Set exposure failed (%d)\n", ret); 
    return V4L2_UTILS_SET_EXPSURE_ERR; 
} 

Example 3: after setting to manual mode, obtain and set the absolute exposure value:

int ret;
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_EXPOSURE_ABSOLUTE;
ret = ioctl(handle, VIDIOC_G_CTRL, &ctrl);
if (ret < 0) 
{
    printf("Set exposure failed (%d)\n", ret);
 
    //return V4L2_UTILS_SET_EXPSURE_ERR;
}
 
printf("\nGet ABS EXP Success:[%d]\n", ctrl.value);
 
sleep(1);
 
//Set absolute exposure value
ctrl.id = V4L2_CID_EXPOSURE_ABSOLUTE;
ctrl.value = 300;  //Unit: 100us
ret = ioctl(handle, VIDIOC_S_CTRL, &ctrl);
if (ret < 0) 
{
    printf("Set exposure failed (%d)\n", ret);
 
    //return V4L2_UTILS_SET_EXPSURE_ERR;
}

(all the above parameters can be set effectively after testing, but the exposure, auto focus and gain cannot be set. The ioctl: Invalid argument problem will occur. The reason is unknown. If any friend knows, please give us your advice. Thank you in advance).

Blog source

CSDN blogger's original link to "human counting": https://blog.csdn.net/qq_41248872/article/details/87928783

Topics: Linux