From fa0e88bfe00baa648ab3b1184b56f7dc5536aa21 Mon Sep 17 00:00:00 2001 From: Gaetan Nadon Date: Sat, 19 Nov 2011 15:33:33 -0500 Subject: Move back ztv with geode driver Now we have a clean separation between CPP flags and C Flags Only the C Flags apply to both geode and ztv driver, however it is not worth doing a per target compilation. Should some flags become mutually exclusive and if we want to have both target in the same makefile, add the incompatible flag on the appropriate target, example: geode_drv_la_CFLAGS = $(AM_CFLAGS) -newCFlag and/or geode_drv_la_CPPFLAGS = $(AM_CPPFLAGS) -newCPPFlag Note that both AM_CFLAGS and AM_CPPFLAGS are picked-up by both geode and ztv driver target. Signed-off-by: Gaetan Nadon --- Makefile.am | 2 +- configure.ac | 1 - src/Makefile.am | 12 +- src/z4l.c | 1739 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ztv/Makefile.am | 12 - ztv/z4l.c | 1739 ------------------------------------------------------- 6 files changed, 1751 insertions(+), 1754 deletions(-) create mode 100644 src/z4l.c delete mode 100644 ztv/Makefile.am delete mode 100644 ztv/z4l.c diff --git a/Makefile.am b/Makefile.am index 31431a8..00c84b5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -SUBDIRS = src ztv +SUBDIRS = src MAINTAINERCLEANFILES = ChangeLog INSTALL EXTRA_DIST = autogen.sh diff --git a/configure.ac b/configure.ac index 26a3642..582eb46 100644 --- a/configure.ac +++ b/configure.ac @@ -144,5 +144,4 @@ AC_SUBST([DRIVER_NAME]) AC_OUTPUT([ Makefile src/Makefile - ztv/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index 5df0a32..1f3dfcb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,7 +37,7 @@ AM_CFLAGS = $(XORG_CFLAGS) $(CWARNFLAGS) $(M32_CFLAGS) geode_drv_la_LTLIBRARIES = geode_drv.la geode_drv_la_LDFLAGS = -module -avoid-version -geode_drv_ladir = @moduledir@/drivers +geode_drv_ladir = $(moduledir)/drivers geode_drv_la_SOURCES = \ cimarron.c \ @@ -142,3 +142,13 @@ EXTRA_DIST = \ \ gx_vga.c \ lx_vga.c + +if BUILD_ZTV + +ztv_drv_la_LTLIBRARIES = ztv_drv.la +ztv_drv_la_LDFLAGS = -module -avoid-version +ztv_drv_ladir = $(moduledir)/drivers + +ztv_drv_la_SOURCES = z4l.c + +endif BUILD_ZTV diff --git a/src/z4l.c b/src/z4l.c new file mode 100644 index 0000000..c6a7c58 --- /dev/null +++ b/src/z4l.c @@ -0,0 +1,1739 @@ +/* + * Copyright (c) 2006 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + +/* prototype Xv interface for lxv4l2 driver */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xf86.h" +#include +#include "xf86_OSproc.h" +#include "compiler.h" +#include "xf86xv.h" +#include "fourcc.h" + +#include + +#define __s64 __s_64 +typedef long long __s64; + +#define __u64 __u_64 +typedef unsigned long long __u64; + +#define __user +#include "linux/videodev2.h" + +typedef signed long long s64; +typedef unsigned long long u64; + +int debuglvl = 0; + +#define NONBLK_IO +#undef HAVE_SELECT + +#define DEBUG 1 +#ifdef DEBUG +#define DBLOG(n,s...) do { \ + if ( debuglvl >= (n) ) \ + xf86Msg(X_INFO, "z4l: " s); \ + } while(0) +#else +#define DBLOG(n,s...) do {} while(0) +#endif + +#define DEFAULT_COLORKEY 0x010203 +#define DEFAULT_KEYMODE 0 + +#define MAX_BUFFERS 4 +#define MAX_OVLY_WIDTH 2048 +#define MAX_OVLY_HEIGHT 2048 + +static char *z4l_dev_paths[] = { + "/dev/videox", NULL +}; + +#define ATTR_ENCODING "encoding" +#define ATTR_ENCODING_ID -1 +#define ATTR_KEYMODE "keymode" +#define ATTR_KEYMODE_ID -2 +#define ATTR_COLORKEY "colorkey" +#define ATTR_COLORKEY_ID -3 +#define ATTR_MAX_ID 3 + +#ifdef XvExtension + +static XF86VideoFormatRec Formats[] = { + {8, PseudoColor}, + {15, TrueColor}, + {16, TrueColor}, + {24, TrueColor} +}; + +#define NUM_FORMATS (sizeof(Formats)/sizeof(Formats[0])) + +#define FOURCC_Y800 0x30303859 +#define XVIMAGE_Y800 \ + { \ + FOURCC_Y800, \ + XvYUV, \ + LSBFirst, \ + {'Y','8','0','0', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 8, \ + XvPacked, \ + 1, \ + 0, 0, 0, 0, \ + 8, 0, 0, \ + 1, 0, 0, \ + 1, 0, 0, \ + {'Y','8','0','0', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +static XF86ImageRec pixfmts[] = { + XVIMAGE_UYVY, XVIMAGE_YUY2, + XVIMAGE_I420, XVIMAGE_YV12, + XVIMAGE_Y800, +}; + +#define NUM_PIXFMTS (sizeof(pixfmts)/sizeof(pixfmts[0])) + +typedef struct s_std_data +{ + int inp; + v4l2_std_id std; + unsigned int fmt; +} t_std_data; + +typedef struct s_ovly_bfrs +{ + void *start; + unsigned long offset; + size_t length; +} t_ovly_bfrs; + +typedef struct +{ + int fd; + int run; + int dir; + int nbfrs; + int bufno; + int bufsz; + int last; + int width, height; + int keymode, colorkey; + int src_is_set, src_x, src_y, src_w, src_h; + int drw_is_set, drw_x, drw_y, drw_w, drw_h; + unsigned int pixfmt; + char dev_path[32]; + t_ovly_bfrs bfrs[MAX_BUFFERS]; + XF86VideoAdaptorPtr adpt; + XF86VideoEncodingPtr enc; + RegionRec clips; + int attrIds[1]; +} Z4lPortPrivRec; + +static int z4l_x_offset = 0; +static int z4l_y_offset = 0; +static int Z4l_nAdaptors = 0; +static XF86VideoAdaptorPtr *Z4l_pAdaptors = NULL; + +static int +IoCtl(int fd, unsigned int fn, void *arg, int flag) +{ + int ret; + + errno = 0; + ret = ioctl(fd, fn, arg); + if (ret != 0 && flag != 0) + DBLOG(0, "ioctl(%08x)=%d\n", fn, ret); + return ret; +} + +static void +z4l_ovly_unmap(Z4lPortPrivRec * pPriv) +{ + int i, nbfrs; + + nbfrs = pPriv->nbfrs; + for (i = 0; i < nbfrs; ++i) { + if (pPriv->bfrs[i].start != NULL) { + munmap(pPriv->bfrs[i].start, pPriv->bfrs[i].length); + pPriv->bfrs[i].start = NULL; + } + } + pPriv->nbfrs = -1; + pPriv->bufsz = -1; + pPriv->last = -1; +} + +static void +z4l_ovly_map(Z4lPortPrivRec * pPriv, int dir) +{ + long offset, bsz; + int i, fd; + struct v4l2_buffer bfr; + struct v4l2_requestbuffers req; + int type = dir >= 0 ? + V4L2_BUF_TYPE_VIDEO_CAPTURE : V4L2_BUF_TYPE_VIDEO_OVERLAY; + if (pPriv->run > 0) { + DBLOG(1, "busy\n"); + return; + } + fd = pPriv->fd; + memset(&req, 0, sizeof(req)); + req.type = type; + req.memory = V4L2_MEMORY_MMAP; + req.count = MAX_BUFFERS; + if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) + goto xit; + pPriv->nbfrs = req.count; + if (pPriv->nbfrs <= 0) { + DBLOG(1, "no vidmem\n"); + return; + } + memset(&pPriv->bfrs, 0, sizeof(pPriv->bfrs)); + + for (i = 0; i < pPriv->nbfrs; ++i) { + memset(&bfr, 0, sizeof(bfr)); + bfr.type = type; + bfr.index = i; + if (ioctl(fd, VIDIOC_QUERYBUF, &bfr) < 0) + goto xit; + offset = bfr.m.offset; + pPriv->bfrs[i].offset = offset; + pPriv->bfrs[i].length = bfr.length; + bsz = offset + bfr.length; + if (pPriv->bufsz < bsz) + pPriv->bufsz = bsz; + } + + for (i = 0; i < pPriv->nbfrs; ++i) { + pPriv->bfrs[i].start = mmap(NULL, bfr.length, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, pPriv->bfrs[i].offset); + if (pPriv->bfrs[i].start == MAP_FAILED) + goto xit; + } + + for (i = 0; i < pPriv->nbfrs; ++i) { + DBLOG(3, "bfr %d ofs %#lx adr %p sz %lu\n", i, pPriv->bfrs[i].offset, + pPriv->bfrs[i].start, (unsigned long)pPriv->bfrs[i].length); + memset(pPriv->bfrs[i].start, 0x80, pPriv->bfrs[i].length); + } + + pPriv->last = 0; + while (pPriv->last < pPriv->nbfrs - 1) { + bfr.index = pPriv->last++; + bfr.type = type; + if (ioctl(fd, VIDIOC_QBUF, &bfr) < 0) + goto xit; + } + return; + + xit: + z4l_ovly_unmap(pPriv); +} + +static int +z4l_ovly_dqbuf(Z4lPortPrivRec * pPriv) +{ + int stat; + struct v4l2_buffer bfr; + int fd = pPriv->fd; + +#ifdef HAVE_SELECT + struct timeval tmo; + fd_set dqset; + + FD_ZERO(&dqset); + FD_SET(pPriv->fd, &dqset); + tmo.tv_sec = 0; + tmo.tv_usec = 0; + if (select(fd + 1, &dqset, NULL, NULL, &tmo) <= 0) + return -1; +#endif + memset(&bfr, 0, sizeof(bfr)); + bfr.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + stat = ioctl(fd, VIDIOC_DQBUF, &bfr); + DBLOG(3, "dqbuf %d,%d,%d,%d\n", stat, bfr.index, pPriv->last, errno); + + return stat == 0 ? bfr.index : -1; +} + +static int +z4l_open_device(Z4lPortPrivRec * pPriv) +{ + int enable; + + if (pPriv->fd < 0) { + pPriv->fd = open(&pPriv->dev_path[0], O_RDWR, 0); + DBLOG(1, "open(%s)=%d\n", &pPriv->dev_path[0], pPriv->fd); + enable = 1; +#ifdef NONBLK_IO + if (IoCtl(pPriv->fd, FIONBIO, &enable, 1) != 0) { + DBLOG(1, "open cant enable nonblocking\n"); + close(pPriv->fd); + pPriv->fd = -1; + } +#endif + } + return pPriv->fd; +} + +static int +z4l_close_device(Z4lPortPrivRec * pPriv) +{ + int ret = 0; + + if (pPriv->fd >= 0) { + ret = close(pPriv->fd); + pPriv->fd = -1; + DBLOG(1, "close()=%d\n", ret); + } + if (pPriv->run > 0) { + z4l_ovly_unmap(pPriv); + pPriv->run = -1; + } + + return ret; +} + +static int +z4l_ovly_reset(Z4lPortPrivRec * pPriv) +{ + int ret = 0; + + if (pPriv->run > 0) { + z4l_close_device(pPriv); + ret = z4l_open_device(pPriv); + } + + return ret; +} + +static unsigned int +z4l_fourcc_pixfmt(int fourcc) +{ + unsigned int pixfmt = -1; + + switch (fourcc) { + case FOURCC_UYVY: + pixfmt = V4L2_PIX_FMT_UYVY; + break; + case FOURCC_YV12: + pixfmt = V4L2_PIX_FMT_YVU420; + break; + case FOURCC_Y800: + case FOURCC_I420: + pixfmt = V4L2_PIX_FMT_YUV420; + break; + case FOURCC_YUY2: + pixfmt = V4L2_PIX_FMT_YUYV; + break; + } + + return pixfmt; +} +static void +z4l_ovly_pixfmt(Z4lPortPrivRec * pPriv, unsigned int pixfmt) +{ + struct v4l2_framebuffer fbuf; + + DBLOG(1, "pixfmt %4.4s %4.4s\n", (char *)&pPriv->pixfmt, (char *)&pixfmt); + memset(&fbuf, 0, sizeof(fbuf)); + IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1); + fbuf.fmt.pixelformat = pixfmt; + fbuf.base = NULL; + IoCtl(pPriv->fd, VIDIOC_S_FBUF, &fbuf, 1); + pPriv->pixfmt = pixfmt; +} + +static void +z4l_ovly_bfr(Z4lPortPrivRec * pPriv, int width, int height) +{ + struct v4l2_format fmt; + + DBLOG(1, "sfmt ovly %dx%d\n", width, height); + memset(&fmt, 0, sizeof(fmt)); + fmt.type = 0x102; + IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1); + fmt.fmt.win.field = V4L2_FIELD_NONE; + fmt.fmt.win.w.width = pPriv->width = width; + fmt.fmt.win.w.height = pPriv->height = height; + IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1); +} + +static void +z4l_ovly_rect(Z4lPortPrivRec * pPriv, + int src_x, int src_y, int src_w, int src_h, + int drw_x, int drw_y, int drw_w, int drw_h) +{ + int x, dx, w, y, dy, h; + struct v4l2_format fmt; + + pPriv->src_x = src_x; + pPriv->src_y = src_y; + pPriv->src_w = src_w; + pPriv->src_h = src_h; + pPriv->drw_x = drw_x; + pPriv->drw_y = drw_y; + pPriv->drw_w = drw_w; + pPriv->drw_h = drw_h; + + if ((drw_x -= z4l_x_offset) < 0) { + if ((w = pPriv->drw_w) <= 0) + w = 1; + x = -drw_x; + dx = x * pPriv->src_w / w; + src_x = pPriv->src_x + dx; + src_w = pPriv->src_w - dx; + drw_w = pPriv->drw_w - x; + drw_x = 0; + } + + if ((drw_y -= z4l_y_offset) < 0) { + if ((h = pPriv->drw_h) <= 0) + h = 1; + y = -drw_y; + dy = y * pPriv->src_h / h; + src_y = pPriv->src_y + dy; + src_h = pPriv->src_h - dy; + drw_h = pPriv->drw_h - y; + drw_y = 0; + } + + memset(&fmt, 0, sizeof(fmt)); + fmt.type = 0x100; + IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1); + if (pPriv->src_is_set != 0) { + if (src_x != fmt.fmt.win.w.left || src_y != fmt.fmt.win.w.top || + src_w != fmt.fmt.win.w.width || src_h != fmt.fmt.win.w.height) + pPriv->src_is_set = 0; + } + if (pPriv->src_is_set == 0) { + pPriv->src_is_set = 1; + fmt.fmt.win.w.left = src_x; + fmt.fmt.win.w.top = src_y; + fmt.fmt.win.w.width = src_w; + fmt.fmt.win.w.height = src_h; + IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1); + DBLOG(3, " set src %d,%d %dx%d\n", src_x, src_y, src_w, src_h); + } + memset(&fmt, 0, sizeof(fmt)); + fmt.type = 0x101; + IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1); + if (pPriv->drw_is_set != 0) { + if (drw_x != fmt.fmt.win.w.left || drw_y != fmt.fmt.win.w.top || + drw_w != fmt.fmt.win.w.width || drw_h != fmt.fmt.win.w.height) + pPriv->drw_is_set = 0; + } + if (pPriv->drw_is_set == 0) { + pPriv->drw_is_set = 1; + fmt.fmt.win.w.left = drw_x; + fmt.fmt.win.w.top = drw_y; + fmt.fmt.win.w.width = drw_w; + fmt.fmt.win.w.height = drw_h; + IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1); + DBLOG(3, " set drw %d,%d %dx%d\n", drw_x, drw_y, drw_w, drw_h); + } +} + +static void +z4l_ovly_pitch(unsigned int pixfmt, int w, int h, int *py_pitch, + int *puv_pitch, int *poffset1, int *poffset2, int *psize) +{ + int y_pitch, uv_pitch; + int offset1, offset2; + int size, is_420; + + switch (pixfmt) { + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YUV420: + is_420 = 1; + y_pitch = ((w + 1) / 2) * 2; + uv_pitch = (w + 1) / 2; + break; + default: + is_420 = 0; + y_pitch = ((w + 1) / 2) * 4; + uv_pitch = 0; + break; + } + + offset1 = y_pitch * h; + offset2 = uv_pitch * h; + + if (is_420 != 0) + offset2 /= 2; + + size = offset1 + 2 * offset2; + *py_pitch = y_pitch; + *puv_pitch = uv_pitch; + *poffset1 = offset1; + *poffset2 = offset2; + *psize = size; +} + +static int +z4l_ovly_set_colorkey(Z4lPortPrivRec * pPriv, int key) +{ + struct v4l2_format fmt; + + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + if (IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1) < 0) + return 0; + fmt.fmt.win.chromakey = key; + if (IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1) < 0) + return 0; + pPriv->colorkey = key; + + return 1; +} + +static int +z4l_ovly_get_colorkey(Z4lPortPrivRec * pPriv, int *key) +{ + struct v4l2_format fmt; + + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + if (IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1) < 0) + return 0; + *key = fmt.fmt.win.chromakey; + + return 1; +} + +static int +z4l_ovly_set_keymode(Z4lPortPrivRec * pPriv, int enable) +{ + struct v4l2_framebuffer fbuf; + + memset(&fbuf, 0, sizeof(fbuf)); + if (IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) + return 0; + + if (enable != 0) + fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; + else + fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; + + fbuf.base = NULL; + if (IoCtl(pPriv->fd, VIDIOC_S_FBUF, &fbuf, 1) < 0) + return 0; + pPriv->keymode = enable; + + return 1; +} + +static int +z4l_ovly_get_keymode(Z4lPortPrivRec * pPriv, int *enable) +{ + struct v4l2_framebuffer fbuf; + + memset(&fbuf, 0, sizeof(fbuf)); + if (IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) + return 0; + *enable = (fbuf.flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0 ? 1 : 0; + + return 1; +} + +static int +z4l_ovly_set_encoding(Z4lPortPrivRec * pPriv, int id) +{ + int l, n, inp; + char *cp; + t_std_data *sp; + XF86VideoEncodingPtr enc; + XF86VideoAdaptorPtr adpt; + v4l2_std_id std; + struct v4l2_format fmt; + struct v4l2_framebuffer fbuf; + + adpt = pPriv->adpt; + DBLOG(1, "z4l_ovly_set_encoding(%d)\n", id); + if (id < 0 || id >= adpt->nEncodings) + return 0; + enc = &adpt->pEncodings[id]; + cp = &enc->name[0]; + n = sizeof(int) - 1; + l = strlen(cp) + 1; + l = (l + n) & ~n; + sp = (t_std_data *) (cp + l); + inp = sp->inp; + + DBLOG(1, " nm %s fmt %4.4s inp %d std %llx\n", + cp, (char *)&sp->fmt, sp->inp, sp->std); + + if (IoCtl(pPriv->fd, VIDIOC_S_INPUT, &inp, 1) < 0) + return 0; + + std = sp->std; + if (IoCtl(pPriv->fd, VIDIOC_S_STD, &std, 1) < 0) + return 0; + + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1) < 0) + return 0; + + fmt.fmt.pix.pixelformat = sp->fmt; + if (IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1) < 0) + return 0; + memset(&fbuf, 0, sizeof(fbuf)); + + if (IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) + return 0; + + fbuf.fmt.pixelformat = sp->fmt; + fbuf.base = NULL; + if (IoCtl(pPriv->fd, VIDIOC_S_FBUF, &fbuf, 1) < 0) + return 0; + pPriv->pixfmt = sp->fmt; + pPriv->enc = enc; + pPriv->src_is_set = pPriv->drw_is_set = 0; + + return 1; +} + +static int +z4l_ovly_get_encoding(Z4lPortPrivRec * pPriv, int *id) +{ + XF86VideoEncodingPtr enc = pPriv->enc; + + *id = enc->id; + return 1; +} + +static void +z4l_ovly_stop(Z4lPortPrivRec * pPriv) +{ + int type, enable, fd; + + if (pPriv->run < 0) + return; + + fd = pPriv->fd; + if (pPriv->dir > 0) { + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ioctl(fd, VIDIOC_STREAMOFF, &type); + } + + if (pPriv->dir <= 0) { + enable = 0; + ioctl(fd, VIDIOC_OVERLAY, &enable); + } + + if (pPriv->dir != 0) + z4l_ovly_unmap(pPriv); + + pPriv->run = -1; + z4l_close_device(pPriv); +} + +static void +z4l_ovly_start(Z4lPortPrivRec * pPriv, int dir) +{ + int enable; + + if (pPriv->run >= 0) + return; + + if ((pPriv->dir = dir) != 0) + z4l_ovly_map(pPriv, dir); + + enable = 1; + + if (IoCtl(pPriv->fd, VIDIOC_OVERLAY, &enable, 1) != 0) { + z4l_ovly_stop(pPriv); + return; + } + + pPriv->run = 1; +} + +static int +z4l_region_equal(RegionPtr ap, RegionPtr bp) +{ + int nboxes; + BoxPtr abox, bbox; + + if (ap == NULL && bp == NULL) + return 1; + if (ap == NULL || bp == NULL) + return 0; + + if ((nboxes = REGION_NUM_RECTS(ap)) != REGION_NUM_RECTS(bp) || + ap->extents.x1 != bp->extents.x1 || + ap->extents.x2 != bp->extents.x2 + || ap->extents.y1 != bp->extents.y1 + || ap->extents.y2 != bp->extents.y2) + return 0; + + abox = REGION_RECTS(ap); + bbox = REGION_RECTS(bp); + + while (--nboxes >= 0) { + if (abox->x1 != bbox->x1 || abox->y1 != bbox->y1 || + abox->x2 != bbox->x2 || abox->y2 != bbox->y2) + return 0; + ++abox; + ++bbox; + } + + return 1; +} + +static void +z4l_setup_colorkey(Z4lPortPrivRec * pPriv, ScreenPtr pScrn, + RegionPtr clipBoxes) +{ + if (pPriv->run > 0 && pPriv->dir <= 0 && pPriv->keymode != 0 && + z4l_region_equal(&pPriv->clips, clipBoxes) == 0) { + xf86XVFillKeyHelper(pScrn, pPriv->colorkey, clipBoxes); + REGION_COPY(pScrn, &pPriv->clips, clipBoxes); + } +} + +static void +Z4lStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit) +{ + Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; + + DBLOG(1, "Z4lStopVideo()\n"); + + if (exit != 0) + z4l_ovly_stop(pPriv); + else + pPriv->src_is_set = pPriv->drw_is_set = 0; + + REGION_EMPTY(pScrni->pScreen, &pPriv->clips); +} + +static void +Z4lQueryBestSize(ScrnInfoPtr pScrni, Bool motion, + short vid_w, short vid_h, short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, pointer data) +{ + if (drw_w > MAX_OVLY_WIDTH) + drw_w = MAX_OVLY_WIDTH; + if (drw_h > MAX_OVLY_HEIGHT) + drw_h = MAX_OVLY_HEIGHT; + + *p_w = drw_w; + *p_h = drw_h; + DBLOG(1, "Z4lQueryBestSize(%d, src %dx%d dst %dx%d)\n", motion, vid_w, + vid_h, drw_w, drw_h); +} + +static int +Z4lPutImage(ScrnInfoPtr pScrni, short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, short drw_w, short drw_h, + int id, unsigned char *buf, short width, short height, + Bool sync, RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) +{ + int fd, size; + int y_pitch, uv_pitch, offset1, offset2; + unsigned char *src, *dst; + unsigned int pixfmt; + struct v4l2_buffer bfr; + Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; + + if (pPriv->run > 0 && pPriv->dir >= 0) + return BadMatch; + if (pPriv->fd < 0) { + z4l_open_device(pPriv); + if (pPriv->fd < 0) + return BadValue; + } + + fd = pPriv->fd; + if (pPriv->run < 0) { + DBLOG(2, "PutImg id %#x src %d,%d %dx%d drw %d,%d %dx%d bfr %p " + "%dx%d data %p\n", id, src_x, src_y, src_w, src_h, drw_x, + drw_y, drw_w, drw_h, buf, width, height, data); + pPriv->pixfmt = pPriv->height = -1; + pPriv->src_is_set = pPriv->drw_is_set = 0; + } + + pixfmt = z4l_fourcc_pixfmt(id); + if (pixfmt != pPriv->pixfmt) { + z4l_ovly_reset(pPriv); + z4l_ovly_pixfmt(pPriv, pixfmt); + } + if (pPriv->width != width || pPriv->height != height) { + z4l_ovly_reset(pPriv); + z4l_ovly_bfr(pPriv, width, height); + } + + if (pPriv->src_is_set == 0 || pPriv->drw_is_set == 0 || + pPriv->src_x != src_x || pPriv->src_y != src_y || + pPriv->src_w != src_w || pPriv->src_h != src_h || + pPriv->drw_x != drw_x || pPriv->drw_y != drw_y || + pPriv->drw_w != drw_w || pPriv->drw_h != drw_h) + z4l_ovly_rect(pPriv, src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, + drw_h); + + if (pPriv->run < 0) { + z4l_ovly_start(pPriv, -1); + if (pPriv->run < 0) + return BadValue; + } + + if (pPriv->last < 0 && (pPriv->last = z4l_ovly_dqbuf(pPriv)) < 0) + return BadAlloc; + + z4l_ovly_pitch(pixfmt, width, height, &y_pitch, &uv_pitch, + &offset1, &offset2, &size); + src = buf; + dst = (unsigned char *)pPriv->bfrs[pPriv->last].start; + DBLOG(3, "cpy %4.4s src %p dst %p yp %d uvp %d o1 %d o2 %d sz %d\n", + (char *)&id, src, dst, y_pitch, uv_pitch, offset1, offset2, size); + + if (id == FOURCC_Y800) { + memcpy(dst, src, offset1); + src += offset1; + dst += offset1; + memset(dst, 0x80, 2 * offset2); + } else + memcpy(dst, src, size); + + memset(&bfr, 0, sizeof(bfr)); + bfr.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + bfr.index = pPriv->last; + bfr.timestamp.tv_sec = 0; + bfr.timestamp.tv_usec = 0; + bfr.flags |= V4L2_BUF_FLAG_TIMECODE; + if (IoCtl(fd, VIDIOC_QBUF, &bfr, 1) != 0) + return BadAccess; + + pPriv->last = z4l_ovly_dqbuf(pPriv); + z4l_setup_colorkey(pPriv, pScrni->pScreen, clipBoxes); + + return Success; +} + +static int +Z4lQueryImageAttributes(ScrnInfoPtr pScrni, int id, unsigned short *width, + unsigned short *height, int *pitches, int *offsets) +{ + int w, h, size; + int y_pitch, uv_pitch, offset1, offset2; + unsigned int pixfmt = z4l_fourcc_pixfmt(id); + + w = *width; + h = *height; + if (w > MAX_OVLY_WIDTH) + w = MAX_OVLY_WIDTH; + if (h > MAX_OVLY_HEIGHT) + h = MAX_OVLY_HEIGHT; + + z4l_ovly_pitch(pixfmt, w, h, &y_pitch, &uv_pitch, + &offset1, &offset2, &size); + + if (offsets != NULL) + offsets[0] = 0; + if (pitches != NULL) + pitches[0] = y_pitch; + + switch (pixfmt) { + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YUV420: + if (offsets != NULL) { + offsets[1] = offset1; + offsets[2] = offset1 + offset2; + } + if (pitches != NULL) + pitches[1] = pitches[2] = uv_pitch; + h = (h + 1) & ~1; + break; + } + + w = (w + 1) & ~1; + *width = w; + *height = h; + DBLOG(1, "Z4lQueryImageAttributes(%4.4s) = %d, %dx%d %d/%d %d/%d\n", + (char *)&id, size, w, h, y_pitch, uv_pitch, offset1, offset2); + + return size; +} + +static int +Z4lPutVideo(ScrnInfoPtr pScrni, short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, short drw_w, short drw_h, + RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) +{ + int id; + Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; + + DBLOG(2, "PutVid src %d,%d %dx%d drw %d,%d %dx%d data %p\n", + src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, data); + + if (z4l_open_device(pPriv) >= 0) { + if (pPriv->run < 0) { + DBLOG(2, "PutVid start\n"); + z4l_ovly_get_encoding(pPriv, &id); + z4l_ovly_set_encoding(pPriv, id); + } + DBLOG(2, "PutVid priv %d,%d %dx%d drw %d,%d %dx%d\n", + pPriv->src_x, pPriv->src_y, pPriv->src_w, pPriv->src_h, + pPriv->drw_x, pPriv->drw_y, pPriv->drw_w, pPriv->drw_h); + if (pPriv->src_is_set == 0 || pPriv->drw_is_set == 0 || + pPriv->src_w != src_w || pPriv->src_h != src_h || + pPriv->drw_x != drw_x || pPriv->drw_y != drw_y || + pPriv->drw_w != drw_w || pPriv->drw_h != drw_h) + z4l_ovly_rect(pPriv, src_x, src_y, src_w, src_h, drw_x, drw_y, + drw_w, drw_h); + if (pPriv->run < 0) + z4l_ovly_start(pPriv, 0); + + z4l_setup_colorkey(pPriv, pScrni->pScreen, clipBoxes); + } + + return Success; +} + +static XF86VideoEncodingPtr +Z4lNewEncoding(XF86VideoEncodingPtr * encs, int *nencs) +{ + XF86VideoEncodingPtr enc; + XF86VideoEncodingPtr tencs = + (XF86VideoEncodingPtr) realloc(*encs, sizeof(*tencs) * (*nencs + 1)); + + if (tencs == NULL) + return NULL; + + *encs = tencs; + enc = &tencs[*nencs]; + ++*nencs; + memset(enc, 0, sizeof(*enc)); + + return enc; +} + +static void +Z4lEncodingName(char *ename, int l, char *inp_name, char *std_name, char *fmt) +{ + int i, ch; + + while ((ch = *inp_name++) != 0) { + if (isalnum(ch) == 0) + continue; + if (--l <= 0) + goto xit; + *ename++ = ch; + } + + if (--l <= 0) + goto xit; + + *ename++ = '-'; + + while ((ch = *std_name++) != 0) { + if (isalnum(ch) == 0) + continue; + if (--l <= 0) + goto xit; + *ename++ = ch; + } + + if (--l <= 0) + goto xit; + + *ename++ = '-'; + i = 4; + + while (--i >= 0 && (ch = *fmt++) != 0) { + if (isalnum(ch) == 0) + continue; + if (--l <= 0) + goto xit; + *ename++ = ch; + } + + xit: + *ename = 0; +} + +static int +Z4lAddEncoding(XF86VideoEncodingPtr enc, char *name, int id, int width, + int height, int numer, int denom, int inp, v4l2_std_id std, + unsigned int fmt) +{ + int l, n; + t_std_data *sp; + char *cp; + n = sizeof(int) - 1; + l = strlen(&name[0]) + 1; + l = (l + n) & ~n; + n = l + sizeof(*sp); + cp = (char *)malloc(n); + + if (cp == NULL) + return 0; + + sp = (t_std_data *) (cp + l); + enc->id = id; + strcpy(cp, &name[0]); + enc->name = cp; + enc->width = width; + enc->height = height; + enc->rate.numerator = numer; + enc->rate.denominator = denom; + sp->inp = inp; + sp->std = std; + sp->fmt = fmt; + DBLOG(1, "enc %s\n", &name[0]); + + return 1; +} + +static XF86ImagePtr +Z4lNewImage(XF86ImagePtr * imgs, int *nimgs) +{ + XF86ImagePtr img; + XF86ImagePtr timgs = + (XF86ImagePtr) realloc(*imgs, sizeof(*timgs) * (*nimgs + 1)); + + if (timgs == NULL) + return NULL; + + *imgs = timgs; + img = &timgs[*nimgs]; + ++*nimgs; + memset(img, 0, sizeof(*img)); + + return img; +} + +static int +Z4lAddImage(XF86ImagePtr img, XF86ImagePtr ip) +{ + *img = *ip; + DBLOG(1, "img %4.4s\n", (char *)&img->id); + return 1; +} + +static XF86AttributePtr +Z4lNewAttribute(XF86AttributePtr * attrs, int *nattrs) +{ + XF86AttributePtr attr; + XF86AttributePtr tattrs = + (XF86AttributePtr) realloc(*attrs, sizeof(*tattrs) * (*nattrs + 1)); + + if (tattrs == NULL) + return NULL; + + *attrs = tattrs; + attr = &tattrs[*nattrs]; + ++*nattrs; + memset(attr, 0, sizeof(*attr)); + + return attr; +} + +static void +Z4lAttributeName(char *bp, int l, char *cp) +{ + int ch; + char *atomNm = bp; + + if (l > 0) { + *bp++ = 'X'; + --l; + } + if (l > 0) { + *bp++ = 'V'; + --l; + } + if (l > 0) { + *bp++ = '_'; + --l; + } + + while (l > 0 && (ch = *cp++) != 0) { + if (isalnum(ch) == 0) + continue; + *bp++ = toupper(ch); + } + + *bp = 0; + MakeAtom(&atomNm[0], strlen(&atomNm[0]), TRUE); +} + +static int +Z4lAddAttribute(XF86AttributePtr attr, char *name, + int min, int max, int flags) +{ + char *cp = (char *)malloc(strlen((char *)&name[0]) + 1); + + if (cp == NULL) + return 0; + + attr->name = cp; + strcpy(&attr->name[0], name); + attr->min_value = min; + attr->max_value = max; + attr->flags = flags; + DBLOG(1, "attr %s\n", attr->name); + + return 1; +} + +static XF86VideoAdaptorPtr +Z4lNewAdaptor(XF86VideoAdaptorPtr ** adpts, int *nadpts, int nattrs) +{ + int n; + Z4lPortPrivRec *pPriv; + XF86VideoAdaptorPtr adpt, *tadpts; + + tadpts = (XF86VideoAdaptorPtr *) realloc(*adpts, + sizeof(*tadpts) * (*nadpts + 1)); + + if (tadpts == NULL) + return NULL; + + *adpts = tadpts; + n = sizeof(*adpt) + sizeof(*pPriv) + 1 * sizeof(*adpt->pPortPrivates); + n += (nattrs - 1) * sizeof(pPriv->attrIds[0]); + adpt = (XF86VideoAdaptorPtr) malloc(n); + + if (adpt == NULL) + return NULL; + + memset(adpt, 0, n); + tadpts[*nadpts] = adpt; + ++*nadpts; + adpt->pPortPrivates = (DevUnion *) & adpt[1]; + pPriv = (Z4lPortPrivRec *) & adpt->pPortPrivates[1]; + adpt->pPortPrivates[0].ptr = (pointer) pPriv; + pPriv->adpt = adpt; + adpt->nPorts = 1; + + return adpt; +} + +static int +Z4lSetPortAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value, + pointer data) +{ + Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; + XF86VideoAdaptorPtr adpt; + XF86AttributePtr attr; + struct v4l2_control ctrl; + int i, nattrs, attrId, val; + const char *name = NameForAtom(attribute); + int old_fd = pPriv->fd; + + DBLOG(1, "Z4lSetPortAttribute(%#lx,%d) '%s'\n", (unsigned long)attribute, + (int)value, name != NULL ? name : "_null_"); + + if (name == NULL) + return BadImplementation; + if (old_fd < 0 && z4l_open_device(pPriv) < 0) + return BadAccess; + + adpt = pPriv->adpt; + attr = adpt->pAttributes; + nattrs = adpt->nAttributes; + + for (i = 0; i < nattrs; ++i, ++attr) + if (strcmp(attr->name, name) == 0) + break; + + if (i >= nattrs) + return BadMatch; + + attrId = pPriv->attrIds[i]; + val = value; + + switch (attrId) { + case ATTR_ENCODING_ID: + z4l_ovly_set_encoding(pPriv, val); + break; + case ATTR_KEYMODE_ID: + z4l_ovly_set_keymode(pPriv, val); + REGION_EMPTY(pScrni->pScreen, &pPriv->clips); + z4l_setup_colorkey(pPriv, pScrni->pScreen, &pPriv->clips); + break; + case ATTR_COLORKEY_ID: + z4l_ovly_set_colorkey(pPriv, val); + break; + default: + memset(&ctrl, 0, sizeof(ctrl)); + ctrl.id = attrId + V4L2_CID_BASE; + ctrl.value = val; + if (IoCtl(pPriv->fd, VIDIOC_S_CTRL, &ctrl, 1) != 0) + return BadMatch; + break; + } + + if (old_fd < 0) + z4l_close_device(pPriv); + + return Success; +} + +static int +Z4lGetPortAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 * value, + pointer data) +{ + Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; + XF86VideoAdaptorPtr adpt; + XF86AttributePtr attr; + struct v4l2_control ctrl; + int i, nattrs, attrId, val; + const char *name = NameForAtom(attribute); + int old_fd = pPriv->fd; + + DBLOG(1, "Z4lGetPortAttribute(%#lx) '%s'\n", + (unsigned long)attribute, name != NULL ? name : "_null_"); + + if (name == NULL) + return BadImplementation; + if (old_fd < 0 && z4l_open_device(pPriv) < 0) + return BadAccess; + + adpt = pPriv->adpt; + attr = adpt->pAttributes; + nattrs = adpt->nAttributes; + + for (i = 0; i < nattrs; ++i, ++attr) + if (strcmp(attr->name, name) == 0) + break; + + if (i >= nattrs) + return BadMatch; + + attrId = pPriv->attrIds[i]; + val = 0; + + switch (attrId) { + case ATTR_ENCODING_ID: + z4l_ovly_get_encoding(pPriv, &val); + *value = val; + break; + case ATTR_KEYMODE_ID: + z4l_ovly_get_keymode(pPriv, &val); + *value = val; + break; + case ATTR_COLORKEY_ID: + z4l_ovly_get_colorkey(pPriv, &val); + break; + default: + memset(&ctrl, 0, sizeof(ctrl)); + ctrl.id = attrId + V4L2_CID_BASE; + if (IoCtl(pPriv->fd, VIDIOC_G_CTRL, &ctrl, 1) != 0) + return BadMatch; + val = ctrl.value; + break; + } + + if (old_fd < 0) + z4l_close_device(pPriv); + + *value = val; + + return Success; +} + +static void (*oldAdjustFrame) (int scrnIndex, int x, int y, int flags) = NULL; + +static void +Z4lAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + int i; + XF86VideoAdaptorPtr adpt; + Z4lPortPrivRec *pPriv; + + DBLOG(3, "Z4lAdjustFrame(%d,%d,%d)\n", x, y, flags); + z4l_x_offset = x; + z4l_y_offset = y; + oldAdjustFrame(scrnIndex, x, y, flags); + + /* xv adjust does not handle putvideo case */ + for (i = 0; i < Z4l_nAdaptors; ++i) { + adpt = Z4l_pAdaptors[i]; + pPriv = (Z4lPortPrivRec *) adpt->pPortPrivates[0].ptr; + if (pPriv->run > 0) { + pPriv->drw_is_set = 0; + z4l_ovly_rect(pPriv, + pPriv->src_x, pPriv->src_y, pPriv->src_w, pPriv->src_h, + pPriv->drw_x, pPriv->drw_y, pPriv->drw_w, pPriv->drw_h); + } + } +} + +static int +Z4lInit(ScrnInfoPtr pScrni, XF86VideoAdaptorPtr ** adaptors) +{ + int i, id, fd, dev, enable, has_video, has_colorkey; + int ctl, cinp, inp, std, fmt, has_image; + int nadpts, nattrs, nencs, cenc, nimgs; + int numer, denom, width, height; + unsigned int pixfmt, cpixfmt, opixfmt; + XF86VideoAdaptorPtr *adpts, adpt; + XF86AttributePtr attrs, attr; + XF86VideoEncodingPtr encs, enc; + XF86ImagePtr ip, img, imgs; + Z4lPortPrivRec *pPriv; + char *dp, *msg; + char enc_name[256], attr_name[256]; + int attrIds[V4L2_CID_LASTP1 - V4L2_CID_BASE + ATTR_MAX_ID]; + struct v4l2_capability capability; + v4l2_std_id cstd_id, std_id; + struct v4l2_standard standard; + struct v4l2_format format, cfmt; + struct v4l2_input input; + struct v4l2_fmtdesc fmtdesc; + struct v4l2_queryctrl queryctrl; + struct v4l2_framebuffer fbuf; + + DBLOG(1, "Init\n"); + if (oldAdjustFrame == NULL) { + oldAdjustFrame = pScrni->AdjustFrame; + pScrni->AdjustFrame = Z4lAdjustFrame; + } + + fd = -1; + enc = NULL; + encs = NULL; + nencs = 0; + img = NULL; + imgs = NULL; + nimgs = 0; + attr = NULL; + attrs = NULL; + nattrs = 0; + adpt = NULL; + adpts = NULL; + nadpts = 0; + has_video = has_image = has_colorkey = 0; + + for (dev = 0; z4l_dev_paths[dev] != NULL; ++dev) { + fd = open(z4l_dev_paths[dev], O_RDWR, 0); + if (fd < 0) + continue; + DBLOG(1, "%s open ok\n", z4l_dev_paths[dev]); + msg = NULL; + enable = 1; + if (IoCtl(fd, VIDIOC_QUERYCAP, &capability, 1) < 0) + msg = "bad querycap"; + else if ((capability.capabilities & V4L2_CAP_VIDEO_OVERLAY) == 0) + msg = "no overlay"; + else if ((capability.capabilities & V4L2_CAP_STREAMING) == 0) + msg = "no streaming"; +#ifdef NONBLK_IO + else if (IoCtl(fd, FIONBIO, &enable, 1) != 0) + msg = "cant enable non-blocking io"; +#endif + if (msg == NULL) { + memset(&format, 0, sizeof(format)); + format.type = 0x100; + if (IoCtl(fd, VIDIOC_G_FMT, &format, 1) != 0) + msg = "no src/dst ovly fmt"; + } + if (msg != NULL) { + DBLOG(0, "%s %s\n", z4l_dev_paths[dev], msg); + close(fd); + continue; + } + + memset(&cfmt, 0, sizeof(cfmt)); + cfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (IoCtl(fd, VIDIOC_G_FMT, &cfmt, 1) < 0) + goto fail; + if (IoCtl(fd, VIDIOC_G_STD, &cstd_id, 1) < 0) + goto fail; + if (IoCtl(fd, VIDIOC_G_INPUT, &cinp, 1) < 0) + goto fail; + cpixfmt = cfmt.fmt.pix.pixelformat; + cenc = 0; + for (inp = 0;; ++inp) { + memset(&input, 0, sizeof(input)); + input.index = inp; + if (IoCtl(fd, VIDIOC_ENUMINPUT, &input, 0) < 0) + break; + id = inp; + if (IoCtl(fd, VIDIOC_S_INPUT, &id, 1) < 0) + goto fail; + for (std = 0;; ++std) { + memset(&standard, 0, sizeof(standard)); + standard.index = std; + if (IoCtl(fd, VIDIOC_ENUMSTD, &standard, 0) < 0) + break; + std_id = standard.id; + denom = standard.frameperiod.denominator; + numer = standard.frameperiod.numerator; + if (IoCtl(fd, VIDIOC_S_STD, &std_id, 1) < 0) + continue; + memset(&format, 0, sizeof(format)); + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (IoCtl(fd, VIDIOC_G_FMT, &format, 1) < 0) + continue; + width = format.fmt.pix.width; + height = format.fmt.pix.height; + for (fmt = 0;; ++fmt) { + memset(&fmtdesc, 0, sizeof(fmtdesc)); + fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmtdesc.index = fmt; + if (IoCtl(fd, VIDIOC_ENUM_FMT, &fmtdesc, 0) < 0) + break; + pixfmt = fmtdesc.pixelformat; + ip = &pixfmts[0]; + for (i = sizeof(pixfmts) / sizeof(pixfmts[0]); --i >= 0; + ++ip) + if (z4l_fourcc_pixfmt(ip->id) == pixfmt) + break; + + if (i >= 0) { + id = nencs; + has_video = 1; + if ((enc = Z4lNewEncoding(&encs, &nencs)) == NULL) + goto fail; + Z4lEncodingName(&enc_name[0], sizeof(enc_name), + (char *)&input.name[0], + (char *)&standard.name[0], (char *)&pixfmt); + if (Z4lAddEncoding(enc, &enc_name[0], id, width, + height, denom, numer, inp, std_id, + pixfmt) == 0) + goto fail; + if (std_id == cstd_id && inp == cinp + && pixfmt == cpixfmt) + cenc = id; + } + } + } + } + + if (IoCtl(fd, VIDIOC_S_INPUT, &cinp, 1) < 0) + goto fail; + if (IoCtl(fd, VIDIOC_S_STD, &cstd_id, 1) < 0) + goto fail; + if (IoCtl(fd, VIDIOC_S_FMT, &cfmt, 1) < 0) + goto fail; + + if (encs == NULL) { + DBLOG(0, "no encodings\n"); + goto fail; + } + + for (fmt = 0;; ++fmt) { + memset(&fmtdesc, 0, sizeof(fmtdesc)); + fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + fmtdesc.index = fmt; + if (IoCtl(fd, VIDIOC_ENUM_FMT, &fmtdesc, 0) < 0) + break; + pixfmt = fmtdesc.pixelformat; + ip = &pixfmts[0]; + for (i = sizeof(pixfmts) / sizeof(pixfmts[0]); --i >= 0; ++ip) + if (z4l_fourcc_pixfmt(ip->id) == pixfmt) + break; + + if (i >= 0) { + has_image = 1; + if ((img = Z4lNewImage(&imgs, &nimgs)) == NULL) + goto fail; + if (Z4lAddImage(img, ip) == 0) + goto fail; + } + } + + if (nimgs > 0) { + id = nencs; + if ((enc = Z4lNewEncoding(&encs, &nencs)) == NULL) + goto fail; + if (Z4lAddEncoding(enc, "XV_IMAGE", id, MAX_OVLY_WIDTH, + MAX_OVLY_HEIGHT, 0, 0, 0, 0, pixfmt) == 0) + goto fail; + } + + ctl = 0; + for (ctl = 0; ctl < (V4L2_CID_LASTP1 - V4L2_CID_BASE); ++ctl) { + memset(&queryctrl, 0, sizeof(queryctrl)); + queryctrl.id = V4L2_CID_BASE + ctl; + if (IoCtl(fd, VIDIOC_QUERYCTRL, &queryctrl, 0) < 0) + continue; + if (queryctrl.type != V4L2_CTRL_TYPE_INTEGER && + queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN) + continue; + attrIds[nattrs] = ctl; + if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) + goto fail; + Z4lAttributeName(&attr_name[0], sizeof(attr_name), + (char *)&queryctrl.name[0]); + if (Z4lAddAttribute(attr, &attr_name[0], + queryctrl.minimum, queryctrl.maximum, + XvSettable | XvGettable) == 0) + goto fail; + } + attrIds[nattrs] = ATTR_ENCODING_ID; + if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) + goto fail; + Z4lAttributeName(&attr_name[0], sizeof(attr_name), ATTR_ENCODING); + if (Z4lAddAttribute(attr, &attr_name[0], 0, nencs - 1, + XvSettable | XvGettable) == 0) + goto fail; + memset(&fbuf, 0, sizeof(fbuf)); + if (IoCtl(fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) + goto fail; + opixfmt = fbuf.fmt.pixelformat; + + if ((fbuf.capability & V4L2_FBUF_CAP_CHROMAKEY) != 0) { + attrIds[nattrs] = ATTR_KEYMODE_ID; + if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) + goto fail; + Z4lAttributeName(&attr_name[0], sizeof(attr_name), ATTR_KEYMODE); + if (Z4lAddAttribute(attr, &attr_name[0], 0, 1, + XvSettable | XvGettable) == 0) + goto fail; + attrIds[nattrs] = ATTR_COLORKEY_ID; + if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) + goto fail; + Z4lAttributeName(&attr_name[0], sizeof(attr_name), ATTR_COLORKEY); + if (Z4lAddAttribute(attr, &attr_name[0], 0, 0xffffff, + XvSettable | XvGettable) == 0) + goto fail; + has_colorkey = 1; + } + + dp = malloc(strlen((char *)&capability.card[0]) + 1); + if (dp == NULL) + goto fail; + strcpy(dp, (char *)&capability.card[0]); + if ((adpt = Z4lNewAdaptor(&adpts, &nadpts, nattrs)) == NULL) + goto fail; + adpt->type = XvWindowMask | XvInputMask; + if (has_video != 0) + adpt->type |= XvVideoMask; + if (has_image != 0) + adpt->type |= XvImageMask; + adpt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adpt->name = dp; + adpt->type = XvInputMask | XvWindowMask | XvVideoMask | XvImageMask; + adpt->pEncodings = encs; + adpt->nEncodings = nencs; + adpt->pFormats = &Formats[0]; + adpt->nFormats = sizeof(Formats) / sizeof(Formats[0]); + adpt->pAttributes = attrs; + adpt->nAttributes = nattrs; + attrs = NULL; + nattrs = 0; + adpt->pImages = imgs; + adpt->nImages = nimgs; + imgs = NULL; + nimgs = 0; + adpt->PutVideo = Z4lPutVideo; + adpt->StopVideo = Z4lStopVideo; + adpt->SetPortAttribute = Z4lSetPortAttribute; + adpt->GetPortAttribute = Z4lGetPortAttribute; + adpt->QueryBestSize = Z4lQueryBestSize; + adpt->PutImage = Z4lPutImage; + adpt->QueryImageAttributes = Z4lQueryImageAttributes; + pPriv = (Z4lPortPrivRec *) adpt->pPortPrivates[0].ptr; + pPriv->fd = fd; + pPriv->run = -1; + pPriv->dir = 0; + pPriv->nbfrs = -1; + pPriv->bufsz = -1; + pPriv->last = -1; + pPriv->pixfmt = opixfmt; +#if defined(REGION_NULL) + REGION_NULL(pScrni->pScreen, &pPriv->clips); +#else + REGION_INIT(pScrni->pScreen, &pPriv->clips, NullBox, 0); +#endif + strncpy(&pPriv->dev_path[0], z4l_dev_paths[dev], + sizeof(pPriv->dev_path)); + pPriv->enc = &encs[cenc]; + for (i = 0; i < adpt->nAttributes; ++i) + pPriv->attrIds[i] = attrIds[i]; + DBLOG(1, "adpt %s\n", dp); + if (has_colorkey != 0) { + z4l_ovly_set_colorkey(pPriv, DEFAULT_COLORKEY); + z4l_ovly_set_keymode(pPriv, DEFAULT_KEYMODE); + } + close(fd); + pPriv->fd = -1; + adpt = NULL; + cenc = 0; + encs = NULL; + nencs = 0; + } + + DBLOG(0, "init done, %d device(s) found\n", nadpts); + Z4l_nAdaptors = nadpts; + Z4l_pAdaptors = adpts; + *adaptors = adpts; + + return nadpts; + + fail: + if (attrs != NULL) { + for (i = 0; i < nattrs; ++i) + if (attrs[i].name != NULL) + free(attrs[i].name); + free(attrs); + } + + if (encs != NULL) { + for (i = 0; i < nencs; ++i) { + if (encs[i].name != NULL) + free(encs[i].name); + } + free(encs); + } + + if (imgs != NULL) + free(imgs); + + if (adpts != NULL) { + for (i = 0; i < nadpts; ++i) { + if ((adpt = adpts[i]) != NULL) { + if (adpt->name != NULL) + free(adpt->name); + if ((attrs = adpt->pAttributes) != NULL) { + for (i = 0; i < adpt->nAttributes; ++i) + if (attrs[i].name != NULL) + free(attrs[i].name); + free(attrs); + } + if ((encs = adpt->pEncodings) != NULL) { + for (i = 0; i < adpt->nEncodings; ++i, ++enc) + if (encs[i].name != NULL) + free(encs[i].name); + free(encs); + } + if ((imgs = adpt->pImages) != NULL) + free(imgs); + free(adpt); + } + } + free(adpts); + } + + if (fd >= 0) + close(fd); + + return 0; +} + +static Bool +Z4lProbe(DriverPtr drv, int flags) +{ + DBLOG(1, "Probe\n"); + if (flags & PROBE_DETECT) + return TRUE; + + xf86XVRegisterGenericAdaptorDriver(Z4lInit); + drv->refCount++; + + return TRUE; +} + +static const OptionInfoRec * +Z4lAvailableOptions(int chipid, int busid) +{ + return NULL; +} + +static void +Z4lIdentify(int flags) +{ + xf86Msg(X_INFO, "z4l driver for Video4Linux\n"); +} + +_X_EXPORT DriverRec Z4l = { + 40001, + "z4l", + Z4lIdentify, + Z4lProbe, + Z4lAvailableOptions, + NULL, + 0 +}; + +#ifdef XFree86LOADER + +static MODULESETUPPROTO(z4lSetup); + +static XF86ModuleVersionInfo z4lVersionRec = { + "ztv", + MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, + XORG_VERSION_CURRENT, 0, 0, 1, + ABI_CLASS_VIDEODRV, ABI_VIDEODRV_VERSION, MOD_CLASS_NONE, + {0, 0, 0, 0} +}; + +_X_EXPORT XF86ModuleData ztvModuleData = { &z4lVersionRec, z4lSetup, NULL }; + +static pointer +z4lSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + const char *osname; + static Bool setupDone = FALSE; + + if (setupDone != FALSE) { + if (errmaj != NULL) + *errmaj = LDR_ONCEONLY; + return NULL; + } + + setupDone = TRUE; + LoaderGetOS(&osname, NULL, NULL, NULL); + + if (osname == NULL || strcmp(osname, "linux") != 0) { + if (errmaj) + *errmaj = LDR_BADOS; + if (errmin) + *errmin = 0; + + return NULL; + } + + xf86AddDriver(&Z4l, module, 0); + + return (pointer) 1; +} + +#endif +#endif /* !XvExtension */ diff --git a/ztv/Makefile.am b/ztv/Makefile.am deleted file mode 100644 index 0bc133e..0000000 --- a/ztv/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ - -if BUILD_ZTV - -AM_CFLAGS = $(XORG_CFLAGS) $(CWARNFLAGS) $(M32_CFLAGS) - -ztv_drv_la_LTLIBRARIES = ztv_drv.la -ztv_drv_la_LDFLAGS = -module -avoid-version -ztv_drv_ladir = $(moduledir)/drivers - -ztv_drv_la_SOURCES = z4l.c - -endif BUILD_ZTV diff --git a/ztv/z4l.c b/ztv/z4l.c deleted file mode 100644 index c6a7c58..0000000 --- a/ztv/z4l.c +++ /dev/null @@ -1,1739 +0,0 @@ -/* - * Copyright (c) 2006 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Neither the name of the Advanced Micro Devices, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - */ - -/* prototype Xv interface for lxv4l2 driver */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "xf86.h" -#include -#include "xf86_OSproc.h" -#include "compiler.h" -#include "xf86xv.h" -#include "fourcc.h" - -#include - -#define __s64 __s_64 -typedef long long __s64; - -#define __u64 __u_64 -typedef unsigned long long __u64; - -#define __user -#include "linux/videodev2.h" - -typedef signed long long s64; -typedef unsigned long long u64; - -int debuglvl = 0; - -#define NONBLK_IO -#undef HAVE_SELECT - -#define DEBUG 1 -#ifdef DEBUG -#define DBLOG(n,s...) do { \ - if ( debuglvl >= (n) ) \ - xf86Msg(X_INFO, "z4l: " s); \ - } while(0) -#else -#define DBLOG(n,s...) do {} while(0) -#endif - -#define DEFAULT_COLORKEY 0x010203 -#define DEFAULT_KEYMODE 0 - -#define MAX_BUFFERS 4 -#define MAX_OVLY_WIDTH 2048 -#define MAX_OVLY_HEIGHT 2048 - -static char *z4l_dev_paths[] = { - "/dev/videox", NULL -}; - -#define ATTR_ENCODING "encoding" -#define ATTR_ENCODING_ID -1 -#define ATTR_KEYMODE "keymode" -#define ATTR_KEYMODE_ID -2 -#define ATTR_COLORKEY "colorkey" -#define ATTR_COLORKEY_ID -3 -#define ATTR_MAX_ID 3 - -#ifdef XvExtension - -static XF86VideoFormatRec Formats[] = { - {8, PseudoColor}, - {15, TrueColor}, - {16, TrueColor}, - {24, TrueColor} -}; - -#define NUM_FORMATS (sizeof(Formats)/sizeof(Formats[0])) - -#define FOURCC_Y800 0x30303859 -#define XVIMAGE_Y800 \ - { \ - FOURCC_Y800, \ - XvYUV, \ - LSBFirst, \ - {'Y','8','0','0', \ - 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ - 8, \ - XvPacked, \ - 1, \ - 0, 0, 0, 0, \ - 8, 0, 0, \ - 1, 0, 0, \ - 1, 0, 0, \ - {'Y','8','0','0', \ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ - XvTopToBottom \ - } - -static XF86ImageRec pixfmts[] = { - XVIMAGE_UYVY, XVIMAGE_YUY2, - XVIMAGE_I420, XVIMAGE_YV12, - XVIMAGE_Y800, -}; - -#define NUM_PIXFMTS (sizeof(pixfmts)/sizeof(pixfmts[0])) - -typedef struct s_std_data -{ - int inp; - v4l2_std_id std; - unsigned int fmt; -} t_std_data; - -typedef struct s_ovly_bfrs -{ - void *start; - unsigned long offset; - size_t length; -} t_ovly_bfrs; - -typedef struct -{ - int fd; - int run; - int dir; - int nbfrs; - int bufno; - int bufsz; - int last; - int width, height; - int keymode, colorkey; - int src_is_set, src_x, src_y, src_w, src_h; - int drw_is_set, drw_x, drw_y, drw_w, drw_h; - unsigned int pixfmt; - char dev_path[32]; - t_ovly_bfrs bfrs[MAX_BUFFERS]; - XF86VideoAdaptorPtr adpt; - XF86VideoEncodingPtr enc; - RegionRec clips; - int attrIds[1]; -} Z4lPortPrivRec; - -static int z4l_x_offset = 0; -static int z4l_y_offset = 0; -static int Z4l_nAdaptors = 0; -static XF86VideoAdaptorPtr *Z4l_pAdaptors = NULL; - -static int -IoCtl(int fd, unsigned int fn, void *arg, int flag) -{ - int ret; - - errno = 0; - ret = ioctl(fd, fn, arg); - if (ret != 0 && flag != 0) - DBLOG(0, "ioctl(%08x)=%d\n", fn, ret); - return ret; -} - -static void -z4l_ovly_unmap(Z4lPortPrivRec * pPriv) -{ - int i, nbfrs; - - nbfrs = pPriv->nbfrs; - for (i = 0; i < nbfrs; ++i) { - if (pPriv->bfrs[i].start != NULL) { - munmap(pPriv->bfrs[i].start, pPriv->bfrs[i].length); - pPriv->bfrs[i].start = NULL; - } - } - pPriv->nbfrs = -1; - pPriv->bufsz = -1; - pPriv->last = -1; -} - -static void -z4l_ovly_map(Z4lPortPrivRec * pPriv, int dir) -{ - long offset, bsz; - int i, fd; - struct v4l2_buffer bfr; - struct v4l2_requestbuffers req; - int type = dir >= 0 ? - V4L2_BUF_TYPE_VIDEO_CAPTURE : V4L2_BUF_TYPE_VIDEO_OVERLAY; - if (pPriv->run > 0) { - DBLOG(1, "busy\n"); - return; - } - fd = pPriv->fd; - memset(&req, 0, sizeof(req)); - req.type = type; - req.memory = V4L2_MEMORY_MMAP; - req.count = MAX_BUFFERS; - if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) - goto xit; - pPriv->nbfrs = req.count; - if (pPriv->nbfrs <= 0) { - DBLOG(1, "no vidmem\n"); - return; - } - memset(&pPriv->bfrs, 0, sizeof(pPriv->bfrs)); - - for (i = 0; i < pPriv->nbfrs; ++i) { - memset(&bfr, 0, sizeof(bfr)); - bfr.type = type; - bfr.index = i; - if (ioctl(fd, VIDIOC_QUERYBUF, &bfr) < 0) - goto xit; - offset = bfr.m.offset; - pPriv->bfrs[i].offset = offset; - pPriv->bfrs[i].length = bfr.length; - bsz = offset + bfr.length; - if (pPriv->bufsz < bsz) - pPriv->bufsz = bsz; - } - - for (i = 0; i < pPriv->nbfrs; ++i) { - pPriv->bfrs[i].start = mmap(NULL, bfr.length, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, pPriv->bfrs[i].offset); - if (pPriv->bfrs[i].start == MAP_FAILED) - goto xit; - } - - for (i = 0; i < pPriv->nbfrs; ++i) { - DBLOG(3, "bfr %d ofs %#lx adr %p sz %lu\n", i, pPriv->bfrs[i].offset, - pPriv->bfrs[i].start, (unsigned long)pPriv->bfrs[i].length); - memset(pPriv->bfrs[i].start, 0x80, pPriv->bfrs[i].length); - } - - pPriv->last = 0; - while (pPriv->last < pPriv->nbfrs - 1) { - bfr.index = pPriv->last++; - bfr.type = type; - if (ioctl(fd, VIDIOC_QBUF, &bfr) < 0) - goto xit; - } - return; - - xit: - z4l_ovly_unmap(pPriv); -} - -static int -z4l_ovly_dqbuf(Z4lPortPrivRec * pPriv) -{ - int stat; - struct v4l2_buffer bfr; - int fd = pPriv->fd; - -#ifdef HAVE_SELECT - struct timeval tmo; - fd_set dqset; - - FD_ZERO(&dqset); - FD_SET(pPriv->fd, &dqset); - tmo.tv_sec = 0; - tmo.tv_usec = 0; - if (select(fd + 1, &dqset, NULL, NULL, &tmo) <= 0) - return -1; -#endif - memset(&bfr, 0, sizeof(bfr)); - bfr.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - stat = ioctl(fd, VIDIOC_DQBUF, &bfr); - DBLOG(3, "dqbuf %d,%d,%d,%d\n", stat, bfr.index, pPriv->last, errno); - - return stat == 0 ? bfr.index : -1; -} - -static int -z4l_open_device(Z4lPortPrivRec * pPriv) -{ - int enable; - - if (pPriv->fd < 0) { - pPriv->fd = open(&pPriv->dev_path[0], O_RDWR, 0); - DBLOG(1, "open(%s)=%d\n", &pPriv->dev_path[0], pPriv->fd); - enable = 1; -#ifdef NONBLK_IO - if (IoCtl(pPriv->fd, FIONBIO, &enable, 1) != 0) { - DBLOG(1, "open cant enable nonblocking\n"); - close(pPriv->fd); - pPriv->fd = -1; - } -#endif - } - return pPriv->fd; -} - -static int -z4l_close_device(Z4lPortPrivRec * pPriv) -{ - int ret = 0; - - if (pPriv->fd >= 0) { - ret = close(pPriv->fd); - pPriv->fd = -1; - DBLOG(1, "close()=%d\n", ret); - } - if (pPriv->run > 0) { - z4l_ovly_unmap(pPriv); - pPriv->run = -1; - } - - return ret; -} - -static int -z4l_ovly_reset(Z4lPortPrivRec * pPriv) -{ - int ret = 0; - - if (pPriv->run > 0) { - z4l_close_device(pPriv); - ret = z4l_open_device(pPriv); - } - - return ret; -} - -static unsigned int -z4l_fourcc_pixfmt(int fourcc) -{ - unsigned int pixfmt = -1; - - switch (fourcc) { - case FOURCC_UYVY: - pixfmt = V4L2_PIX_FMT_UYVY; - break; - case FOURCC_YV12: - pixfmt = V4L2_PIX_FMT_YVU420; - break; - case FOURCC_Y800: - case FOURCC_I420: - pixfmt = V4L2_PIX_FMT_YUV420; - break; - case FOURCC_YUY2: - pixfmt = V4L2_PIX_FMT_YUYV; - break; - } - - return pixfmt; -} -static void -z4l_ovly_pixfmt(Z4lPortPrivRec * pPriv, unsigned int pixfmt) -{ - struct v4l2_framebuffer fbuf; - - DBLOG(1, "pixfmt %4.4s %4.4s\n", (char *)&pPriv->pixfmt, (char *)&pixfmt); - memset(&fbuf, 0, sizeof(fbuf)); - IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1); - fbuf.fmt.pixelformat = pixfmt; - fbuf.base = NULL; - IoCtl(pPriv->fd, VIDIOC_S_FBUF, &fbuf, 1); - pPriv->pixfmt = pixfmt; -} - -static void -z4l_ovly_bfr(Z4lPortPrivRec * pPriv, int width, int height) -{ - struct v4l2_format fmt; - - DBLOG(1, "sfmt ovly %dx%d\n", width, height); - memset(&fmt, 0, sizeof(fmt)); - fmt.type = 0x102; - IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1); - fmt.fmt.win.field = V4L2_FIELD_NONE; - fmt.fmt.win.w.width = pPriv->width = width; - fmt.fmt.win.w.height = pPriv->height = height; - IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1); -} - -static void -z4l_ovly_rect(Z4lPortPrivRec * pPriv, - int src_x, int src_y, int src_w, int src_h, - int drw_x, int drw_y, int drw_w, int drw_h) -{ - int x, dx, w, y, dy, h; - struct v4l2_format fmt; - - pPriv->src_x = src_x; - pPriv->src_y = src_y; - pPriv->src_w = src_w; - pPriv->src_h = src_h; - pPriv->drw_x = drw_x; - pPriv->drw_y = drw_y; - pPriv->drw_w = drw_w; - pPriv->drw_h = drw_h; - - if ((drw_x -= z4l_x_offset) < 0) { - if ((w = pPriv->drw_w) <= 0) - w = 1; - x = -drw_x; - dx = x * pPriv->src_w / w; - src_x = pPriv->src_x + dx; - src_w = pPriv->src_w - dx; - drw_w = pPriv->drw_w - x; - drw_x = 0; - } - - if ((drw_y -= z4l_y_offset) < 0) { - if ((h = pPriv->drw_h) <= 0) - h = 1; - y = -drw_y; - dy = y * pPriv->src_h / h; - src_y = pPriv->src_y + dy; - src_h = pPriv->src_h - dy; - drw_h = pPriv->drw_h - y; - drw_y = 0; - } - - memset(&fmt, 0, sizeof(fmt)); - fmt.type = 0x100; - IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1); - if (pPriv->src_is_set != 0) { - if (src_x != fmt.fmt.win.w.left || src_y != fmt.fmt.win.w.top || - src_w != fmt.fmt.win.w.width || src_h != fmt.fmt.win.w.height) - pPriv->src_is_set = 0; - } - if (pPriv->src_is_set == 0) { - pPriv->src_is_set = 1; - fmt.fmt.win.w.left = src_x; - fmt.fmt.win.w.top = src_y; - fmt.fmt.win.w.width = src_w; - fmt.fmt.win.w.height = src_h; - IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1); - DBLOG(3, " set src %d,%d %dx%d\n", src_x, src_y, src_w, src_h); - } - memset(&fmt, 0, sizeof(fmt)); - fmt.type = 0x101; - IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1); - if (pPriv->drw_is_set != 0) { - if (drw_x != fmt.fmt.win.w.left || drw_y != fmt.fmt.win.w.top || - drw_w != fmt.fmt.win.w.width || drw_h != fmt.fmt.win.w.height) - pPriv->drw_is_set = 0; - } - if (pPriv->drw_is_set == 0) { - pPriv->drw_is_set = 1; - fmt.fmt.win.w.left = drw_x; - fmt.fmt.win.w.top = drw_y; - fmt.fmt.win.w.width = drw_w; - fmt.fmt.win.w.height = drw_h; - IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1); - DBLOG(3, " set drw %d,%d %dx%d\n", drw_x, drw_y, drw_w, drw_h); - } -} - -static void -z4l_ovly_pitch(unsigned int pixfmt, int w, int h, int *py_pitch, - int *puv_pitch, int *poffset1, int *poffset2, int *psize) -{ - int y_pitch, uv_pitch; - int offset1, offset2; - int size, is_420; - - switch (pixfmt) { - case V4L2_PIX_FMT_YVU420: - case V4L2_PIX_FMT_YUV420: - is_420 = 1; - y_pitch = ((w + 1) / 2) * 2; - uv_pitch = (w + 1) / 2; - break; - default: - is_420 = 0; - y_pitch = ((w + 1) / 2) * 4; - uv_pitch = 0; - break; - } - - offset1 = y_pitch * h; - offset2 = uv_pitch * h; - - if (is_420 != 0) - offset2 /= 2; - - size = offset1 + 2 * offset2; - *py_pitch = y_pitch; - *puv_pitch = uv_pitch; - *poffset1 = offset1; - *poffset2 = offset2; - *psize = size; -} - -static int -z4l_ovly_set_colorkey(Z4lPortPrivRec * pPriv, int key) -{ - struct v4l2_format fmt; - - memset(&fmt, 0, sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - if (IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1) < 0) - return 0; - fmt.fmt.win.chromakey = key; - if (IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1) < 0) - return 0; - pPriv->colorkey = key; - - return 1; -} - -static int -z4l_ovly_get_colorkey(Z4lPortPrivRec * pPriv, int *key) -{ - struct v4l2_format fmt; - - memset(&fmt, 0, sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - if (IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1) < 0) - return 0; - *key = fmt.fmt.win.chromakey; - - return 1; -} - -static int -z4l_ovly_set_keymode(Z4lPortPrivRec * pPriv, int enable) -{ - struct v4l2_framebuffer fbuf; - - memset(&fbuf, 0, sizeof(fbuf)); - if (IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) - return 0; - - if (enable != 0) - fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; - else - fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; - - fbuf.base = NULL; - if (IoCtl(pPriv->fd, VIDIOC_S_FBUF, &fbuf, 1) < 0) - return 0; - pPriv->keymode = enable; - - return 1; -} - -static int -z4l_ovly_get_keymode(Z4lPortPrivRec * pPriv, int *enable) -{ - struct v4l2_framebuffer fbuf; - - memset(&fbuf, 0, sizeof(fbuf)); - if (IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) - return 0; - *enable = (fbuf.flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0 ? 1 : 0; - - return 1; -} - -static int -z4l_ovly_set_encoding(Z4lPortPrivRec * pPriv, int id) -{ - int l, n, inp; - char *cp; - t_std_data *sp; - XF86VideoEncodingPtr enc; - XF86VideoAdaptorPtr adpt; - v4l2_std_id std; - struct v4l2_format fmt; - struct v4l2_framebuffer fbuf; - - adpt = pPriv->adpt; - DBLOG(1, "z4l_ovly_set_encoding(%d)\n", id); - if (id < 0 || id >= adpt->nEncodings) - return 0; - enc = &adpt->pEncodings[id]; - cp = &enc->name[0]; - n = sizeof(int) - 1; - l = strlen(cp) + 1; - l = (l + n) & ~n; - sp = (t_std_data *) (cp + l); - inp = sp->inp; - - DBLOG(1, " nm %s fmt %4.4s inp %d std %llx\n", - cp, (char *)&sp->fmt, sp->inp, sp->std); - - if (IoCtl(pPriv->fd, VIDIOC_S_INPUT, &inp, 1) < 0) - return 0; - - std = sp->std; - if (IoCtl(pPriv->fd, VIDIOC_S_STD, &std, 1) < 0) - return 0; - - memset(&fmt, 0, sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1) < 0) - return 0; - - fmt.fmt.pix.pixelformat = sp->fmt; - if (IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1) < 0) - return 0; - memset(&fbuf, 0, sizeof(fbuf)); - - if (IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) - return 0; - - fbuf.fmt.pixelformat = sp->fmt; - fbuf.base = NULL; - if (IoCtl(pPriv->fd, VIDIOC_S_FBUF, &fbuf, 1) < 0) - return 0; - pPriv->pixfmt = sp->fmt; - pPriv->enc = enc; - pPriv->src_is_set = pPriv->drw_is_set = 0; - - return 1; -} - -static int -z4l_ovly_get_encoding(Z4lPortPrivRec * pPriv, int *id) -{ - XF86VideoEncodingPtr enc = pPriv->enc; - - *id = enc->id; - return 1; -} - -static void -z4l_ovly_stop(Z4lPortPrivRec * pPriv) -{ - int type, enable, fd; - - if (pPriv->run < 0) - return; - - fd = pPriv->fd; - if (pPriv->dir > 0) { - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - ioctl(fd, VIDIOC_STREAMOFF, &type); - } - - if (pPriv->dir <= 0) { - enable = 0; - ioctl(fd, VIDIOC_OVERLAY, &enable); - } - - if (pPriv->dir != 0) - z4l_ovly_unmap(pPriv); - - pPriv->run = -1; - z4l_close_device(pPriv); -} - -static void -z4l_ovly_start(Z4lPortPrivRec * pPriv, int dir) -{ - int enable; - - if (pPriv->run >= 0) - return; - - if ((pPriv->dir = dir) != 0) - z4l_ovly_map(pPriv, dir); - - enable = 1; - - if (IoCtl(pPriv->fd, VIDIOC_OVERLAY, &enable, 1) != 0) { - z4l_ovly_stop(pPriv); - return; - } - - pPriv->run = 1; -} - -static int -z4l_region_equal(RegionPtr ap, RegionPtr bp) -{ - int nboxes; - BoxPtr abox, bbox; - - if (ap == NULL && bp == NULL) - return 1; - if (ap == NULL || bp == NULL) - return 0; - - if ((nboxes = REGION_NUM_RECTS(ap)) != REGION_NUM_RECTS(bp) || - ap->extents.x1 != bp->extents.x1 || - ap->extents.x2 != bp->extents.x2 - || ap->extents.y1 != bp->extents.y1 - || ap->extents.y2 != bp->extents.y2) - return 0; - - abox = REGION_RECTS(ap); - bbox = REGION_RECTS(bp); - - while (--nboxes >= 0) { - if (abox->x1 != bbox->x1 || abox->y1 != bbox->y1 || - abox->x2 != bbox->x2 || abox->y2 != bbox->y2) - return 0; - ++abox; - ++bbox; - } - - return 1; -} - -static void -z4l_setup_colorkey(Z4lPortPrivRec * pPriv, ScreenPtr pScrn, - RegionPtr clipBoxes) -{ - if (pPriv->run > 0 && pPriv->dir <= 0 && pPriv->keymode != 0 && - z4l_region_equal(&pPriv->clips, clipBoxes) == 0) { - xf86XVFillKeyHelper(pScrn, pPriv->colorkey, clipBoxes); - REGION_COPY(pScrn, &pPriv->clips, clipBoxes); - } -} - -static void -Z4lStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit) -{ - Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; - - DBLOG(1, "Z4lStopVideo()\n"); - - if (exit != 0) - z4l_ovly_stop(pPriv); - else - pPriv->src_is_set = pPriv->drw_is_set = 0; - - REGION_EMPTY(pScrni->pScreen, &pPriv->clips); -} - -static void -Z4lQueryBestSize(ScrnInfoPtr pScrni, Bool motion, - short vid_w, short vid_h, short drw_w, short drw_h, - unsigned int *p_w, unsigned int *p_h, pointer data) -{ - if (drw_w > MAX_OVLY_WIDTH) - drw_w = MAX_OVLY_WIDTH; - if (drw_h > MAX_OVLY_HEIGHT) - drw_h = MAX_OVLY_HEIGHT; - - *p_w = drw_w; - *p_h = drw_h; - DBLOG(1, "Z4lQueryBestSize(%d, src %dx%d dst %dx%d)\n", motion, vid_w, - vid_h, drw_w, drw_h); -} - -static int -Z4lPutImage(ScrnInfoPtr pScrni, short src_x, short src_y, short drw_x, - short drw_y, short src_w, short src_h, short drw_w, short drw_h, - int id, unsigned char *buf, short width, short height, - Bool sync, RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) -{ - int fd, size; - int y_pitch, uv_pitch, offset1, offset2; - unsigned char *src, *dst; - unsigned int pixfmt; - struct v4l2_buffer bfr; - Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; - - if (pPriv->run > 0 && pPriv->dir >= 0) - return BadMatch; - if (pPriv->fd < 0) { - z4l_open_device(pPriv); - if (pPriv->fd < 0) - return BadValue; - } - - fd = pPriv->fd; - if (pPriv->run < 0) { - DBLOG(2, "PutImg id %#x src %d,%d %dx%d drw %d,%d %dx%d bfr %p " - "%dx%d data %p\n", id, src_x, src_y, src_w, src_h, drw_x, - drw_y, drw_w, drw_h, buf, width, height, data); - pPriv->pixfmt = pPriv->height = -1; - pPriv->src_is_set = pPriv->drw_is_set = 0; - } - - pixfmt = z4l_fourcc_pixfmt(id); - if (pixfmt != pPriv->pixfmt) { - z4l_ovly_reset(pPriv); - z4l_ovly_pixfmt(pPriv, pixfmt); - } - if (pPriv->width != width || pPriv->height != height) { - z4l_ovly_reset(pPriv); - z4l_ovly_bfr(pPriv, width, height); - } - - if (pPriv->src_is_set == 0 || pPriv->drw_is_set == 0 || - pPriv->src_x != src_x || pPriv->src_y != src_y || - pPriv->src_w != src_w || pPriv->src_h != src_h || - pPriv->drw_x != drw_x || pPriv->drw_y != drw_y || - pPriv->drw_w != drw_w || pPriv->drw_h != drw_h) - z4l_ovly_rect(pPriv, src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, - drw_h); - - if (pPriv->run < 0) { - z4l_ovly_start(pPriv, -1); - if (pPriv->run < 0) - return BadValue; - } - - if (pPriv->last < 0 && (pPriv->last = z4l_ovly_dqbuf(pPriv)) < 0) - return BadAlloc; - - z4l_ovly_pitch(pixfmt, width, height, &y_pitch, &uv_pitch, - &offset1, &offset2, &size); - src = buf; - dst = (unsigned char *)pPriv->bfrs[pPriv->last].start; - DBLOG(3, "cpy %4.4s src %p dst %p yp %d uvp %d o1 %d o2 %d sz %d\n", - (char *)&id, src, dst, y_pitch, uv_pitch, offset1, offset2, size); - - if (id == FOURCC_Y800) { - memcpy(dst, src, offset1); - src += offset1; - dst += offset1; - memset(dst, 0x80, 2 * offset2); - } else - memcpy(dst, src, size); - - memset(&bfr, 0, sizeof(bfr)); - bfr.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - bfr.index = pPriv->last; - bfr.timestamp.tv_sec = 0; - bfr.timestamp.tv_usec = 0; - bfr.flags |= V4L2_BUF_FLAG_TIMECODE; - if (IoCtl(fd, VIDIOC_QBUF, &bfr, 1) != 0) - return BadAccess; - - pPriv->last = z4l_ovly_dqbuf(pPriv); - z4l_setup_colorkey(pPriv, pScrni->pScreen, clipBoxes); - - return Success; -} - -static int -Z4lQueryImageAttributes(ScrnInfoPtr pScrni, int id, unsigned short *width, - unsigned short *height, int *pitches, int *offsets) -{ - int w, h, size; - int y_pitch, uv_pitch, offset1, offset2; - unsigned int pixfmt = z4l_fourcc_pixfmt(id); - - w = *width; - h = *height; - if (w > MAX_OVLY_WIDTH) - w = MAX_OVLY_WIDTH; - if (h > MAX_OVLY_HEIGHT) - h = MAX_OVLY_HEIGHT; - - z4l_ovly_pitch(pixfmt, w, h, &y_pitch, &uv_pitch, - &offset1, &offset2, &size); - - if (offsets != NULL) - offsets[0] = 0; - if (pitches != NULL) - pitches[0] = y_pitch; - - switch (pixfmt) { - case V4L2_PIX_FMT_YVU420: - case V4L2_PIX_FMT_YUV420: - if (offsets != NULL) { - offsets[1] = offset1; - offsets[2] = offset1 + offset2; - } - if (pitches != NULL) - pitches[1] = pitches[2] = uv_pitch; - h = (h + 1) & ~1; - break; - } - - w = (w + 1) & ~1; - *width = w; - *height = h; - DBLOG(1, "Z4lQueryImageAttributes(%4.4s) = %d, %dx%d %d/%d %d/%d\n", - (char *)&id, size, w, h, y_pitch, uv_pitch, offset1, offset2); - - return size; -} - -static int -Z4lPutVideo(ScrnInfoPtr pScrni, short src_x, short src_y, short drw_x, - short drw_y, short src_w, short src_h, short drw_w, short drw_h, - RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) -{ - int id; - Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; - - DBLOG(2, "PutVid src %d,%d %dx%d drw %d,%d %dx%d data %p\n", - src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, data); - - if (z4l_open_device(pPriv) >= 0) { - if (pPriv->run < 0) { - DBLOG(2, "PutVid start\n"); - z4l_ovly_get_encoding(pPriv, &id); - z4l_ovly_set_encoding(pPriv, id); - } - DBLOG(2, "PutVid priv %d,%d %dx%d drw %d,%d %dx%d\n", - pPriv->src_x, pPriv->src_y, pPriv->src_w, pPriv->src_h, - pPriv->drw_x, pPriv->drw_y, pPriv->drw_w, pPriv->drw_h); - if (pPriv->src_is_set == 0 || pPriv->drw_is_set == 0 || - pPriv->src_w != src_w || pPriv->src_h != src_h || - pPriv->drw_x != drw_x || pPriv->drw_y != drw_y || - pPriv->drw_w != drw_w || pPriv->drw_h != drw_h) - z4l_ovly_rect(pPriv, src_x, src_y, src_w, src_h, drw_x, drw_y, - drw_w, drw_h); - if (pPriv->run < 0) - z4l_ovly_start(pPriv, 0); - - z4l_setup_colorkey(pPriv, pScrni->pScreen, clipBoxes); - } - - return Success; -} - -static XF86VideoEncodingPtr -Z4lNewEncoding(XF86VideoEncodingPtr * encs, int *nencs) -{ - XF86VideoEncodingPtr enc; - XF86VideoEncodingPtr tencs = - (XF86VideoEncodingPtr) realloc(*encs, sizeof(*tencs) * (*nencs + 1)); - - if (tencs == NULL) - return NULL; - - *encs = tencs; - enc = &tencs[*nencs]; - ++*nencs; - memset(enc, 0, sizeof(*enc)); - - return enc; -} - -static void -Z4lEncodingName(char *ename, int l, char *inp_name, char *std_name, char *fmt) -{ - int i, ch; - - while ((ch = *inp_name++) != 0) { - if (isalnum(ch) == 0) - continue; - if (--l <= 0) - goto xit; - *ename++ = ch; - } - - if (--l <= 0) - goto xit; - - *ename++ = '-'; - - while ((ch = *std_name++) != 0) { - if (isalnum(ch) == 0) - continue; - if (--l <= 0) - goto xit; - *ename++ = ch; - } - - if (--l <= 0) - goto xit; - - *ename++ = '-'; - i = 4; - - while (--i >= 0 && (ch = *fmt++) != 0) { - if (isalnum(ch) == 0) - continue; - if (--l <= 0) - goto xit; - *ename++ = ch; - } - - xit: - *ename = 0; -} - -static int -Z4lAddEncoding(XF86VideoEncodingPtr enc, char *name, int id, int width, - int height, int numer, int denom, int inp, v4l2_std_id std, - unsigned int fmt) -{ - int l, n; - t_std_data *sp; - char *cp; - n = sizeof(int) - 1; - l = strlen(&name[0]) + 1; - l = (l + n) & ~n; - n = l + sizeof(*sp); - cp = (char *)malloc(n); - - if (cp == NULL) - return 0; - - sp = (t_std_data *) (cp + l); - enc->id = id; - strcpy(cp, &name[0]); - enc->name = cp; - enc->width = width; - enc->height = height; - enc->rate.numerator = numer; - enc->rate.denominator = denom; - sp->inp = inp; - sp->std = std; - sp->fmt = fmt; - DBLOG(1, "enc %s\n", &name[0]); - - return 1; -} - -static XF86ImagePtr -Z4lNewImage(XF86ImagePtr * imgs, int *nimgs) -{ - XF86ImagePtr img; - XF86ImagePtr timgs = - (XF86ImagePtr) realloc(*imgs, sizeof(*timgs) * (*nimgs + 1)); - - if (timgs == NULL) - return NULL; - - *imgs = timgs; - img = &timgs[*nimgs]; - ++*nimgs; - memset(img, 0, sizeof(*img)); - - return img; -} - -static int -Z4lAddImage(XF86ImagePtr img, XF86ImagePtr ip) -{ - *img = *ip; - DBLOG(1, "img %4.4s\n", (char *)&img->id); - return 1; -} - -static XF86AttributePtr -Z4lNewAttribute(XF86AttributePtr * attrs, int *nattrs) -{ - XF86AttributePtr attr; - XF86AttributePtr tattrs = - (XF86AttributePtr) realloc(*attrs, sizeof(*tattrs) * (*nattrs + 1)); - - if (tattrs == NULL) - return NULL; - - *attrs = tattrs; - attr = &tattrs[*nattrs]; - ++*nattrs; - memset(attr, 0, sizeof(*attr)); - - return attr; -} - -static void -Z4lAttributeName(char *bp, int l, char *cp) -{ - int ch; - char *atomNm = bp; - - if (l > 0) { - *bp++ = 'X'; - --l; - } - if (l > 0) { - *bp++ = 'V'; - --l; - } - if (l > 0) { - *bp++ = '_'; - --l; - } - - while (l > 0 && (ch = *cp++) != 0) { - if (isalnum(ch) == 0) - continue; - *bp++ = toupper(ch); - } - - *bp = 0; - MakeAtom(&atomNm[0], strlen(&atomNm[0]), TRUE); -} - -static int -Z4lAddAttribute(XF86AttributePtr attr, char *name, - int min, int max, int flags) -{ - char *cp = (char *)malloc(strlen((char *)&name[0]) + 1); - - if (cp == NULL) - return 0; - - attr->name = cp; - strcpy(&attr->name[0], name); - attr->min_value = min; - attr->max_value = max; - attr->flags = flags; - DBLOG(1, "attr %s\n", attr->name); - - return 1; -} - -static XF86VideoAdaptorPtr -Z4lNewAdaptor(XF86VideoAdaptorPtr ** adpts, int *nadpts, int nattrs) -{ - int n; - Z4lPortPrivRec *pPriv; - XF86VideoAdaptorPtr adpt, *tadpts; - - tadpts = (XF86VideoAdaptorPtr *) realloc(*adpts, - sizeof(*tadpts) * (*nadpts + 1)); - - if (tadpts == NULL) - return NULL; - - *adpts = tadpts; - n = sizeof(*adpt) + sizeof(*pPriv) + 1 * sizeof(*adpt->pPortPrivates); - n += (nattrs - 1) * sizeof(pPriv->attrIds[0]); - adpt = (XF86VideoAdaptorPtr) malloc(n); - - if (adpt == NULL) - return NULL; - - memset(adpt, 0, n); - tadpts[*nadpts] = adpt; - ++*nadpts; - adpt->pPortPrivates = (DevUnion *) & adpt[1]; - pPriv = (Z4lPortPrivRec *) & adpt->pPortPrivates[1]; - adpt->pPortPrivates[0].ptr = (pointer) pPriv; - pPriv->adpt = adpt; - adpt->nPorts = 1; - - return adpt; -} - -static int -Z4lSetPortAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value, - pointer data) -{ - Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; - XF86VideoAdaptorPtr adpt; - XF86AttributePtr attr; - struct v4l2_control ctrl; - int i, nattrs, attrId, val; - const char *name = NameForAtom(attribute); - int old_fd = pPriv->fd; - - DBLOG(1, "Z4lSetPortAttribute(%#lx,%d) '%s'\n", (unsigned long)attribute, - (int)value, name != NULL ? name : "_null_"); - - if (name == NULL) - return BadImplementation; - if (old_fd < 0 && z4l_open_device(pPriv) < 0) - return BadAccess; - - adpt = pPriv->adpt; - attr = adpt->pAttributes; - nattrs = adpt->nAttributes; - - for (i = 0; i < nattrs; ++i, ++attr) - if (strcmp(attr->name, name) == 0) - break; - - if (i >= nattrs) - return BadMatch; - - attrId = pPriv->attrIds[i]; - val = value; - - switch (attrId) { - case ATTR_ENCODING_ID: - z4l_ovly_set_encoding(pPriv, val); - break; - case ATTR_KEYMODE_ID: - z4l_ovly_set_keymode(pPriv, val); - REGION_EMPTY(pScrni->pScreen, &pPriv->clips); - z4l_setup_colorkey(pPriv, pScrni->pScreen, &pPriv->clips); - break; - case ATTR_COLORKEY_ID: - z4l_ovly_set_colorkey(pPriv, val); - break; - default: - memset(&ctrl, 0, sizeof(ctrl)); - ctrl.id = attrId + V4L2_CID_BASE; - ctrl.value = val; - if (IoCtl(pPriv->fd, VIDIOC_S_CTRL, &ctrl, 1) != 0) - return BadMatch; - break; - } - - if (old_fd < 0) - z4l_close_device(pPriv); - - return Success; -} - -static int -Z4lGetPortAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 * value, - pointer data) -{ - Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; - XF86VideoAdaptorPtr adpt; - XF86AttributePtr attr; - struct v4l2_control ctrl; - int i, nattrs, attrId, val; - const char *name = NameForAtom(attribute); - int old_fd = pPriv->fd; - - DBLOG(1, "Z4lGetPortAttribute(%#lx) '%s'\n", - (unsigned long)attribute, name != NULL ? name : "_null_"); - - if (name == NULL) - return BadImplementation; - if (old_fd < 0 && z4l_open_device(pPriv) < 0) - return BadAccess; - - adpt = pPriv->adpt; - attr = adpt->pAttributes; - nattrs = adpt->nAttributes; - - for (i = 0; i < nattrs; ++i, ++attr) - if (strcmp(attr->name, name) == 0) - break; - - if (i >= nattrs) - return BadMatch; - - attrId = pPriv->attrIds[i]; - val = 0; - - switch (attrId) { - case ATTR_ENCODING_ID: - z4l_ovly_get_encoding(pPriv, &val); - *value = val; - break; - case ATTR_KEYMODE_ID: - z4l_ovly_get_keymode(pPriv, &val); - *value = val; - break; - case ATTR_COLORKEY_ID: - z4l_ovly_get_colorkey(pPriv, &val); - break; - default: - memset(&ctrl, 0, sizeof(ctrl)); - ctrl.id = attrId + V4L2_CID_BASE; - if (IoCtl(pPriv->fd, VIDIOC_G_CTRL, &ctrl, 1) != 0) - return BadMatch; - val = ctrl.value; - break; - } - - if (old_fd < 0) - z4l_close_device(pPriv); - - *value = val; - - return Success; -} - -static void (*oldAdjustFrame) (int scrnIndex, int x, int y, int flags) = NULL; - -static void -Z4lAdjustFrame(int scrnIndex, int x, int y, int flags) -{ - int i; - XF86VideoAdaptorPtr adpt; - Z4lPortPrivRec *pPriv; - - DBLOG(3, "Z4lAdjustFrame(%d,%d,%d)\n", x, y, flags); - z4l_x_offset = x; - z4l_y_offset = y; - oldAdjustFrame(scrnIndex, x, y, flags); - - /* xv adjust does not handle putvideo case */ - for (i = 0; i < Z4l_nAdaptors; ++i) { - adpt = Z4l_pAdaptors[i]; - pPriv = (Z4lPortPrivRec *) adpt->pPortPrivates[0].ptr; - if (pPriv->run > 0) { - pPriv->drw_is_set = 0; - z4l_ovly_rect(pPriv, - pPriv->src_x, pPriv->src_y, pPriv->src_w, pPriv->src_h, - pPriv->drw_x, pPriv->drw_y, pPriv->drw_w, pPriv->drw_h); - } - } -} - -static int -Z4lInit(ScrnInfoPtr pScrni, XF86VideoAdaptorPtr ** adaptors) -{ - int i, id, fd, dev, enable, has_video, has_colorkey; - int ctl, cinp, inp, std, fmt, has_image; - int nadpts, nattrs, nencs, cenc, nimgs; - int numer, denom, width, height; - unsigned int pixfmt, cpixfmt, opixfmt; - XF86VideoAdaptorPtr *adpts, adpt; - XF86AttributePtr attrs, attr; - XF86VideoEncodingPtr encs, enc; - XF86ImagePtr ip, img, imgs; - Z4lPortPrivRec *pPriv; - char *dp, *msg; - char enc_name[256], attr_name[256]; - int attrIds[V4L2_CID_LASTP1 - V4L2_CID_BASE + ATTR_MAX_ID]; - struct v4l2_capability capability; - v4l2_std_id cstd_id, std_id; - struct v4l2_standard standard; - struct v4l2_format format, cfmt; - struct v4l2_input input; - struct v4l2_fmtdesc fmtdesc; - struct v4l2_queryctrl queryctrl; - struct v4l2_framebuffer fbuf; - - DBLOG(1, "Init\n"); - if (oldAdjustFrame == NULL) { - oldAdjustFrame = pScrni->AdjustFrame; - pScrni->AdjustFrame = Z4lAdjustFrame; - } - - fd = -1; - enc = NULL; - encs = NULL; - nencs = 0; - img = NULL; - imgs = NULL; - nimgs = 0; - attr = NULL; - attrs = NULL; - nattrs = 0; - adpt = NULL; - adpts = NULL; - nadpts = 0; - has_video = has_image = has_colorkey = 0; - - for (dev = 0; z4l_dev_paths[dev] != NULL; ++dev) { - fd = open(z4l_dev_paths[dev], O_RDWR, 0); - if (fd < 0) - continue; - DBLOG(1, "%s open ok\n", z4l_dev_paths[dev]); - msg = NULL; - enable = 1; - if (IoCtl(fd, VIDIOC_QUERYCAP, &capability, 1) < 0) - msg = "bad querycap"; - else if ((capability.capabilities & V4L2_CAP_VIDEO_OVERLAY) == 0) - msg = "no overlay"; - else if ((capability.capabilities & V4L2_CAP_STREAMING) == 0) - msg = "no streaming"; -#ifdef NONBLK_IO - else if (IoCtl(fd, FIONBIO, &enable, 1) != 0) - msg = "cant enable non-blocking io"; -#endif - if (msg == NULL) { - memset(&format, 0, sizeof(format)); - format.type = 0x100; - if (IoCtl(fd, VIDIOC_G_FMT, &format, 1) != 0) - msg = "no src/dst ovly fmt"; - } - if (msg != NULL) { - DBLOG(0, "%s %s\n", z4l_dev_paths[dev], msg); - close(fd); - continue; - } - - memset(&cfmt, 0, sizeof(cfmt)); - cfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (IoCtl(fd, VIDIOC_G_FMT, &cfmt, 1) < 0) - goto fail; - if (IoCtl(fd, VIDIOC_G_STD, &cstd_id, 1) < 0) - goto fail; - if (IoCtl(fd, VIDIOC_G_INPUT, &cinp, 1) < 0) - goto fail; - cpixfmt = cfmt.fmt.pix.pixelformat; - cenc = 0; - for (inp = 0;; ++inp) { - memset(&input, 0, sizeof(input)); - input.index = inp; - if (IoCtl(fd, VIDIOC_ENUMINPUT, &input, 0) < 0) - break; - id = inp; - if (IoCtl(fd, VIDIOC_S_INPUT, &id, 1) < 0) - goto fail; - for (std = 0;; ++std) { - memset(&standard, 0, sizeof(standard)); - standard.index = std; - if (IoCtl(fd, VIDIOC_ENUMSTD, &standard, 0) < 0) - break; - std_id = standard.id; - denom = standard.frameperiod.denominator; - numer = standard.frameperiod.numerator; - if (IoCtl(fd, VIDIOC_S_STD, &std_id, 1) < 0) - continue; - memset(&format, 0, sizeof(format)); - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (IoCtl(fd, VIDIOC_G_FMT, &format, 1) < 0) - continue; - width = format.fmt.pix.width; - height = format.fmt.pix.height; - for (fmt = 0;; ++fmt) { - memset(&fmtdesc, 0, sizeof(fmtdesc)); - fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmtdesc.index = fmt; - if (IoCtl(fd, VIDIOC_ENUM_FMT, &fmtdesc, 0) < 0) - break; - pixfmt = fmtdesc.pixelformat; - ip = &pixfmts[0]; - for (i = sizeof(pixfmts) / sizeof(pixfmts[0]); --i >= 0; - ++ip) - if (z4l_fourcc_pixfmt(ip->id) == pixfmt) - break; - - if (i >= 0) { - id = nencs; - has_video = 1; - if ((enc = Z4lNewEncoding(&encs, &nencs)) == NULL) - goto fail; - Z4lEncodingName(&enc_name[0], sizeof(enc_name), - (char *)&input.name[0], - (char *)&standard.name[0], (char *)&pixfmt); - if (Z4lAddEncoding(enc, &enc_name[0], id, width, - height, denom, numer, inp, std_id, - pixfmt) == 0) - goto fail; - if (std_id == cstd_id && inp == cinp - && pixfmt == cpixfmt) - cenc = id; - } - } - } - } - - if (IoCtl(fd, VIDIOC_S_INPUT, &cinp, 1) < 0) - goto fail; - if (IoCtl(fd, VIDIOC_S_STD, &cstd_id, 1) < 0) - goto fail; - if (IoCtl(fd, VIDIOC_S_FMT, &cfmt, 1) < 0) - goto fail; - - if (encs == NULL) { - DBLOG(0, "no encodings\n"); - goto fail; - } - - for (fmt = 0;; ++fmt) { - memset(&fmtdesc, 0, sizeof(fmtdesc)); - fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - fmtdesc.index = fmt; - if (IoCtl(fd, VIDIOC_ENUM_FMT, &fmtdesc, 0) < 0) - break; - pixfmt = fmtdesc.pixelformat; - ip = &pixfmts[0]; - for (i = sizeof(pixfmts) / sizeof(pixfmts[0]); --i >= 0; ++ip) - if (z4l_fourcc_pixfmt(ip->id) == pixfmt) - break; - - if (i >= 0) { - has_image = 1; - if ((img = Z4lNewImage(&imgs, &nimgs)) == NULL) - goto fail; - if (Z4lAddImage(img, ip) == 0) - goto fail; - } - } - - if (nimgs > 0) { - id = nencs; - if ((enc = Z4lNewEncoding(&encs, &nencs)) == NULL) - goto fail; - if (Z4lAddEncoding(enc, "XV_IMAGE", id, MAX_OVLY_WIDTH, - MAX_OVLY_HEIGHT, 0, 0, 0, 0, pixfmt) == 0) - goto fail; - } - - ctl = 0; - for (ctl = 0; ctl < (V4L2_CID_LASTP1 - V4L2_CID_BASE); ++ctl) { - memset(&queryctrl, 0, sizeof(queryctrl)); - queryctrl.id = V4L2_CID_BASE + ctl; - if (IoCtl(fd, VIDIOC_QUERYCTRL, &queryctrl, 0) < 0) - continue; - if (queryctrl.type != V4L2_CTRL_TYPE_INTEGER && - queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN) - continue; - attrIds[nattrs] = ctl; - if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) - goto fail; - Z4lAttributeName(&attr_name[0], sizeof(attr_name), - (char *)&queryctrl.name[0]); - if (Z4lAddAttribute(attr, &attr_name[0], - queryctrl.minimum, queryctrl.maximum, - XvSettable | XvGettable) == 0) - goto fail; - } - attrIds[nattrs] = ATTR_ENCODING_ID; - if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) - goto fail; - Z4lAttributeName(&attr_name[0], sizeof(attr_name), ATTR_ENCODING); - if (Z4lAddAttribute(attr, &attr_name[0], 0, nencs - 1, - XvSettable | XvGettable) == 0) - goto fail; - memset(&fbuf, 0, sizeof(fbuf)); - if (IoCtl(fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) - goto fail; - opixfmt = fbuf.fmt.pixelformat; - - if ((fbuf.capability & V4L2_FBUF_CAP_CHROMAKEY) != 0) { - attrIds[nattrs] = ATTR_KEYMODE_ID; - if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) - goto fail; - Z4lAttributeName(&attr_name[0], sizeof(attr_name), ATTR_KEYMODE); - if (Z4lAddAttribute(attr, &attr_name[0], 0, 1, - XvSettable | XvGettable) == 0) - goto fail; - attrIds[nattrs] = ATTR_COLORKEY_ID; - if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) - goto fail; - Z4lAttributeName(&attr_name[0], sizeof(attr_name), ATTR_COLORKEY); - if (Z4lAddAttribute(attr, &attr_name[0], 0, 0xffffff, - XvSettable | XvGettable) == 0) - goto fail; - has_colorkey = 1; - } - - dp = malloc(strlen((char *)&capability.card[0]) + 1); - if (dp == NULL) - goto fail; - strcpy(dp, (char *)&capability.card[0]); - if ((adpt = Z4lNewAdaptor(&adpts, &nadpts, nattrs)) == NULL) - goto fail; - adpt->type = XvWindowMask | XvInputMask; - if (has_video != 0) - adpt->type |= XvVideoMask; - if (has_image != 0) - adpt->type |= XvImageMask; - adpt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; - adpt->name = dp; - adpt->type = XvInputMask | XvWindowMask | XvVideoMask | XvImageMask; - adpt->pEncodings = encs; - adpt->nEncodings = nencs; - adpt->pFormats = &Formats[0]; - adpt->nFormats = sizeof(Formats) / sizeof(Formats[0]); - adpt->pAttributes = attrs; - adpt->nAttributes = nattrs; - attrs = NULL; - nattrs = 0; - adpt->pImages = imgs; - adpt->nImages = nimgs; - imgs = NULL; - nimgs = 0; - adpt->PutVideo = Z4lPutVideo; - adpt->StopVideo = Z4lStopVideo; - adpt->SetPortAttribute = Z4lSetPortAttribute; - adpt->GetPortAttribute = Z4lGetPortAttribute; - adpt->QueryBestSize = Z4lQueryBestSize; - adpt->PutImage = Z4lPutImage; - adpt->QueryImageAttributes = Z4lQueryImageAttributes; - pPriv = (Z4lPortPrivRec *) adpt->pPortPrivates[0].ptr; - pPriv->fd = fd; - pPriv->run = -1; - pPriv->dir = 0; - pPriv->nbfrs = -1; - pPriv->bufsz = -1; - pPriv->last = -1; - pPriv->pixfmt = opixfmt; -#if defined(REGION_NULL) - REGION_NULL(pScrni->pScreen, &pPriv->clips); -#else - REGION_INIT(pScrni->pScreen, &pPriv->clips, NullBox, 0); -#endif - strncpy(&pPriv->dev_path[0], z4l_dev_paths[dev], - sizeof(pPriv->dev_path)); - pPriv->enc = &encs[cenc]; - for (i = 0; i < adpt->nAttributes; ++i) - pPriv->attrIds[i] = attrIds[i]; - DBLOG(1, "adpt %s\n", dp); - if (has_colorkey != 0) { - z4l_ovly_set_colorkey(pPriv, DEFAULT_COLORKEY); - z4l_ovly_set_keymode(pPriv, DEFAULT_KEYMODE); - } - close(fd); - pPriv->fd = -1; - adpt = NULL; - cenc = 0; - encs = NULL; - nencs = 0; - } - - DBLOG(0, "init done, %d device(s) found\n", nadpts); - Z4l_nAdaptors = nadpts; - Z4l_pAdaptors = adpts; - *adaptors = adpts; - - return nadpts; - - fail: - if (attrs != NULL) { - for (i = 0; i < nattrs; ++i) - if (attrs[i].name != NULL) - free(attrs[i].name); - free(attrs); - } - - if (encs != NULL) { - for (i = 0; i < nencs; ++i) { - if (encs[i].name != NULL) - free(encs[i].name); - } - free(encs); - } - - if (imgs != NULL) - free(imgs); - - if (adpts != NULL) { - for (i = 0; i < nadpts; ++i) { - if ((adpt = adpts[i]) != NULL) { - if (adpt->name != NULL) - free(adpt->name); - if ((attrs = adpt->pAttributes) != NULL) { - for (i = 0; i < adpt->nAttributes; ++i) - if (attrs[i].name != NULL) - free(attrs[i].name); - free(attrs); - } - if ((encs = adpt->pEncodings) != NULL) { - for (i = 0; i < adpt->nEncodings; ++i, ++enc) - if (encs[i].name != NULL) - free(encs[i].name); - free(encs); - } - if ((imgs = adpt->pImages) != NULL) - free(imgs); - free(adpt); - } - } - free(adpts); - } - - if (fd >= 0) - close(fd); - - return 0; -} - -static Bool -Z4lProbe(DriverPtr drv, int flags) -{ - DBLOG(1, "Probe\n"); - if (flags & PROBE_DETECT) - return TRUE; - - xf86XVRegisterGenericAdaptorDriver(Z4lInit); - drv->refCount++; - - return TRUE; -} - -static const OptionInfoRec * -Z4lAvailableOptions(int chipid, int busid) -{ - return NULL; -} - -static void -Z4lIdentify(int flags) -{ - xf86Msg(X_INFO, "z4l driver for Video4Linux\n"); -} - -_X_EXPORT DriverRec Z4l = { - 40001, - "z4l", - Z4lIdentify, - Z4lProbe, - Z4lAvailableOptions, - NULL, - 0 -}; - -#ifdef XFree86LOADER - -static MODULESETUPPROTO(z4lSetup); - -static XF86ModuleVersionInfo z4lVersionRec = { - "ztv", - MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, - XORG_VERSION_CURRENT, 0, 0, 1, - ABI_CLASS_VIDEODRV, ABI_VIDEODRV_VERSION, MOD_CLASS_NONE, - {0, 0, 0, 0} -}; - -_X_EXPORT XF86ModuleData ztvModuleData = { &z4lVersionRec, z4lSetup, NULL }; - -static pointer -z4lSetup(pointer module, pointer opts, int *errmaj, int *errmin) -{ - const char *osname; - static Bool setupDone = FALSE; - - if (setupDone != FALSE) { - if (errmaj != NULL) - *errmaj = LDR_ONCEONLY; - return NULL; - } - - setupDone = TRUE; - LoaderGetOS(&osname, NULL, NULL, NULL); - - if (osname == NULL || strcmp(osname, "linux") != 0) { - if (errmaj) - *errmaj = LDR_BADOS; - if (errmin) - *errmin = 0; - - return NULL; - } - - xf86AddDriver(&Z4l, module, 0); - - return (pointer) 1; -} - -#endif -#endif /* !XvExtension */ -- cgit v1.2.3