📄 drv-v4l.c
字号:
/* check against max. size */ xioctl(h->fd,VIDIOCGCAP,&h->capability); if (h->win.width > h->capability.maxwidth) { h->win.width = h->capability.maxwidth; h->win.x += (fmt->width - h->win.width)/2; } if (h->win.height > h->capability.maxheight) { h->win.height = h->capability.maxheight; h->win.y += (fmt->height - h->win.height)/2; } if (aspect) ng_ratio_fixup(&h->win.width,&h->win.height,&h->win.x,&h->win.y);#if 0 /* pass aligned values -- the driver does'nt get it right yet */ h->win.width &= ~3; h->win.height &= ~3; h->win.x &= ~3; if (h->win.x < x) h->win.x += 4; if (h->win.x+h->win.width > x+fmt->width) h->win.width -= 4;#endif /* fixups */ ng_check_clipping(h->win.width, h->win.height, x - h->win.x, y - h->win.y, oc, &count); /* handle clipping */ if (h->win.clips) { free(h->win.clips); h->win.clips = NULL; } h->win.clipcount = 0; if (h->capability.type & VID_TYPE_CLIPPING && count > 0) { h->win.clipcount = count; h->win.clips = malloc(count * sizeof(struct video_clip)); for (i = 0; i < count; i++) { h->win.clips[i].x = oc[i].x1; h->win.clips[i].y = oc[i].y1; h->win.clips[i].width = oc[i].x2-oc[i].x1; h->win.clips[i].height = oc[i].y2-oc[i].y1; } } if (h->capability.type & VID_TYPE_CHROMAKEY) h->win.chromakey = ng_chromakey; h->ov_enabled = 1; h->ov_fmtid = fmt->fmtid; v4l_overlay_set(h,h->ov_enabled); if (ng_debug) fprintf(stderr,"v4l: overlay win=%dx%d+%d+%d, %d clips\n", fmt->width,fmt->height,x,y,count); return 0;}/* ---------------------------------------------------------------------- */static intmm_queue(struct v4l_handle *h){ int frame = h->queue % h->nbuf; int rc; if (0 != h->buf_me[frame].refcount) { if (0 != h->queue - h->waiton) return -1; fprintf(stderr,"v4l: waiting for a free buffer\n"); ng_waiton_video_buf(h->buf_me+frame); } rc = xioctl(h->fd,VIDIOCMCAPTURE,h->buf_v4l+frame); if (0 == rc) h->queue++; return rc;}static voidmm_queue_all(struct v4l_handle *h){ for (;;) { if (h->queue - h->waiton >= h->nbuf) return; if (0 != mm_queue(h)) return; }}static intmm_waiton(struct v4l_handle *h){ int frame = h->waiton % h->nbuf; int rc; if (0 == h->queue - h->waiton) return -1; h->waiton++; alarms=0; alarm(SYNC_TIMEOUT); retry: if (-1 == (rc = xioctl(h->fd,VIDIOCSYNC,h->buf_v4l+frame))) { if (errno == EINTR && !alarms) goto retry; } alarm(0); if (-1 == rc) return -1; return frame;}static voidmm_clear(struct v4l_handle *h){ while (h->queue > h->waiton) mm_waiton(h); h->queue = 0; h->waiton = 0;}static intmm_probe(struct v4l_handle *h, unsigned int fmtid){ if (0 != h->probe[fmtid]) goto done; if (ng_debug) fprintf(stderr, "v4l: capture probe %s...\t", ng_vfmt_to_desc[fmtid]); h->buf_v4l[0].frame = 0; h->buf_v4l[0].width = h->capability.minwidth; h->buf_v4l[0].height = h->capability.minheight; h->buf_v4l[0].format = GETELEM(format2palette,fmtid,0);#if 1 /* bug compatibility: bttv up to 0.7.67 reports wrong minwidth */ if (h->buf_v4l[0].width == 32) h->buf_v4l[0].width = 48;#endif if (0 == h->buf_v4l[0].format) goto fail; if (-1 == mm_queue(h)) goto fail; if (-1 == mm_waiton(h)) goto fail; if (ng_debug) fprintf(stderr, "ok\n"); h->probe[fmtid] = 1; goto done; fail: if (ng_debug) fprintf(stderr, "failed\n"); h->probe[fmtid] = 2; done: mm_clear(h); return h->probe[fmtid] == 1;}static intmm_setparams(struct v4l_handle *h, struct ng_video_fmt *fmt){ unsigned int i; /* buffers available ? */ if (h->mbuf.frames < 1) return -1; /* verify parameters */ xioctl(h->fd,VIDIOCGCAP,&h->capability); if (fmt->width > h->capability.maxwidth) fmt->width = h->capability.maxwidth; if (fmt->height > h->capability.maxheight) fmt->height = h->capability.maxheight; fmt->bytesperline = fmt->width * ng_vfmt_to_depth[fmt->fmtid] / 8; /* check if we can handle the format */ if (!mm_probe(h,fmt->fmtid)) return -1; /* initialize everything */ h->nbuf = h->mbuf.frames; for (i = 0; i < h->nbuf; i++) { h->buf_v4l[i].format = GETELEM(format2palette,fmt->fmtid,0); h->buf_v4l[i].frame = i; h->buf_v4l[i].width = fmt->width; h->buf_v4l[i].height = fmt->height; h->buf_me[i].fmt = *fmt; h->buf_me[i].data = h->mmap + h->mbuf.offsets[i]; h->buf_me[i].size = fmt->height * fmt->bytesperline; } return 0;}/* ---------------------------------------------------------------------- */static intread_setformat(struct v4l_handle *h, struct ng_video_fmt *fmt){ xioctl(h->fd,VIDIOCGCAP,&h->capability); if (fmt->width > h->capability.maxwidth) fmt->width = h->capability.maxwidth; if (fmt->height > h->capability.maxheight) fmt->height = h->capability.maxheight; fmt->bytesperline = fmt->width * ng_vfmt_to_depth[fmt->fmtid] / 8; h->rd_win.width = fmt->width; h->rd_win.height = fmt->height; h->rd_fmtid = fmt->fmtid; h->pict.depth = ng_vfmt_to_depth[h->rd_fmtid]; h->pict.palette = GETELEM(format2palette,h->rd_fmtid,0); if (-1 == xioctl(h->fd, VIDIOCSPICT, &h->pict)) return -1; if (-1 == xioctl(h->fd, VIDIOCSWIN, &h->rd_win)) return -1; fmt->width = h->rd_win.width; fmt->height = h->rd_win.height; fmt->bytesperline = fmt->width * ng_vfmt_to_depth[fmt->fmtid] / 8; h->rd_fmt = *fmt; return 0;}static struct ng_video_buf*read_getframe(struct v4l_handle *h){ struct ng_video_buf* buf; int size; h->pict.depth = ng_vfmt_to_depth[h->rd_fmtid]; h->pict.palette = GETELEM(format2palette,h->rd_fmtid,0); xioctl(h->fd, VIDIOCSPICT, &h->pict); xioctl(h->fd, VIDIOCSWIN, &h->rd_win); size = h->rd_fmt.bytesperline * h->rd_fmt.height; buf = ng_malloc_video_buf(&h->rd_fmt, size); if (NULL == buf) return NULL; if (size != read(h->fd,buf->data,size)) { ng_release_video_buf(buf); return NULL; } return buf;}/* ---------------------------------------------------------------------- */intv4l_setformat(void *handle, struct ng_video_fmt *fmt){ struct v4l_handle *h = handle; int rc;#if 0 /* for debugging color space conversion functions: force xawtv to capture some specific format */ if (fmt->fmtid != VIDEO_YUV420P) return -1;#endif if (ng_debug) fprintf(stderr,"v4l: setformat\n"); if (h->use_read) { v4l_overlay_set(h,0); rc = read_setformat(h,fmt); v4l_overlay_set(h,h->ov_enabled); } else { if (h->queue != h->waiton) fprintf(stderr,"v4l: Huh? setformat: found queued buffers (%d %d)\n", h->queue, h->waiton); mm_clear(h); rc = mm_setparams(h,fmt); } return rc;}intv4l_startvideo(void *handle, int fps, unsigned int buffers){ struct v4l_handle *h = handle; if (ng_debug) fprintf(stderr,"v4l: startvideo\n"); if (0 != h->fps) fprintf(stderr,"v4l: Huh? start: fps != 0\n"); if (!h->use_read) { if (h->nbuf > buffers) h->nbuf = buffers; mm_queue_all(h); } h->start = ng_get_timestamp(); h->fps = fps; return 0;}voidv4l_stopvideo(void *handle){ struct v4l_handle *h = handle; if (ng_debug) fprintf(stderr,"v4l: stopvideo\n"); if (0 == h->fps) fprintf(stderr,"v4l: Huh? stop: fps == 0\n"); if (!h->use_read) mm_clear(h); h->fps = 0;}struct ng_video_buf*v4l_nextframe(void *handle){ struct v4l_handle *h = handle; struct ng_video_buf* buf = NULL; int frame = 0; if (ng_debug > 1) fprintf(stderr,"v4l: getimage\n"); if (0 == h->fps) { fprintf(stderr,"v4l: nextframe: fps == 0\n"); return NULL; } if (h->use_read) { if (buf) ng_release_video_buf(buf); v4l_overlay_set(h,0); buf = read_getframe(h); v4l_overlay_set(h,h->ov_enabled); if (NULL == buf) return NULL; memset(&buf->info,0,sizeof(buf->info)); buf->info.ts = ng_get_timestamp() - h->start; return buf; } else { mm_queue_all(h); frame = mm_waiton(h); if (-1 == frame) return NULL; memset(&h->buf_me[frame].info,0,sizeof(h->buf_me[frame].info)); h->buf_me[frame].refcount++; h->buf_me[frame].info.ts = ng_get_timestamp() - h->start; return h->buf_me+frame; }}/* ---------------------------------------------------------------------- */struct ng_video_buf*v4l_getimage(void *handle){ struct v4l_handle *h = handle; struct ng_video_buf* buf = NULL; int frame; if (ng_debug) fprintf(stderr,"v4l: getimage\n"); if (0 != h->fps) { fprintf(stderr,"v4l: getimage: fps != 0\n"); return NULL; } if (h->use_read) { v4l_overlay_set(h,0); buf = read_getframe(h); v4l_overlay_set(h,h->ov_enabled); return buf; } else { mm_queue(h); frame = mm_waiton(h); if (-1 == frame) return NULL; h->buf_me[frame].refcount++; return h->buf_me+frame; }}/* ---------------------------------------------------------------------- */#if 0extern void ng_plugin_init(void);void ng_plugin_init(void){ ng_vid_driver_register(NG_PLUGIN_MAGIC,__FILE__,&v4l_driver);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -