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>
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.
- 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).

131
nit.c
View File

@ -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: {

16
nit.h
View File

@ -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:

20
sdt.c
View File

@ -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();
}