void MjpegCamera::print_control_range(__u32 id) { struct v4l2_queryctrl queryctrl; query_control(id, queryctrl); fprintf(stderr, "%s: min=%d max=%d step=%d", queryctrl.name, (int) queryctrl.minimum, (int) queryctrl.maximum, (int) queryctrl.step ); }
void MjpegCamera::gain(int gain) { struct v4l2_queryctrl queryctrl; query_control(V4L2_CID_BRIGHTNESS, queryctrl); if (gain < 0) { gain = 0; } if (gain > 100) { gain = 100; } int new_brightness = gain * (queryctrl.maximum - queryctrl.minimum) / 100 + queryctrl.minimum; try_set_control(V4L2_CID_BRIGHTNESS, new_brightness); }
void MjpegCamera::focus(int focus_value) { struct v4l2_queryctrl queryctrl; query_control(V4L2_CID_FOCUS_ABSOLUTE, queryctrl); if (focus_value < 0) { focus_value = 0; } if (focus_value > 100) { focus_value = 100; } int new_focus = focus_value * (queryctrl.maximum - queryctrl.minimum) / 100 + queryctrl.minimum; try_set_control(V4L2_CID_FOCUS_AUTO, 0); try_set_control(V4L2_CID_FOCUS_ABSOLUTE, new_focus); }
void MjpegCamera::try_set_control(__u32 id, __s32 value) { struct v4l2_queryctrl queryctrl; struct v4l2_control control; query_control(id, queryctrl); if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) { return; /* control not supported */ } else { memset(&control, 0, sizeof(control)); control.id = id; control.value = value; xioctl(VIDIOC_S_CTRL, &control); } }
bool AVConfig::Init() { int video_device = NULL; const char *device_name; struct stat st; //check if there're essential settings if(!getRoot()->exists("audio")) getRoot()->add("audio", Setting::TypeGroup); if(!getRoot()->exists("video")) getRoot()->add("video", Setting::TypeGroup); //open video device if(!getVideoSettings()->exists("device")) getVideoSettings()->add("device", Setting::TypeString) = "/dev/video0"; device_name = (*getVideoSettings())["device"]; if(-1 == stat(device_name, &st)) { log_message(1, "AVConfig: Cannot identify '%s': %d, %s.", device_name, errno, strerror (errno)); return false; } if(!S_ISCHR(st.st_mode)) { log_message(1, "AVConfig: %s is no device.", device_name); return false; } video_device = open(device_name, O_RDWR | O_NONBLOCK, 0); if(-1 == video_device) { log_message(1, "AVConfig: Cannot open '%s': %d, %s.", device_name, errno, strerror (errno)); exit (EXIT_FAILURE); } //determine video device capabilities v4l2_capability cap; if(-1 == xioctl(video_device, VIDIOC_QUERYCAP, &cap)) { if (EINVAL == errno) { log_message(1, "AVConfig: %s is no V4L2 device.", device_name); exit(1); } else log_message(1, "AVConfig: VIDIOC_QUERYCAP: %d, %s.", errno, strerror(errno)); } if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { log_message(1, "AVConfig: %s is no video capture device.", device_name); exit(1); } if(cap.capabilities & V4L2_CAP_READWRITE) log_message(0, "AVConfig: %s supports read i/o.", device_name); if(cap.capabilities & V4L2_CAP_STREAMING) log_message(0, "AVConfig: %s supports streaming i/o.", device_name); //enumerate inputs vector<v4l2_input> input_list; v4l2_input input; int current_input; CLEAR(input); input.index = 0; while(-1 != xioctl(video_device, VIDIOC_ENUMINPUT, &input)) { input_list.push_back(input); log_message(0, "AVConfig: Input [%d -- %s] is found.", input.index, input.name); input.index++; } if(-1 == xioctl(video_device, VIDIOC_G_INPUT, ¤t_input)) { log_errno("AVConfig: VIDIOC_G_INPUT"); exit(1); } log_message(0, "AVConfig: Currently selected input is: %d -- %s.", current_input, input_list[current_input].name); //enumerate standards if applied vector<v4l2_standard> standard_list; v4l2_standard standard; v4l2_std_id current_standard; CLEAR(standard); standard.index = 0; if(-1 != xioctl(video_device, VIDIOC_G_STD, ¤t_standard)) { while(0 == xioctl(video_device, VIDIOC_ENUMSTD, &standard)) { if(standard.id & input_list[current_input].std) { standard_list.push_back(standard); log_message(0, "AVConfig: Standard %s is supported by current input.", standard.name); log_message(0, "AVConfig: The framerate defined by this standard is: %d", standard.frameperiod.denominator/standard.frameperiod.numerator); if(standard.id == current_standard) log_message(0, "AVConfig: Standard %s is currently selected on input.", standard.name); } standard.index++; } if(errno != EINVAL || standard.index == 0) { log_errno("AVConfig: VIDIOC_ENUMSTD"); return false; } } //enumerate controls vector<v4l2_queryctrl> queryctrl_list; vector<v4l2_control> control_list; map<unsigned long, vector<v4l2_querymenu> > querymenu_list; v4l2_queryctrl queryctrl; v4l2_control control; CLEAR(queryctrl); CLEAR(control); log_message(0, "AVConfig: Quering standard controls"); queryctrl.id = V4L2_CID_BASE; while(queryctrl.id < V4L2_CID_LASTP1) { queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; control.id = queryctrl.id; int res = query_control(video_device, &queryctrl, &control, queryctrl_list, control_list, querymenu_list); if(-1 == res) { log_errno("AVConfig: unable to query device control"); return false; } else if(0 == res) break; } log_message(0, "AVConfig: Quering driver specific controls"); queryctrl.id = V4L2_CID_PRIVATE_BASE; while(true) { queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; control.id = queryctrl.id; int res = query_control(video_device, &queryctrl, &control, queryctrl_list, control_list, querymenu_list); if(-1 == res) { log_errno("AVConfig: unable to query device control"); return false; } else if(0 == res) break; } //close the device close(video_device); //construct inputs setting Setting *video = getVideoSettings(); try{ video->remove("input"); } catch(...){} video->add("input", Setting::TypeInt) = current_input; try{ video->remove("inputs"); } catch(...){} Setting &inputs = video->add("inputs", Setting::TypeGroup); for(int i = 0; i < input_list.size(); i++) inputs.add(fix_str(input_list[i].name), Setting::TypeInt) = i; //construct standarts setting try{ video->remove("standard"); } catch(...){} try{ video->remove("standards"); } catch(...){} if(!standard_list.empty()) { video->add("standard", Setting::TypeInt64) = (long long)current_standard; Setting &standards = video->add("standards", Setting::TypeGroup); for(int i = 0; i < standard_list.size(); i++) standards.add(fix_str(standard_list[i].name), Setting::TypeInt64) = (long long)standard_list[i].id; } //construct controls setting try{ video->remove("controls"); } catch(...){} Setting &controls = video->add("controls", Setting::TypeGroup); for(int i = 0; i < queryctrl_list.size(); i++) { Setting &control = controls.add(fix_str(queryctrl_list[i].name), Setting::TypeGroup); control.add("id", Setting::TypeInt) = (int)queryctrl_list[i].id; control.add("value", Setting::TypeInt) = (int)control_list[i].value; control.add("default_value", Setting::TypeInt) = (int)queryctrl_list[i].default_value; if(queryctrl_list[i].type == V4L2_CTRL_TYPE_MENU) { vector<v4l2_querymenu> items = querymenu_list[(int)queryctrl_list[i].id]; for(int j = 0; j < items.size(); j++) control.add(fix_str(items[j].name), Setting::TypeInt64) = (long long)items[j].index; } else { control.add("minimum", Setting::TypeInt) = (int)queryctrl_list[i].minimum; control.add("maximum", Setting::TypeInt) = (int)queryctrl_list[i].maximum; control.add("step", Setting::TypeInt) = (int)queryctrl_list[i].step; } } return true; }