Hi,

Reinhard Nissl schrieb:

> the first patch optimizes cNitFilter::Process() by looping only over the
> relevant channels. It introduces a further hash in cChannels and
> implements an iterator for hiding this implementation detail.

Sorry, but a line from the DVB-S2 patch slipped through. Please find
attached an updated version.

Bye.
-- 
Dipl.-Inform. (FH) Reinhard Nissl
mailto:[EMAIL PROTECTED]
--- ../vdr-1.5.12-orig/channels.h	2007-09-02 12:23:11.000000000 +0200
+++ channels.h	2007-12-28 22:56:02.000000000 +0100
@@ -219,13 +219,49 @@ public:
   void SetRefChannel(cChannel *RefChannel);
   };
 
+class cIteratorImpl {
+private:
+  int refCount;
+  cIteratorImpl(const cIteratorImpl &);
+  const cIteratorImpl &operator =(const cIteratorImpl &);
+public:
+  cIteratorImpl(void) { refCount = 0; }
+  virtual ~cIteratorImpl() {}
+  virtual int AddRef(void) { return ++refCount; }
+  virtual int DelRef(void) { int RefCount = --refCount; if (RefCount <= 0) delete this; return RefCount; }
+  virtual void *First(void) = 0;
+  virtual void *Last(void)  = 0;
+  virtual void *Prev(void)  = 0;
+  virtual void *Next(void)  = 0;
+  virtual void *Current(void) const = 0;
+  };
+
+template <class T> class cIterator
+{
+private:
+  cIteratorImpl *impl;
+public:
+  cIterator(cIteratorImpl *Impl) { impl = Impl; impl->AddRef(); }
+  cIterator(const cIterator &rhs) { impl = rhs.impl; impl->AddRef(); }
+  ~cIterator() { impl->DelRef(); }
+  const cIterator &operator =(const cIterator &rhs) { rhs.impl->AddRef(); impl->DelRef(); impl = rhs.impl; return *this; }
+  T *First(void) const   { return (T *)impl->First(); }
+  T *Last(void) const    { return (T *)impl->Last(); }
+  T *Prev(void) const    { return (T *)impl->Prev(); }
+  T *Next(void) const    { return (T *)impl->Next(); }
+  T *Current(void) const { return (T *)impl->Current(); }
+  };
+
 class cChannels : public cRwLock, public cConfig<cChannel> {
 private:
   int maxNumber;
   int modified;
   int beingEdited;
   cHash<cChannel> channelsHashSid;
+  cHash<cChannel> channelsHashNidTid;
   void DeleteDuplicateChannels(void);
+  void ClearChannelHashes(void);
+  static unsigned int HashKeyNidTid(unsigned short Nid, unsigned short Tid);
 public:
   cChannels(void);
   bool Load(const char *FileName, bool AllowComments = false, bool MustExist = false);
@@ -240,6 +276,7 @@ public:
   cChannel *GetByServiceID(int Source, int Transponder, unsigned short ServiceID);
   cChannel *GetByChannelID(tChannelID ChannelID, bool TryWithoutRid = false, bool TryWithoutPolarization = false);
   cChannel *GetByTransponderID(tChannelID ChannelID);
+  cIterator<cChannel> GetChannelsBySourceNidTid(int Source, unsigned short Nid, unsigned short Tid);
   int BeingEdited(void) { return beingEdited; }
   void IncBeingEdited(void) { beingEdited++; }
   void DecBeingEdited(void) { beingEdited--; }
--- ../vdr-1.5.12-orig/channels.c	2007-10-12 16:40:53.000000000 +0200
+++ channels.c	2007-12-28 22:56:02.000000000 +0100
@@ -905,14 +905,72 @@ bool cChannels::Load(const char *FileNam
   return false;
 }
 
+void cChannels::ClearChannelHashes(void)
+{
+  channelsHashSid.Clear();
+  channelsHashNidTid.Clear();
+}
+
 void cChannels::HashChannel(cChannel *Channel)
 {
   channelsHashSid.Add(Channel, Channel->Sid());
+  channelsHashNidTid.Add(Channel, HashKeyNidTid(Channel->Nid(), Channel->Tid()));
 }
 
 void cChannels::UnhashChannel(cChannel *Channel)
 {
   channelsHashSid.Del(Channel, Channel->Sid());
+  channelsHashNidTid.Del(Channel, HashKeyNidTid(Channel->Nid(), Channel->Tid()));
+}
+
+unsigned int cChannels::HashKeyNidTid(unsigned short Nid, unsigned short Tid)
+{
+  return Nid << 16 | Tid;
+}
+
+cIterator<cChannel> cChannels::GetChannelsBySourceNidTid(int Source, unsigned short Nid, unsigned short Tid)
+{
+  class cIteratorImplSourceNidTid : public cIteratorImpl {
+  private:
+    cList<cHashObject> *hashList;
+    cHashObject *current;
+    int source;
+    unsigned short nid;
+    unsigned short tid;
+    cChannel *FindMatchingChannel(bool reverse, bool reset = false) {
+      if (!hashList || (!current && !reset))
+         return NULL;
+      while (true) {
+            if (reset) {
+               reset = false;
+               current = reverse ? hashList->Last() : hashList->First();
+               }
+            else
+               current = reverse ? hashList->Prev(current) : hashList->Next(current);
+            if (!current)
+               break;
+            cChannel *Channel = (cChannel *)current->Object();
+            if (Channel->Source() == source && Channel->Nid() == nid && Channel->Tid() == tid)
+               return Channel;
+            }
+      return NULL;
+      }
+  public:
+    cIteratorImplSourceNidTid(cList<cHashObject> *HashList, int Source, unsigned short Nid, unsigned short Tid) {
+       hashList = HashList;
+       source = Source;
+       nid = Nid;
+       tid = Tid;
+       current = NULL;
+       }
+    virtual void *First(void) { return FindMatchingChannel(false, true); }
+    virtual void *Last(void)  { return FindMatchingChannel(true,  true); }
+    virtual void *Prev(void)  { return FindMatchingChannel(false); }
+    virtual void *Next(void)  { return FindMatchingChannel(true);  }
+    virtual void *Current(void) const  { return current ? (cChannel *)current->Object() : NULL; }
+    };
+
+  return cIterator<cChannel>(new cIteratorImplSourceNidTid(channelsHashNidTid.GetList(HashKeyNidTid(Nid, Tid)), Source, Nid, Tid));
 }
 
 int cChannels::GetNextGroup(int Idx)
@@ -949,7 +1007,7 @@ int cChannels::GetPrevNormal(int Idx)
 
 void cChannels::ReNumber( void )
 {
-  channelsHashSid.Clear();
+  ClearChannelHashes();
   int Number = 1;
   for (cChannel *channel = First(); channel; channel = Next(channel)) {
       if (channel->GroupSep()) {
--- ../vdr-1.5.12-orig/nit.c	2007-08-17 16:02:45.000000000 +0200
+++ nit.c	2007-12-29 00:49:01.000000000 +0100
@@ -142,20 +142,19 @@ void cNitFilter::Process(u_short Pid, u_
                     }
                  if (Setup.UpdateChannels >= 5) {
                     bool found = false;
-                    for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
-                        if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
-                           int transponder = Channel->Transponder();
-                           if (!ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), transponder)) {
-                              for (int n = 0; n < NumFrequencies; n++) {
-                                  if (ISTRANSPONDER(cChannel::Transponder(Frequencies[n], Polarization), transponder)) {
-                                     Frequency = Frequencies[n];
-                                     break;
-                                     }
+                    cIterator<cChannel> ChannelIterator = Channels.GetChannelsBySourceNidTid(Source, ts.getOriginalNetworkId(), ts.getTransportStreamId());
+                    for (cChannel *Channel = ChannelIterator.First(); Channel; Channel = ChannelIterator.Next()) {
+                        int transponder = Channel->Transponder();
+                        if (!ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), transponder)) {
+                           for (int n = 0; n < NumFrequencies; n++) {
+                               if (ISTRANSPONDER(cChannel::Transponder(Frequencies[n], Polarization), transponder)) {
+                                  Frequency = Frequencies[n];
+                                  break;
                                   }
-                              }
-                           if (ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), Transponder())) // only modify channels if we're actually receiving this transponder
-                              Channel->SetSatTransponderData(Source, Frequency, Polarization, SymbolRate, CodeRate);
+                               }
                            }
+                        if (ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), Transponder())) // only modify channels if we're actually receiving this transponder
+                           Channel->SetSatTransponderData(Source, Frequency, Polarization, SymbolRate, CodeRate);
                         found = true;
                         }
                     if (!found) {
@@ -193,20 +192,19 @@ void cNitFilter::Process(u_short Pid, u_
                     }
                  if (Setup.UpdateChannels >= 5) {
                     bool found = false;
-                    for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
-                        if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
-                           int transponder = Channel->Transponder();
-                           if (!ISTRANSPONDER(Frequency / 1000, transponder)) {
-                              for (int n = 0; n < NumFrequencies; n++) {
-                                  if (ISTRANSPONDER(Frequencies[n] / 1000, transponder)) {
-                                     Frequency = Frequencies[n];
-                                     break;
-                                     }
+                    cIterator<cChannel> ChannelIterator = Channels.GetChannelsBySourceNidTid(Source, ts.getOriginalNetworkId(), ts.getTransportStreamId());
+                    for (cChannel *Channel = ChannelIterator.First(); Channel; Channel = ChannelIterator.Next()) {
+                        int transponder = Channel->Transponder();
+                        if (!ISTRANSPONDER(Frequency / 1000, transponder)) {
+                           for (int n = 0; n < NumFrequencies; n++) {
+                               if (ISTRANSPONDER(Frequencies[n] / 1000, transponder)) {
+                                  Frequency = Frequencies[n];
+                                  break;
                                   }
-                              }
-                           if (ISTRANSPONDER(Frequency / 1000, Transponder())) // only modify channels if we're actually receiving this transponder
-                              Channel->SetCableTransponderData(Source, Frequency, Modulation, SymbolRate, CodeRate);
+                               }
                            }
+                        if (ISTRANSPONDER(Frequency / 1000, Transponder())) // only modify channels if we're actually receiving this transponder
+                           Channel->SetCableTransponderData(Source, Frequency, Modulation, SymbolRate, CodeRate);
                         found = true;
                         }
                     if (!found) {
@@ -251,20 +249,19 @@ void cNitFilter::Process(u_short Pid, u_
                     }
                  if (Setup.UpdateChannels >= 5) {
                     bool found = false;
-                    for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
-                        if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
-                           int transponder = Channel->Transponder();
-                           if (!ISTRANSPONDER(Frequency / 1000000, transponder)) {
-                              for (int n = 0; n < NumFrequencies; n++) {
-                                  if (ISTRANSPONDER(Frequencies[n] / 1000000, transponder)) {
-                                     Frequency = Frequencies[n];
-                                     break;
-                                     }
+                    cIterator<cChannel> ChannelIterator = Channels.GetChannelsBySourceNidTid(Source, ts.getOriginalNetworkId(), ts.getTransportStreamId());
+                    for (cChannel *Channel = ChannelIterator.First(); Channel; Channel = ChannelIterator.Next()) {
+                        int transponder = Channel->Transponder();
+                        if (!ISTRANSPONDER(Frequency / 1000000, transponder)) {
+                           for (int n = 0; n < NumFrequencies; n++) {
+                               if (ISTRANSPONDER(Frequencies[n] / 1000000, transponder)) {
+                                  Frequency = Frequencies[n];
+                                  break;
                                   }
-                              }
-                           if (ISTRANSPONDER(Frequency / 1000000, Transponder())) // only modify channels if we're actually receiving this transponder
-                              Channel->SetTerrTransponderData(Source, Frequency, Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode);
+                               }
                            }
+                        if (ISTRANSPONDER(Frequency / 1000000, Transponder())) // only modify channels if we're actually receiving this transponder
+                           Channel->SetTerrTransponderData(Source, Frequency, Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode);
                         found = true;
                         }
                     if (!found) {
@@ -276,7 +273,7 @@ void cNitFilter::Process(u_short Pid, u_
                            else
                               delete Channel;
                            }
-                        }
+                       }
                     }
                  }
                  break;
_______________________________________________
vdr mailing list
vdr@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr

Reply via email to