📄 drv1-v4l.c
字号:
if (h->audio.flags & VIDEO_AUDIO_BASS) fprintf(stderr,"bass=%d ",h->audio.bass); if (h->audio.flags & VIDEO_AUDIO_TREBLE) fprintf(stderr,"treble=%d ",h->audio.treble); fprintf(stderr,"\n"); } v4l_add_attr(h,ATTR_ID_MUTE,ATTR_TYPE_BOOL,0,NULL); v4l_add_attr(h,ATTR_ID_AUDIO_MODE,ATTR_TYPE_CHOICE,0,stereo); if (h->audio.flags & VIDEO_AUDIO_VOLUME) v4l_add_attr(h,ATTR_ID_VOLUME,ATTR_TYPE_INTEGER,0,NULL); } /* tv norms / tuner */ norms = malloc(sizeof(norms_v4l)); memcpy(norms,norms_v4l,sizeof(norms_v4l)); if (h->capability.type & VID_TYPE_TUNER) { /* have tuner */ xioctl(h->fd,VIDIOCGTUNER,&h->tuner); if (ng_debug) fprintf(stderr," tuner : %s %lu-%lu", h->tuner.name,h->tuner.rangelow,h->tuner.rangehigh); for (i = 0; norms[i].str != NULL; i++) { if (h->tuner.flags & (1<<i)) { if (ng_debug) fprintf(stderr," %s",norms[i].str); } else norms[i].nr = -1; } if (ng_debug) fprintf(stderr,"\n"); } else { /* no tuner */ struct video_channel vchan; memcpy(&vchan, &h->channels[0], sizeof(struct video_channel)); for (i = 0; norms[i].str != NULL; i++) { vchan.norm = i; if (-1 == xioctl(h->fd,VIDIOCSCHAN,&vchan)) norms[i].nr = -1; else if (ng_debug) fprintf(stderr," %s",norms[i].str); } /* restore settings after probe */ memcpy(&vchan, &h->channels[0], sizeof(struct video_channel)); xioctl(h->fd,VIDIOCSCHAN,&vchan); if (ng_debug) fprintf(stderr,"\n"); } #if 1#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) /* dirty hack time / v4l design flaw -- works with bttv only * this adds support for a few less common PAL versions */ if (-1 != (rc = ioctl(h->fd,BTTV_VERSION,&i))) { norms = norms_bttv; if (ng_debug || rc < 0x000700) fprintf(stderr,"v4l: bttv version %d.%d.%d\n", (rc >> 16) & 0xff, (rc >> 8) & 0xff, rc & 0xff); if (rc < 0x000700) fprintf(stderr, "v4l: prehistoric bttv version found, please try to\n" " upgrade the driver before mailing bug reports\n"); }#endif v4l_add_attr(h,ATTR_ID_NORM,ATTR_TYPE_CHOICE,0,norms); /* frame buffer */ xioctl(h->fd,VIDIOCGFBUF,&h->fbuf); if (ng_debug) fprintf(stderr," fbuffer : base=0x%p size=%dx%d depth=%d bpl=%d\n", h->fbuf.base, h->fbuf.width, h->fbuf.height, h->fbuf.depth, h->fbuf.bytesperline); /* picture parameters */ xioctl(h->fd,VIDIOCGPICT,&h->pict); v4l_add_attr(h,ATTR_ID_BRIGHT, ATTR_TYPE_INTEGER,0,NULL); v4l_add_attr(h,ATTR_ID_HUE, ATTR_TYPE_INTEGER,0,NULL); v4l_add_attr(h,ATTR_ID_COLOR, ATTR_TYPE_INTEGER,0,NULL); v4l_add_attr(h,ATTR_ID_CONTRAST,ATTR_TYPE_INTEGER,0,NULL); if (ng_debug) { fprintf(stderr, " picture : brightness=%d hue=%d colour=%d contrast=%d\n", h->pict.brightness, h->pict.hue, h->pict.colour, h->pict.contrast); fprintf(stderr, " picture : whiteness=%d depth=%d palette=%s\n", h->pict.whiteness, h->pict.depth, PALETTE(h->pict.palette)); } v4l_close(h); return h;err: if (h->fd != -1) close(h->fd); free(h); return NULL;}static intv4l_fini(void *handle){ struct v4l_handle *h = handle; BUG_ON(h->fd != -1,"device still open"); if (ng_debug) fprintf(stderr, "v4l: close\n"); free(h->device); free(h); return 0;}/* ---------------------------------------------------------------------- */static char*v4l_devname(void *handle){ struct v4l_handle *h = handle; return h->capability.name;}static struct ng_devinfo* v4l_probe(int verbose){ struct ng_devinfo *info = NULL; struct video_capability cap; int i,n,fd; n = 0; for (i = 0; NULL != ng_dev.video_scan[i]; i++) { fd = ng_chardev_open(ng_dev.video_scan[i], O_RDONLY | O_NONBLOCK, 81, verbose); if (-1 == fd) continue; if (-1 == xioctl(fd,VIDIOCGCAP,&cap)) { if (verbose) perror("ioctl VIDIOCGCAP"); close(fd); continue; } info = realloc(info,sizeof(*info) * (n+2)); memset(info+n,0,sizeof(*info)*2); strcpy(info[n].device, ng_dev.video_scan[i]); sprintf(info[n].name, "%.32s", cap.name); close(fd); n++; } return info;}static int v4l_flags(void *handle){ struct v4l_handle *h = handle; int ret = 0;#if 0 if (h->capability.type & VID_TYPE_OVERLAY) ret |= CAN_OVERLAY;#endif if (h->capability.type & VID_TYPE_CAPTURE && !h->ov_error) ret |= CAN_CAPTURE; if (h->capability.type & VID_TYPE_TUNER) ret |= CAN_TUNE; if (h->capability.type & VID_TYPE_CHROMAKEY) ret |= NEEDS_CHROMAKEY; return ret;}static struct ng_attribute* v4l_attrs(void *handle){ struct v4l_handle *h = handle; return h->attr;}static int audio_mode_mask2bit(int mode){ if (mode & VIDEO_SOUND_STEREO) return VIDEO_SOUND_STEREO; if (mode & VIDEO_SOUND_LANG1) return VIDEO_SOUND_LANG1; if (mode & VIDEO_SOUND_LANG2) return VIDEO_SOUND_LANG2; if (mode & VIDEO_SOUND_MONO) return VIDEO_SOUND_MONO; return 0;}static int v4l_read_attr(struct ng_attribute *attr){ struct v4l_handle *h = attr->handle; BUG_ON(h->fd == -1,"device not open"); switch (attr->id) { case ATTR_ID_INPUT: return -1; case ATTR_ID_NORM: xioctl(h->fd, VIDIOCGCHAN, &h->channels[h->input]); return h->channels[h->input].norm; case ATTR_ID_MUTE: xioctl(h->fd, VIDIOCGAUDIO, &h->audio); return h->audio.flags & VIDEO_AUDIO_MUTE; case ATTR_ID_VOLUME: xioctl(h->fd, VIDIOCGAUDIO, &h->audio); return h->audio.volume; case ATTR_ID_AUDIO_MODE: xioctl(h->fd, VIDIOCGAUDIO, &h->audio); return audio_mode_mask2bit(h->audio.mode); case ATTR_ID_COLOR: xioctl(h->fd, VIDIOCGPICT, &h->pict); return h->pict.colour; case ATTR_ID_BRIGHT: xioctl(h->fd, VIDIOCGPICT, &h->pict); return h->pict.brightness; case ATTR_ID_HUE: xioctl(h->fd, VIDIOCGPICT, &h->pict); return h->pict.hue; case ATTR_ID_CONTRAST: xioctl(h->fd, VIDIOCGPICT, &h->pict); return h->pict.contrast; } return -1;}static void v4l_write_attr(struct ng_attribute *attr, int val){ struct v4l_handle *h = attr->handle; BUG_ON(h->fd == -1,"device not open"); /* read ... */ switch (attr->id) { case ATTR_ID_INPUT: /* nothing */ break; case ATTR_ID_NORM: xioctl(h->fd, VIDIOCGCHAN, &h->channels[h->input]); break; case ATTR_ID_MUTE: case ATTR_ID_VOLUME: case ATTR_ID_AUDIO_MODE: xioctl(h->fd, VIDIOCGAUDIO, &h->audio); break; case ATTR_ID_COLOR: case ATTR_ID_BRIGHT: case ATTR_ID_HUE: case ATTR_ID_CONTRAST: xioctl(h->fd, VIDIOCGPICT, &h->pict); break; } /* ... modify ... */ switch (attr->id) { case ATTR_ID_INPUT: h->input = val; h->audio_mode = 0; break; case ATTR_ID_NORM: h->channels[h->input].norm = val; h->audio_mode = 0; break; case ATTR_ID_MUTE: if (val) h->audio.flags |= VIDEO_AUDIO_MUTE; else h->audio.flags &= ~VIDEO_AUDIO_MUTE; break; case ATTR_ID_VOLUME: h->audio.volume = val; break; case ATTR_ID_AUDIO_MODE: h->audio_mode = val; break; case ATTR_ID_COLOR: h->pict.colour = val; break; case ATTR_ID_BRIGHT: h->pict.brightness = val; break; case ATTR_ID_HUE: h->pict.hue = val; break; case ATTR_ID_CONTRAST: h->pict.contrast = val; break; } /* have to set that all the time as read and write have slightly different semantics: read == bitmask with all available modes flagged write == one bit set (for the selected mode, zero is autodetect) */ h->audio.mode = h->audio_mode; /* ... write */ switch (attr->id) { case ATTR_ID_INPUT: case ATTR_ID_NORM: xioctl(h->fd, VIDIOCSCHAN, &h->channels[h->input]); break; case ATTR_ID_MUTE: case ATTR_ID_VOLUME: case ATTR_ID_AUDIO_MODE: xioctl(h->fd, VIDIOCSAUDIO, &h->audio); break; case ATTR_ID_COLOR: case ATTR_ID_BRIGHT: case ATTR_ID_HUE: case ATTR_ID_CONTRAST: xioctl(h->fd, VIDIOCSPICT, &h->pict); break; }}static unsigned longv4l_getfreq(void *handle){ struct v4l_handle *h = handle; unsigned long freq; BUG_ON(h->fd == -1,"device not open"); xioctl(h->fd, VIDIOCGFREQ, &freq); return freq;}static voidv4l_setfreq(void *handle, unsigned long freq){ struct v4l_handle *h = handle; if (ng_debug) fprintf(stderr,"v4l: freq: %.3f\n",(float)freq/16); BUG_ON(h->fd == -1,"device not open"); xioctl(h->fd, VIDIOCSFREQ, &freq); h->audio_mode = 0;}static intv4l_tuned(void *handle){ struct v4l_handle *h = handle; BUG_ON(h->fd == -1,"device not open"); /* usleep(10000); */ if (-1 == xioctl(h->fd,VIDIOCGTUNER,&h->tuner)) return 0; return h->tuner.signal ? 1 : 0;}/* ---------------------------------------------------------------------- *//* do overlay */#if 0intv4l_setupfb(void *handle, struct ng_video_fmt *fmt, void *base){ struct v4l_handle *h = handle; BUG_ON(h->fd == -1,"device not open"); /* overlay supported ?? */ if (!(h->capability.type & VID_TYPE_OVERLAY)) { if (ng_debug) fprintf(stderr,"v4l: device has no overlay support\n"); return -1; } /* double-check settings */ if (ng_debug) fprintf(stderr,"v4l: %dx%d, %d bit/pixel, %d byte/scanline\n", h->fbuf.width,h->fbuf.height, h->fbuf.depth,h->fbuf.bytesperline); if ((fmt->bytesperline > 0 && h->fbuf.bytesperline != fmt->bytesperline) || (h->fbuf.width != fmt->width) || (h->fbuf.height != fmt->height)) { fprintf(stderr, "WARNING: v4l and x11 disagree about the screen size\n" "WARNING: Is v4l-conf installed correctly?\n"); h->ov_error = 1; } if (ng_vfmt_to_depth[fmt->fmtid] != ((h->fbuf.depth+7)&0xf8)) { fprintf(stderr, "WARNING: v4l and x11 disagree about the color depth\n" "WARNING: fbuf.depth=%d, x11 depth=%d\n" "WARNING: Is v4l-conf installed correctly?\n", h->fbuf.depth,ng_vfmt_to_depth[fmt->fmtid]); h->ov_error = 1; } if (NULL != base) { /* XXX: minor differences are legal... (matrox problems) */ if ((void*)((unsigned long)h->fbuf.base & 0xfffff000) != (void*)((unsigned long)base & 0xfffff000)) { fprintf(stderr, "WARNING: v4l and dga disagree about the framebuffer base\n" "WARNING: fbuf.base=%p, dga=%p\n" "WARNING: Is v4l-conf installed correctly?\n", h->fbuf.base,base); h->ov_error = 1; } } if (h->ov_error) { fprintf(stderr,"WARNING: overlay mode disabled\n"); return -1; } return 0;}static voidv4l_overlay_set(struct v4l_handle *h, int state){ int rc; if (0 == state) { /* off */ if (0 == h->ov_on) return; xioctl(h->fd, VIDIOCCAPTURE, &zero); h->ov_on = 0; } else { /* on */ h->pict.depth = ng_vfmt_to_depth[h->ov_fmtid]; h->pict.palette = GETELEM(format2palette,h->ov_fmtid,0); xioctl(h->fd, VIDIOCSPICT, &h->pict); rc = xioctl(h->fd, VIDIOCSWIN, &h->win); if (0 == rc) { if (0 != h->ov_on) return; xioctl(h->fd, VIDIOCCAPTURE, &one); h->ov_on = 1; } else { /* disable overlay on SWIN failure */ xioctl(h->fd, VIDIOCCAPTURE, &zero); h->ov_on = 0; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -