From fd7ccc7627b08ab66122d644cb301aba42ae0c06 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Tue, 17 Mar 2015 12:27:18 +0100 Subject: [PATCH] Fixed setting the source value of newly created channels, in case the NIT is received from a different, but very close satellite position (cont'd) --- CONTRIBUTORS | 5 ++ HISTORY | 7 ++- nit.c | 131 +++++++++++++++------------------------------------ nit.h | 16 +------ sdt.c | 20 ++++++-- 5 files changed, 65 insertions(+), 114 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index fe7fa877..f4a667fc 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -3405,3 +3405,8 @@ Tomasz Maciej Nowak Gabriel Bonich for translating OSD texts to the Spanish language + +Daniel Ribeiro + for reporting a problem with setting the source value of newly created channels, in + case the NIT is received from a different, but very close satellite position, and + for helping to debug this diff --git a/HISTORY b/HISTORY index 8f75a408..43f926ee 100644 --- a/HISTORY +++ b/HISTORY @@ -8596,7 +8596,7 @@ Video Disk Recorder Revision History - Bumped all version numbers to 2.2.0. - Official release. -2015-03-13: Version 2.3.1 +2015-03-17: Version 2.3.1 - The new function cOsd::MaxPixmapSize() can be called to determine the maximum size a cPixmap may have on the current OSD. The 'osddemo' example has been modified @@ -8612,6 +8612,9 @@ Video Disk Recorder Revision History https://bitbucket.org/powARman/dvbhddevice. - Added a section about Output Devices to the INSTALL file. - Fixed setting the source value of newly created channels, in case the NIT is - received from a different, but very close satellite position. + received from a different, but very close satellite position (reported by Daniel + Ribeiro). The code for handling different NITs has been removed from nit.c, because + according to the DVB standard table id 0x40 carries only the NIT of the actual + network. - Added some comment to cPixmap about the relation between OSD, ViewPort and DrawPort (suggested by Thomas Reufer). diff --git a/nit.c b/nit.c index 13183755..aaf7c88c 100644 --- a/nit.c +++ b/nit.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: nit.c 3.5 2015/02/04 09:13:54 kls Exp $ + * $Id: nit.c 4.1 2015/03/16 15:24:18 kls Exp $ */ #include "nit.h" @@ -19,19 +19,22 @@ #define DVB_SYSTEM_1 0 // see also dvbdevice.c #define DVB_SYSTEM_2 1 +#define MAXNETWORKNAME Utf8BufSize(256) + +// Set to 'true' for debug output: +static bool DebugNit = false; + +#define dbgnit(a...) if (DebugNit) fprintf(stderr, a) + cNitFilter::cNitFilter(cSdtFilter *SdtFilter) { sdtFilter = SdtFilter; - numNits = 0; - networkId = 0; - Set(0x10, 0x40); // NIT + Set(0x10, SI::TableIdNIT); } void cNitFilter::SetStatus(bool On) { cFilter::SetStatus(On); - numNits = 0; - networkId = 0; sectionSyncer.Reset(); } @@ -40,63 +43,28 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length SI::NIT nit(Data, false); if (!nit.CheckCRCAndParse()) return; - // Some broadcasters send more than one NIT, with no apparent way of telling which - // one is the right one to use. This is an attempt to find the NIT that contains - // the transponder it was transmitted on and use only that one: - int ThisNIT = -1; - if (!networkId) { - for (int i = 0; i < numNits; i++) { - if (nits[i].networkId == nit.getNetworkId()) { - if (nit.getSectionNumber() == 0) { - // all NITs have passed by - for (int j = 0; j < numNits; j++) { - if (nits[j].hasTransponder) { - networkId = nits[j].networkId; - //printf("taking NIT with network ID %d\n", networkId); - //XXX what if more than one NIT contains this transponder??? - break; - } - } - if (!networkId) { - //printf("none of the NITs contains transponder %d\n", Transponder()); - return; - } - } - else { - ThisNIT = i; - break; - } - } - } - if (!networkId && ThisNIT < 0 && numNits < MAXNITS) { - if (nit.getSectionNumber() == 0) { - *nits[numNits].name = 0; - SI::Descriptor *d; - for (SI::Loop::Iterator it; (d = nit.commonDescriptors.getNext(it)); ) { - switch (d->getDescriptorTag()) { - case SI::NetworkNameDescriptorTag: { - SI::NetworkNameDescriptor *nnd = (SI::NetworkNameDescriptor *)d; - nnd->name.getText(nits[numNits].name, MAXNETWORKNAME); - } - break; - default: ; - } - delete d; - } - nits[numNits].networkId = nit.getNetworkId(); - nits[numNits].hasTransponder = false; - //printf("NIT[%d] %5d '%s'\n", numNits, nits[numNits].networkId, nits[numNits].name); - ThisNIT = numNits; - numNits++; + if (!sectionSyncer.Sync(nit.getVersionNumber(), nit.getSectionNumber(), nit.getLastSectionNumber())) + return; + if (DebugNit) { + char NetworkName[MAXNETWORKNAME] = ""; + SI::Descriptor *d; + for (SI::Loop::Iterator it; (d = nit.commonDescriptors.getNext(it)); ) { + switch (d->getDescriptorTag()) { + case SI::NetworkNameDescriptorTag: { + SI::NetworkNameDescriptor *nnd = (SI::NetworkNameDescriptor *)d; + nnd->name.getText(NetworkName, MAXNETWORKNAME); + } + break; + default: ; } - } + delete d; + } + dbgnit("NIT: %02X %2d %2d %2d %s %d %d '%s'\n", Tid, nit.getVersionNumber(), nit.getSectionNumber(), nit.getLastSectionNumber(), *cSource::ToString(Source()), nit.getNetworkId(), Transponder(), NetworkName); } - else if (networkId != nit.getNetworkId()) - return; // ignore all other NITs - else if (!sectionSyncer.Sync(nit.getVersionNumber(), nit.getSectionNumber(), nit.getLastSectionNumber())) - return; - if (!Channels.Lock(true, 10)) + if (!Channels.Lock(true, 10)) { + sectionSyncer.Reset(); // let's not miss any section of the NIT return; + } SI::NIT::TransportStream ts; for (SI::Loop::Iterator it; nit.transportStreamLoop.getNext(ts, it); ) { SI::Descriptor *d; @@ -118,6 +86,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length default: ; } Frequencies[n++] = f; + dbgnit(" Frequencies[%d] = %d\n", n - 1, f); } } else @@ -142,16 +111,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length static int RollOffs[] = { ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_AUTO }; dtp.SetRollOff(sd->getModulationSystem() ? RollOffs[sd->getRollOff()] : ROLLOFF_AUTO); int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10; - if (ThisNIT >= 0) { - for (int n = 0; n < NumFrequencies; n++) { - if (ISTRANSPONDER(cChannel::Transponder(Frequencies[n], dtp.Polarization()), Transponder())) { - nits[ThisNIT].hasTransponder = true; - //printf("has transponder %d\n", Transponder()); - break; - } - } - break; - } + dbgnit(" %s %d %c %d %d\n", *cSource::ToString(Source), Frequency, Polarizations[sd->getPolarization()], SymbolRate, cChannel::Transponder(Frequency, Polarizations[sd->getPolarization()])); if (Setup.UpdateChannels >= 5) { bool found = false; bool forceTransponderUpdate = false; @@ -184,7 +144,8 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length } } } - sdtFilter->Trigger(Source); + if (ISTRANSPONDER(cChannel::Transponder(Frequency, dtp.Polarization()), Transponder())) + sdtFilter->Trigger(Source); } break; case SI::S2SatelliteDeliverySystemDescriptorTag: { @@ -213,16 +174,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length static int Modulations[] = { QPSK, QAM_16, QAM_32, QAM_64, QAM_128, QAM_256, QAM_AUTO }; dtp.SetModulation(Modulations[min(sd->getModulation(), 6)]); int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10; - if (ThisNIT >= 0) { - for (int n = 0; n < NumFrequencies; n++) { - if (ISTRANSPONDER(Frequencies[n] / 1000, Transponder())) { - nits[ThisNIT].hasTransponder = true; - //printf("has transponder %d\n", Transponder()); - break; - } - } - break; - } + dbgnit(" %s %d %d %d %d\n", *cSource::ToString(Source), Frequency, CodeRates[sd->getFecInner()], Modulations[min(sd->getModulation(), 6)], SymbolRate); if (Setup.UpdateChannels >= 5) { bool found = false; bool forceTransponderUpdate = false; @@ -255,7 +207,8 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length } } } - sdtFilter->Trigger(Source); + if (ISTRANSPONDER(Frequency / 1000, Transponder())) + sdtFilter->Trigger(Source); } break; case SI::TerrestrialDeliverySystemDescriptorTag: { @@ -277,16 +230,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length dtp.SetGuard(GuardIntervals[sd->getGuardInterval()]); static int TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_4K, TRANSMISSION_MODE_AUTO }; dtp.SetTransmission(TransmissionModes[sd->getTransmissionMode()]); - if (ThisNIT >= 0) { - for (int n = 0; n < NumFrequencies; n++) { - if (ISTRANSPONDER(Frequencies[n] / 1000000, Transponder())) { - nits[ThisNIT].hasTransponder = true; - //printf("has transponder %d\n", Transponder()); - break; - } - } - break; - } + dbgnit(" %s %d %d %d %d %d %d %d %d\n", *cSource::ToString(Source), Frequency, Bandwidths[sd->getBandwidth()], Constellations[sd->getConstellation()], Hierarchies[sd->getHierarchy()], CodeRates[sd->getCodeRateHP()], CodeRates[sd->getCodeRateLP()], GuardIntervals[sd->getGuardInterval()], TransmissionModes[sd->getTransmissionMode()]); if (Setup.UpdateChannels >= 5) { bool found = false; bool forceTransponderUpdate = false; @@ -319,7 +263,8 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length } } } - sdtFilter->Trigger(Source); + if (ISTRANSPONDER(Frequency / 1000000, Transponder())) + sdtFilter->Trigger(Source); } break; case SI::ExtensionDescriptorTag: { diff --git a/nit.h b/nit.h index 4673f960..52676c0d 100644 --- a/nit.h +++ b/nit.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: nit.h 3.1 2014/03/10 14:12:05 kls Exp $ + * $Id: nit.h 4.1 2015/03/16 12:41:38 kls Exp $ */ #ifndef __NIT_H @@ -13,24 +13,10 @@ #include "filter.h" #include "sdt.h" -#define MAXNITS 16 -#define MAXNETWORKNAME Utf8BufSize(256) - class cNitFilter : public cFilter { private: - - class cNit { - public: - u_short networkId; - char name[MAXNETWORKNAME]; - bool hasTransponder; - }; - cSectionSyncer sectionSyncer; cSdtFilter *sdtFilter; - cNit nits[MAXNITS]; - u_short networkId; - int numNits; protected: virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length); public: diff --git a/sdt.c b/sdt.c index b75a243a..0b33e52a 100644 --- a/sdt.c +++ b/sdt.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: sdt.c 4.1 2015/03/13 11:39:42 kls Exp $ + * $Id: sdt.c 4.3 2015/03/16 15:24:12 kls Exp $ */ #include "sdt.h" @@ -13,6 +13,11 @@ #include "libsi/section.h" #include "libsi/descriptor.h" +// Set to 'true' for debug output: +static bool DebugSdt = false; + +#define dbgsdt(a...) if (DebugSdt) fprintf(stderr, a) + // --- cSdtFilter ------------------------------------------------------------ cSdtFilter::cSdtFilter(cPatFilter *PatFilter) @@ -47,8 +52,11 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length return; if (!sectionSyncer.Sync(sdt.getVersionNumber(), sdt.getSectionNumber(), sdt.getLastSectionNumber())) return; - if (!Channels.Lock(true, 10)) + if (!Channels.Lock(true, 10)) { + sectionSyncer.Reset(); // let's not miss any section of the SDT return; + } + dbgsdt("SDT: %2d %2d %2d %s %d\n", sdt.getVersionNumber(), sdt.getSectionNumber(), sdt.getLastSectionNumber(), *cSource::ToString(source), Transponder()); SI::SDT::Service SiSdtService; for (SI::Loop::Iterator it; sdt.serviceLoop.getNext(SiSdtService, it); ) { cChannel *channel = Channels.GetByChannelID(tChannelID(source, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId())); @@ -104,6 +112,7 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length // channel->SetCa(SiSdtService.getFreeCaMode() ? 0xFFFF : 0); } else if (*pn && Setup.UpdateChannels >= 4) { + dbgsdt(" %5d %5d %5d %s/%s %d %s\n", sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId(), *cSource::ToString(Channel()->Source()), *cSource::ToString(source), Channel()->Transponder(), pn); channel = Channels.NewChannel(Channel(), pn, ps, pp, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId()); channel->SetSource(source); // in case this comes from a satellite with a slightly different position patFilter->Trigger(SiSdtService.getServiceId()); @@ -154,8 +163,11 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length } } if (sdt.getSectionNumber() == sdt.getLastSectionNumber()) { - if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3) - Channels.MarkObsoleteChannels(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId()); + if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3) { + Channels.MarkObsoleteChannels(source, sdt.getOriginalNetworkId(), sdt.getTransportStreamId()); + if (source != Source()) + Channels.MarkObsoleteChannels(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId()); + } } Channels.Unlock(); }