Hi,
I finally found some time to go over the v4l patch. I've cleaned it up
a bit (move yuv detection stuff into a function, loop instead of
cut+paste, ...). It survived the ItWorksForMe[tm] test, but I'd like to
know whenever it still works for the dvb people before I send it the way
to the xfree86 cvs ...
Gerd
==============================[ cut here ]==============================
diff -ur /home/my-cvs/xfree86/xc/programs/Xserver/hw/xfree86/drivers/v4l/v4l.c
xc/programs/Xserver/hw/xfree86/drivers/v4l/v4l.c
--- /home/my-cvs/xfree86/xc/programs/Xserver/hw/xfree86/drivers/v4l/v4l.c Thu
Nov 1 12:23:10 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/v4l/v4l.c Fri Mar 1 12:22:50 2002
@@ -132,7 +132,7 @@
XF86OffscreenImagePtr format; /* list */
int nformat; /* # if list entries */
XF86OffscreenImagePtr myfmt; /* which one is YUY2 (packed) */
- int have_yuv;
+ int yuv_format;
int yuv_width,yuv_height;
XF86SurfacePtr surface;
@@ -286,7 +286,7 @@
return Success;
}
- if (pPPriv->have_yuv) {
+ 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 */
@@ -338,7 +338,7 @@
perror("ioctl VIDIOCSFBUF");
if (-1 == ioctl(V4L_FD,VIDIOCGPICT,&pPPriv->pict))
perror("ioctl VIDIOCGPICT");
- pPPriv->pict.palette = VIDEO_PALETTE_YUV422;
+ pPPriv->pict.palette = pPPriv->yuv_format;
pPPriv->pict.depth = 16;
if (-1 == ioctl(V4L_FD,VIDIOCSPICT,&pPPriv->pict))
perror("ioctl VIDIOCSPICT");
@@ -585,7 +585,7 @@
} else if (attribute == xvFreq) {
if (-1 == ioctl(V4L_FD,VIDIOCSFREQ,&value))
perror("ioctl VIDIOCSFREQ");
- } else if (pPPriv->have_yuv &&
+ } else if (0 != pPPriv->yuv_format &&
pPPriv->myfmt->setAttribute) {
/* not mine -> pass to yuv scaler driver */
ret = pPPriv->myfmt->setAttribute(pScrn, attribute, value);
@@ -636,7 +636,7 @@
}
} else if (attribute == xvFreq) {
ioctl(V4L_FD,VIDIOCGFREQ,value);
- } else if (pPPriv->have_yuv &&
+ } else if (0 != pPPriv->yuv_format &&
pPPriv->myfmt->getAttribute) {
/* not mine -> pass to yuv scaler driver */
ret = pPPriv->myfmt->getAttribute(pScrn, attribute, value);
@@ -660,7 +660,7 @@
int maxx = pPPriv->enc[pPPriv->cenc].width;
int maxy = pPPriv->enc[pPPriv->cenc].height;
- if (pPPriv->have_yuv) {
+ if (0 != pPPriv->yuv_format) {
*p_w = pPPriv->myfmt->max_width;
*p_h = pPPriv->myfmt->max_height;
} else {
@@ -838,10 +838,54 @@
(*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)
{
- ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
PortPrivPtr pPPriv;
DevUnion *Private;
XF86VideoAdaptorPtr *VAR = NULL;
@@ -880,35 +924,7 @@
V4LBuildEncodings(pPPriv,fd,pPPriv->cap.channels);
if (NULL == pPPriv->enc)
return FALSE;
-
-#if 1
- /* test v4l device for yuv support: check if the driver
- accepts VIDEO_PALETTE_YUV422 */
- ioctl(fd,VIDIOCGPICT,&pPPriv->pict);
- pPPriv->pict.palette = VIDEO_PALETTE_YUV422;
- pPPriv->pict.depth = 16;
- if (0 == ioctl(fd,VIDIOCSPICT,&pPPriv->pict)) {
- ioctl(fd,VIDIOCGPICT,&pPPriv->pict);
- if (VIDEO_PALETTE_YUV422 == pPPriv->pict.palette) {
- /* works, check screen capabilities */
- DEBUG(xf86Msg(X_INFO, "v4l: kernel driver supports yuv422.\n"));
- pPPriv->format = xf86XVQueryOffscreenImages
- (pScreen,&pPPriv->nformat);
- DEBUG(xf86Msg(X_INFO, "v4l: screen driver supports %d yuv formats
(%p)\n",
- pPPriv->nformat,pPPriv->format));
- for (j = 0; j < pPPriv->nformat; j++) {
- DEBUG(xf86Msg(X_INFO, "v4l: yuv format: %4.4s\n",
- (char*)&(pPPriv->format[j].image->id)));
- if (pPPriv->format[j].image->id == 0x32595559 &&
- pPPriv->format[j].image->format == XvPacked) {
- pPPriv->have_yuv = 1;
- pPPriv->myfmt = pPPriv->format+j;
- DEBUG(xf86Msg(X_INFO, "v4l: matching format found, offscreen
yuv enabled.\n"));
- }
- }
- }
- }
-#endif
+ v4l_check_yuv(pScrn,pPPriv,dev,fd);
/* alloc VideoAdaptorRec */
VAR = xrealloc(VAR,sizeof(XF86VideoAdaptorPtr)*(i+1));
@@ -938,7 +954,7 @@
v4l_add_attr(&VAR[i]->pAttributes, &VAR[i]->nAttributes,
&FreqAttr);
}
- if (pPPriv->have_yuv) {
+ 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,
_______________________________________________
Video4linux-list mailing list
[EMAIL PROTECTED]
https://listman.redhat.com/mailman/listinfo/video4linux-list