void enumerateControls(struct vdIn *vd, globals *pglobal, int id) { // enumerating v4l2 controls struct v4l2_queryctrl ctrl; pglobal->in[id].parametercount = 0; pglobal->in[id].in_parameters = NULL; /* Enumerate the v4l2 controls Try the extended control API first */ #ifdef V4L2_CTRL_FLAG_NEXT_CTRL DBG("V4L2 API's V4L2_CTRL_FLAG_NEXT_CTRL is supported\n"); ctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL; if(0 == IOCTL_VIDEO(vd->fd, VIDIOC_QUERYCTRL, &ctrl)) { do { control_readed(vd, &ctrl, pglobal, id); ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; } while(0 == IOCTL_VIDEO(vd->fd, VIDIOC_QUERYCTRL, &ctrl)); // note: use simple ioctl or v4l2_ioctl instead of the xioctl } else #endif { DBG("V4L2 API's V4L2_CTRL_FLAG_NEXT_CTRL is NOT supported\n"); /* Fall back on the standard API */ /* Check all the standard controls */ int i; for(i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) { ctrl.id = i; if(IOCTL_VIDEO(vd->fd, VIDIOC_QUERYCTRL, &ctrl) == 0) { control_readed(vd, &ctrl, pglobal, id); } } /* Check any custom controls */ for(i = V4L2_CID_PRIVATE_BASE; ; i++) { ctrl.id = i; if(IOCTL_VIDEO(vd->fd, VIDIOC_QUERYCTRL, &ctrl) == 0) { control_readed(vd, &ctrl, pglobal, id); } else { break; } } } memset(&pglobal->in[id].jpegcomp, 0, sizeof(struct v4l2_jpegcompression)); if(xioctl(vd->fd, VIDIOC_G_JPEGCOMP, &pglobal->in[id].jpegcomp) != EINVAL) { DBG("JPEG compression details:\n"); DBG("Quality: %d\n", pglobal->in[id].jpegcomp.quality); DBG("APPn: %d\n", pglobal->in[id].jpegcomp.APPn); DBG("APP length: %d\n", pglobal->in[id].jpegcomp.APP_len); DBG("APP data: %s\n", pglobal->in[id].jpegcomp.APP_data); DBG("COM length: %d\n", pglobal->in[id].jpegcomp.COM_len); DBG("COM data: %s\n", pglobal->in[id].jpegcomp.COM_data); struct v4l2_queryctrl ctrl_jpeg; ctrl_jpeg.id = 1; sprintf((char*)&ctrl_jpeg.name, "JPEG quality"); ctrl_jpeg.minimum = 0; ctrl_jpeg.maximum = 100; ctrl_jpeg.step = 1; ctrl_jpeg.default_value = 50; ctrl_jpeg.flags = 0; ctrl_jpeg.type = V4L2_CTRL_TYPE_INTEGER; if (pglobal->in[id].in_parameters == NULL) { pglobal->in[id].in_parameters = (control*)calloc(1, sizeof(control)); } else { pglobal->in[id].in_parameters = (control*)realloc(pglobal->in[id].in_parameters,(pglobal->in[id].parametercount + 1) * sizeof(control)); } if (pglobal->in[id].in_parameters == NULL) { DBG("Calloc/realloc failed\n"); return; } memcpy(&pglobal->in[id].in_parameters[pglobal->in[id].parametercount].ctrl, &ctrl_jpeg, sizeof(struct v4l2_queryctrl)); pglobal->in[id].in_parameters[pglobal->in[id].parametercount].group = IN_CMD_JPEG_QUALITY; pglobal->in[id].in_parameters[pglobal->in[id].parametercount].value = pglobal->in[id].jpegcomp.quality; pglobal->in[id].parametercount++; } else { DBG("Modifying the setting of the JPEG compression is not supported\n"); pglobal->in[id].jpegcomp.quality = -1; } }
int init_videoIn(struct vdIn *vd, char *device, int width, int height, int fps, int format, int grabmethod, globals *pglobal) { if (vd == NULL || device == NULL) return -1; if (width == 0 || height == 0) return -1; if (grabmethod < 0 || grabmethod > 1) grabmethod = 1; //mmap by default; vd->videodevice = NULL; vd->status = NULL; vd->pictName = NULL; vd->videodevice = (char *) calloc (1, 16 * sizeof (char)); vd->status = (char *) calloc (1, 100 * sizeof (char)); vd->pictName = (char *) calloc (1, 80 * sizeof (char)); snprintf (vd->videodevice, 16-1, "%s", device); vd->toggleAvi = 0; vd->getPict = 0; vd->signalquit = 1; vd->width = width; vd->height = height; vd->fps = fps; vd->formatIn = format; vd->grabmethod = grabmethod; if (init_v4l2 (vd) < 0) { fprintf (stderr, " Init v4L2 failed !! exit fatal \n"); goto error;; } // enumerating v4l2 controls struct v4l2_queryctrl ctrl; pglobal->in.parametercount = 0; pglobal->in.in_parameters = malloc(0 * sizeof(input_control)); /* Enumerate the v4l2 controls Try the extended control API first */ #ifdef V4L2_CTRL_FLAG_NEXT_CTRL ctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL; if(0 == IOCTL_VIDEO(vd->fd, VIDIOC_QUERYCTRL, &ctrl)) { do { control_readed(vd, &ctrl, pglobal); ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; } while(0 == ioctl (vd->fd, VIDIOC_QUERYCTRL, &ctrl)); } else #endif { /* Fall back on the standard API */ /* Check all the standard controls */ int i; for(i = V4L2_CID_BASE; i<V4L2_CID_LASTP1; i++) { ctrl.id = i; if(IOCTL_VIDEO(vd->fd, VIDIOC_QUERYCTRL, &ctrl) == 0) { control_readed(vd, &ctrl, pglobal); } } /* Check any custom controls */ for(i=V4L2_CID_PRIVATE_BASE; ; i++) { ctrl.id = i; if(IOCTL_VIDEO(vd->fd, VIDIOC_QUERYCTRL, &ctrl) == 0) { control_readed(vd, &ctrl, pglobal); } else { break; } } } // enumerating formats int currentWidth, currentHeight = 0; struct v4l2_format currentFormat; currentFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (IOCTL_VIDEO(vd->fd, VIDIOC_G_FMT, ¤tFormat) == 0) { currentWidth = currentFormat.fmt.pix.width; currentHeight = currentFormat.fmt.pix.height; DBG("%Current size: dx%d\n", currentWidth, currentHeight); } pglobal->in.in_formats = malloc(0 * sizeof(struct v4l2_fmtdesc)); for (pglobal->in.formatCount = 0; 1; pglobal->in.formatCount++) { struct v4l2_fmtdesc fmtdesc; fmtdesc.index = pglobal->in.formatCount; fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (IOCTL_VIDEO(vd->fd, VIDIOC_ENUM_FMT, &fmtdesc) < 0) { break; } pglobal->in.in_formats = (input_format*)realloc(pglobal->in.in_formats, (pglobal->in.formatCount + 1) * sizeof(input_format)); memcpy(&pglobal->in.in_formats[pglobal->in.formatCount], &fmtdesc, sizeof(input_format)); if (fmtdesc.pixelformat == format) pglobal->in.currentFormat = pglobal->in.formatCount; DBG("Supported format: %s\n", fmtdesc.description); struct v4l2_frmsizeenum fsenum; fsenum.index = pglobal->in.formatCount; fsenum.pixel_format = fmtdesc.pixelformat; int j = 0; pglobal->in.in_formats[pglobal->in.formatCount].supportedResolutions = malloc(0); pglobal->in.in_formats[pglobal->in.formatCount].resolutionCount = 0; pglobal->in.in_formats[pglobal->in.formatCount].currentResolution = -1; while (1) { fsenum.index = j; j++; if(IOCTL_VIDEO(vd->fd, VIDIOC_ENUM_FRAMESIZES, &fsenum) == 0) { pglobal->in.in_formats[pglobal->in.formatCount].resolutionCount++; pglobal->in.in_formats[pglobal->in.formatCount].supportedResolutions = (input_resolution*) realloc(pglobal->in.in_formats[pglobal->in.formatCount].supportedResolutions, j * sizeof(input_resolution)); pglobal->in.in_formats[pglobal->in.formatCount].supportedResolutions[j-1].width = fsenum.discrete.width; pglobal->in.in_formats[pglobal->in.formatCount].supportedResolutions[j-1].height = fsenum.discrete.height; if (format == fmtdesc.pixelformat) { pglobal->in.in_formats[pglobal->in.formatCount].currentResolution = (j-1); DBG("\tSupported size with the current format: %dx%d\n", fsenum.discrete.width, fsenum.discrete.height); } else { DBG("\tSupported size: %dx%d\n", fsenum.discrete.width, fsenum.discrete.height); } } else { break; } } } /* alloc a temp buffer to reconstruct the pict */ vd->framesizeIn = (vd->width * vd->height << 1); switch (vd->formatIn) { case V4L2_PIX_FMT_MJPEG: vd->tmpbuffer = (unsigned char *) calloc(1, (size_t) vd->framesizeIn); if (!vd->tmpbuffer) goto error; vd->framebuffer = (unsigned char *) calloc(1, (size_t) vd->width * (vd->height + 8) * 2); break; case V4L2_PIX_FMT_YUYV: vd->framebuffer = (unsigned char *) calloc(1, (size_t) vd->framesizeIn); break; default: fprintf(stderr, " should never arrive exit fatal !!\n"); goto error; break; } if (!vd->framebuffer) goto error; return 0; error: free(pglobal->in.in_parameters); free(vd->videodevice); free(vd->status); free(vd->pictName); close(vd->fd); return -1; }