Code Search for Developers
 
 
  

drv0-bsd.c from aMSN at Krugle


Show drv0-bsd.c syntax highlighted

/*
 * 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 0
static 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 int
xioctl(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 void
bsd_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 int
bsd_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 int
bsd_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 int
bsd_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 &&
			   h->pf[h->pf_count].swap_shorts == 1) {
		    format = VIDEO_BGR32;
		} else if (h->pf[h->pf_count].Bpp == 4 &&
			   h->pf[h->pf_count].swap_bytes == 0 &&
			   h->pf[h->pf_count].swap_shorts == 0) {
		    format = VIDEO_RGB32;
		}
	    }
	    break;
	case METEOR_PIXTYPE_YUV:
	    format = VIDEO_YUV422P;
	    break;
#if 0
	case METEOR_PIXTYPE_YUV_PACKED:
	    format = VIDEO_YUV422;
	    h->pf[h->pf_count].swap_shorts = 0; /* seems not to work */
	    break;
#endif
	case METEOR_PIXTYPE_YUV_12:
	case METEOR_PIXTYPE_YUV_PACKED:
	    /* nothing */
	    break;
	}
	if (-1 != format)
	    h->xawtv2pf[format] = h->pf_count;

	if (ng_debug)
	  bsd_print_format(h->pf+h->pf_count,format);
    }
    bsd_close(h);
    siginit();

    h->attr = malloc(sizeof(bsd_attr));
    memcpy(h->attr,bsd_attr,sizeof(bsd_attr));
    for (i = 0; h->attr[i].name != NULL; i++)
	h->attr[i].handle = h;

    return h;

 err2:
    bsd_close(h);
 err1:
    bsd_fini(h);
    return NULL;
}

static char*
bsd_devname(void *handle)
{
    return "bsd bkdr device";
}

static struct ng_devinfo* bsd_probe(void)
{
    struct ng_devinfo *info = NULL;
    int i,n,fd,status;
    
    n = 0;
    for (i = 0; NULL != ng_dev.video_scan[i]; i++) {
	fd = open(ng_dev.video_scan[i], O_RDONLY);
	if (-1 == fd)
	    continue;
	if (-1 == ioctl(fd,BT848_GSTATUS,&status)) {
	    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, ng_dev.video_scan[i]);
	close(fd);
	n++;
    }
    return info;
}

static int bsd_flags(void *handle)
{
    int ret = 0;

    ret |= CAN_CAPTURE;
    ret |= CAN_TUNE;
    return ret;
}

static struct ng_attribute* bsd_attrs(void *handle)
{
    struct bsd_handle *h = handle;

    return h->attr;
}

/* ---------------------------------------------------------------------- */

static int
bsd_get_range(int id, int *get, long *set)
{
    switch (id) {
    case ATTR_ID_HUE:
	*get = BT848_GHUE;
	*set = BT848_SHUE;
	break;
    case ATTR_ID_BRIGHT:
	*get = BT848_GBRIG;
	*set = BT848_SBRIG;
	break;
    case ATTR_ID_CONTRAST:
	*get = BT848_GCONT;
	*set = BT848_SCONT;
	break;
    case ATTR_ID_COLOR:
	*get = BT848_GCSAT;
	*set = BT848_SCSAT;
	break;
    default:
	return -1;
    }
    return 0;
}

static int bsd_read_attr(struct ng_attribute *attr)
{
    struct bsd_handle *h = attr->handle;
    int get, i;
    long arg, set;
    int value = -1;

    BUG_ON(h->fd == -1,"device not open");
    switch (attr->id) {
    case ATTR_ID_NORM:
	if (-1 != xioctl(h->fd,BT848GFMT,&arg))
	    for (i = 0; i < sizeof(norms_map)/sizeof(*norms_map); i++)
		if (arg == norms_map[i])
		    value = i;
	break;
    case ATTR_ID_INPUT:
	if (-1 != xioctl(h->fd,METEORGINPUT,&arg))
	    for (i = 0; i < sizeof(inputs_map)/sizeof(*inputs_map); i++)
		if (arg == inputs_map[i])
		    value = i;
	break;
    case ATTR_ID_MUTE:
	if (-1 != xioctl(h->tfd, BT848_GAUDIO, &arg))
	    value = (arg == AUDIO_MUTE) ? 1 : 0;
	break;
    case ATTR_ID_HUE:
    case ATTR_ID_BRIGHT:
    case ATTR_ID_CONTRAST:
    case ATTR_ID_COLOR:
	bsd_get_range(attr->id,&get,&set);
	if (-1 != xioctl(h->tfd,get,&arg))
	    value = arg;
	break;
    case ATTR_ID_COUNT+1: /* AUDIO */
	if (-1 != xioctl(h->tfd, BT848_GAUDIO, &arg))
	    for (i = 0; i < sizeof(audio_map)/sizeof(*audio_map); i++)
		if (arg == audio_map[i])
		    value = i;
	break;
    default:
	break;
    }
    return value;
}

static void bsd_write_attr(struct ng_attribute *attr, int value)
{
    struct bsd_handle *h = attr->handle;
    int get;
    long arg, set;

    BUG_ON(h->fd == -1,"device not open");
    switch (attr->id) {
    case ATTR_ID_NORM:
	xioctl(h->fd,BT848SFMT,&norms_map[value]);
	break;
    case ATTR_ID_INPUT:
	xioctl(h->fd,METEORSINPUT,&inputs_map[value]);
	break;
    case ATTR_ID_MUTE:
	h->muted = value;
	arg = h->muted ? AUDIO_MUTE : AUDIO_UNMUTE;
	xioctl(h->tfd, BT848_SAUDIO, &arg);
	break;
    case ATTR_ID_HUE:
    case ATTR_ID_BRIGHT:
    case ATTR_ID_CONTRAST:
    case ATTR_ID_COLOR:
	bsd_get_range(attr->id,&get,&set);
	arg = value;
	xioctl(h->tfd,set,&arg);
	break;
    case ATTR_ID_COUNT+1: /* audio */
	xioctl(h->tfd, BT848_SAUDIO,&audio_map[value]);
	break;
    default:
	break;
    }
}

static unsigned long bsd_getfreq(void *handle)
{
    struct bsd_handle *h = handle;
    unsigned long freq = 0;

    BUG_ON(h->fd == -1,"device not open");
    if (-1 == ioctl(h->tfd, TVTUNER_GETFREQ, &freq))
	perror("bktr: ioctl TVTUNER_GETFREQ");
    if (ng_debug)
	fprintf(stderr,"bktr: get freq: %.3f\n",(float)freq/16);
    return freq;
}

static void bsd_setfreq(void *handle, unsigned long freq)
{
    struct bsd_handle *h = handle;

    BUG_ON(h->fd == -1,"device not open");
    if (ng_debug)
	fprintf(stderr,"bktr: set freq: %.3f\n",(float)freq/16);
    if (-1 == ioctl(h->tfd, TVTUNER_SETFREQ, &freq))
	perror("bktr: ioctl TVTUNER_SETFREQ");
}

static int bsd_tuned(void *handle)
{
    struct bsd_handle *h = handle;
    int signal;

    BUG_ON(h->fd == -1,"device not open");
    usleep(10000);
    if (-1 == xioctl(h->tfd, TVTUNER_GETSTATUS, &signal))
        return 0;
    return signal == 106 ? 1 : 0;
}

/* ---------------------------------------------------------------------- */
/* overlay                                                                */


static void
set_overlay(struct bsd_handle *h, int state)
{
    if (h->ov_on == state)
	return;
    h->ov_on = state;
    
    if (state) {
	/* enable */
	xioctl(h->fd, METEORSVIDEO, &h->pos);
	xioctl(h->fd, METEORSETGEO, &h->ovgeo);
	xioctl(h->fd, METEORSACTPIXFMT, h->ovfmt);
	xioctl(h->fd, BT848SCLIP, &h->clip);
	xioctl(h->fd, METEORCAPTUR, &start);
    } else {
	/* disable */
	xioctl(h->fd, METEORCAPTUR, &stop);
    }
}

#if 0
static int bsd_setupfb(void *handle, struct ng_video_fmt *fmt, void *base)
{
    struct bsd_handle *h = handle;

    h->fb.addr     = (long)base;
    h->fb.width    = fmt->bytesperline;
    h->fb.banksize = fmt->bytesperline * fmt->height;
    h->fb.ramsize  = fmt->bytesperline * fmt->height / 1024;
    return 0;
}

static int bsd_overlay(void *handle, struct ng_video_fmt *fmt, int x, int y,
		       struct OVERLAY_CLIP *oc, int count, int aspect)
{
    struct bsd_handle *h = handle;
    int i,win_width,win_height,win_x,win_y;

    h->ov_enabled = 0;
    set_overlay(h,h->ov_enabled);
    if (NULL == fmt)
	return 0;

    if (-1 == h->xawtv2pf[fmt->fmtid])
	return -1;

    /* fixups - fixme: no fixed max size */
    win_x      = x;
    win_y      = y;
    win_width  = fmt->width;
    win_height = fmt->height;
    if (win_width > 768) {
	win_width = 768;
	win_x += (fmt->width - win_width)/2;
    }
    if (win_height > 576) {
	win_height = 576;
	win_y +=  (fmt->height - win_height)/2;
    }
    if (aspect)
	ng_ratio_fixup(&win_width,&win_height,&win_x,&win_y);
    ng_check_clipping(win_width, win_height,
		      x - win_x, y - win_y,
		      oc, &count);

    /* fill data */
    h->pos           = h->fb;
    h->pos.addr     += win_y*h->pos.width;
    h->pos.addr     += win_x*ng_vfmt_to_depth[fmt->fmtid]>>3;
    h->ovgeo.rows    = win_height;
    h->ovgeo.columns = win_width;
    h->ovgeo.frames  = 1;
    h->ovgeo.oformat = 0x10000;

    if (ng_debug)
	fprintf(stderr,"bktr: overlay win=%dx%d+%d+%d, %d clips\n",
		win_width,win_height,win_x,win_y,count);

    /* clipping */
    memset(h->clip,0,sizeof(h->clip));
    for (i = 0; i < count; i++) {
#if 0
	/* This way it *should* work IMHO ... */
	h->clip[i].x_min      = oc[i].x1;
	h->clip[i].x_max      = oc[i].x2;
	h->clip[i].y_min      = oc[i].y1;
	h->clip[i].y_max      = oc[i].y2;
#else
	/* This way it does work.  Sort of ... */
	h->clip[i].x_min      = (oc[i].y1) >> 1;
	h->clip[i].x_max      = (oc[i].y2) >> 1;
	h->clip[i].y_min      = oc[i].x1;
	h->clip[i].y_max      = oc[i].x2;
#endif
    }
    h->ovfmt = h->pf+h->xawtv2pf[fmt->fmtid];

    h->ov_enabled = 1;
    set_overlay(h,h->ov_enabled);
    return 0;
}
#endif

/* ---------------------------------------------------------------------- */
/* capture                                                                */

static void
catchsignal(int signal)
{
    if (signal == SIGUSR1  &&  ng_debug > 1)
	fprintf(stderr,"bktr: sigusr1\n");
    if (signal == SIGALRM)
	fprintf(stderr,"bktr: sigalrm\n");
}

static void
siginit(void)
{
    struct sigaction act,old;

    memset(&act,0,sizeof(act));
    sigemptyset(&act.sa_mask);
    act.sa_handler  = catchsignal;
    sigaction(SIGUSR1,&act,&old);
    sigaction(SIGALRM,&act,&old);
}

static int bsd_setformat(void *handle, struct ng_video_fmt *fmt)
{
    struct bsd_handle *h = handle;

    BUG_ON(h->fd == -1,"device not open");
    if (-1 == h->xawtv2pf[fmt->fmtid])
	return -1;

    if (fmt->width > 768)
	fmt->width = 768;
    if (fmt->height > 576)
	fmt->height = 576;
    fmt->bytesperline = fmt->width * ng_vfmt_to_depth[fmt->fmtid] / 8;

    h->capfmt = h->pf+h->xawtv2pf[fmt->fmtid];
    h->capgeo.rows    = fmt->height;
    h->capgeo.columns = fmt->width;
    h->capgeo.frames  = 1;
    h->capgeo.oformat = 0 /* FIXME */;
    if (fmt->height <= 320)
	h->capgeo.oformat |= METEOR_GEO_ODD_ONLY;
    h->fmt = *fmt;
    return 0;
}

static void
set_capture(struct bsd_handle *h, int state)
{
    if (state) {
	/* enable */
	xioctl(h->fd, METEORSVIDEO, &h->nofb);
	xioctl(h->fd, METEORSETGEO, &h->capgeo);
	xioctl(h->fd, METEORSACTPIXFMT, h->capfmt);
	xioctl(h->fd, BT848SCLIP, &h->noclip);
    } else {
	/* disable */
	xioctl(h->fd, METEORCAPTUR, &stop);
    }
}

static int bsd_startvideo(void *handle, int fps, unsigned int buffers)
{
    struct bsd_handle *h = handle;

    BUG_ON(h->fd == -1,"device not open");
    set_overlay(h,0);
    h->fps = fps;
    h->start = ng_get_timestamp();
    set_capture(h,1);
    xioctl(h->fd, METEORSSIGNAL, &signal_on);
    xioctl(h->fd, METEORCAPTUR, &start);
    return 0;
}

static void bsd_stopvideo(void *handle)
{
    struct bsd_handle *h = handle;

    BUG_ON(h->fd == -1,"device not open");
    h->fps = 0;
    set_capture(h,0);
    xioctl(h->fd, METEORCAPTUR, &stop);
    xioctl(h->fd, METEORSSIGNAL, &signal_off);
    set_overlay(h,h->ov_enabled);
}

static struct ng_video_buf* bsd_nextframe(void *handle)
{
    struct bsd_handle *h = handle;
    struct ng_video_buf *buf;
    int size;
    sigset_t sa_mask;

    BUG_ON(h->fd == -1,"device not open");
    size = h->fmt.bytesperline * h->fmt.height;
    buf = ng_malloc_video_buf(NULL,&h->fmt);

    alarm(1);
    sigfillset(&sa_mask);
    sigdelset(&sa_mask,SIGUSR1);
    sigdelset(&sa_mask,SIGALRM);
    sigsuspend(&sa_mask);
    alarm(0);

    memcpy(buf->data,h->map,size);
    buf->info.ts = ng_get_timestamp() - h->start;
    return buf;
}

static struct ng_video_buf* bsd_getimage(void *handle)
{
    struct bsd_handle *h = handle;
    struct ng_video_buf *buf;
    int size;

    BUG_ON(h->fd == -1,"device not open");
    set_overlay(h,0);
    set_capture(h,1);

    size = h->fmt.bytesperline * h->fmt.height;
    buf = ng_malloc_video_buf(NULL,&h->fmt);
    xioctl(h->fd, METEORCAPTUR, &single);
    memcpy(buf->data,h->map,size);

    set_capture(h,0);
    set_overlay(h,h->ov_enabled);

    return buf;
}

/* ---------------------------------------------------------------------- */

static void __init plugin_init(void)
{
    ng_vid_driver_register(NG_PLUGIN_MAGIC,__FILE__,&bsd_driver);
}




See more files for this project here

aMSN

A very nice MSN compatible messenger application, aMSN Messenger is a multiplatform MSN messenger clone. Works pretty much like its Windows based counterpart. Perfect for keeping in touch with those friends who have not yet seen the light. Works on linux

Project homepage: http://sourceforge.net/projects/amsn
Programming language(s): C,C++,PHP,Tcl,XML
License: other

  Makefile
  Rules.mk
  conv-mjpeg.c
  drv0-bsd.c
  drv0-v4l2-old.c
  drv0-v4l2.c
  drv1-v4l.c
  sn9c10x.c