📄 drv0-v4l2-old.c
字号:
buf->index, buf->type < sizeof(type)/sizeof(char*) ? type[buf->type] : "unknown", buf->offset,buf->length,buf->bytesused);}static voidprint_fbinfo(struct v4l2_framebuffer *fb){ static char *fb_cap[] = { "extern", "chromakey", "clipping", "scale-up", "scale-down" }; static char *fb_flags[] = { "primary", "overlay", "chromakey" }; /* capabilities */ fprintf(stderr,"v4l2: framebuffer info\n"); print_bits(" cap",fb_cap,sizeof(fb_cap)/sizeof(char*),fb->capability); print_bits(" flags",fb_cap,sizeof(fb_flags)/sizeof(char*),fb->flags); fprintf(stderr," base: %p %p %p\n",fb->base[0],fb->base[1],fb->base[2]); fprintf(stderr," format: %dx%d, %c%c%c%c, %d byte\n", fb->fmt.width, fb->fmt.height, fb->fmt.pixelformat & 0xff, (fb->fmt.pixelformat >> 8) & 0xff, (fb->fmt.pixelformat >> 16) & 0xff, (fb->fmt.pixelformat >> 24) & 0xff, fb->fmt.sizeimage);}/* ---------------------------------------------------------------------- *//* helpers */static voidget_device_capabilities(struct v4l2_handle *h){ unsigned int i; for (h->ninputs = 0; h->ninputs < h->cap.inputs; h->ninputs++) { h->inp[h->ninputs].index = h->ninputs; if (-1 == xioctl(h->fd, VIDIOC_ENUMINPUT, &h->inp[h->ninputs], 0)) break; } for (h->nstds = 0; h->nstds < MAX_NORM; h->nstds++) { h->std[h->nstds].index = h->nstds; if (-1 == xioctl(h->fd, VIDIOC_ENUMSTD, &h->std[h->nstds], EINVAL)) break; } for (h->nfmts = 0; h->nfmts < MAX_FORMAT; h->nfmts++) { h->fmt[h->nfmts].index = h->nfmts; if (-1 == xioctl(h->fd, VIDIOC_ENUM_PIXFMT, &h->fmt[h->nfmts], EINVAL)) break; } h->streamparm.type = V4L2_BUF_TYPE_CAPTURE; ioctl(h->fd,VIDIOC_G_PARM,&h->streamparm); /* controls */ for (i = 0; i < MAX_CTRL; i++) { h->ctl[i].id = V4L2_CID_BASE+i; if (-1 == xioctl(h->fd, VIDIOC_QUERYCTRL, &h->ctl[i], EINVAL) || (h->ctl[i].flags & V4L2_CTRL_FLAG_DISABLED)) h->ctl[i].id = -1; } for (i = 0; i < MAX_CTRL; i++) { h->ctl[i+MAX_CTRL].id = V4L2_CID_PRIVATE_BASE+i; if (-1 == xioctl(h->fd, VIDIOC_QUERYCTRL, &h->ctl[i+MAX_CTRL], EINVAL) || (h->ctl[i+MAX_CTRL].flags & V4L2_CTRL_FLAG_DISABLED)) h->ctl[i+MAX_CTRL].id = -1; }}static struct STRTAB *build_norms(struct v4l2_handle *h){ struct STRTAB *norms; unsigned int i; norms = malloc(sizeof(struct STRTAB) * (h->nstds+1)); for (i = 0; i < h->nstds; i++) { norms[i].nr = i; norms[i].str = h->std[i].std.name; } norms[i].nr = -1; norms[i].str = NULL; return norms;}static struct STRTAB *build_inputs(struct v4l2_handle *h){ struct STRTAB *inputs; unsigned int i; inputs = malloc(sizeof(struct STRTAB) * (h->ninputs+1)); for (i = 0; i < h->ninputs; i++) { inputs[i].nr = i; inputs[i].str = h->inp[i].name; } inputs[i].nr = -1; inputs[i].str = NULL; return inputs;}/* ---------------------------------------------------------------------- */static struct V4L2_ATTR { unsigned int id; unsigned int v4l2;} v4l2_attr[] = { { ATTR_ID_VOLUME, V4L2_CID_AUDIO_VOLUME }, { ATTR_ID_MUTE, V4L2_CID_AUDIO_MUTE }, { ATTR_ID_COLOR, V4L2_CID_SATURATION }, { ATTR_ID_BRIGHT, V4L2_CID_BRIGHTNESS }, { ATTR_ID_HUE, V4L2_CID_HUE }, { ATTR_ID_CONTRAST, V4L2_CID_CONTRAST },};#define NUM_ATTR (sizeof(v4l2_attr)/sizeof(struct V4L2_ATTR))static struct STRTAB*v4l2_menu(int fd, const struct v4l2_queryctrl *ctl){ struct STRTAB *menu; struct v4l2_querymenu item; int i; menu = malloc(sizeof(struct STRTAB) * (ctl->maximum-ctl->minimum+2)); for (i = ctl->minimum; i <= ctl->maximum; i++) { item.id = ctl->id; item.index = i; if (-1 == xioctl(fd, VIDIOC_QUERYMENU, &item, 0)) { free(menu); return NULL; } menu[i-ctl->minimum].nr = i; menu[i-ctl->minimum].str = strdup(item.name); } menu[i-ctl->minimum].nr = -1; menu[i-ctl->minimum].str = NULL; return menu;}static voidv4l2_add_attr(struct v4l2_handle *h, struct v4l2_queryctrl *ctl, int id, struct STRTAB *choices){ static int private_ids = ATTR_ID_COUNT; unsigned int i; h->attr = realloc(h->attr,(h->nattr+2) * sizeof(struct ng_attribute)); memset(h->attr+h->nattr,0,sizeof(struct ng_attribute)*2); if (ctl) { for (i = 0; i < NUM_ATTR; i++) if (v4l2_attr[i].v4l2 == ctl->id) break; if (i != NUM_ATTR) { h->attr[h->nattr].id = v4l2_attr[i].id; } else { h->attr[h->nattr].id = private_ids++; } h->attr[h->nattr].name = ctl->name; h->attr[h->nattr].priv = ctl; h->attr[h->nattr].defval = ctl->default_value; switch (ctl->type) { case V4L2_CTRL_TYPE_INTEGER: h->attr[h->nattr].type = ATTR_TYPE_INTEGER; h->attr[h->nattr].defval = ctl->default_value; h->attr[h->nattr].min = ctl->minimum; h->attr[h->nattr].max = ctl->maximum; break; case V4L2_CTRL_TYPE_BOOLEAN: h->attr[h->nattr].type = ATTR_TYPE_BOOL; break; case V4L2_CTRL_TYPE_MENU: h->attr[h->nattr].type = ATTR_TYPE_CHOICE; h->attr[h->nattr].choices = v4l2_menu(h->fd, ctl); break; default: return; } } else { /* for norms + inputs */ h->attr[h->nattr].id = id; h->attr[h->nattr].defval = 0; h->attr[h->nattr].type = ATTR_TYPE_CHOICE; h->attr[h->nattr].choices = choices; } if (h->attr[h->nattr].id < ATTR_ID_COUNT) h->attr[h->nattr].name = ng_attr_to_desc[h->attr[h->nattr].id]; h->attr[h->nattr].read = v4l2_read_attr; h->attr[h->nattr].write = v4l2_write_attr; h->attr[h->nattr].handle = h; h->nattr++;}static int v4l2_read_attr(struct ng_attribute *attr){ struct v4l2_handle *h = attr->handle; const struct v4l2_queryctrl *ctl = attr->priv; struct v4l2_control c; struct v4l2_tuner tuner; int value = 0; if (NULL != ctl) { c.id = ctl->id; xioctl(h->fd,VIDIOC_G_CTRL,&c,0); value = c.value; } else if (attr->id == ATTR_ID_NORM) { value = -1; /* FIXME */ } else if (attr->id == ATTR_ID_INPUT) { xioctl(h->fd,VIDIOC_G_INPUT,&value,0); } else if (attr->id == ATTR_ID_AUDIO_MODE) { memset(&tuner,0,sizeof(tuner)); xioctl(h->fd,VIDIOC_G_TUNER,&tuner,0); value = tuner.audmode;#if 1 if (ng_debug) { fprintf(stderr,"v4l2: tuner cap:%s%s%s\n", (tuner.capability&V4L2_TUNER_CAP_STEREO) ? " STEREO" : "", (tuner.capability&V4L2_TUNER_CAP_LANG1) ? " LANG1" : "", (tuner.capability&V4L2_TUNER_CAP_LANG2) ? " LANG2" : ""); fprintf(stderr,"v4l2: tuner rxs:%s%s%s%s\n", (tuner.rxsubchans&V4L2_TUNER_SUB_MONO) ? " MONO" : "", (tuner.rxsubchans&V4L2_TUNER_SUB_STEREO) ? " STEREO" : "", (tuner.rxsubchans&V4L2_TUNER_SUB_LANG1) ? " LANG1" : "", (tuner.rxsubchans&V4L2_TUNER_SUB_LANG2) ? " LANG2" : ""); fprintf(stderr,"v4l2: tuner cur:%s%s%s%s\n", (tuner.audmode==V4L2_TUNER_MODE_MONO) ? " MONO" : "", (tuner.audmode==V4L2_TUNER_MODE_STEREO) ? " STEREO" : "", (tuner.audmode==V4L2_TUNER_MODE_LANG1) ? " LANG1" : "", (tuner.audmode==V4L2_TUNER_MODE_LANG2) ? " LANG2" : ""); }#endif } return value;}static void v4l2_write_attr(struct ng_attribute *attr, int value){ struct v4l2_handle *h = attr->handle; const struct v4l2_queryctrl *ctl = attr->priv; struct v4l2_control c; struct v4l2_tuner tuner; if (NULL != ctl) { c.id = ctl->id; c.value = value; xioctl(h->fd,VIDIOC_S_CTRL,&c,0); } else if (attr->id == ATTR_ID_NORM) { xioctl(h->fd,VIDIOC_S_STD,&h->std[value].std,0); } else if (attr->id == ATTR_ID_INPUT) { xioctl(h->fd,VIDIOC_S_INPUT,&value,0); } else if (attr->id == ATTR_ID_AUDIO_MODE) { memset(&tuner,0,sizeof(tuner)); xioctl(h->fd,VIDIOC_G_TUNER,&tuner,0); tuner.audmode = value; xioctl(h->fd,VIDIOC_S_TUNER,&tuner,0); }}/* ---------------------------------------------------------------------- */static void*v4l2_open(char *device){ struct v4l2_handle *h; int i; h = malloc(sizeof(*h)); if (NULL == h) return NULL; memset(h,0,sizeof(*h)); if (-1 == (h->fd = open(device, O_RDWR))) { fprintf(stderr,"v4l2: open %s: %s\n",device,strerror(errno)); goto err; } if (-1 == ioctl(h->fd,VIDIOC_QUERYCAP,&h->cap)) goto err; if (ng_debug) fprintf(stderr, "v4l2: open\n"); fcntl(h->fd,F_SETFD,FD_CLOEXEC); if (ng_debug) fprintf(stderr,"v4l2: device is %s\n",h->cap.name); get_device_capabilities(h); if (ng_debug) print_device_capabilities(h); /* attributes */ v4l2_add_attr(h, NULL, ATTR_ID_NORM, build_norms(h)); v4l2_add_attr(h, NULL, ATTR_ID_INPUT, build_inputs(h)); if (h->cap.flags & V4L2_FLAG_TUNER) v4l2_add_attr(h, NULL, ATTR_ID_AUDIO_MODE, stereo); for (i = 0; i < MAX_CTRL*2; i++) { if (h->ctl[i].id == UNSET) continue; v4l2_add_attr(h, &h->ctl[i], 0, NULL); } /* capture buffers */ for (i = 0; i < WANTED_BUFFERS; i++) { ng_init_video_buf(h->buf_me+i); h->buf_me[i].release = ng_wakeup_video_buf; } return h; err: if (h->fd != -1) close(h->fd); if (h) free(h); return NULL;}static intv4l2_close(void *handle){ struct v4l2_handle *h = handle; if (ng_debug) fprintf(stderr, "v4l2: close\n"); close(h->fd); free(h); return 0;}static char*v4l2_devname(void *handle){ struct v4l2_handle *h = handle; return h->cap.name;}static int v4l2_flags(void *handle){ struct v4l2_handle *h = handle; int ret = 0; if (h->cap.flags & V4L2_FLAG_PREVIEW && !h->ov_error) ret |= CAN_OVERLAY; if ((h->cap.flags & V4L2_FLAG_STREAMING) || (h->cap.flags & V4L2_FLAG_READ)) ret |= CAN_CAPTURE; if (h->cap.flags & V4L2_FLAG_TUNER) ret |= CAN_TUNE; return ret;}static struct ng_attribute* v4l2_attrs(void *handle){ struct v4l2_handle *h = handle; return h->attr;}/* ---------------------------------------------------------------------- */static unsigned longv4l2_getfreq(void *handle){ struct v4l2_handle *h = handle; unsigned long freq; xioctl(h->fd, VIDIOC_G_FREQ, &freq, 0); return freq;}static voidv4l2_setfreq(void *handle, unsigned long freq){ struct v4l2_handle *h = handle; if (ng_debug) fprintf(stderr,"v4l2: freq: %.3f\n",(float)freq/16); xioctl(h->fd, VIDIOC_S_FREQ, &freq, 0);}static intv4l2_tuned(void *handle){ struct v4l2_handle *h = handle; struct v4l2_tuner tuner; usleep(10000); if (-1 == xioctl(h->fd,VIDIOC_G_TUNER,&tuner,0)) return 0; return tuner.signal ? 1 : 0;}/* ---------------------------------------------------------------------- *//* overlay */static intv4l2_setupfb(void *handle, struct ng_video_fmt *fmt, void *base){ struct v4l2_handle *h = handle; if (-1 == xioctl(h->fd, VIDIOC_G_FBUF, &h->ov_fb, 0)) return -1; if (1 /* ng_debug */) print_fbinfo(&h->ov_fb); /* double-check settings */ if (NULL != base && h->ov_fb.base[0] != base) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -