[ANNOUNCE] DVB-S2 + H.264 support for VDR-1.5.12

Message ID 477FC42C.5030709@gmx.de
State New
Headers

Commit Message

Reinhard Nissl Jan. 5, 2008, 5:53 p.m. UTC
  Hi,

Reinhard Nissl schrieb:

>> Well, I was in contact with Marco already and attached you'll
>> find a minimalistic change which reports "channel not available".
>> Now VDR should already be able to kick a low priority DVB-S
>> recording (or transfer thread) from a DVB-S2 device.
> 
> The previous patch was wrong. Only DVB-S2 devices "could" provide
> channels. The revised patch works now as expected.
> 
>> Still missing is to prefer DVB-S devices for DVB-S recordings so
>> that DVB-S2 devices remain available for DVB-S2 recordings of
>> same priority.
> 
> Still to do.

The attached version implements this behavior now. You may want
to experiment a bit with the decision logic as explained below.

The decision is based on the number of modulation systems a card
provides. For example, my NOVA-S provides one (DVB-S) and my
SkyStar HD provides three (DVB-S, DVB-DSS, DVB-S2).

The decision logic is implemented in cDevice::GetDevice(), so
have a look into device.c. After applying the patch, you'll find
two lines in that function marked with comments like /*1*/ and
/*2*/, and the latter one was disabled by a line comment.

In my scenario with just the above cards and vdr-xine as software
device, watching a channel requires VDR to operate in transfer
mode. Therefore it selects a device which provides for example a
DVB-S channel. The patched version will choose the NOVA-S with
either implementation /*1*/ or /*2*/.

Let's then start a DVB-S recording on a different transponder.
When implementation /*2*/ would be active, VDR would choose the
SkyStar HD, as the NOVA-S is claimed by transfer mode. Then, try
to switch to a DVB-S2 channel. It wouldn't work, as the SkyStar
HD would be claimed by a DVB-S recording.

That's why I've chosen implementation /*1*/ as default. For the
above scenario, starting a DVB-S recording on a different
transponder will choose the NOVA-S and kick off transfer mode.
Then VDR will look for a card to set up transfer mode again and
it will choose the only remaining card, the SkyStar HD. If you
then try to switch to a DVB-S2 channel, it will work as the
SkyStar HD is not claimed by a recording.

>> The patch is incremental to the original dvbs2 patch from
>> yesterday, i. e. you can simply apply it to your already patched VDR.

Bye.
  

Comments

Grégoire Favre Jan. 6, 2008, 6:23 p.m. UTC | #1
On Sat, Jan 05, 2008 at 06:53:48PM +0100, Reinhard Nissl wrote:

Hello,

with the last patch, VDR refuse to tune to any DVB-S2 channels.
I guess that VDR thinks all my card are only DVB-S ones.
I get "Channel not available!" on all DVB-S2 channels.

Any maybe not directly interesting, but with this patch, graphlcd
make vdr segault at start.

Thanks,

> The attached version implements this behavior now. You may want
> to experiment a bit with the decision logic as explained below.
> 
> The decision is based on the number of modulation systems a card
> provides. For example, my NOVA-S provides one (DVB-S) and my
> SkyStar HD provides three (DVB-S, DVB-DSS, DVB-S2).
> 
> The decision logic is implemented in cDevice::GetDevice(), so
> have a look into device.c. After applying the patch, you'll find
> two lines in that function marked with comments like /*1*/ and
> /*2*/, and the latter one was disabled by a line comment.
> 
> In my scenario with just the above cards and vdr-xine as software
> device, watching a channel requires VDR to operate in transfer
> mode. Therefore it selects a device which provides for example a
> DVB-S channel. The patched version will choose the NOVA-S with
> either implementation /*1*/ or /*2*/.
> 
> Let's then start a DVB-S recording on a different transponder.
> When implementation /*2*/ would be active, VDR would choose the
> SkyStar HD, as the NOVA-S is claimed by transfer mode. Then, try
> to switch to a DVB-S2 channel. It wouldn't work, as the SkyStar
> HD would be claimed by a DVB-S recording.
> 
> That's why I've chosen implementation /*1*/ as default. For the
> above scenario, starting a DVB-S recording on a different
> transponder will choose the NOVA-S and kick off transfer mode.
> Then VDR will look for a card to set up transfer mode again and
> it will choose the only remaining card, the SkyStar HD. If you
> then try to switch to a DVB-S2 channel, it will work as the
> SkyStar HD is not claimed by a recording.
> 
> >> The patch is incremental to the original dvbs2 patch from
> >> yesterday, i. e. you can simply apply it to your already patched VDR.
> 
> Bye.
> -- 
> Dipl.-Inform. (FH) Reinhard Nissl
> mailto:rnissl@gmx.de

> --- ../vdr-1.5.12-dvbs2-other/device.c	2008-01-01 22:55:18.000000000 +0100
> +++ device.c	2008-01-05 18:06:15.000000000 +0100
> @@ -359,6 +359,21 @@ cDevice *cDevice::GetDevice(int Index)
>    return (0 <= Index && Index < numDevices) ? device[Index] : NULL;
>  }
>  
> +inline int GetClippedModulationSystemCount(int AvailableBits, cDevice *Device)
> +{
> +  int ModulationSystemCount = Device->ModulationSystemCount();
> +  int MaxModulationSystemCount = 1 << AvailableBits;
> +  if (ModulationSystemCount > MaxModulationSystemCount) {
> +     esyslog("ERROR: device %d supports %d modulation systems but cDevice::GetDevice() currently only supports %d modulation systems which should be fixed", Device->CardIndex() + 1, ModulationSystemCount, MaxModulationSystemCount);
> +     ModulationSystemCount = MaxModulationSystemCount;
> +     }
> +  else if (ModulationSystemCount <= 0) {
> +     esyslog("ERROR: device %d reported an invalid number (%d) of supported modulation systems. The device should be fixed to return at least 1", Device->CardIndex() + 1, ModulationSystemCount);
> +     ModulationSystemCount = 1;
> +     }
> +  return ModulationSystemCount;
> +}
> +
>  cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView)
>  {
>    // Collect the current priorities of all CAM slots that can decrypt the channel:
> @@ -408,11 +423,13 @@ cDevice *cDevice::GetDevice(const cChann
>               imp <<= 1; imp |= LiveView ? !device[i]->IsPrimaryDevice() || ndr : 0;                                  // prefer the primary device for live viewing if we don't need to detach existing receivers
>               imp <<= 1; imp |= !device[i]->Receiving() && (device[i] != cTransferControl::ReceiverDevice() || device[i]->IsPrimaryDevice()) || ndr; // use receiving devices if we don't need to detach existing receivers, but avoid primary device in local transfer mode
>               imp <<= 1; imp |= device[i]->Receiving();                                                               // avoid devices that are receiving
> +/*1*/        imp <<= 2; imp |= GetClippedModulationSystemCount(2, device[i]) - 1;                                    // avoid cards which support multiple modulation systems
>               imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice();                                      // avoid the Transfer Mode receiver device
>               imp <<= 8; imp |= min(max(device[i]->Priority() + MAXPRIORITY, 0), 0xFF);                               // use the device with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used)
>               imp <<= 8; imp |= min(max((NumUsableSlots ? SlotPriority[j] : 0) + MAXPRIORITY, 0), 0xFF);              // use the CAM slot with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used)
>               imp <<= 1; imp |= ndr;                                                                                  // avoid devices if we need to detach existing receivers
>               imp <<= 1; imp |= device[i]->IsPrimaryDevice();                                                         // avoid the primary device
> +///*2*/        imp <<= 2; imp |= GetClippedModulationSystemCount(2, device[i]) - 1;                                    // avoid cards which support multiple modulation systems
>               imp <<= 1; imp |= NumUsableSlots ? 0 : device[i]->HasCi();                                              // avoid cards with Common Interface for FTA channels
>               imp <<= 1; imp |= device[i]->HasDecoder();                                                              // avoid full featured cards
>               imp <<= 1; imp |= NumUsableSlots ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel
> --- ../vdr-1.5.12-dvbs2-other/device.h	2007-10-21 11:21:52.000000000 +0200
> +++ device.h	2008-01-05 17:22:25.000000000 +0100
> @@ -224,6 +224,10 @@ public:
>           ///< function itself actually returns true.
>           ///< The default implementation always returns false, so a derived cDevice
>           ///< class that can provide channels must implement this function.
> +  virtual int ModulationSystemCount() const { return 0; }
> +         ///< Returns the number of modulation systems the device supports.
> +         ///< The default implementation always returns 0, so a derived cDevice
> +         ///< class that can provide channels must implement this function.
>    virtual bool IsTunedToTransponder(const cChannel *Channel);
>           ///< Returns true if this device is currently tuned to the given Channel's
>           ///< transponder.
> --- ../vdr-1.5.12-dvbs2-other/dvbdevice.c	2008-01-01 22:55:18.000000000 +0100
> +++ dvbdevice.c	2008-01-05 17:36:36.000000000 +0100
> @@ -406,6 +406,7 @@ cDvbDevice::cDvbDevice(int n)
>  {
>    ciAdapter = NULL;
>    dvbTuner = NULL;
> +  modulationSystemCount = 0;
>    frontendType = DVBFE_DELSYS_DUMMY;
>    spuDecoder = NULL;
>    digitalAudio = false;
> @@ -468,8 +469,14 @@ cDvbDevice::cDvbDevice(int n)
>    // We only check the devices that must be present - the others will be checked before accessing them://XXX
>  
>    if (fd_frontend >= 0) {
> -     if (ioctl(fd_frontend, DVBFE_GET_DELSYS, &frontendType) >= 0)
> +     if (ioctl(fd_frontend, DVBFE_GET_DELSYS, &frontendType) >= 0) {
> +        // determine number of supported modulation systems by counting the bits
> +        for (int i = 0; i < 32; i++) {
> +            if (frontendType & (1u << i))
> +               modulationSystemCount++;
> +            }
>          dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType);
> +        }
>       else
>          LOG_ERROR;
>       }
> @@ -798,7 +805,13 @@ bool cDvbDevice::ProvidesSource(int Sour
>  
>  bool cDvbDevice::ProvidesTransponder(const cChannel *Channel) const
>  {
> -  return ProvidesSource(Channel->Source()) && (!cSource::IsSat(Channel->Source()) || !Setup.DiSEqC || Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization()));
> +  if (!ProvidesSource(Channel->Source()))
> +     return false; // doesn't provide source
> +  if (!cSource::IsSat(Channel->Source()))
> +     return true; // source is sufficient for non sat
> +  if (!(frontendType & Channel->ModulationSystem()))
> +     return false; // requires modulation system which frontend doesn't provide
> +  return !Setup.DiSEqC || Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization());
>  }
>  
>  bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
> @@ -807,7 +820,7 @@ bool cDvbDevice::ProvidesChannel(const c
>    bool hasPriority = Priority < 0 || Priority > this->Priority();
>    bool needsDetachReceivers = false;
>  
> -  if (ProvidesSource(Channel->Source())) {
> +  if (ProvidesTransponder(Channel)) {
>       result = hasPriority;
>       if (Priority >= 0 && Receiving(true)) {
>          if (dvbTuner->IsTunedTo(Channel)) {
> --- ../vdr-1.5.12-dvbs2-other/dvbdevice.h	2008-01-01 22:55:18.000000000 +0100
> +++ dvbdevice.h	2008-01-05 17:29:49.000000000 +0100
> @@ -35,6 +35,7 @@ public:
>           ///< Must be called before accessing any DVB functions.
>           ///< \return True if any devices are available.
>  private:
> +  int modulationSystemCount;
>    dvbfe_delsys frontendType;
>    int fd_osd, fd_audio, fd_video, fd_dvr, fd_stc, fd_ca;
>  protected:
> @@ -66,6 +67,7 @@ public:
>    virtual bool ProvidesSource(int Source) const;
>    virtual bool ProvidesTransponder(const cChannel *Channel) const;
>    virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
> +  virtual int ModulationSystemCount() const { return modulationSystemCount; }
>    virtual bool IsTunedToTransponder(const cChannel *Channel);
>  protected:
>    virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);

> _______________________________________________
> vdr mailing list
> vdr@linuxtv.org
> http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
  
Reinhard Nissl Jan. 6, 2008, 8:34 p.m. UTC | #2
Hi,

Gregoire Favre schrieb:

> with the last patch, VDR refuse to tune to any DVB-S2 channels.
> I guess that VDR thinks all my card are only DVB-S ones.
> I get "Channel not available!" on all DVB-S2 channels.

Please add some debug code to cDvbDevice::ProvidesTransponder()
to find out what's going wrong in your case, i. e. compare the
provided and requested modulation systems.

> Any maybe not directly interesting, but with this patch, graphlcd
> make vdr segault at start.

Did you recompile all plugins as a virtual function had been added?

Please provide a backtrace otherwise.

Bye.
  
Grégoire Favre Jan. 6, 2008, 10:07 p.m. UTC | #3
On Sun, Jan 06, 2008 at 09:34:32PM +0100, Reinhard Nissl wrote:
> Hi,

Hello :-)

> Please add some debug code to cDvbDevice::ProvidesTransponder()
> to find out what's going wrong in your case, i. e. compare the
> provided and requested modulation systems.

I'll do tomorrow ;-)

> > Any maybe not directly interesting, but with this patch, graphlcd
> > make vdr segault at start.
> 
> Did you recompile all plugins as a virtual function had been added?
> 
> Please provide a backtrace otherwise.

The two fix solve it :-) (not the non tunable DVB-S2).

Thanks,
  
Grégoire Favre Jan. 7, 2008, 4:19 p.m. UTC | #4
On Sun, Jan 06, 2008 at 09:34:32PM +0100, Reinhard Nissl wrote:
> Hi,
> 
> Please add some debug code to cDvbDevice::ProvidesTransponder()
> to find out what's going wrong in your case, i. e. compare the
> provided and requested modulation systems.

My cards :

0: 101469280
1: 101469280
2: 101469280

But the card 1 : Hauppauge HVR-4000 is the dvb-s2 one ???

DVB: registering frontend 0 (ST STV0299 DVB-S)...
DVB: registering frontend 1 (Conexant CX24116/CX24118)...
DVB: registering frontend 2 (Conexant CX24123/CX24109)...
Without the patch and with -D1 DVB-S2 works perfectly.
  

Patch

--- ../vdr-1.5.12-dvbs2-other/device.c	2008-01-01 22:55:18.000000000 +0100
+++ device.c	2008-01-05 18:06:15.000000000 +0100
@@ -359,6 +359,21 @@  cDevice *cDevice::GetDevice(int Index)
   return (0 <= Index && Index < numDevices) ? device[Index] : NULL;
 }
 
+inline int GetClippedModulationSystemCount(int AvailableBits, cDevice *Device)
+{
+  int ModulationSystemCount = Device->ModulationSystemCount();
+  int MaxModulationSystemCount = 1 << AvailableBits;
+  if (ModulationSystemCount > MaxModulationSystemCount) {
+     esyslog("ERROR: device %d supports %d modulation systems but cDevice::GetDevice() currently only supports %d modulation systems which should be fixed", Device->CardIndex() + 1, ModulationSystemCount, MaxModulationSystemCount);
+     ModulationSystemCount = MaxModulationSystemCount;
+     }
+  else if (ModulationSystemCount <= 0) {
+     esyslog("ERROR: device %d reported an invalid number (%d) of supported modulation systems. The device should be fixed to return at least 1", Device->CardIndex() + 1, ModulationSystemCount);
+     ModulationSystemCount = 1;
+     }
+  return ModulationSystemCount;
+}
+
 cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView)
 {
   // Collect the current priorities of all CAM slots that can decrypt the channel:
@@ -408,11 +423,13 @@  cDevice *cDevice::GetDevice(const cChann
              imp <<= 1; imp |= LiveView ? !device[i]->IsPrimaryDevice() || ndr : 0;                                  // prefer the primary device for live viewing if we don't need to detach existing receivers
              imp <<= 1; imp |= !device[i]->Receiving() && (device[i] != cTransferControl::ReceiverDevice() || device[i]->IsPrimaryDevice()) || ndr; // use receiving devices if we don't need to detach existing receivers, but avoid primary device in local transfer mode
              imp <<= 1; imp |= device[i]->Receiving();                                                               // avoid devices that are receiving
+/*1*/        imp <<= 2; imp |= GetClippedModulationSystemCount(2, device[i]) - 1;                                    // avoid cards which support multiple modulation systems
              imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice();                                      // avoid the Transfer Mode receiver device
              imp <<= 8; imp |= min(max(device[i]->Priority() + MAXPRIORITY, 0), 0xFF);                               // use the device with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used)
              imp <<= 8; imp |= min(max((NumUsableSlots ? SlotPriority[j] : 0) + MAXPRIORITY, 0), 0xFF);              // use the CAM slot with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used)
              imp <<= 1; imp |= ndr;                                                                                  // avoid devices if we need to detach existing receivers
              imp <<= 1; imp |= device[i]->IsPrimaryDevice();                                                         // avoid the primary device
+///*2*/        imp <<= 2; imp |= GetClippedModulationSystemCount(2, device[i]) - 1;                                    // avoid cards which support multiple modulation systems
              imp <<= 1; imp |= NumUsableSlots ? 0 : device[i]->HasCi();                                              // avoid cards with Common Interface for FTA channels
              imp <<= 1; imp |= device[i]->HasDecoder();                                                              // avoid full featured cards
              imp <<= 1; imp |= NumUsableSlots ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel
--- ../vdr-1.5.12-dvbs2-other/device.h	2007-10-21 11:21:52.000000000 +0200
+++ device.h	2008-01-05 17:22:25.000000000 +0100
@@ -224,6 +224,10 @@  public:
          ///< function itself actually returns true.
          ///< The default implementation always returns false, so a derived cDevice
          ///< class that can provide channels must implement this function.
+  virtual int ModulationSystemCount() const { return 0; }
+         ///< Returns the number of modulation systems the device supports.
+         ///< The default implementation always returns 0, so a derived cDevice
+         ///< class that can provide channels must implement this function.
   virtual bool IsTunedToTransponder(const cChannel *Channel);
          ///< Returns true if this device is currently tuned to the given Channel's
          ///< transponder.
--- ../vdr-1.5.12-dvbs2-other/dvbdevice.c	2008-01-01 22:55:18.000000000 +0100
+++ dvbdevice.c	2008-01-05 17:36:36.000000000 +0100
@@ -406,6 +406,7 @@  cDvbDevice::cDvbDevice(int n)
 {
   ciAdapter = NULL;
   dvbTuner = NULL;
+  modulationSystemCount = 0;
   frontendType = DVBFE_DELSYS_DUMMY;
   spuDecoder = NULL;
   digitalAudio = false;
@@ -468,8 +469,14 @@  cDvbDevice::cDvbDevice(int n)
   // We only check the devices that must be present - the others will be checked before accessing them://XXX
 
   if (fd_frontend >= 0) {
-     if (ioctl(fd_frontend, DVBFE_GET_DELSYS, &frontendType) >= 0)
+     if (ioctl(fd_frontend, DVBFE_GET_DELSYS, &frontendType) >= 0) {
+        // determine number of supported modulation systems by counting the bits
+        for (int i = 0; i < 32; i++) {
+            if (frontendType & (1u << i))
+               modulationSystemCount++;
+            }
         dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType);
+        }
      else
         LOG_ERROR;
      }
@@ -798,7 +805,13 @@  bool cDvbDevice::ProvidesSource(int Sour
 
 bool cDvbDevice::ProvidesTransponder(const cChannel *Channel) const
 {
-  return ProvidesSource(Channel->Source()) && (!cSource::IsSat(Channel->Source()) || !Setup.DiSEqC || Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization()));
+  if (!ProvidesSource(Channel->Source()))
+     return false; // doesn't provide source
+  if (!cSource::IsSat(Channel->Source()))
+     return true; // source is sufficient for non sat
+  if (!(frontendType & Channel->ModulationSystem()))
+     return false; // requires modulation system which frontend doesn't provide
+  return !Setup.DiSEqC || Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization());
 }
 
 bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
@@ -807,7 +820,7 @@  bool cDvbDevice::ProvidesChannel(const c
   bool hasPriority = Priority < 0 || Priority > this->Priority();
   bool needsDetachReceivers = false;
 
-  if (ProvidesSource(Channel->Source())) {
+  if (ProvidesTransponder(Channel)) {
      result = hasPriority;
      if (Priority >= 0 && Receiving(true)) {
         if (dvbTuner->IsTunedTo(Channel)) {
--- ../vdr-1.5.12-dvbs2-other/dvbdevice.h	2008-01-01 22:55:18.000000000 +0100
+++ dvbdevice.h	2008-01-05 17:29:49.000000000 +0100
@@ -35,6 +35,7 @@  public:
          ///< Must be called before accessing any DVB functions.
          ///< \return True if any devices are available.
 private:
+  int modulationSystemCount;
   dvbfe_delsys frontendType;
   int fd_osd, fd_audio, fd_video, fd_dvr, fd_stc, fd_ca;
 protected:
@@ -66,6 +67,7 @@  public:
   virtual bool ProvidesSource(int Source) const;
   virtual bool ProvidesTransponder(const cChannel *Channel) const;
   virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
+  virtual int ModulationSystemCount() const { return modulationSystemCount; }
   virtual bool IsTunedToTransponder(const cChannel *Channel);
 protected:
   virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);