Hi,

The current method used in mplayer to detect an PVR350 at the ivtv-vidix-driver fails, if the PVR350 is not the first ivtv-card and you haven't set FRAMEBUFFER in your environment.

I developed a patch against the current trunk of mplayer, which iterates through the /sys/class/video4linux/video an /sys/class/graphics/fb directories or, if they are not present, the /dev/video and /dev/fb files.

VIDIOC_QUERYCAP tells me the right driver and capabilites of the found devices and like the example in the v4l2-spec I search for the related framebuffer.

The only hack is a missing possibility of distinguish the multiple devices of a PVR350 (video0, video16, video32, video48 etc) to get the YUV-decoder. v4l2 returns the same capabilities for every device. The
code has to know it's at video48+x.

Since this is my first v4l2-related coding, some ivtv/v4l2-prof can have a look at it, that I'm doing things right. After that I would post it at mplayer-dev-eng.

Lars.
Index: vidix/ivtv_vid.c
===================================================================
--- vidix/ivtv_vid.c    (Revision 26994)
+++ vidix/ivtv_vid.c    (Arbeitskopie)
@@ -22,6 +22,7 @@
  */
 
 #include <errno.h>
+#include <glob.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -30,6 +31,7 @@
 #include <inttypes.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <sys/stat.h>
 #include <linux/types.h>
 #include <linux/version.h>
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
@@ -224,100 +226,173 @@
 
 int ivtv_probe(int verbose,int force __attribute__ ((unused)))
 {
-       unsigned char fb_number = 0;
-       char *device_name = NULL;
-       char *alpha = NULL;
-       struct fb_var_screeninfo vinfo;
-       char fb_dev_name[] = "/dev/fb0\0";
-       pciinfo_t lst[MAX_PCI_DEVICES];
-       int err = 0;
-       unsigned int i, num_pci = 0;
+       int    i;
+       struct stat fileStat;
+       char   sysfsVideoClass[] = "/sys/class/video4linux\0";
+       char   sysfsGraphicsClass[] = "/sys/class/graphics\0";
+       char   *yuv_searchPattern[] = { "/sys/class/video4linux/video*\0", 
"/dev/video*\0"};
+       char   *fb_searchPattern[] = { "/sys/class/graphics/fb*\0", 
"/dev/fb*\0"};
+       int    yuv_patNr = 0;
+       int    fb_patNr = 0;
+       glob_t searchResult;
+       char   deviceName[] = "/dev/videoXXXXX\0";
+       int    devLen = 0;
+       struct v4l2_capability vcap;
+       struct v4l2_fmtdesc vfdesc;
+       int    found_yuv_format = 0;
+       char   *tmpStr = 0;
+       int    yuvDevNumber = -1;
+       struct v4l2_framebuffer fbuf;
+       struct fb_fix_screeninfo fbsi;
 
        if(verbose)
-               printf(IVTV_MSG"probe\n");
-
+               printf(IVTV_MSG"probe\n");
+
        ivtv_verbose = verbose;
+       
+       /* test if sysfs is present, otherwise fallback to /dev */
+       if(access(sysfsVideoClass, F_OK) < 0)
+               yuv_patNr = 1;
+       if(access(sysfsGraphicsClass, F_OK) < 0)
+               fb_patNr = 1;
 
-       err = pci_scan(lst, &num_pci);
-       if(err) {
-               printf(IVTV_MSG"Error occured during pci scan: %s\n", 
strerror(err));
-               return err;
-       }
+       /* search for the installed video devices */
+       if(glob(yuv_searchPattern[yuv_patNr], GLOB_MARK, 0, &searchResult) == 
0) {
+               for(i = 0; (yuvDevNumber < 0) && (i < searchResult.gl_pathc); 
i++) {
+                       if(stat(searchResult.gl_pathv[i], &fileStat) == 0) {
+                               devLen = 0;
+                               if((yuv_patNr == 0) && 
S_ISDIR(fileStat.st_mode)) {
+                                       /* get the related device-node */
+                                       snprintf(deviceName, 
sizeof(deviceName), "/dev/%s", searchResult.gl_pathv[i] + 
strlen(sysfsVideoClass) + 1);
+                                       devLen = strlen(deviceName);
+                                       if(deviceName[devLen - 1] == '/') {
+                                               devLen--;
+                                               deviceName[devLen]= 0;
+                                       }
+                               } else if((yuv_patNr == 1) && 
!S_ISDIR(fileStat.st_mode)) {
+                                       snprintf(deviceName, 
sizeof(deviceName), "%s", searchResult.gl_pathv[i]);
+                                       devLen = strlen(deviceName);
+                               }
+                               
+                               if(devLen > 0) {
+                                       yuvdev = open(deviceName, O_RDONLY);
+                                       if(-1 == yuvdev) {
+                                               printf(IVTV_MSG"Error occured 
during opening %s\n", deviceName);
+                                       } else {
+                                               if(ioctl(yuvdev, 
VIDIOC_QUERYCAP, &vcap) < 0) {
+                                                       printf(IVTV_MSG"unable 
to query capabilites of %s\n", deviceName);
+                                               } else if(strncmp(vcap.driver, 
"ivtv", 4) == 0) {
+                                                       if(vcap.capabilities & 
V4L2_CAP_VIDEO_OUTPUT) {
+                                                               /* it is a 
device handled by ivtv and it has an output */
+                                                               vfdesc.index = 
0;
+                                                               vfdesc.type = 
V4L2_BUF_TYPE_VIDEO_OUTPUT;
+                                                               
found_yuv_format = 0;
+                                                               
while(ioctl(yuvdev, VIDIOC_ENUM_FMT, &vfdesc) == 0) {
+                                                                       
if(vfdesc.pixelformat == V4L2_PIX_FMT_HM12) {
+                                                                               
found_yuv_format= 1;
+                                                                               
break;
+                                                                       }
+                                                                       
vfdesc.index++;
+                                                               }
+                                                               
if(found_yuv_format) {
+                                                                       /* it 
supports the needed pixel format */
 
-       if(ivtv_verbose)
-               printf(IVTV_MSG"Found %d pci devices\n", num_pci);
-
-       for(i = 0; i < num_pci; i++) {
-               if(2 == ivtv_verbose)
-                       printf(IVTV_MSG"Found chip [%04X:%04X] '%s' '%s'\n"
-                               ,lst[i].vendor
-                               ,lst[i].device
-                               ,pci_vendor_name(lst[i].vendor)
-                               ,pci_device_name(lst[i].vendor,lst[i].device));
-               if(VENDOR_INTERNEXT == lst[i].vendor) {
-                       switch(lst[i].device)
-                       {
-                       case DEVICE_INTERNEXT_ITVC15_MPEG_2_ENCODER:
-                               if(ivtv_verbose)
-                                       printf(IVTV_MSG"Found PVR 350\n");
-                               goto card_found;
+                                                                       /* hack 
is here
+                                                                       there 
is a problem at the v4l2-api
+                                                                       a 
PVR350 has multiple devices
+                                                                       
/dev/video0
+                                                                       
/dev/video16
+                                                                       
/dev/video32
+                                                                       
/dev/video48
+                                                                       
VIDIOC_QUERYCAP returns the same for every device
+                                                                       so the 
code has to know that the YUV-decoder is
+                                                                       at 
/dev/video48 or higher
+
+                                                                       maybe 
this is solved in the future...
+                                                                       */
+                                                                       tmpStr 
= deviceName + devLen;
+                                                                       
while((tmpStr >= deviceName) && isdigit((tmpStr-1)[0]))
+                                                                               
tmpStr--;
+                                                                       
if(tmpStr > deviceName) {
+                                                                               
yuvDevNumber = atoi(tmpStr);
+                                                                               
/* which one of the devices of the PVR350 have I found? */
+                                                                               
if(yuvDevNumber >= 48) {
+                                                                               
        /* this is the right device, do nothing */
+                                                                               
} else if(yuvDevNumber >= 32) {
+                                                                               
        yuvDevNumber = 48 + yuvDevNumber - 32;
+                                                                               
} else if(yuvDevNumber >= 16) {
+                                                                               
        yuvDevNumber = 48 + yuvDevNumber - 16;
+                                                                               
} else if(yuvDevNumber >= 0) {
+                                                                               
        yuvDevNumber = 48 + yuvDevNumber - 0;
+                                                                               
} else
+                                                                               
        yuvDevNumber = -1;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                               close(yuvdev);
+                                               yuvdev = -1;
+                                       }
+                               }
                        }
                }
        }
-       
-       if(ivtv_verbose)
-               printf(IVTV_MSG"Can't find chip\n");
-       return ENXIO;
-
-card_found:
-
-       device_name = getenv("FRAMEBUFFER");
-       if(NULL == device_name) {
-               device_name = fb_dev_name;
+       globfree(&searchResult);
+       if(yuvDevNumber < 0) {
+               printf(IVTV_MSG"no ivtv-driven yuv-decoder found\n");
+               return ENXIO;
        }
 
-       fb_number = atoi(device_name+strlen("/dev/fb"));
-
-       fbdev = open(device_name, O_RDWR);
-       if(-1 != fbdev) {
-               if(ioctl(fbdev, FBIOGET_VSCREENINFO, &vinfo) < 0) {
-                       printf(IVTV_MSG"Unable to read screen info\n");
-                       close(fbdev);
-                       return ENXIO;
-               } else {
-                       fb_width = vinfo.xres;
-                       fb_height = vinfo.yres;
-                       if(2 == ivtv_verbose) {
-                               printf(IVTV_MSG"framebuffer width : 
%3.0f\n",fb_width);
-                               printf(IVTV_MSG"framebuffer height: 
%3.0f\n",fb_height);
+       snprintf(deviceName, sizeof(deviceName), "/dev/video%d", yuvDevNumber);
+       yuvdev = open(deviceName, O_RDWR);
+       if(-1 == yuvdev) {
+               printf(IVTV_MSG"Error opening yuv-decoder %s\n", deviceName);
+       } else {
+               if(verbose)
+                       printf(IVTV_MSG"Found yuv-decoder %s\n", deviceName);
+               if(ioctl(yuvdev, VIDIOC_G_FBUF, &fbuf) == 0) {
+                       /* searching for the related framebuffer-device */
+                       if(glob(fb_searchPattern[fb_patNr], GLOB_MARK, 0, 
&searchResult) == 0) {
+                               for(i = 0; i < searchResult.gl_pathc; i++) {
+                                       if(stat(searchResult.gl_pathv[ i], 
&fileStat) == 0) {
+                                               devLen = 0;
+                                               if((fb_patNr == 0) && 
S_ISDIR(fileStat.st_mode)) {
+                                                       snprintf(deviceName, 
sizeof(deviceName), "/dev/%s", searchResult.gl_pathv[i] + 
strlen(sysfsGraphicsClass) + 1);
+                                                       devLen = strlen( 
deviceName);
+                                                       if(deviceName[devLen - 
1] == '/') {
+                                                               devLen--;
+                                                               
deviceName[devLen] = 0;
+                                                       }
+                                               } else if((fb_patNr == 1) && 
!S_ISDIR(fileStat.st_mode)) {
+                                                       snprintf(deviceName, 
sizeof(deviceName), "%s", searchResult.gl_pathv[i]);
+                                                       devLen = 
strlen(deviceName);
+                                               }
+                                               
+                                               if(devLen > 0) {
+                                                       fbdev = 
open(deviceName, O_RDWR);
+                                                       if(-1 == fbdev) {
+                                                               
printf(IVTV_MSG"Error occured during opening %s\n", deviceName);
+                                                       } else {
+                                                               if(0 == 
ioctl(fbdev, FBIOGET_FSCREENINFO, &fbsi)) {
+                                                                       
if(fbsi.smem_start == (unsigned long) fbuf.base)
+                                                                               
break; /* found it */
+                                                               }
+                                                               close(fbdev);
+                                                               fbdev = -1;
+                                                       }
+                                               }
+                                       }
+                               }
+                               globfree(&searchResult);
                        }
                }
-               if(NULL != (alpha = getenv("VIDIXIVTVALPHA"))) {
-                       if(0 == strcmp(alpha, "disable")) {
-                               alpha_disable = 1;
-                       }
-               }
-       } else {
-               printf(IVTV_MSG"Failed to open /dev/fb%u\n", fb_number);
-               return ENXIO;
+               if(-1 == fbdev) {
+                       printf(IVTV_MSG"no related framebuffer found\n");
+                       close(yuvdev);
+                       yuvdev = -1;
+               } else
+                       goto yuv_found;
        }
-
-       /* Try to find YUV device */
-       unsigned char yuv_device_number = 48, yuv_device = 48 + fb_number;
-       char yuv_device_name[] = "/dev/videoXXX\0";
-       
-       do {
-               sprintf(yuv_device_name, "/dev/video%u", yuv_device);
-               yuvdev = open(yuv_device_name, O_RDWR);
-               if(-1 != yuvdev) {
-                       if(ivtv_verbose)
-                               printf(IVTV_MSG"YUV device found 
/dev/video%u\n", yuv_device);
-                       goto yuv_found;
-               } else {
-                       if(ivtv_verbose)
-                               printf(IVTV_MSG"YUV device not found: 
/dev/video%u\n", yuv_device);
-               }
-       } while(yuv_device-- > yuv_device_number);
        return ENXIO;
 
 yuv_found:
_______________________________________________
ivtv-devel mailing list
[email protected]
http://ivtvdriver.org/mailman/listinfo/ivtv-devel

Reply via email to