⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drv-v4l.c

📁 基于s3c2410的摄像头驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * interface to the v4l driver * *   (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org> *	2005-3-23 modified by threewater<threewater@up-tech.com> * */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <math.h>#include <errno.h>#include <fcntl.h>#include <string.h>#include <signal.h>#include <pthread.h>#include <sys/types.h>#include <sys/time.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <sys/mman.h>#include <linux/videodev.h>#include "grab-ng.h"#include "struct-dump.h"#include "struct-v4l.h"#define SYNC_TIMEOUT 5/* ---------------------------------------------------------------------- *//* open+close */static void*   v4l_open(char *device);static int     v4l_close(void *handle);/* attributes */static char*   v4l_devname(void *handle);static int     v4l_flags(void *handle);static struct ng_attribute* v4l_attrs(void *handle);static int     v4l_read_attr(struct ng_attribute*);static void    v4l_write_attr(struct ng_attribute*, int val);/* overlay */static int   v4l_setupfb(void *handle, struct ng_video_fmt *fmt, void *base);static int   v4l_overlay(void *handle, struct ng_video_fmt *fmt, int x, int y,			 struct OVERLAY_CLIP *oc, int count, int aspect);/* capture video */static int v4l_setformat(void *handle, struct ng_video_fmt *fmt);static int v4l_startvideo(void *handle, int fps, unsigned int buffers);static void v4l_stopvideo(void *handle);static struct ng_video_buf* v4l_nextframe(void *handle);static struct ng_video_buf* v4l_getimage(void *handle);/* tuner */static unsigned long v4l_getfreq(void *handle);static void v4l_setfreq(void *handle, unsigned long freq);static int v4l_tuned(void *handle);/* ---------------------------------------------------------------------- */static const char *device_cap[] = {    "capture", "tuner", "teletext", "overlay", "chromakey", "clipping",    "frameram", "scales", "monochrome", NULL};static const char *device_pal[] = {    "-", "grey", "hi240", "rgb16", "rgb24", "rgb32", "rgb15",    "yuv422", "yuyv", "uyvy", "yuv420", "yuv411", "raw",    "yuv422p", "yuv411p", "yuv420p", "yuv410p"};#define PALETTE(x) ((x < sizeof(device_pal)/sizeof(char*)) ? device_pal[x] : "UNKNOWN")static struct STRTAB stereo[] = {    {  0,                  "auto"    },    {  VIDEO_SOUND_MONO,   "mono"    },    {  VIDEO_SOUND_STEREO, "stereo"  },    {  VIDEO_SOUND_LANG1,  "lang1"   },    {  VIDEO_SOUND_LANG2,  "lang2"   },    { -1, NULL },};static struct STRTAB norms_v4l[] = {    {  VIDEO_MODE_PAL,     "PAL"   },    {  VIDEO_MODE_NTSC,    "NTSC"  },    {  VIDEO_MODE_SECAM,   "SECAM" },    {  VIDEO_MODE_AUTO,    "AUTO"  },    { -1, NULL }};static struct STRTAB norms_bttv[] = {    {  VIDEO_MODE_PAL,   "PAL"     },    {  VIDEO_MODE_NTSC,  "NTSC"    },    {  VIDEO_MODE_SECAM, "SECAM"   },    {  3,                "PAL-NC"  },    {  4,                "PAL-M"   },    {  5,                "PAL-N"   },    {  6,                "NTSC-JP" },    { -1, NULL }};static unsigned short format2palette[VIDEO_FMT_COUNT] = {    [ VIDEO_RGB08 ]    = VIDEO_PALETTE_HI240,    [ VIDEO_GRAY ]     = VIDEO_PALETTE_GREY,    [ VIDEO_RGB15_LE ] = VIDEO_PALETTE_RGB555,    [ VIDEO_RGB16_LE ] = VIDEO_PALETTE_RGB565,    [ VIDEO_BGR24 ]    = VIDEO_PALETTE_RGB24,    [ VIDEO_BGR32 ]    = VIDEO_PALETTE_RGB32,    [ VIDEO_YUYV ]     = VIDEO_PALETTE_YUV422,    [ VIDEO_UYVY ]     = VIDEO_PALETTE_UYVY,    [ VIDEO_YUV422P ]  = VIDEO_PALETTE_YUV422P,    [ VIDEO_YUV420P ]  = VIDEO_PALETTE_YUV420P,};/* pass 0/1 by reference */static int                      one = 1, zero = 0;/* ---------------------------------------------------------------------- */struct v4l_handle {    int                      fd;    /* general informations */    struct video_capability  capability;    struct video_channel     *channels;    struct video_tuner       tuner;    struct video_audio       audio;    struct video_picture     pict;    /* attributes */    int                      nattr;    struct ng_attribute      *attr;    int                      input;    int                      audio_mode;        /* overlay */    struct video_buffer      fbuf;    struct video_window      win;    int                      ov_error;    unsigned int             ov_fmtid;    int                      ov_enabled;    int                      ov_on;    /* capture */    int                      use_read;    struct ng_video_fmt      fmt;    long long                start;    int                      fps;        /* capture via read() */    struct ng_video_fmt      rd_fmt;    struct video_window      rd_win;    unsigned int             rd_fmtid;        /* capture to mmap()'ed buffers */    struct video_mbuf        mbuf;    unsigned char            *mmap;    unsigned int             nbuf;    unsigned int             queue;    unsigned int             waiton;    int                      probe[VIDEO_FMT_COUNT];    struct video_mmap        *buf_v4l;    struct ng_video_buf      *buf_me;};struct ng_vid_driver v4l_driver = {    name:          "v4l",    open:          v4l_open,    close:         v4l_close,    get_devname:   v4l_devname,    capabilities:  v4l_flags,    list_attrs:    v4l_attrs,    setupfb:       v4l_setupfb,    overlay:       v4l_overlay,    setformat:     v4l_setformat,    startvideo:    v4l_startvideo,    stopvideo:     v4l_stopvideo,    nextframe:     v4l_nextframe,    getimage:      v4l_getimage,        getfreq:       v4l_getfreq,    setfreq:       v4l_setfreq,    is_tuned:      v4l_tuned,};/* ---------------------------------------------------------------------- */static int alarms;static voidsigalarm(int signal){    alarms++;    fprintf(stderr,"v4l: timeout (got SIGALRM), hardware/driver problems?\n");}static voidsiginit(void){    struct sigaction act,old;        memset(&act,0,sizeof(act));    act.sa_handler  = sigalarm;    sigemptyset(&act.sa_mask);    sigaction(SIGALRM,&act,&old);}/* ---------------------------------------------------------------------- */#define PREFIX "ioctl: "static intxioctl(int fd, int cmd, void *arg){    int rc;    rc = ioctl(fd,cmd,arg);    if (0 == rc && ng_debug < 2)	return 0;    print_ioctl(stderr,ioctls_v4l1,PREFIX,cmd,arg);    fprintf(stderr,": %s\n",(rc == 0) ? "ok" : strerror(errno));    return rc;}/* ---------------------------------------------------------------------- */static voidv4l_add_attr(struct v4l_handle *h, int id, int type,	     int defval, struct STRTAB *choices){    h->attr = realloc(h->attr,(h->nattr+2) * sizeof(struct ng_attribute));    memset(h->attr+h->nattr,0,sizeof(struct ng_attribute)*2);    h->attr[h->nattr].id      = id;    h->attr[h->nattr].type    = type;    h->attr[h->nattr].defval  = defval;    h->attr[h->nattr].choices = choices;    if (ATTR_TYPE_INTEGER == type) {	h->attr[h->nattr].min = 0;	h->attr[h->nattr].max = 65535;    }    if (id < ATTR_ID_COUNT)	h->attr[h->nattr].name = ng_attr_to_desc[id];    h->attr[h->nattr].read    = v4l_read_attr;    h->attr[h->nattr].write   = v4l_write_attr;    h->attr[h->nattr].handle  = h;    h->nattr++;}static void*v4l_open(char *device){    struct v4l_handle *h;    struct STRTAB *inputs;    struct STRTAB *norms;    unsigned int i;    int rc;    h = malloc(sizeof(*h));    if (NULL == h)	return NULL;    memset(h,0,sizeof(*h));    /* open device */    if (-1 == (h->fd = open(device,O_RDWR))) {	fprintf(stderr,"v4l: open %s: %s\n",device,strerror(errno));	goto err;    }    if (-1 == ioctl(h->fd,VIDIOCGCAP,&h->capability))	goto err;    if (ng_debug)	fprintf(stderr, "v4l: open: %s (%s)\n",device,h->capability.name);    fcntl(h->fd,F_SETFD,FD_CLOEXEC);    siginit();    if (ng_debug) {	fprintf(stderr,"  capabilities: ");	for (i = 0; device_cap[i] != NULL; i++)	    if (h->capability.type & (1 << i))		fprintf(stderr," %s",device_cap[i]);	fprintf(stderr,"\n");	fprintf(stderr,"  size    : %dx%d => %dx%d\n",		h->capability.minwidth,h->capability.minheight,		h->capability.maxwidth,h->capability.maxheight);    }    /* input sources */    if (ng_debug)	fprintf(stderr,"  channels: %d\n",h->capability.channels);    h->channels = malloc(sizeof(struct video_channel)*h->capability.channels);    memset(h->channels,0,sizeof(struct video_channel)*h->capability.channels);    inputs = malloc(sizeof(struct STRTAB)*(h->capability.channels+1));    memset(inputs,0,sizeof(struct STRTAB)*(h->capability.channels+1));    for (i = 0; i < h->capability.channels; i++) {	h->channels[i].channel = i;	xioctl(h->fd,VIDIOCGCHAN,&(h->channels[i]));	inputs[i].nr  = i;	inputs[i].str = h->channels[i].name;	if (ng_debug)	    fprintf(stderr,"    %s: %d %s%s %s%s\n",		    h->channels[i].name,		    h->channels[i].tuners,		    (h->channels[i].flags & VIDEO_VC_TUNER)   ? "tuner "  : "",		    (h->channels[i].flags & VIDEO_VC_AUDIO)   ? "audio "  : "",		    (h->channels[i].type & VIDEO_TYPE_TV)     ? "tv "     : "",		    (h->channels[i].type & VIDEO_TYPE_CAMERA) ? "camera " : "");    }    inputs[i].nr  = -1;    inputs[i].str = NULL;    v4l_add_attr(h,ATTR_ID_INPUT,ATTR_TYPE_CHOICE,0,inputs);        /* audios */    if (ng_debug)	fprintf(stderr,"  audios  : %d\n",h->capability.audios);    if (h->capability.audios) {	h->audio.audio = 0;	xioctl(h->fd,VIDIOCGAUDIO,&h->audio);	if (ng_debug) {	    fprintf(stderr,"    %d (%s): ",i,h->audio.name);	    if (h->audio.flags & VIDEO_AUDIO_MUTABLE)		fprintf(stderr,"muted=%s ",			(h->audio.flags&VIDEO_AUDIO_MUTE) ? "yes":"no");	    if (h->audio.flags & VIDEO_AUDIO_VOLUME)		fprintf(stderr,"volume=%d ",h->audio.volume);	    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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -