Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] Re: VDR Admin GRAB command



Andreas Kool wrote:
> 
> On Tue, Sep 16, 2003 at 11:52:04PM +0200, Klaus Schmidinger wrote:
> > Andreas Kool wrote:
> > >
> > > On Sun, Sep 14, 2003 at 06:20:51PM -0700, Dirk Essl wrote:
> > > >
> > > >
> > > > Hi everybody,
> > > >
> > > > I got a problem while using the "TV" Window in VDR Admin
> > > > it grabs a frame from my Hauppauge WinTV, and not from the DVB Card.
> > > > The bttv09 module is loaded before the DVB driver, because only this way
> > > > it works at my system.
> > >
> > > Use this patch:
> > >
> > > ---8<-----if--you--cut--here--you--will--probably--destroy--your--monitor---
> > > --- dvbdevice.c.orig    2003-08-26 18:15:51.000000000 +0200
> > > +++ dvbdevice.c 2003-08-26 18:13:50.000000000 +0200
> > > @@ -583,7 +583,35 @@
> > >  bool cDvbDevice::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY)
> > >  {
> > >    char buffer[PATH_MAX];
> > > -  snprintf(buffer, sizeof(buffer), "%s%d", DEV_VIDEO, CardIndex());
> > > +  static int ofs = -1;
> > > +  FILE *f;
> > > +
> > > +  if (ofs == -1) { // firsttime
> > > +    while (1) {
> > > +      snprintf(buffer, sizeof buffer, "/proc/video/dev/video%d", ++ofs);
> > > +
> > > +      if ((f = fopen(buffer, "r")) == (FILE *)NULL) { // does not exist?
> > > +        ofs = 0;
> > > +        break;
> > > +      }
> > > +
> > > +      if (fgets(buffer, sizeof buffer, f)) {
> > > +        if (strstr(buffer, "DVB Board")) // found the _first_ DVB card
> > > +          break;
> > > +      }
> > > +      else {
> > > +        ofs = 0;
> > > +        break;
> > > +      }
> > > +
> > > +      fclose(f);
> > > +    }
> > > +
> > > +    fclose(f);
> > > +
> > > +  }
> > > +
> > > +  snprintf(buffer, sizeof(buffer), "%s%d", DEV_VIDEO, CardIndex() + ofs);
> > >    isyslog("grabbing from %s", buffer);
> > >    int videoDev = open(buffer, O_RDWR);
> > >    if (videoDev < 0)
> > > ---8<-----if--you--cut--here--you--will--probably--destroy--your--monitor---
> >
> > I'm not sure whether this is a real _solution_ to the problem.
> 
> No, it is'nt, but better than nothing/*wrong* functionality!
> 
> > It _may_ work, if the primary device id the _first_ DVB card.
> > But what if it isn't?
> 
> Sorry, Klaus, but my patch works in *any* combination (i can think about)!
> 
> Lets think about a really big machine:
> 
> /dev/video0 -> non DVB-card, maybe a WEBCAM
> /dev/video1 -> non DVB-card, a grabber card
> /dev/video2 -> non DVB-card, a analog tv-card
> /dev/video3 -> DVB-card
> /dev/video4 -> DVB-card
> /dev/video5 -> DVB-card
> /dev/video6 -> DVB-card
> 
> -> my patch skips over the first 3 *non* DVB-cards : result correct
> 
> Or a totally simple machine:
> 
> /dev/video0 -> DVB-card
> 
> -> my patch does nothing : result correct
> 
> Your machine (i think):
> 
> /dev/video0 -> DVB-card
> /dev/video1 -> DVB-card
> /dev/video2 -> DVB-card
> /dev/video3 -> MPEG-encoder-card
> 
> -> my patch does nothing : result correct (for the first 3 cards for sure ...)
> 
> My machine:
> 
> /dev/video0 -> non DVB-card, a analogue tv-card
> /dev/video1 -> non DVB-card, a WEBCAM
> /dev/video2 -> DVB-card
> 
> -> my patch skips over the first 2 *non* DVB-cards : result correct
> 
> Are there *any* other combinations possible?
> 
> OK, a *very* exotic combination could be
> 
> /dev/video0 -> DVB-card
> /dev/video1 -> non DVB-card
> /dev/video2 -> DVB-card
> 
> *here* my patch fails, but this combination is *only* possible with
> 2 different DVB-card-drivers, right?
> 
> > The real problem is that the /dev/dvb/... devices can have completely
> > different numbers than the related /dev/video... devices. What we would
> 
> Sorry, but *not* "completely" different numbers! Both numbers are simply
> incrementing (by 1) from 0 to n or x to n + x
> 
> > need is a way of having the DVB device tell VDR which /dev/video device
> > belongs to it.
> 
> Yes, sure, but up to now there simply dont exists such a table or whatever.

I'm afraid you forgot one possible scenario:

1. full featured DVB card (/dev/video0)
2. budget DVB card
3. full featured DVB card (/dev/video1)

Now if the "primary device" is set to '3' it won't work.
Actually this didn't work before, either, but while we're
at it I guess we should take care of this case, too.

I therefore have modified your patch a little and moved it
into the cDvbDevice constructor:

--- dvbdevice.h 2003/08/15 12:34:55     1.22
+++ dvbdevice.h 2003/10/04 11:54:50
@@ -73,6 +73,9 @@
 
 // Image Grab facilities
   
+private:
+  static int devVideoOffset;
+  int devVideoIndex;
 public:
   virtual bool GrabImage(const char *FileName, bool Jpeg = true, int Quality = -1, int SizeX = -1, int SizeY = -1);
 
--- dvbdevice.c 2003/09/06 13:19:33     1.64
+++ dvbdevice.c 2003/10/04 12:31:15
@@ -307,6 +307,8 @@
 
 // --- cDvbDevice ------------------------------------------------------------
 
+int cDvbDevice::devVideoOffset = -1;
+
 cDvbDevice::cDvbDevice(int n)
 {
   dvbTuner = NULL;
@@ -317,8 +319,7 @@
 
   // Devices that are present on all card types:
 
-  int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK);
-
+  int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK); 
   // Devices that are only present on cards with decoders:
 
   fd_osd      = DvbOpen(DEV_DVB_OSD,    n, O_RDWR);
@@ -329,6 +330,35 @@
 
   fd_dvr = -1;
 
+  // The offset of the /dev/video devices:
+
+  if (devVideoOffset < 0) { // the first one checks this
+     FILE *f = NULL;
+     char buffer[PATH_MAX];
+     for (int ofs = 0; ofs < 100; ofs++) {
+         snprintf(buffer, sizeof(buffer), "/proc/video/dev/video%d", ofs);
+         if ((f = fopen(buffer, "r")) != NULL) {
+            if (fgets(buffer, sizeof(buffer), f)) {
+               if (strstr(buffer, "DVB Board")) { // found the _first_ DVB card
+                  devVideoOffset = ofs;
+                  dsyslog("video device offset is %d", devVideoOffset);
+                  break;
+                  }
+               }
+            else
+               break;
+            fclose(f);
+            }
+         else
+            break;
+         }
+     if (devVideoOffset < 0)
+        devVideoOffset = 0;
+     if (f)
+        fclose(f);
+     }
+  devVideoIndex = (devVideoOffset >= 0 && HasDecoder()) ? devVideoOffset++ : -1;
+
   // Video format:
 
   SetVideoFormat(Setup.VideoFormat ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3);
@@ -427,8 +457,10 @@
 
 bool cDvbDevice::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY)
 {
+  if (devVideoIndex < 0)
+     return false;
   char buffer[PATH_MAX];
-  snprintf(buffer, sizeof(buffer), "%s%d", DEV_VIDEO, CardIndex());
+  snprintf(buffer, sizeof(buffer), "%s%d", DEV_VIDEO, devVideoIndex);
   int videoDev = open(buffer, O_RDWR);
   if (videoDev < 0)
      LOG_ERROR_STR(buffer);


Unfortunately this seems to trigger a driver bug, because with
the primary device set to 3 in my case it initiates the grab
correctly with /dev/video1, but gets stuck in the line

  result |= ioctl(videoDev, VIDIOCSYNC, &vm.frame);

inside cDvbDevice::GrabImage(). Maybe somebody could do
some debugging here to see whether this really is a driver
issue or if something in VDR is done wrong in such a case.

Klaus


-- 
Info:
To unsubscribe send a mail to ecartis@linuxtv.org with "unsubscribe vdr" as subject.



Home | Main Index | Thread Index