int src_v4l2_set_control(src_t *src, struct v4l2_queryctrl *queryctrl) { src_v4l2_t *s = (src_v4l2_t *) src->state; struct v4l2_control control; struct v4l2_querymenu querymenu; char *sv; int iv; if(queryctrl->flags & V4L2_CTRL_FLAG_DISABLED) return(0); if(src_get_option_by_name(src->option, (char *) queryctrl->name, &sv)) return(0); memset(&querymenu, 0, sizeof(querymenu)); memset(&control, 0, sizeof(control)); control.id = queryctrl->id; switch(queryctrl->type) { case V4L2_CTRL_TYPE_INTEGER: /* Convert the value to an integer. */ iv = atoi(sv); /* Is the value a precentage? */ if(strchr(sv, '%')) { /* Adjust the precentage to fit the controls range. */ iv = SCALE(queryctrl->minimum, queryctrl->maximum, 0, 100, iv); } MSG("Setting %s to %i (%i%%).", queryctrl->name, iv, SCALE(0, 100, queryctrl->minimum, queryctrl->maximum, iv)); if(iv < queryctrl->minimum || iv > queryctrl->maximum) WARN("Value is out of range. Setting anyway."); control.value = iv; ioctl(s->fd, VIDIOC_S_CTRL, &control); break; case V4L2_CTRL_TYPE_BOOLEAN: iv = -1; if(!strcasecmp(sv, "1") || !strcasecmp(sv, "true")) iv = 1; if(!strcasecmp(sv, "0") || !strcasecmp(sv, "false")) iv = 0; if(iv == -1) { WARN("Unknown boolean value '%s' for %s.", sv, queryctrl->name); return(-1); } MSG("Setting %s to %s (%i).", queryctrl->name, sv, iv); control.value = iv; ioctl(s->fd, VIDIOC_S_CTRL, &control); break; case V4L2_CTRL_TYPE_MENU: /* Scan for a matching value. */ querymenu.id = queryctrl->id; for(iv = queryctrl->minimum; iv <= queryctrl->maximum; iv++) { querymenu.index = iv; if(ioctl(s->fd, VIDIOC_QUERYMENU, &querymenu)) { ERROR("Error querying menu."); continue; } if(!strncasecmp((char *) querymenu.name, sv, 32)) break; } if(iv > queryctrl->maximum) { MSG("Unknown value '%s' for %s.", sv, queryctrl->name); return(-1); } MSG("Setting %s to %s (%i).", queryctrl->name, querymenu.name, iv); control.value = iv; ioctl(s->fd, VIDIOC_S_CTRL, &control); break; case V4L2_CTRL_TYPE_BUTTON: MSG("Triggering %s control.", queryctrl->name); ioctl(s->fd, VIDIOC_S_CTRL, &control); break; default: WARN("Not setting unknown control type %i (%s).", queryctrl->name); break; } return(0); }
int src_v4l_set_picture(src_t *src, int fd, struct video_capability *vd) { src_v4l_t *s = (src_v4l_t *) src->state; struct video_picture vp; int v4l_pal; char *value; if(ioctl(fd, VIDIOCGPICT, &vp) < 0) { ERROR("Error getting picture information."); ERROR("VIDIOCGPICT: %s", strerror(errno)); return(-1); } if(src->list & SRC_LIST_CONTROLS) { int i; HEAD("--- Avaliable controls:"); for(i = 0; i < 5; i++) { char *name; int value; char t[64]; switch(i) { case 0: name = "brightness"; value = vp.brightness; break; case 1: name = "hue"; value = vp.hue; break; case 2: name = "colour"; value = vp.colour; break; case 3: name = "contrast"; value = vp.contrast; break; case 4: name = "whiteness"; value = vp.whiteness; break; } snprintf(t, 63, "%i (%i%%)", SCALE(-100, 100, 0x0000, 0xFFFF, vp.brightness), SCALE(0, 100, 0x0000, 0xFFFF, vp.brightness)); MSG("%-25s %-15s 100 - -100", name, t); } } if(!src_get_option_by_name(src->option, "brightness", &value)) vp.brightness = SCALE(0x0000, 0xFFFF, -100, 100, atoi(value)); if(!src_get_option_by_name(src->option, "hue", &value)) vp.hue = SCALE(0x0000, 0xFFFF, -100, 100, atoi(value)); if(!src_get_option_by_name(src->option, "colour", &value)) vp.colour = SCALE(0x0000, 0xFFFF, -100, 100, atoi(value)); if(!src_get_option_by_name(src->option, "contrast", &value)) vp.contrast = SCALE(0x0000, 0xFFFF, -100, 100, atoi(value)); if(!src_get_option_by_name(src->option, "whiteness", &value)) vp.whiteness = SCALE(0x0000, 0xFFFF, -100, 100, atoi(value)); /* MJPEG devices are a special case... */ if(vd->type & VID_TYPE_MJPEG_ENCODER) { WARN("Device is MJPEG only. Forcing JPEG palette."); src->palette = SRC_PAL_JPEG; } if(src->palette == SRC_PAL_JPEG && !(vd->type & VID_TYPE_MJPEG_ENCODER)) { ERROR("MJPEG palette requsted for a non-MJPEG device."); return(-1); } if(src->palette == SRC_PAL_JPEG) { struct mjpeg_params mparm; if(ioctl(s->fd, MJPIOC_G_PARAMS, &mparm)) { ERROR("Error querying video parameters."); ERROR("MJPIOC_G_PARAMS: %s", strerror(errno)); return(-1); } DEBUG("%s: Video parameters...", src->source); DEBUG("major_version = %i", mparm.major_version); DEBUG("minor_version = %i", mparm.minor_version); DEBUG("input = %i", mparm.input); DEBUG("norm = %i", mparm.norm); DEBUG("decimation = %i", mparm.decimation); DEBUG("HorDcm = %i", mparm.HorDcm); DEBUG("VerDcm = %i", mparm.VerDcm); DEBUG("TmpDcm = %i", mparm.TmpDcm); DEBUG("field_per_buff = %i", mparm.field_per_buff); DEBUG("img_x = %i", mparm.img_x); DEBUG("img_y = %i", mparm.img_y); DEBUG("img_width = %i", mparm.img_width); DEBUG("img_height = %i", mparm.img_height); DEBUG("quality = %i", mparm.quality); DEBUG("odd_even = %i", mparm.odd_even); DEBUG("APPn = %i", mparm.APPn); DEBUG("APP_len = %i", mparm.APP_len); DEBUG("APP_data = \"%s\"", mparm.APP_data); DEBUG("COM_len = %i", mparm.COM_len); DEBUG("COM_data = \"%s\"", mparm.COM_data); DEBUG("jpeg_markers = %i", mparm.jpeg_markers); if(mparm.jpeg_markers & JPEG_MARKER_DHT) DEBUG("- DHT"); if(mparm.jpeg_markers & JPEG_MARKER_DQT) DEBUG("- DQT"); if(mparm.jpeg_markers & JPEG_MARKER_DRI) DEBUG("- DRI"); if(mparm.jpeg_markers & JPEG_MARKER_COM) DEBUG("- COM"); if(mparm.jpeg_markers & JPEG_MARKER_APP) DEBUG("- APP"); DEBUG("VFIFO_FB = %i", mparm.VFIFO_FB); /* Set the usual parameters. */ mparm.input = 0; mparm.norm = VIDEO_MODE_PAL; /* TODO: Allow user to select PAL/SECAM/NTSC */ mparm.decimation = 0; mparm.quality = 80; mparm.HorDcm = 1; mparm.VerDcm = 1; mparm.TmpDcm = 1; mparm.field_per_buff = 2; /* Ask the driver to include the DHT with each frame. */ mparm.jpeg_markers |= JPEG_MARKER_DHT; if(ioctl(s->fd, MJPIOC_S_PARAMS, &mparm)) { ERROR("Error setting video parameters."); ERROR("MJPIOC_S_PARAMS: %s", strerror(errno)); return(-1); } src->width = mparm.img_width / mparm.HorDcm; src->height = mparm.img_height / mparm.VerDcm * mparm.field_per_buff; return(0); } v4l_pal = 2; /* Skip the JPEG palette. */ if(src->palette != -1) { v4l_pal = 0; while(v4l_palette[v4l_pal].depth) { if(v4l_palette[v4l_pal].src == src->palette) break; v4l_pal++; } if(!v4l_palette[v4l_pal].depth) { ERROR("Unable to handle palette format %s.", src_palette[src->palette]); return(-1); } } while(v4l_palette[v4l_pal].depth) { vp.palette = v4l_palette[v4l_pal].v4l; vp.depth = v4l_palette[v4l_pal].depth; if(!ioctl(fd, VIDIOCSPICT, &vp)) { s->palette = v4l_pal; src->palette = v4l_palette[v4l_pal].src; MSG("Using palette %s.",src_palette[src->palette].name); return(0); } if(src->palette != -1) break; WARN("The device does not support palette %s.", src_palette[v4l_palette[v4l_pal].src].name); v4l_pal++; } ERROR("Unable to find a compatible palette."); return(-1); }