📄 drv0-bsd.c
字号:
/* * interface to the bsd bktr driver * * (c) 2000-04 Gerd Knorr <kraxel@bytesex.org> * */#include "config.h"#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>#if defined(HAVE_DEV_IC_BT8XX_H)# include <dev/ic/bt8xx.h>#elif defined(HAVE_DEV_BKTR_IOCTL_BT848_H)# include <dev/bktr/ioctl_bt848.h># include <dev/bktr/ioctl_meteor.h>#else# include <machine/ioctl_bt848.h># include <machine/ioctl_meteor.h>#endif#include "grab-ng.h"/* ---------------------------------------------------------------------- *//* global variables */struct bsd_handle { int fd; int tfd; char *device; char *tdevice; /* formats */ int pf_count; struct meteor_pixfmt pf[64]; int xawtv2pf[VIDEO_FMT_COUNT]; unsigned char *map; /* attributes */ int muted; struct ng_attribute *attr; /* overlay */ struct meteor_video fb,pos; struct meteor_geomet ovgeo; struct meteor_pixfmt *ovfmt; struct bktr_clip clip[BT848_MAX_CLIP_NODE]; int ov_enabled,ov_on; /* capture */ int fps; long long start; struct ng_video_fmt fmt; struct meteor_video nofb; struct meteor_geomet capgeo; struct meteor_pixfmt *capfmt; struct bktr_clip noclip[BT848_MAX_CLIP_NODE];};/* ---------------------------------------------------------------------- *//* prototypes *//* open/close */static void* bsd_init(char *device);static int bsd_open(void *handle);static int bsd_close(void *handle);static int bsd_fini(void *handle);static char* bsd_devname(void *handle);static struct ng_devinfo* bsd_probe(void);/* attributes */static int bsd_flags(void *handle);static struct ng_attribute* bsd_attrs(void *handle);static int bsd_read_attr(struct ng_attribute*);static void bsd_write_attr(struct ng_attribute*, int val);#if 0static int bsd_setupfb(void *handle, struct ng_video_fmt *fmt, void *base);static int bsd_overlay(void *handle, struct ng_video_fmt *fmt, int x, int y, struct OVERLAY_CLIP *oc, int count, int aspect);#endif/* capture */static void catchsignal(int signal);static void siginit(void);static int bsd_setformat(void *handle, struct ng_video_fmt *fmt);static int bsd_startvideo(void *handle, int fps, unsigned int buffers);static void bsd_stopvideo(void *handle);static struct ng_video_buf* bsd_nextframe(void *handle);static struct ng_video_buf* bsd_getimage(void *handle);/* tuner */static unsigned long bsd_getfreq(void *handle);static void bsd_setfreq(void *handle, unsigned long freq);static int bsd_tuned(void *handle);struct ng_vid_driver bsd_driver = { .name = "bktr", .priority = 1, .init = bsd_init, .open = bsd_open, .close = bsd_close, .fini = bsd_fini, .devname = bsd_devname, .probe = bsd_probe, .capabilities = bsd_flags, .list_attrs = bsd_attrs,#if 0 .setupfb = bsd_setupfb, .overlay = bsd_overlay,#endif .setformat = bsd_setformat, .startvideo = bsd_startvideo, .stopvideo = bsd_stopvideo, .nextframe = bsd_nextframe, .getimage = bsd_getimage, .getfreq = bsd_getfreq, .setfreq = bsd_setfreq, .is_tuned = bsd_tuned,};/* ---------------------------------------------------------------------- */static struct STRTAB inputs[] = { { 0, "Television" }, { 1, "Composite1" }, { 2, "S-Video" }, { 3, "CSVIDEO" }, { -1, NULL }};static long inputs_map[] = { METEOR_INPUT_DEV1, METEOR_INPUT_DEV0, METEOR_INPUT_DEV_SVIDEO, METEOR_INPUT_DEV2,};static struct STRTAB norms[] = { { 0, "NTSC" }, { 1, "NTSC-JP" }, { 2, "PAL" }, { 3, "PAL-M" }, { 4, "PAL-N" }, { 5, "SECAM" }, { 6, "RSVD" }, { -1, NULL }};static long norms_map[] = { BT848_IFORM_F_NTSCM, BT848_IFORM_F_NTSCJ, BT848_IFORM_F_PALBDGHI, BT848_IFORM_F_PALM, BT848_IFORM_F_PALN, BT848_IFORM_F_SECAM, BT848_IFORM_F_RSVD,};static struct STRTAB audio[] = { { 0, "Tuner" }, { 1, "Extern" }, { 2, "Intern" }, { -1, NULL }};static long audio_map[] = { AUDIO_TUNER, AUDIO_EXTERN, AUDIO_INTERN,};static struct ng_attribute bsd_attr[] = { { .id = ATTR_ID_COUNT+1, .name = "audio", .priority = 2, .type = ATTR_TYPE_CHOICE, .choices = audio, .read = bsd_read_attr, .write = bsd_write_attr, },{ .id = ATTR_ID_NORM, .name = "norm", .priority = 2, .type = ATTR_TYPE_CHOICE, .choices = norms, .read = bsd_read_attr, .write = bsd_write_attr, },{ .id = ATTR_ID_INPUT, .name = "input", .priority = 2, .type = ATTR_TYPE_CHOICE, .choices = inputs, .read = bsd_read_attr, .write = bsd_write_attr, },{ .id = ATTR_ID_MUTE, .name = "mute", .priority = 2, .type = ATTR_TYPE_BOOL, .read = bsd_read_attr, .write = bsd_write_attr, },{ .id = ATTR_ID_HUE, .name = "hue", .priority = 2, .type = ATTR_TYPE_INTEGER, .min = BT848_HUEREGMIN, .max = BT848_HUEREGMAX, .read = bsd_read_attr, .write = bsd_write_attr, },{ .id = ATTR_ID_BRIGHT, .name = "bright", .priority = 2, .type = ATTR_TYPE_INTEGER, .min = BT848_BRIGHTREGMIN, .max = BT848_BRIGHTREGMAX, .read = bsd_read_attr, .write = bsd_write_attr, },{ .id = ATTR_ID_CONTRAST, .name = "contrast", .priority = 2, .type = ATTR_TYPE_INTEGER, .min = BT848_CONTRASTREGMIN, .max = BT848_CONTRASTREGMAX, .read = bsd_read_attr, .write = bsd_write_attr, },{ .id = ATTR_ID_COLOR, .name = "color", .priority = 2, .type = ATTR_TYPE_INTEGER, .min = BT848_CHROMAREGMIN, .max = BT848_CHROMAREGMAX, .read = bsd_read_attr, .write = bsd_write_attr, },{ /* end of list */ }};static int single = METEOR_CAP_SINGLE;static int start = METEOR_CAP_CONTINOUS;static int stop = METEOR_CAP_STOP_CONT;static int signal_on = SIGUSR1;static int signal_off = METEOR_SIG_MODE_MASK;/* ---------------------------------------------------------------------- */#define PREFIX "bktr: ioctl: "static intxioctl(int fd, unsigned long cmd, void *arg){ int rc; rc = ioctl(fd,cmd,arg); if (0 == rc && ng_debug < 2) return 0; switch (cmd) { case METEORSVIDEO: { struct meteor_video *a = arg; fprintf(stderr,PREFIX "METEORSVIDEO(addr=0x%08lx,width=%ld,bank=%ld,ram=%ld)", a->addr,a->width,a->banksize,a->ramsize); break; } case METEORSETGEO: { struct meteor_geomet *a = arg; fprintf(stderr,PREFIX "METEORSETGEO(%dx%d,frames=%d,oformat=0x%lx)", a->columns,a->rows,a->frames,a->oformat); break; } case METEORSACTPIXFMT: { struct meteor_pixfmt *a = arg; fprintf(stderr,PREFIX "METEORSACTPIXFMT(%d,type=%d,bpp=%d," "masks=0x%lx/0x%lx/0x%lx,sb=%d,ss=%d)", a->index,a->type,a->Bpp,a->masks[0],a->masks[1],a->masks[2], a->swap_bytes,a->swap_shorts); break; } case METEORCAPTUR: { int *a = arg; fprintf(stderr,PREFIX "METEORCAPTUR(%d)",*a); break; } case METEORSSIGNAL: { int *a = arg; fprintf(stderr,PREFIX "METEORSSIGNAL(0x%x)",*a); break; } case BT848SCLIP: { fprintf(stderr,PREFIX "BT848SCLIP"); break; } default: fprintf(stderr,PREFIX "UNKNOWN(cmd=0x%lx)",cmd); break; } fprintf(stderr,": %s\n",(rc == 0) ? "ok" : strerror(errno)); return rc;}/* ---------------------------------------------------------------------- */static voidbsd_print_format(struct meteor_pixfmt *pf, int format){ switch (pf->type) { case METEOR_PIXTYPE_RGB: fprintf(stderr, "bktr: pf: rgb bpp=%d mask=%ld,%ld,%ld", pf->Bpp,pf->masks[0],pf->masks[1],pf->masks[2]); break; case METEOR_PIXTYPE_YUV: fprintf(stderr,"bktr: pf: yuv h422 v111 (planar)"); break; case METEOR_PIXTYPE_YUV_PACKED: fprintf(stderr,"bktr: pf: yuyv h422 v111 (packed)"); break; case METEOR_PIXTYPE_YUV_12: fprintf(stderr,"bktr: pf: yuv h422 v422 (planar)"); break; default: fprintf(stderr,"bktr: pf: unknown"); } fprintf(stderr," sbytes=%d sshorts=%d (fmt=%d)\n", pf->swap_bytes,pf->swap_shorts,format);}/* ---------------------------------------------------------------------- */static intbsd_open(void *handle){ struct bsd_handle *h = handle; BUG_ON(h->fd != -1,"device is open"); if (ng_debug) fprintf(stderr, "bktr: open\n"); if (-1 == (h->fd = open(h->device,O_RDONLY))) { fprintf(stderr,"bktr: open %s: %s\n", h->device, strerror(errno)); goto err1; } if (-1 == (h->tfd = open(h->tdevice,O_RDONLY))) { fprintf(stderr,"bktr: open %s: %s\n", h->tdevice, strerror(errno)); goto err2; } h->map = mmap(0,768*576*4, PROT_READ, MAP_SHARED, h->fd, 0); if (MAP_FAILED == h->map) { perror("bktr: mmap"); h->map = NULL; goto err3; } return 0; err3: close(h->tfd); h->tfd = -1; err2: close(h->fd); h->fd = -1; err1: return -1;}static intbsd_close(void *handle){ struct bsd_handle *h = handle; BUG_ON(h->fd == -1,"device not open"); if (ng_debug) fprintf(stderr, "bktr: close\n"); close(h->fd); if (-1 != h->tfd) close(h->tfd); if (NULL != h->map) munmap(h->map,768*576*4); h->fd = -1; h->tfd = -1; return 0;}static intbsd_fini(void *handle){ struct bsd_handle *h = handle; BUG_ON(h->fd != -1,"device is open"); if (ng_debug) fprintf(stderr, "bktr: fini\n"); if (h->device) free(h->device); if (h->tdevice) free(h->tdevice); if (h->attr) free(h->attr); free(h); return 0;}static void*bsd_init(char *filename){ struct bsd_handle *h; int format,i; if (NULL == filename) return NULL; if (0 != strncmp(filename,"/dev/",5)) return NULL; h = malloc(sizeof(*h)); if (NULL == h) return NULL; memset(h,0,sizeof(*h)); h->fd = -1; h->tfd = -1; h->device = strdup(filename); h->tdevice = strdup("/dev/tuner0"); // FIXME if (-1 == bsd_open(h)) goto err1; /* video formats */ for (format = 0; format < VIDEO_FMT_COUNT; format++) h->xawtv2pf[format] = -1; for (h->pf_count = 0; h->pf_count < 64; h->pf_count++) { h->pf[h->pf_count].index = h->pf_count; if (-1 == ioctl(h->fd, METEORGSUPPIXFMT,h->pf+h->pf_count)) { if (ng_debug) perror("bktr: ioctl METEORGSUPPIXFMT"); if (0 == h->pf_count) goto err2; break; } format = -1; switch (h->pf[h->pf_count].type) { case METEOR_PIXTYPE_RGB: switch(h->pf[h->pf_count].masks[0]) { case 31744: /* 15 bpp */ format = h->pf[h->pf_count].swap_bytes ? VIDEO_RGB15_LE : VIDEO_RGB15_BE; break; case 63488: /* 16 bpp */ format = h->pf[h->pf_count].swap_bytes ? VIDEO_RGB16_LE : VIDEO_RGB16_BE; break; case 16711680: /* 24/32 bpp */ if (h->pf[h->pf_count].Bpp == 3 && h->pf[h->pf_count].swap_bytes == 1) { format = VIDEO_BGR24; } else if (h->pf[h->pf_count].Bpp == 4 && h->pf[h->pf_count].swap_bytes == 1 &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -