diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
commit | 5c72acfc65bcea784244f6c8412b6c6c22bcd05d (patch) | |
tree | b5c60b347b82109d8105b4ac1e4b2e590d6dd263 |
Initial revisionXORG-STABLE
-rw-r--r-- | README | 37 | ||||
-rw-r--r-- | man/v4l.man | 39 | ||||
-rw-r--r-- | src/v4l.c | 1023 | ||||
-rw-r--r-- | src/videodev.h | 255 |
4 files changed, 1354 insertions, 0 deletions
@@ -0,0 +1,37 @@ + + Video 4 Linux adaptor driver for XFree86 v4.0 + + Developed by Gerd Knorr <kraxel@goldbach.in-berlin.de> and + David Woodhouse <David.Woodhouse@mvhi.com> + +---------------------------------------------------------------------------- + + This chipset driver does not provide a graphics adaptor driver, but instead + registers a number of generic Xv adaptors which can be used with any graphics + chipset driver. + + In order to use v4l adaptors with your favourite graphics driver, the + graphics driver must do two things: + + 1. Correctly set pScrn->memPhysBase and pScrn->fbOffset for the screens that + it provides, to the physical address of the frame buffer memory, and + the offset within that memory that the current mode starts, + respectively. + + 2. Use the xf86XVListGenericAdaptors() routine to list all available Xv + adaptors which are usable with any target device, and initialise + them on its screens with xf86XVScreenInit() as follows... + + { + XF86VideoAdaptorPtr *ptr; + + int xvexts = xf86XVListGenericAdaptors(&ptr); + + if (xvexts) { + xf86XVScreenInit(pScreen, ptr, xvexts); + } + } + + + +$XFree86: xc/programs/Xserver/hw/xfree86/drivers/v4l/README,v 1.2 2001/05/07 21:59:07 tsi Exp $ diff --git a/man/v4l.man b/man/v4l.man new file mode 100644 index 0000000..5337112 --- /dev/null +++ b/man/v4l.man @@ -0,0 +1,39 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/v4l/v4l.man,v 1.3 2001/05/29 22:24:06 dawes Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH V4L __drivermansuffix__ __vendorversion__ +.SH NAME +v4l \- video4linux driver +.SH SYNOPSIS +.nf +.B "Section \*qModule\*q" +\ \ ... +.B " Load \*qv4l\*q" +.B EndSection +.fi +.SH DESCRIPTION +.B v4l +is an XFree86 driver for video4linux cards. It provides a Xvideo +extention port for video overlay. Just add the driver to the module +list within the module section of your XF86Config file if you want +to use it. There are no config options. +.P +Note that the the extmod module is also required for the Xvideo +support (and lots of other extentions too). +.SH SUPPORTED HARDWARE +The +.B v4l +driver works with every piece of hardware which is supported by a +video4linux (kernel-) device driver and is able to handle video +overlay. +.P +bt848/bt878-based TV cards are the most popular hardware these +days. +.SH CONFIGURATION DETAILS +Please refer to XF86Config(__filemansuffix__) for general configuration +details. This section only covers configuration details specific to this +driver. +.SH "SEE ALSO" +XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__) +.SH AUTHORS +Authors include: Gerd Knorr <kraxel@bytesex.org> diff --git a/src/v4l.c b/src/v4l.c new file mode 100644 index 0000000..156d63c --- /dev/null +++ b/src/v4l.c @@ -0,0 +1,1023 @@ +/* + * video4linux Xv Driver + * based on Michael Schimek's permedia 2 driver. + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/v4l/v4l.c,v 1.30 2002/05/14 20:19:53 alanh Exp $ */ + +#include "videodev.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Pci.h" +#include "xf86PciInfo.h" +#include "xf86fbman.h" +#include "xf86xv.h" +#include "Xv.h" +#include "miscstruct.h" +#include "dgaproc.h" +#include "xf86str.h" + +#include <asm/ioctl.h> /* _IORW(xxx) #defines are here */ + +#if 0 +# define DEBUG(x) (x) +#else +# define DEBUG(x) +#endif + +static void V4LIdentify(int flags); +static Bool V4LProbe(DriverPtr drv, int flags); +static const OptionInfoRec * V4LAvailableOptions(int chipid, int busid); + +DriverRec V4L = { + 40000, + "v4l", + V4LIdentify, /* Identify*/ + V4LProbe, /* Probe */ + V4LAvailableOptions, + NULL, + 0 +}; + + +#ifdef XFree86LOADER + +static MODULESETUPPROTO(v4lSetup); + +static XF86ModuleVersionInfo v4lVersRec = +{ + "v4l", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + 0, 0, 1, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0,0,0,0} +}; + +XF86ModuleData v4lModuleData = { &v4lVersRec, v4lSetup, NULL }; + +static pointer +v4lSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + const char *osname; + static Bool setupDone = FALSE; + + if (setupDone) { + if (errmaj) + *errmaj = LDR_ONCEONLY; + return NULL; + } + + setupDone = TRUE; + + /* Check that we're being loaded on a Linux system */ + LoaderGetOS(&osname, NULL, NULL, NULL); + if (!osname || strcmp(osname, "linux") != 0) { + if (errmaj) + *errmaj = LDR_BADOS; + if (errmin) + *errmin = 0; + return NULL; + } else { + /* OK */ + + xf86AddDriver (&V4L, module, 0); + + return (pointer)1; + } +} + +#else + +#include <fcntl.h> +#include <sys/ioctl.h> + +#endif + +#define VIDEO_OFF 0 /* really off */ +#define VIDEO_RGB 1 /* rgb overlay (directly to fb) */ +#define VIDEO_YUV 2 /* yuv overlay (to offscreen memory + hw scaling) */ +#define VIDEO_RECLIP 3 /* temporarly off, window clipping changes */ + +typedef struct _PortPrivRec { + ScrnInfoPtr pScrn; + FBAreaPtr pFBArea[2]; + int VideoOn; + Bool StreamOn; + + /* file handle */ + int nr; + struct video_capability cap; + + /* RGB overlay */ + struct video_buffer rgb_fbuf; + struct video_window rgb_win; + int rgbpalette; + int rgbdepth; + + /* attributes */ + struct video_picture pict; + struct video_audio audio; + + XF86VideoEncodingPtr enc; + int *input; + int *norm; + int nenc,cenc; + + /* yuv to offscreen */ + XF86OffscreenImagePtr format; /* list */ + int nformat; /* # if list entries */ + XF86OffscreenImagePtr myfmt; /* which one is YUY2 (packed) */ + int yuv_format; + + int yuv_width,yuv_height; + XF86SurfacePtr surface; + struct video_buffer yuv_fbuf; + struct video_window yuv_win; +} PortPrivRec, *PortPrivPtr; + +#define XV_ENCODING "XV_ENCODING" +#define XV_BRIGHTNESS "XV_BRIGHTNESS" +#define XV_CONTRAST "XV_CONTRAST" +#define XV_SATURATION "XV_SATURATION" +#define XV_HUE "XV_HUE" + +#define XV_FREQ "XV_FREQ" +#define XV_MUTE "XV_MUTE" +#define XV_VOLUME "XV_VOLUME" + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvEncoding, xvBrightness, xvContrast, xvSaturation, xvHue; +static Atom xvFreq, xvMute, xvVolume; + +static XF86VideoFormatRec +InputVideoFormats[] = { + { 15, TrueColor }, + { 16, TrueColor }, + { 24, TrueColor }, + { 32, TrueColor }, +}; + +#define V4L_ATTR (sizeof(Attributes) / sizeof(XF86AttributeRec)) + +static const XF86AttributeRec Attributes[] = { + {XvSettable | XvGettable, -1000, 1000, XV_ENCODING}, + {XvSettable | XvGettable, -1000, 1000, XV_BRIGHTNESS}, + {XvSettable | XvGettable, -1000, 1000, XV_CONTRAST}, + {XvSettable | XvGettable, -1000, 1000, XV_SATURATION}, + {XvSettable | XvGettable, -1000, 1000, XV_HUE}, +}; +static const XF86AttributeRec VolumeAttr = + {XvSettable | XvGettable, -1000, 1000, XV_VOLUME}; +static const XF86AttributeRec MuteAttr = + {XvSettable | XvGettable, 0, 1, XV_MUTE}; +static const XF86AttributeRec FreqAttr = + {XvSettable | XvGettable, 0, 16*1000, XV_FREQ}; + + +#define MAX_V4L_DEVICES 4 +#define V4L_FD (v4l_devices[pPPriv->nr].fd) +#define V4L_REF (v4l_devices[pPPriv->nr].useCount) +#define V4L_NAME (v4l_devices[pPPriv->nr].devName) + +static struct V4L_DEVICE { + int fd; + int useCount; + char devName[16]; +} v4l_devices[MAX_V4L_DEVICES] = { + { -1 }, + { -1 }, + { -1 }, + { -1 }, +}; + +/* ---------------------------------------------------------------------- */ +/* forward decl */ + +static void V4lQueryBestSize(ScrnInfoPtr pScrn, Bool motion, + short vid_w, short vid_h, short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, pointer data); + +/* ---------------------------------------------------------------------- */ + +static int V4lOpenDevice(PortPrivPtr pPPriv, ScrnInfoPtr pScrn) +{ + static int first = 1; + + if (-1 == V4L_FD) { + V4L_FD = open(V4L_NAME, O_RDWR, 0); + + pPPriv->rgb_fbuf.width = pScrn->virtualX; + pPPriv->rgb_fbuf.height = pScrn->virtualY; + pPPriv->rgb_fbuf.depth = pScrn->bitsPerPixel; + pPPriv->rgb_fbuf.bytesperline = pScrn->displayWidth * ((pScrn->bitsPerPixel + 7)/8); + pPPriv->rgb_fbuf.base = (pointer)(pScrn->memPhysBase + pScrn->fbOffset); + if (first) { + first = 0; + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, + "v4l: memPhysBase=%p\n", pScrn->memPhysBase); + } + + switch (pScrn->bitsPerPixel) { + case 16: + if (pScrn->weight.green == 5) { + pPPriv->rgbpalette = VIDEO_PALETTE_RGB555; + pPPriv->rgbdepth = 16; + } else { + pPPriv->rgbpalette = VIDEO_PALETTE_RGB565; + pPPriv->rgbdepth = 16; + } + break; + case 24: + pPPriv->rgbpalette = VIDEO_PALETTE_RGB24; + pPPriv->rgbdepth = 24; + break; + case 32: + pPPriv->rgbpalette = VIDEO_PALETTE_RGB32; + pPPriv->rgbdepth = 32; + break; + } + } + + if (-1 == V4L_FD) + return errno; + + V4L_REF++; + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, + "Xv/open: refcount=%d\n",V4L_REF)); + + return 0; +} + +static void V4lCloseDevice(PortPrivPtr pPPriv, ScrnInfoPtr pScrn) +{ + V4L_REF--; + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, + "Xv/close: refcount=%d\n",V4L_REF)); + if (0 == V4L_REF && -1 != V4L_FD) { + close(V4L_FD); + V4L_FD = -1; + } +} + +static int +V4lPutVideo(ScrnInfoPtr pScrn, + short vid_x, short vid_y, short drw_x, short drw_y, + short vid_w, short vid_h, short drw_w, short drw_h, + RegionPtr clipBoxes, pointer data) +{ + PortPrivPtr pPPriv = (PortPrivPtr) data; + struct video_clip *clip; + BoxPtr pBox; + RegionRec newReg; + BoxRec newBox; + unsigned int i,dx,dy,dw,dh; + int width,height; + int one=1; + + /* Open a file handle to the device */ + if (VIDEO_OFF == pPPriv->VideoOn) { + if (V4lOpenDevice(pPPriv, pScrn)) + return Success; + } + + if (0 != pPPriv->yuv_format) { + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Xv/PV yuv\n")); + width = pPPriv->enc[pPPriv->cenc].width; + height = pPPriv->enc[pPPriv->cenc].height/2; /* no interlace */ + if (drw_w < width) + width = drw_w; + if (drw_h < height) + height = drw_h; + if ((height != pPPriv->yuv_height) || (width != pPPriv->yuv_width)) { + /* new size -- free old surface */ + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, " surface resize\n")); + if (pPPriv->surface) { + pPPriv->VideoOn = VIDEO_OFF; + pPPriv->myfmt->stop(pPPriv->surface); + pPPriv->myfmt->free_surface(pPPriv->surface); + xfree(pPPriv->surface); + pPPriv->surface = NULL; + } + pPPriv->yuv_width = width; + pPPriv->yuv_height = height; + } + if (!pPPriv->surface) { + /* allocate + setup offscreen surface */ + if (NULL == (pPPriv->surface = xalloc(sizeof(XF86SurfaceRec)))) + return FALSE; + if (Success != pPPriv->myfmt->alloc_surface + (pScrn,pPPriv->myfmt->image->id, + pPPriv->yuv_width,pPPriv->yuv_height,pPPriv->surface)) { + xfree(pPPriv->surface); + pPPriv->surface = NULL; + goto fallback_to_rgb; + } + pPPriv->yuv_fbuf.width = pPPriv->surface->width; + pPPriv->yuv_fbuf.height = pPPriv->surface->height; + pPPriv->yuv_fbuf.depth = 16; + pPPriv->yuv_fbuf.bytesperline = pPPriv->surface->pitches[0]; + pPPriv->yuv_fbuf.base = + (pointer)(pScrn->memPhysBase + pPPriv->surface->offsets[0]); + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, " surface: %p+%d = %p, %dx%d, pitch %d\n", + pScrn->memPhysBase,pPPriv->surface->offsets[0], + pScrn->memPhysBase+pPPriv->surface->offsets[0], + pPPriv->surface->width,pPPriv->surface->height, + pPPriv->surface->pitches[0])); + pPPriv->yuv_win.width = pPPriv->surface->width; + pPPriv->yuv_win.height = pPPriv->surface->height; + } + + /* program driver */ + if (-1 == ioctl(V4L_FD,VIDIOCSFBUF,&(pPPriv->yuv_fbuf))) + perror("ioctl VIDIOCSFBUF"); + if (-1 == ioctl(V4L_FD,VIDIOCGPICT,&pPPriv->pict)) + perror("ioctl VIDIOCGPICT"); + pPPriv->pict.palette = pPPriv->yuv_format; + pPPriv->pict.depth = 16; + if (-1 == ioctl(V4L_FD,VIDIOCSPICT,&pPPriv->pict)) + perror("ioctl VIDIOCSPICT"); + if (-1 == ioctl(V4L_FD,VIDIOCSWIN,&(pPPriv->yuv_win))) + perror("ioctl VIDIOCSWIN"); + if (-1 == ioctl(V4L_FD, VIDIOCCAPTURE, &one)) + perror("ioctl VIDIOCCAPTURE(1)"); + + if (0 == (pPPriv->myfmt->flags & VIDEO_INVERT_CLIPLIST)) { + /* invert cliplist */ + newBox.x1 = drw_x; + newBox.y1 = drw_y; + newBox.x2 = drw_x + drw_w; + newBox.y2 = drw_y + drw_h; + + if (pPPriv->myfmt->flags & VIDEO_CLIP_TO_VIEWPORT) { + /* trim to the viewport */ + if(newBox.x1 < pScrn->frameX0) + newBox.x1 = pScrn->frameX0; + if(newBox.x2 > pScrn->frameX1) + newBox.x2 = pScrn->frameX1; + + if(newBox.y1 < pScrn->frameY0) + newBox.y1 = pScrn->frameY0; + if(newBox.y2 > pScrn->frameY1) + newBox.y2 = pScrn->frameY1; + } + + REGION_INIT(pScrn->pScreen, &newReg, &newBox, 1); + REGION_SUBTRACT(pScrn->pScreen, &newReg, &newReg, clipBoxes); + clipBoxes = &newReg; + } + + /* start overlay */ + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, + "over: - %d,%d -> %d,%d (%dx%d) (yuv=%dx%d)\n", + drw_x, drw_y, + drw_x+drw_w, drw_y+drw_h, + drw_w, drw_h, + pPPriv->surface->width,pPPriv->surface->height)); + pPPriv->myfmt->display(pPPriv->surface, + 0, 0, drw_x, drw_y, + pPPriv->surface->width, + pPPriv->surface->height, + drw_w, drw_h, + clipBoxes); + if (0 == (pPPriv->myfmt->flags & VIDEO_INVERT_CLIPLIST)) { + REGION_UNINIT(pScrn->pScreen, &newReg); + } + pPPriv->VideoOn = VIDEO_YUV; + return Success; + } + + fallback_to_rgb: + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Xv/PV rgb\n")); + /* FIXME: vid-* is ignored for now, not supported by v4l */ + + dw = (drw_w < pPPriv->enc[pPPriv->cenc].width) ? + drw_w : pPPriv->enc[pPPriv->cenc].width; + dh = (drw_h < pPPriv->enc[pPPriv->cenc].height) ? + drw_h : pPPriv->enc[pPPriv->cenc].height; + /* if the window is too big, center the video */ + dx = drw_x + (drw_w - dw)/2; + dy = drw_y + (drw_h - dh)/2; + /* bttv prefeares aligned addresses */ + dx &= ~3; + if (dx < drw_x) dx += 4; + if (dx+dw > drw_x+drw_w) dw -= 4; + + /* window */ + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, " win: %dx%d+%d+%d\n", + drw_w,drw_h,drw_x,drw_y)); + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, " use: %dx%d+%d+%d\n", + dw,dh,dx,dy)); + pPPriv->rgb_win.x = dx; + pPPriv->rgb_win.y = dy; + pPPriv->rgb_win.width = dw; + pPPriv->rgb_win.height = dh; + pPPriv->rgb_win.flags = 0; + + /* clipping */ + if (pPPriv->rgb_win.clips) { + xfree(pPPriv->rgb_win.clips); + pPPriv->rgb_win.clips = NULL; + } + pPPriv->rgb_win.clipcount = REGION_NUM_RECTS(clipBoxes); + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2," clip: have #%d\n", + pPPriv->rgb_win.clipcount)); + if (0 != pPPriv->rgb_win.clipcount) { + pPPriv->rgb_win.clips = xalloc(pPPriv->rgb_win.clipcount*sizeof(struct video_clip)); + if (NULL != pPPriv->rgb_win.clips) { + memset(pPPriv->rgb_win.clips,0,pPPriv->rgb_win.clipcount*sizeof(struct video_clip)); + pBox = REGION_RECTS(clipBoxes); + clip = pPPriv->rgb_win.clips; + for (i = 0; i < REGION_NUM_RECTS(clipBoxes); i++, pBox++, clip++) { + clip->x = pBox->x1 - dx; + clip->y = pBox->y1 - dy; + clip->width = pBox->x2 - pBox->x1; + clip->height = pBox->y2 - pBox->y1; + } + } + } + + /* start */ + if (-1 == ioctl(V4L_FD,VIDIOCSFBUF,&(pPPriv->rgb_fbuf))) + perror("ioctl VIDIOCSFBUF"); + if (-1 == ioctl(V4L_FD,VIDIOCGPICT,&pPPriv->pict)) + perror("ioctl VIDIOCGPICT"); + pPPriv->pict.palette = pPPriv->rgbpalette; + pPPriv->pict.depth = pPPriv->rgbdepth; + if (-1 == ioctl(V4L_FD,VIDIOCSPICT,&pPPriv->pict)) + perror("ioctl VIDIOCSPICT"); + if (-1 == ioctl(V4L_FD,VIDIOCSWIN,&(pPPriv->rgb_win))) + perror("ioctl VIDIOCSWIN"); + if (-1 == ioctl(V4L_FD, VIDIOCCAPTURE, &one)) + perror("ioctl VIDIOCCAPTURE(1)"); + pPPriv->VideoOn = VIDEO_RGB; + + return Success; +} + +static int +V4lPutStill(ScrnInfoPtr pScrn, + short vid_x, short vid_y, short drw_x, short drw_y, + short vid_w, short vid_h, short drw_w, short drw_h, + RegionPtr clipBoxes, pointer data) +{ +#if 0 + PortPrivPtr pPPriv = (PortPrivPtr) data; +#endif + + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Xv/PS\n")); + + /* FIXME */ + return Success; +} + +static void +V4lStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) +{ + PortPrivPtr pPPriv = (PortPrivPtr) data; + int zero=0; + + if (VIDEO_OFF == pPPriv->VideoOn) { + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, + "Xv/StopVideo called with video already off\n")); + return; + } + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Xv/StopVideo shutdown=%d\n",shutdown)); + + if (!shutdown) { + /* just reclipping, we have to stop DMA transfers to the visible screen */ + if (VIDEO_RGB == pPPriv->VideoOn) { + if (-1 == ioctl(V4L_FD, VIDIOCCAPTURE, &zero)) + perror("ioctl VIDIOCCAPTURE(0)"); + pPPriv->VideoOn = VIDEO_RECLIP; + } + } else { + /* video stop - turn off and free everything */ + if (VIDEO_YUV == pPPriv->VideoOn) { + pPPriv->myfmt->stop(pPPriv->surface); + pPPriv->myfmt->free_surface(pPPriv->surface); + xfree(pPPriv->surface); + pPPriv->surface = NULL; + } + if (-1 == ioctl(V4L_FD, VIDIOCCAPTURE, &zero)) + perror("ioctl VIDIOCCAPTURE(0)"); + + V4lCloseDevice(pPPriv,pScrn); + pPPriv->VideoOn = VIDEO_OFF; + } +} + +/* v4l uses range 0 - 65535; Xv uses -1000 - 1000 */ +static int +v4l_to_xv(int val) { + val = val * 2000 / 65536 - 1000; + if (val < -1000) val = -1000; + if (val > 1000) val = 1000; + return val; +} +static int +xv_to_v4l(int val) { + val = val * 65536 / 2000 + 32768; + if (val < -0) val = 0; + if (val > 65535) val = 65535; + return val; +} + +static int +V4lSetPortAttribute(ScrnInfoPtr pScrn, + Atom attribute, INT32 value, pointer data) +{ + PortPrivPtr pPPriv = (PortPrivPtr) data; + struct video_channel chan; + int ret = Success; + + if (V4lOpenDevice(pPPriv, pScrn)) + return Success; + + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Xv/SPA %d, %d\n", + attribute, value)); + + if (-1 == V4L_FD) { + ret = Success; + } else if (attribute == xvEncoding) { + if (value >= 0 && value < pPPriv->nenc) { + pPPriv->cenc = value; + chan.channel = pPPriv->input[value]; + chan.norm = pPPriv->norm[value]; + if (-1 == ioctl(V4L_FD,VIDIOCSCHAN,&chan)) + perror("ioctl VIDIOCSCHAN"); + } else { + ret = BadValue; + } + } else if (attribute == xvBrightness || + attribute == xvContrast || + attribute == xvSaturation || + attribute == xvHue) { + ioctl(V4L_FD,VIDIOCGPICT,&pPPriv->pict); + if (attribute == xvBrightness) pPPriv->pict.brightness = xv_to_v4l(value); + if (attribute == xvContrast) pPPriv->pict.contrast = xv_to_v4l(value); + if (attribute == xvSaturation) pPPriv->pict.colour = xv_to_v4l(value); + if (attribute == xvHue) pPPriv->pict.hue = xv_to_v4l(value); + if (-1 == ioctl(V4L_FD,VIDIOCSPICT,&pPPriv->pict)) + perror("ioctl VIDIOCSPICT"); + } else if (attribute == xvMute || + attribute == xvVolume) { + ioctl(V4L_FD,VIDIOCGAUDIO,&pPPriv->audio); + if (attribute == xvMute) { + if (value) + pPPriv->audio.flags |= VIDEO_AUDIO_MUTE; + else + pPPriv->audio.flags &= ~VIDEO_AUDIO_MUTE; + } else if (attribute == xvVolume) { + if (pPPriv->audio.flags & VIDEO_AUDIO_VOLUME) + pPPriv->audio.volume = xv_to_v4l(value); + } else { + ret = BadValue; + } + if (ret != BadValue) + if (-1 == ioctl(V4L_FD,VIDIOCSAUDIO,&pPPriv->audio)) + perror("ioctl VIDIOCSAUDIO"); + } else if (attribute == xvFreq) { + if (-1 == ioctl(V4L_FD,VIDIOCSFREQ,&value)) + perror("ioctl VIDIOCSFREQ"); + } else if (0 != pPPriv->yuv_format && + pPPriv->myfmt->setAttribute) { + /* not mine -> pass to yuv scaler driver */ + ret = pPPriv->myfmt->setAttribute(pScrn, attribute, value); + } else { + ret = BadValue; + } + + V4lCloseDevice(pPPriv,pScrn); + return ret; +} + +static int +V4lGetPortAttribute(ScrnInfoPtr pScrn, + Atom attribute, INT32 *value, pointer data) +{ + PortPrivPtr pPPriv = (PortPrivPtr) data; + int ret = Success; + + if (V4lOpenDevice(pPPriv, pScrn)) + return Success; + + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Xv/GPA %d\n", + attribute)); + + if (-1 == V4L_FD) { + ret = Success; + } else if (attribute == xvEncoding) { + *value = pPPriv->cenc; + } else if (attribute == xvBrightness || + attribute == xvContrast || + attribute == xvSaturation || + attribute == xvHue) { + ioctl(V4L_FD,VIDIOCGPICT,&pPPriv->pict); + if (attribute == xvBrightness) *value = v4l_to_xv(pPPriv->pict.brightness); + if (attribute == xvContrast) *value = v4l_to_xv(pPPriv->pict.contrast); + if (attribute == xvSaturation) *value = v4l_to_xv(pPPriv->pict.colour); + if (attribute == xvHue) *value = v4l_to_xv(pPPriv->pict.hue); + } else if (attribute == xvMute || + attribute == xvVolume) { + ioctl(V4L_FD,VIDIOCGAUDIO,&pPPriv->audio); + if (attribute == xvMute) { + *value = (pPPriv->audio.flags & VIDEO_AUDIO_MUTE) ? 1 : 0; + } else if (attribute == xvVolume) { + if (pPPriv->audio.flags & VIDEO_AUDIO_VOLUME) + *value = v4l_to_xv(pPPriv->audio.volume); + } else { + ret = BadValue; + } + } else if (attribute == xvFreq) { + ioctl(V4L_FD,VIDIOCGFREQ,value); + } else if (0 != pPPriv->yuv_format && + pPPriv->myfmt->getAttribute) { + /* not mine -> pass to yuv scaler driver */ + ret = pPPriv->myfmt->getAttribute(pScrn, attribute, value); + } else { + ret = BadValue; + } + + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Xv/GPA %d, %d\n", + attribute, *value)); + + V4lCloseDevice(pPPriv,pScrn); + return ret; +} + +static void +V4lQueryBestSize(ScrnInfoPtr pScrn, Bool motion, + short vid_w, short vid_h, short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, pointer data) +{ + PortPrivPtr pPPriv = (PortPrivPtr) data; + int maxx = pPPriv->enc[pPPriv->cenc].width; + int maxy = pPPriv->enc[pPPriv->cenc].height; + + if (0 != pPPriv->yuv_format) { + *p_w = pPPriv->myfmt->max_width; + *p_h = pPPriv->myfmt->max_height; + } else { + *p_w = (drw_w < maxx) ? drw_w : maxx; + *p_h = (drw_h < maxy) ? drw_h : maxy; + } + + DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Xv/BS %d %dx%d %dx%d\n", + pPPriv->cenc,drw_w,drw_h,*p_w,*p_h)); +} + +static const OptionInfoRec * +V4LAvailableOptions(int chipid, int busid) +{ + return NULL; +} + +static void +V4LIdentify(int flags) +{ + xf86Msg(X_INFO, "v4l driver for Video4Linux\n"); +} + +static char* +fixname(char *str) +{ + int s,d; + for (s=0, d=0;; s++) { + if (str[s] == '-') + continue; + str[d++] = tolower(str[s]); + if (0 == str[s]) + break; + } + return str; +} + +static int +v4l_add_enc(XF86VideoEncodingPtr enc, int i, + char *norm, char *input, int width, int height, int n, int d) +{ + enc[i].id = i; + enc[i].name = xalloc(strlen(norm)+strlen(input)+2); + if (NULL == enc[i].name) + return -1; + enc[i].width = width; + enc[i].height = height; + enc[i].rate.numerator = n; + enc[i].rate.denominator = d; + sprintf(enc[i].name,"%s-%s",norm,fixname(input)); + return 0; +} + +static void +V4LBuildEncodings(PortPrivPtr p, int fd, int channels) +{ + static struct video_channel channel; + int i,entries,have_bttv; + +#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) + have_bttv = 0; + if (-1 != ioctl(fd,BTTV_VERSION,NULL)) + have_bttv = 1; + + entries = (have_bttv ? 7 : 3) * channels; + p->enc = xalloc(sizeof(XF86VideoEncodingRec) * entries); + if (NULL == p->enc) + goto fail; + memset(p->enc,0,sizeof(XF86VideoEncodingRec) * entries); + p->norm = xalloc(sizeof(int) * entries); + if (NULL == p->norm) + goto fail; + memset(p->norm,0,sizeof(int) * entries); + p->input = xalloc(sizeof(int) * entries); + if (NULL == p->input) + goto fail; + memset(p->input,0,sizeof(int) * entries); + + p->nenc = 0; + for (i = 0; i < channels; i++) { + channel.channel = i; + if (-1 == ioctl(fd,VIDIOCGCHAN,&channel)) { + perror("ioctl VIDIOCGCHAN"); + continue; + } + + v4l_add_enc(p->enc, p->nenc,"pal", channel.name, 768,576, 1,50); + p->norm[p->nenc] = VIDEO_MODE_PAL; + p->input[p->nenc] = i; + p->nenc++; + + v4l_add_enc(p->enc,p->nenc,"ntsc", channel.name, 640,480, 1001,60000); + p->norm[p->nenc] = VIDEO_MODE_NTSC; + p->input[p->nenc] = i; + p->nenc++; + + v4l_add_enc(p->enc,p->nenc,"secam",channel.name, 768,576, 1,50); + p->norm[p->nenc] = VIDEO_MODE_SECAM; + p->input[p->nenc] = i; + p->nenc++; + + if (have_bttv) { + /* workaround for a v4l design flaw: The v4l API knows just pal, + ntsc and secam. But there are a few more norms (pal versions + with a different timings used in south america for example). + The bttv driver can handle these too. */ + if (0 != v4l_add_enc(p->enc,p->nenc,"palnc",channel.name, + 640, 576, 1,50)) + goto fail; + p->norm[p->nenc] = 3; + p->input[p->nenc] = i; + p->nenc++; + + if (0 != v4l_add_enc(p->enc,p->nenc,"palm",channel.name, + 640, 576, 1,50)) + goto fail; + p->norm[p->nenc] = 4; + p->input[p->nenc] = i; + p->nenc++; + + if (0 != v4l_add_enc(p->enc, p->nenc,"paln", channel.name, + 768,576, 1,50)) + goto fail; + p->norm[p->nenc] = 5; + p->input[p->nenc] = i; + p->nenc++; + + if (0 != v4l_add_enc(p->enc,p->nenc,"ntscjp", channel.name, + 640,480, 1001,60000)) + goto fail; + p->norm[p->nenc] = 6; + p->input[p->nenc] = i; + p->nenc++; + } + } + return; + + fail: + if (p->input) + xfree(p->input); + p->input = NULL; + if (p->norm) + xfree(p->norm); + p->norm = NULL; + if (p->enc) + xfree(p->enc); + p->enc = NULL; + p->nenc = 0; +} + +/* add a attribute a list */ +static void +v4l_add_attr(XF86AttributeRec **list, int *count, + const XF86AttributeRec *attr) +{ + XF86AttributeRec *oldlist = *list; + int i; + + for (i = 0; i < *count; i++) { + if (0 == strcmp((*list)[i].name,attr->name)) { + DEBUG(xf86Msg(X_INFO, "v4l: skip dup attr %s\n",attr->name)); + return; + } + } + + DEBUG(xf86Msg(X_INFO, "v4l: add attr %s\n",attr->name)); + *list = xalloc((*count + 1) * sizeof(XF86AttributeRec)); + if (NULL == *list) { + *count = 0; + return; + } + if (*count) + memcpy(*list, oldlist, *count * sizeof(XF86AttributeRec)); + memcpy(*list + *count, attr, sizeof(XF86AttributeRec)); + (*count)++; +} + +/* setup yuv overlay + hw scaling: look if we find some common video + format which both v4l driver and the X-Server can handle */ +static void v4l_check_yuv(ScrnInfoPtr pScrn, PortPrivPtr pPPriv, + char *dev, int fd) +{ + static const struct { + unsigned int v4l_palette; + unsigned int v4l_depth; + unsigned int xv_id; + unsigned int xv_format; + } yuvlist[] = { + { VIDEO_PALETTE_YUV422, 16, 0x32595559, XvPacked }, + { VIDEO_PALETTE_UYVY, 16, 0x59565955, XvPacked }, + { 0 /* end of list */ }, + }; + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + int fmt,i; + + pPPriv->format = xf86XVQueryOffscreenImages(pScreen,&pPPriv->nformat); + for (fmt = 0; yuvlist[fmt].v4l_palette != 0; fmt++) { + /* check v4l ... */ + ioctl(fd,VIDIOCGPICT,&pPPriv->pict); + pPPriv->pict.palette = yuvlist[fmt].v4l_palette; + pPPriv->pict.depth = yuvlist[fmt].v4l_depth; + if (-1 == ioctl(fd,VIDIOCSPICT,&pPPriv->pict)) + continue; + ioctl(fd,VIDIOCGPICT,&pPPriv->pict); + if (pPPriv->pict.palette != yuvlist[fmt].v4l_palette) + continue; + /* ... works, check available offscreen image formats now ... */ + for (i = 0; i < pPPriv->nformat; i++) { + if (pPPriv->format[i].image->id == yuvlist[fmt].xv_id && + pPPriv->format[i].image->format == yuvlist[fmt].xv_format) { + /* ... match found, good. */ + pPPriv->yuv_format = yuvlist[fmt].v4l_palette; + pPPriv->myfmt = pPPriv->format+i; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "v4l[%s]: using hw video scaling [%4.4s].\n", + dev,(char*)&(pPPriv->format[i].image->id)); + return; + } + } + } +} + +static int +V4LInit(ScrnInfoPtr pScrn, XF86VideoAdaptorPtr **adaptors) +{ + PortPrivPtr pPPriv; + DevUnion *Private; + XF86VideoAdaptorPtr *VAR = NULL; + char dev[18]; + int fd,i,j,d; + + DEBUG(xf86Msg(X_INFO, "v4l: init start\n")); + + for (i = 0, d = 0; d < MAX_V4L_DEVICES; d++) { + sprintf(dev, "/dev/video%d", d); + fd = open(dev, O_RDWR, 0); + if (fd == -1) { + sprintf(dev, "/dev/v4l/video%d", d); + fd = open(dev, O_RDWR, 0); + if (fd == -1) + break; + } + DEBUG(xf86Msg(X_INFO, "v4l: %s open ok\n",dev)); + + /* our private data */ + pPPriv = xalloc(sizeof(PortPrivRec)); + if (!pPPriv) + return FALSE; + memset(pPPriv,0,sizeof(PortPrivRec)); + pPPriv->nr = d; + + /* check device */ + if (-1 == ioctl(fd,VIDIOCGCAP,&pPPriv->cap) || + 0 == (pPPriv->cap.type & VID_TYPE_OVERLAY)) { + DEBUG(xf86Msg(X_INFO, "v4l: %s: no overlay support\n",dev)); + xfree(pPPriv); + close(fd); + continue; + } + strncpy(V4L_NAME, dev, 16); + V4LBuildEncodings(pPPriv,fd,pPPriv->cap.channels); + if (NULL == pPPriv->enc) + return FALSE; + v4l_check_yuv(pScrn,pPPriv,dev,fd); + + /* alloc VideoAdaptorRec */ + VAR = xrealloc(VAR,sizeof(XF86VideoAdaptorPtr)*(i+1)); + VAR[i] = xalloc(sizeof(XF86VideoAdaptorRec)); + if (!VAR[i]) + return FALSE; + memset(VAR[i],0,sizeof(XF86VideoAdaptorRec)); + + + /* build attribute list */ + for (j = 0; j < V4L_ATTR; j++) { + /* video attributes */ + v4l_add_attr(&VAR[i]->pAttributes, &VAR[i]->nAttributes, + &Attributes[j]); + } + if (0 == ioctl(fd,VIDIOCGAUDIO,&pPPriv->audio)) { + /* audio attributes */ + if (pPPriv->audio.flags & VIDEO_AUDIO_VOLUME) + v4l_add_attr(&VAR[i]->pAttributes, &VAR[i]->nAttributes, + &VolumeAttr); + if (pPPriv->audio.flags & VIDEO_AUDIO_MUTABLE) + v4l_add_attr(&VAR[i]->pAttributes, &VAR[i]->nAttributes, + &MuteAttr); + } + if (pPPriv->cap.type & VID_TYPE_TUNER) { + /* tuner attributes */ + v4l_add_attr(&VAR[i]->pAttributes, &VAR[i]->nAttributes, + &FreqAttr); + } + if (0 != pPPriv->yuv_format) { + /* pass throuth scaler attributes */ + for (j = 0; j < pPPriv->myfmt->num_attributes; j++) { + v4l_add_attr(&VAR[i]->pAttributes, &VAR[i]->nAttributes, + pPPriv->myfmt->attributes+j); + } + } + + + /* hook in private data */ + Private = xalloc(sizeof(DevUnion)); + if (!Private) + return FALSE; + memset(Private,0,sizeof(DevUnion)); + Private->ptr = (pointer)pPPriv; + VAR[i]->pPortPrivates = Private; + VAR[i]->nPorts = 1; + + /* init VideoAdaptorRec */ + VAR[i]->type = XvInputMask | XvWindowMask | XvVideoMask; + VAR[i]->name = "video4linux"; + VAR[i]->flags = VIDEO_INVERT_CLIPLIST; + + VAR[i]->PutVideo = V4lPutVideo; + VAR[i]->PutStill = V4lPutStill; + VAR[i]->StopVideo = V4lStopVideo; + VAR[i]->SetPortAttribute = V4lSetPortAttribute; + VAR[i]->GetPortAttribute = V4lGetPortAttribute; + VAR[i]->QueryBestSize = V4lQueryBestSize; + + VAR[i]->nEncodings = pPPriv->nenc; + VAR[i]->pEncodings = pPPriv->enc; + VAR[i]->nFormats = + sizeof(InputVideoFormats) / sizeof(InputVideoFormats[0]); + VAR[i]->pFormats = InputVideoFormats; + + if (fd != -1) + close(fd); + i++; + } + + xvEncoding = MAKE_ATOM(XV_ENCODING); + xvHue = MAKE_ATOM(XV_HUE); + xvSaturation = MAKE_ATOM(XV_SATURATION); + xvBrightness = MAKE_ATOM(XV_BRIGHTNESS); + xvContrast = MAKE_ATOM(XV_CONTRAST); + + xvFreq = MAKE_ATOM(XV_FREQ); + xvMute = MAKE_ATOM(XV_MUTE); + xvVolume = MAKE_ATOM(XV_VOLUME); + + DEBUG(xf86Msg(X_INFO, "v4l: init done, %d device(s) found\n",i)); + + *adaptors = VAR; + return i; +} + +static Bool +V4LProbe(DriverPtr drv, int flags) +{ + if (flags & PROBE_DETECT) + return TRUE; + + xf86XVRegisterGenericAdaptorDriver(V4LInit); + drv->refCount++; + return TRUE; +} diff --git a/src/videodev.h b/src/videodev.h new file mode 100644 index 0000000..77b592e --- /dev/null +++ b/src/videodev.h @@ -0,0 +1,255 @@ +#ifndef __LINUX_VIDEODEV_H +#define __LINUX_VIDEODEV_H + +/* Linux V4L API, Version 1 + * videodev.h from v4l driver in Linux 2.2.3 + * + * Used here with the explicit permission of the original author, Alan Cox. + * <alan@lxorguk.ukuu.org.uk> + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/v4l/videodev.h,v 1.8 2001/03/03 22:46:31 tsi Exp $ */ + +#include "Xmd.h" + +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ + +struct video_capability +{ + char name[32]; + int type; + int channels; /* Num channels */ + int audios; /* Num audio devices */ + int maxwidth; /* Supported width */ + int maxheight; /* And height */ + int minwidth; /* Supported width */ + int minheight; /* And height */ +}; + + +struct video_channel +{ + int channel; + char name[32]; + int tuners; + CARD32 flags; +#define VIDEO_VC_TUNER 1 /* Channel has a tuner */ +#define VIDEO_VC_AUDIO 2 /* Channel has audio */ + CARD16 type; +#define VIDEO_TYPE_TV 1 +#define VIDEO_TYPE_CAMERA 2 + CARD16 norm; /* Norm set by channel */ +}; + +struct video_tuner +{ + int tuner; + char name[32]; + unsigned long rangelow, rangehigh; /* Tuner range */ + CARD32 flags; +#define VIDEO_TUNER_PAL 1 +#define VIDEO_TUNER_NTSC 2 +#define VIDEO_TUNER_SECAM 4 +#define VIDEO_TUNER_LOW 8 /* Uses KHz not MHz */ +#define VIDEO_TUNER_NORM 16 /* Tuner can set norm */ +#define VIDEO_TUNER_STEREO_ON 128 /* Tuner is seeing stereo */ + CARD16 mode; /* PAL/NTSC/SECAM/OTHER */ +#define VIDEO_MODE_PAL 0 +#define VIDEO_MODE_NTSC 1 +#define VIDEO_MODE_SECAM 2 +#define VIDEO_MODE_AUTO 3 + CARD16 signal; /* Signal strength 16bit scale */ +}; + +struct video_picture +{ + CARD16 brightness; + CARD16 hue; + CARD16 colour; + CARD16 contrast; + CARD16 whiteness; /* Black and white only */ + CARD16 depth; /* Capture depth */ + CARD16 palette; /* Palette in use */ +#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */ +#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */ +#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */ +#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */ +#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */ +#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */ +#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */ +#define VIDEO_PALETTE_YUYV 8 +#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */ +#define VIDEO_PALETTE_YUV420 10 +#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */ +#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */ +#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */ +#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */ +#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */ +#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */ +#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */ +#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */ +}; + +struct video_audio +{ + int audio; /* Audio channel */ + CARD16 volume; /* If settable */ + CARD16 bass, treble; + CARD32 flags; +#define VIDEO_AUDIO_MUTE 1 +#define VIDEO_AUDIO_MUTABLE 2 +#define VIDEO_AUDIO_VOLUME 4 +#define VIDEO_AUDIO_BASS 8 +#define VIDEO_AUDIO_TREBLE 16 + char name[16]; +#define VIDEO_SOUND_MONO 1 +#define VIDEO_SOUND_STEREO 2 +#define VIDEO_SOUND_LANG1 4 +#define VIDEO_SOUND_LANG2 8 + CARD16 mode; + CARD16 balance; /* Stereo balance */ + CARD16 step; /* Step actual volume uses */ +}; + +struct video_clip +{ + INT32 x,y; + INT32 width, height; + struct video_clip *next; /* For user use/driver use only */ +}; + +struct video_window +{ + CARD32 x,y; /* Position of window */ + CARD32 width,height; /* Its size */ + CARD32 chromakey; + CARD32 flags; + struct video_clip *clips; /* Set only */ + int clipcount; +#define VIDEO_WINDOW_INTERLACE 1 +#define VIDEO_CLIP_BITMAP -1 +/* bitmap is 1024x625, a '1' bit represents a clipped pixel */ +#define VIDEO_CLIPMAP_SIZE (128 * 625) +}; + +struct video_capture +{ + CARD32 x,y; /* Offsets into image */ + CARD32 width, height; /* Area to capture */ + CARD16 decimation; /* Decimation divder */ + CARD16 flags; /* Flags for capture */ +#define VIDEO_CAPTURE_ODD 0 /* Temporal */ +#define VIDEO_CAPTURE_EVEN 1 +}; + +struct video_buffer +{ + void *base; + int height,width; + int depth; + int bytesperline; +}; + +struct video_mmap +{ + unsigned int frame; /* Frame (0 - n) for double buffer */ + int height,width; + unsigned int format; /* should be VIDEO_PALETTE_* */ +}; + +struct video_key +{ + CARD8 key[8]; + CARD32 flags; +}; + + +#define VIDEO_MAX_FRAME 32 + +struct video_mbuf +{ + int size; /* Total memory to map */ + int frames; /* Frames */ + int offsets[VIDEO_MAX_FRAME]; +}; + + +#define VIDEO_NO_UNIT (-1) + + +struct video_unit +{ + int video; /* Video minor */ + int vbi; /* VBI minor */ + int radio; /* Radio minor */ + int audio; /* Audio minor */ + int teletext; /* Teletext minor */ +}; + +#define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */ +#define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */ +#define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */ +#define VIDIOCGTUNER _IOWR('v',4,struct video_tuner) /* Get tuner abilities */ +#define VIDIOCSTUNER _IOW('v',5,struct video_tuner) /* Tune the tuner for the current channel */ +#define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */ +#define VIDIOCSPICT _IOW('v',7,struct video_picture) /* Set picture properties */ +#define VIDIOCCAPTURE _IOW('v',8,int) /* Start, end capture */ +#define VIDIOCGWIN _IOR('v',9, struct video_window) /* Set the video overlay window */ +#define VIDIOCSWIN _IOW('v',10, struct video_window) /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */ +#define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */ +#define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */ +#define VIDIOCKEY _IOR('v',13, struct video_key) /* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */ +#define VIDIOCGFREQ _IOR('v',14, unsigned long) /* Set tuner */ +#define VIDIOCSFREQ _IOW('v',15, unsigned long) /* Set tuner */ +#define VIDIOCGAUDIO _IOR('v',16, struct video_audio) /* Get audio info */ +#define VIDIOCSAUDIO _IOW('v',17, struct video_audio) /* Audio source, mute etc */ +#define VIDIOCSYNC _IOW('v',18, int) /* Sync with mmap grabbing */ +#define VIDIOCMCAPTURE _IOW('v',19, struct video_mmap) /* Grab frames */ +#define VIDIOCGMBUF _IOR('v', 20, struct video_mbuf) /* Memory map buffer info */ +#define VIDIOCGUNIT _IOR('v', 21, struct video_unit) /* Get attached units */ +#define VIDIOCGCAPTURE _IOR('v',22, struct video_capture) /* Get frame buffer */ +#define VIDIOCSCAPTURE _IOW('v',23, struct video_capture) /* Set frame buffer - root only */ + +#define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */ + + +#define VID_HARDWARE_BT848 1 +#define VID_HARDWARE_QCAM_BW 2 +#define VID_HARDWARE_PMS 3 +#define VID_HARDWARE_QCAM_C 4 +#define VID_HARDWARE_PSEUDO 5 +#define VID_HARDWARE_SAA5249 6 +#define VID_HARDWARE_AZTECH 7 +#define VID_HARDWARE_SF16MI 8 +#define VID_HARDWARE_RTRACK 9 +#define VID_HARDWARE_ZOLTRIX 10 +#define VID_HARDWARE_SAA7146 11 +#define VID_HARDWARE_VIDEUM 12 /* Reserved for Winnov videum */ +#define VID_HARDWARE_RTRACK2 13 +#define VID_HARDWARE_PERMEDIA2 14 /* Reserved for Permedia2 */ +#define VID_HARDWARE_RIVA128 15 /* Reserved for RIVA 128 */ +#define VID_HARDWARE_PLANB 16 /* PowerMac motherboard video-in */ +#define VID_HARDWARE_BROADWAY 17 /* Broadway project */ +#define VID_HARDWARE_GEMTEK 18 +#define VID_HARDWARE_TYPHOON 19 +#define VID_HARDWARE_VINO 20 /* Reserved for SGI Indy Vino */ + +/* + * Initialiser list + */ + +struct video_init +{ + char *name; + int (*init)(struct video_init *); +}; + +#endif |