1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

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)

This commit is contained in:
Klaus Schmidinger 2015-03-17 12:27:18 +01:00
parent 0bcf5d6da6
commit fd7ccc7627
5 changed files with 65 additions and 114 deletions

View File

@ -3405,3 +3405,8 @@ Tomasz Maciej Nowak <tmn505@gmail.com>
Gabriel Bonich <gbonich@gmail.com> Gabriel Bonich <gbonich@gmail.com>
for translating OSD texts to the Spanish language for translating OSD texts to the Spanish language
Daniel Ribeiro <drwyrm@gmail.com>
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

View File

@ -8596,7 +8596,7 @@ Video Disk Recorder Revision History
- Bumped all version numbers to 2.2.0. - Bumped all version numbers to 2.2.0.
- Official release. - 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 - 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 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. https://bitbucket.org/powARman/dvbhddevice.
- Added a section about Output Devices to the INSTALL file. - Added a section about Output Devices to the INSTALL file.
- Fixed setting the source value of newly created channels, in case the NIT is - 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 - Added some comment to cPixmap about the relation between OSD, ViewPort and DrawPort
(suggested by Thomas Reufer). (suggested by Thomas Reufer).

103
nit.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "nit.h"
@ -19,19 +19,22 @@
#define DVB_SYSTEM_1 0 // see also dvbdevice.c #define DVB_SYSTEM_1 0 // see also dvbdevice.c
#define DVB_SYSTEM_2 1 #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) cNitFilter::cNitFilter(cSdtFilter *SdtFilter)
{ {
sdtFilter = SdtFilter; sdtFilter = SdtFilter;
numNits = 0; Set(0x10, SI::TableIdNIT);
networkId = 0;
Set(0x10, 0x40); // NIT
} }
void cNitFilter::SetStatus(bool On) void cNitFilter::SetStatus(bool On)
{ {
cFilter::SetStatus(On); cFilter::SetStatus(On);
numNits = 0;
networkId = 0;
sectionSyncer.Reset(); 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); SI::NIT nit(Data, false);
if (!nit.CheckCRCAndParse()) if (!nit.CheckCRCAndParse())
return; return;
// Some broadcasters send more than one NIT, with no apparent way of telling which if (!sectionSyncer.Sync(nit.getVersionNumber(), nit.getSectionNumber(), nit.getLastSectionNumber()))
// 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; return;
} if (DebugNit) {
} char NetworkName[MAXNETWORKNAME] = "";
else {
ThisNIT = i;
break;
}
}
}
if (!networkId && ThisNIT < 0 && numNits < MAXNITS) {
if (nit.getSectionNumber() == 0) {
*nits[numNits].name = 0;
SI::Descriptor *d; SI::Descriptor *d;
for (SI::Loop::Iterator it; (d = nit.commonDescriptors.getNext(it)); ) { for (SI::Loop::Iterator it; (d = nit.commonDescriptors.getNext(it)); ) {
switch (d->getDescriptorTag()) { switch (d->getDescriptorTag()) {
case SI::NetworkNameDescriptorTag: { case SI::NetworkNameDescriptorTag: {
SI::NetworkNameDescriptor *nnd = (SI::NetworkNameDescriptor *)d; SI::NetworkNameDescriptor *nnd = (SI::NetworkNameDescriptor *)d;
nnd->name.getText(nits[numNits].name, MAXNETWORKNAME); nnd->name.getText(NetworkName, MAXNETWORKNAME);
} }
break; break;
default: ; default: ;
} }
delete d; delete d;
} }
nits[numNits].networkId = nit.getNetworkId(); 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);
nits[numNits].hasTransponder = false;
//printf("NIT[%d] %5d '%s'\n", numNits, nits[numNits].networkId, nits[numNits].name);
ThisNIT = numNits;
numNits++;
} }
} if (!Channels.Lock(true, 10)) {
} sectionSyncer.Reset(); // let's not miss any section of the NIT
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))
return; return;
}
SI::NIT::TransportStream ts; SI::NIT::TransportStream ts;
for (SI::Loop::Iterator it; nit.transportStreamLoop.getNext(ts, it); ) { for (SI::Loop::Iterator it; nit.transportStreamLoop.getNext(ts, it); ) {
SI::Descriptor *d; SI::Descriptor *d;
@ -118,6 +86,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
default: ; default: ;
} }
Frequencies[n++] = f; Frequencies[n++] = f;
dbgnit(" Frequencies[%d] = %d\n", n - 1, f);
} }
} }
else 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 }; static int RollOffs[] = { ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_AUTO };
dtp.SetRollOff(sd->getModulationSystem() ? RollOffs[sd->getRollOff()] : ROLLOFF_AUTO); dtp.SetRollOff(sd->getModulationSystem() ? RollOffs[sd->getRollOff()] : ROLLOFF_AUTO);
int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10; int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
if (ThisNIT >= 0) { dbgnit(" %s %d %c %d %d\n", *cSource::ToString(Source), Frequency, Polarizations[sd->getPolarization()], SymbolRate, cChannel::Transponder(Frequency, Polarizations[sd->getPolarization()]));
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;
}
if (Setup.UpdateChannels >= 5) { if (Setup.UpdateChannels >= 5) {
bool found = false; bool found = false;
bool forceTransponderUpdate = false; bool forceTransponderUpdate = false;
@ -184,6 +144,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
} }
} }
} }
if (ISTRANSPONDER(cChannel::Transponder(Frequency, dtp.Polarization()), Transponder()))
sdtFilter->Trigger(Source); sdtFilter->Trigger(Source);
} }
break; break;
@ -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 }; static int Modulations[] = { QPSK, QAM_16, QAM_32, QAM_64, QAM_128, QAM_256, QAM_AUTO };
dtp.SetModulation(Modulations[min(sd->getModulation(), 6)]); dtp.SetModulation(Modulations[min(sd->getModulation(), 6)]);
int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10; int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
if (ThisNIT >= 0) { dbgnit(" %s %d %d %d %d\n", *cSource::ToString(Source), Frequency, CodeRates[sd->getFecInner()], Modulations[min(sd->getModulation(), 6)], SymbolRate);
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;
}
if (Setup.UpdateChannels >= 5) { if (Setup.UpdateChannels >= 5) {
bool found = false; bool found = false;
bool forceTransponderUpdate = false; bool forceTransponderUpdate = false;
@ -255,6 +207,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
} }
} }
} }
if (ISTRANSPONDER(Frequency / 1000, Transponder()))
sdtFilter->Trigger(Source); sdtFilter->Trigger(Source);
} }
break; break;
@ -277,16 +230,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
dtp.SetGuard(GuardIntervals[sd->getGuardInterval()]); dtp.SetGuard(GuardIntervals[sd->getGuardInterval()]);
static int TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_4K, TRANSMISSION_MODE_AUTO }; static int TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_4K, TRANSMISSION_MODE_AUTO };
dtp.SetTransmission(TransmissionModes[sd->getTransmissionMode()]); dtp.SetTransmission(TransmissionModes[sd->getTransmissionMode()]);
if (ThisNIT >= 0) { 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()]);
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;
}
if (Setup.UpdateChannels >= 5) { if (Setup.UpdateChannels >= 5) {
bool found = false; bool found = false;
bool forceTransponderUpdate = false; bool forceTransponderUpdate = false;
@ -319,6 +263,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
} }
} }
} }
if (ISTRANSPONDER(Frequency / 1000000, Transponder()))
sdtFilter->Trigger(Source); sdtFilter->Trigger(Source);
} }
break; break;

16
nit.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __NIT_H
@ -13,24 +13,10 @@
#include "filter.h" #include "filter.h"
#include "sdt.h" #include "sdt.h"
#define MAXNITS 16
#define MAXNETWORKNAME Utf8BufSize(256)
class cNitFilter : public cFilter { class cNitFilter : public cFilter {
private: private:
class cNit {
public:
u_short networkId;
char name[MAXNETWORKNAME];
bool hasTransponder;
};
cSectionSyncer sectionSyncer; cSectionSyncer sectionSyncer;
cSdtFilter *sdtFilter; cSdtFilter *sdtFilter;
cNit nits[MAXNITS];
u_short networkId;
int numNits;
protected: protected:
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length); virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
public: public:

18
sdt.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "sdt.h"
@ -13,6 +13,11 @@
#include "libsi/section.h" #include "libsi/section.h"
#include "libsi/descriptor.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::cSdtFilter(cPatFilter *PatFilter) cSdtFilter::cSdtFilter(cPatFilter *PatFilter)
@ -47,8 +52,11 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
return; return;
if (!sectionSyncer.Sync(sdt.getVersionNumber(), sdt.getSectionNumber(), sdt.getLastSectionNumber())) if (!sectionSyncer.Sync(sdt.getVersionNumber(), sdt.getSectionNumber(), sdt.getLastSectionNumber()))
return; return;
if (!Channels.Lock(true, 10)) if (!Channels.Lock(true, 10)) {
sectionSyncer.Reset(); // let's not miss any section of the SDT
return; return;
}
dbgsdt("SDT: %2d %2d %2d %s %d\n", sdt.getVersionNumber(), sdt.getSectionNumber(), sdt.getLastSectionNumber(), *cSource::ToString(source), Transponder());
SI::SDT::Service SiSdtService; SI::SDT::Service SiSdtService;
for (SI::Loop::Iterator it; sdt.serviceLoop.getNext(SiSdtService, it); ) { for (SI::Loop::Iterator it; sdt.serviceLoop.getNext(SiSdtService, it); ) {
cChannel *channel = Channels.GetByChannelID(tChannelID(source, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId())); 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); // channel->SetCa(SiSdtService.getFreeCaMode() ? 0xFFFF : 0);
} }
else if (*pn && Setup.UpdateChannels >= 4) { 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 = 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 channel->SetSource(source); // in case this comes from a satellite with a slightly different position
patFilter->Trigger(SiSdtService.getServiceId()); 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 (sdt.getSectionNumber() == sdt.getLastSectionNumber()) {
if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3) 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.MarkObsoleteChannels(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId());
} }
}
Channels.Unlock(); Channels.Unlock();
} }