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:rnissl@xxxxxx
--- ../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@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr