📄 v4l2_ctrl.cpp
字号:
exit(1);
}
return opt;
}
static void parse_next_subopt(char **subs, char **value)
{
static char *const subopts[] = {
NULL
};
int opt = getsubopt(subs, subopts, value);
if (value == NULL) {
fprintf(stderr, "No value given to suboption <%s>\n",
subopts[opt]);
usage();
exit(1);
}
}
int main(int argc, char **argv)
{
char *value, *subs;
int i;
int fd = -1;
/* bitfield for fmts */
unsigned int set_fmts = 0;
int mode = V4L2_TUNER_MODE_STEREO; /* set audio mode */
/* command args */
char ch, *device = strdup("/dev/video0"); /* -d device */
struct v4l2_format vfmt; /* set_format/get_format */
struct v4l2_tuner tuner; /* set_tuner/get_tuner */
struct v4l2_capability vcap; /* list_cap */
struct v4l2_input vin; /* list_inputs */
struct v4l2_output vout; /* list_outputs */
struct v4l2_audio vaudio; /* list audio inputs */
struct v4l2_audioout vaudout = { 0 }; /* audio outputs */
int input; /* set_input/get_input */
int output; /* set_output/get_output */
v4l2_std_id std; /* get_std/set_std */
double freq = 0; /* get/set frequency */
struct v4l2_frequency vf; /* get_freq/set_freq */
struct v4l2_standard vs; /* list_std */
char short_options[26 * 2 * 2 + 1];
int idx = 0;
if (argc == 1) {
usage();
return 0;
}
for (i = 0; long_options[i].name; i++) {
if (!isalpha(long_options[i].val))
continue;
short_options[idx++] = long_options[i].val;
if (long_options[i].has_arg == required_argument)
short_options[idx++] = ':';
}
while (1) {
int option_index = 0;
short_options[idx] = 0;
ch = getopt_long(argc, argv, short_options,
long_options, &option_index);
if (ch == -1)
break;
options[(int)ch] = 1;
switch (ch) {
case OptHelp:
usage();
return 0;
case OptSetDevice:
device = strdup(optarg);
if (device[0] >= '0' && device[0] <= '9' && device[1] == 0) {
char dev = device[0];
sprintf(device, "/dev/video%c", dev);
}
break;
case OptSetVideoFormat:
subs = optarg;
while (*subs != '\0') {
static char *const subopts[] = {
"width",
"height",
NULL
};
switch (parse_subopt(&subs, subopts, &value)) {
case 0:
vfmt.fmt.pix.width = strtol(value, 0L, 0);
set_fmts |= FMTWidth;
break;
case 1:
vfmt.fmt.pix.height = strtol(value, 0L, 0);
set_fmts |= FMTHeight;
break;
}
}
break;
case OptSetInput:
input = strtol(optarg, 0L, 0);
break;
case OptSetOutput:
output = strtol(optarg, 0L, 0);
break;
case OptSetAudioInput:
vaudio.index = strtol(optarg, 0L, 0);
break;
case OptSetAudioOutput:
vaudout.index = strtol(optarg, 0L, 0);
break;
case OptSetFreq:
freq = strtod(optarg, NULL);
break;
case OptSetStandard:
if (!strncmp(optarg, "pal", 3)) {
if (optarg[3])
std = parse_pal(optarg + 3);
else
std = V4L2_STD_PAL;
}
else if (!strncmp(optarg, "ntsc", 4)) {
if (optarg[4])
std = parse_ntsc(optarg + 4);
else
std = V4L2_STD_NTSC;
}
else if (!strncmp(optarg, "secam", 5)) {
if (optarg[5])
std = parse_secam(optarg + 5);
else
std = V4L2_STD_SECAM;
}
else {
std = strtol(optarg, 0L, 0);
}
break;
case OptGetCtrl:
subs = optarg;
while (*subs != '\0') {
parse_next_subopt(&subs, &value);
if (strchr(value, '=')) {
usage();
exit(1);
}
else {
get_ctrls.push_back(value);
}
}
break;
case OptSetCtrl:
subs = optarg;
while (*subs != '\0') {
parse_next_subopt(&subs, &value);
if (const char *equal = strchr(value, '=')) {
set_ctrls[std::string(value, (equal - value))] = equal + 1;
}
else {
fprintf(stderr, "control '%s' without '='\n", value);
exit(1);
}
}
break;
case OptSetTuner:
if (!strcmp(optarg, "stereo"))
mode = V4L2_TUNER_MODE_STEREO;
else if (!strcmp(optarg, "lang1"))
mode = V4L2_TUNER_MODE_LANG1;
else if (!strcmp(optarg, "lang2"))
mode = V4L2_TUNER_MODE_LANG2;
else if (!strcmp(optarg, "bilingual"))
mode = V4L2_TUNER_MODE_LANG1_LANG2;
else if (!strcmp(optarg, "mono"))
mode = V4L2_TUNER_MODE_MONO;
else {
fprintf(stderr, "Unknown audio mode\n");
usage();
return 1;
}
break;
case ':':
fprintf(stderr, "Option `%s' requires a value\n",
argv[optind]);
usage();
return 1;
case '?':
fprintf(stderr, "Unknown argument `%s'\n",
argv[optind]);
usage();
return 1;
}
}
if (optind < argc) {
printf("unknown arguments: ");
while (optind < argc)
printf("%s ", argv[optind++]);
printf("\n");
usage();
return 1;
}
if ((fd = open(device, O_RDWR)) < 0) {
fprintf(stderr, "Failed to open %s: %s\n", device,
strerror(errno));
exit(1);
}
free(device);
find_controls(fd);
for (ctrl_get_list::iterator iter = get_ctrls.begin(); iter != get_ctrls.end(); ++iter) {
if (ctrl_str2id.find(*iter) == ctrl_str2id.end()) {
fprintf(stderr, "unknown control '%s'\n", (*iter).c_str());
exit(1);
}
}
for (ctrl_set_map::iterator iter = set_ctrls.begin(); iter != set_ctrls.end(); ++iter) {
if (ctrl_str2id.find(iter->first) == ctrl_str2id.end()) {
fprintf(stderr, "unknown control '%s'\n", iter->first.c_str());
exit(1);
}
}
if (option_all) {
options[OptGetVideoFormat] = 1;
options[OptGetDriverInfo] = 1;
options[OptGetInput] = 1;
options[OptGetOutput] = 1;
options[OptGetAudioInput] = 1;
options[OptGetAudioOutput] = 1;
options[OptGetStandard] = 1;
options[OptGetFreq] = 1;
options[OptGetTuner] = 1;
}
/* Setting Opts */
if (options[OptSetVideoFormat]) {
struct v4l2_format in_vfmt;
printf("ioctl: VIDIOC_S_FMT\n");
in_vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_G_FMT, &in_vfmt) < 0)
fprintf(stderr, "ioctl: VIDIOC_G_FMT failed\n");
else {
printf("\tBefore:\n");
if (printfmt(in_vfmt) != 0)
fprintf(stderr, "error printing result\n");
if (set_fmts & FMTWidth)
in_vfmt.fmt.pix.width = vfmt.fmt.pix.width;
if (set_fmts & FMTHeight)
in_vfmt.fmt.pix.height = vfmt.fmt.pix.height;
if (ioctl(fd, VIDIOC_S_FMT, &in_vfmt) < 0)
fprintf(stderr, "ioctl: VIDIOC_S_FMT failed\n");
vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_G_FMT, &vfmt) < 0)
fprintf(stderr, "ioctl: VIDIOC_G_FMT failed\n");
else {
printf("\n\tAfter:\n");
if (printfmt(vfmt) != 0)
fprintf(stderr,
"error printing result\n");
}
}
}
if (option_streamoff) {
int dummy = 0;
doioctl(fd, VIDIOC_STREAMOFF, &dummy, "VIDIOC_STREAMOFF");
}
if (options[OptSetFreq]) {
double fac = 16;
if (doioctl(fd, VIDIOC_G_TUNER, &tuner, "VIDIOC_G_TUNER") == 0) {
fac = (tuner.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16;
}
vf.tuner = 0;
vf.type = tuner.type;
vf.frequency = __u32(freq * fac);
if (doioctl(fd, VIDIOC_S_FREQUENCY, &vf,
"VIDIOC_S_FREQUENCY") == 0)
printf("Frequency set to %d (%f MHz)\n", vf.frequency,
vf.frequency / fac);
}
if (options[OptSetStandard]) {
if (std < 16) {
vs.index = std;
if (ioctl(fd, VIDIOC_ENUMSTD, &vs) >= 0) {
std = vs.id;
}
}
if (doioctl(fd, VIDIOC_S_STD, &std, "VIDIOC_S_STD") == 0)
printf("Standard set to %08llx\n", (unsigned long long)std);
}
if (options[OptSetCtrl] && !set_ctrls.empty()) {
struct v4l2_ext_controls ctrls = { 0 };
for (ctrl_set_map::iterator iter = set_ctrls.begin();
iter != set_ctrls.end(); ++iter) {
struct v4l2_ext_control ctrl = { 0 };
ctrl.id = ctrl_str2id[iter->first];
ctrl.value = atol(iter->second.c_str());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -