vdr  1.7.27
nit.c
Go to the documentation of this file.
00001 /*
00002  * nit.c: NIT section filter
00003  *
00004  * See the main source file 'vdr.c' for copyright information and
00005  * how to reach the author.
00006  *
00007  * $Id: nit.c 2.9 2012/01/12 08:43:52 kls Exp $
00008  */
00009 
00010 #include "nit.h"
00011 #include <linux/dvb/frontend.h>
00012 #include "channels.h"
00013 #include "dvbdevice.h"
00014 #include "eitscan.h"
00015 #include "libsi/section.h"
00016 #include "libsi/descriptor.h"
00017 #include "tools.h"
00018 
00019 #define DVB_SYSTEM_1 0 // see also dvbdevice.c
00020 #define DVB_SYSTEM_2 1
00021 
00022 cNitFilter::cNitFilter(void)
00023 {
00024   numNits = 0;
00025   networkId = 0;
00026   Set(0x10, 0x40);  // NIT
00027 }
00028 
00029 void cNitFilter::SetStatus(bool On)
00030 {
00031   cFilter::SetStatus(On);
00032   numNits = 0;
00033   networkId = 0;
00034   sectionSyncer.Reset();
00035 }
00036 
00037 void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
00038 {
00039   SI::NIT nit(Data, false);
00040   if (!nit.CheckCRCAndParse())
00041      return;
00042   // Some broadcasters send more than one NIT, with no apparent way of telling which
00043   // one is the right one to use. This is an attempt to find the NIT that contains
00044   // the transponder it was transmitted on and use only that one:
00045   int ThisNIT = -1;
00046   if (!networkId) {
00047      for (int i = 0; i < numNits; i++) {
00048          if (nits[i].networkId == nit.getNetworkId()) {
00049             if (nit.getSectionNumber() == 0) {
00050                // all NITs have passed by
00051                for (int j = 0; j < numNits; j++) {
00052                    if (nits[j].hasTransponder) {
00053                       networkId = nits[j].networkId;
00054                       //printf("taking NIT with network ID %d\n", networkId);
00055                       //XXX what if more than one NIT contains this transponder???
00056                       break;
00057                       }
00058                    }
00059                if (!networkId) {
00060                   //printf("none of the NITs contains transponder %d\n", Transponder());
00061                   return;
00062                   }
00063                }
00064             else {
00065                ThisNIT = i;
00066                break;
00067                }
00068             }
00069          }
00070      if (!networkId && ThisNIT < 0 && numNits < MAXNITS) {
00071         if (nit.getSectionNumber() == 0) {
00072            *nits[numNits].name = 0;
00073            SI::Descriptor *d;
00074            for (SI::Loop::Iterator it; (d = nit.commonDescriptors.getNext(it)); ) {
00075                switch (d->getDescriptorTag()) {
00076                  case SI::NetworkNameDescriptorTag: {
00077                       SI::NetworkNameDescriptor *nnd = (SI::NetworkNameDescriptor *)d;
00078                       nnd->name.getText(nits[numNits].name, MAXNETWORKNAME);
00079                       }
00080                       break;
00081                  default: ;
00082                  }
00083                delete d;
00084                }
00085            nits[numNits].networkId = nit.getNetworkId();
00086            nits[numNits].hasTransponder = false;
00087            //printf("NIT[%d] %5d '%s'\n", numNits, nits[numNits].networkId, nits[numNits].name);
00088            ThisNIT = numNits;
00089            numNits++;
00090            }
00091         }
00092      }
00093   else if (networkId != nit.getNetworkId())
00094      return; // ignore all other NITs
00095   else if (!sectionSyncer.Sync(nit.getVersionNumber(), nit.getSectionNumber(), nit.getLastSectionNumber()))
00096      return;
00097   if (!Channels.Lock(true, 10))
00098      return;
00099   SI::NIT::TransportStream ts;
00100   for (SI::Loop::Iterator it; nit.transportStreamLoop.getNext(ts, it); ) {
00101       SI::Descriptor *d;
00102 
00103       SI::Loop::Iterator it2;
00104       SI::FrequencyListDescriptor *fld = (SI::FrequencyListDescriptor *)ts.transportStreamDescriptors.getNext(it2, SI::FrequencyListDescriptorTag);
00105       int NumFrequencies = fld ? fld->frequencies.getCount() + 1 : 1;
00106       int Frequencies[NumFrequencies];
00107       if (fld) {
00108          int ct = fld->getCodingType();
00109          if (ct > 0) {
00110             int n = 1;
00111             for (SI::Loop::Iterator it3; fld->frequencies.hasNext(it3); ) {
00112                 int f = fld->frequencies.getNext(it3);
00113                 switch (ct) {
00114                   case 1: f = BCD2INT(f) / 100; break;
00115                   case 2: f = BCD2INT(f) / 10; break;
00116                   case 3: f = f * 10;  break;
00117                   default: ;
00118                   }
00119                 Frequencies[n++] = f;
00120                 }
00121             }
00122          else
00123             NumFrequencies = 1;
00124          }
00125       delete fld;
00126 
00127       for (SI::Loop::Iterator it2; (d = ts.transportStreamDescriptors.getNext(it2)); ) {
00128           switch (d->getDescriptorTag()) {
00129             case SI::SatelliteDeliverySystemDescriptorTag: {
00130                  SI::SatelliteDeliverySystemDescriptor *sd = (SI::SatelliteDeliverySystemDescriptor *)d;
00131                  cDvbTransponderParameters dtp;
00132                  int Source = cSource::FromData(cSource::stSat, BCD2INT(sd->getOrbitalPosition()), sd->getWestEastFlag());
00133                  int Frequency = Frequencies[0] = BCD2INT(sd->getFrequency()) / 100;
00134                  static char Polarizations[] = { 'H', 'V', 'L', 'R' };
00135                  dtp.SetPolarization(Polarizations[sd->getPolarization()]);
00136                  static int CodeRates[] = { FEC_NONE, FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_8_9, FEC_3_5, FEC_4_5, FEC_9_10, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_NONE };
00137                  dtp.SetCoderateH(CodeRates[sd->getFecInner()]);
00138                  static int Modulations[] = { QAM_AUTO, QPSK, PSK_8, QAM_16 };
00139                  dtp.SetModulation(Modulations[sd->getModulationType()]);
00140                  dtp.SetSystem(sd->getModulationSystem() ? DVB_SYSTEM_2 : DVB_SYSTEM_1);
00141                  static int RollOffs[] = { ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_AUTO };
00142                  dtp.SetRollOff(sd->getModulationSystem() ? RollOffs[sd->getRollOff()] : ROLLOFF_AUTO);
00143                  int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
00144                  if (ThisNIT >= 0) {
00145                     for (int n = 0; n < NumFrequencies; n++) {
00146                         if (ISTRANSPONDER(cChannel::Transponder(Frequencies[n], dtp.Polarization()), Transponder())) {
00147                            nits[ThisNIT].hasTransponder = true;
00148                            //printf("has transponder %d\n", Transponder());
00149                            break;
00150                            }
00151                         }
00152                     break;
00153                     }
00154                  if (Setup.UpdateChannels >= 5) {
00155                     bool found = false;
00156                     bool forceTransponderUpdate = false;
00157                     for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
00158                         if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
00159                            int transponder = Channel->Transponder();
00160                            found = true;
00161                            if (!ISTRANSPONDER(cChannel::Transponder(Frequency, dtp.Polarization()), transponder)) {
00162                               for (int n = 0; n < NumFrequencies; n++) {
00163                                   if (ISTRANSPONDER(cChannel::Transponder(Frequencies[n], dtp.Polarization()), transponder)) {
00164                                      Frequency = Frequencies[n];
00165                                      break;
00166                                      }
00167                                   }
00168                               }
00169                            if (ISTRANSPONDER(cChannel::Transponder(Frequency, dtp.Polarization()), Transponder())) // only modify channels if we're actually receiving this transponder
00170                               Channel->SetTransponderData(Source, Frequency, SymbolRate, dtp.ToString('S'));
00171                            else if (Channel->Srate() != SymbolRate || strcmp(Channel->Parameters(), dtp.ToString('S')))
00172                               forceTransponderUpdate = true; // get us receiving this transponder
00173                            }
00174                         }
00175                     if (!found || forceTransponderUpdate) {
00176                        for (int n = 0; n < NumFrequencies; n++) {
00177                            cChannel *Channel = new cChannel;
00178                            Channel->SetId(ts.getOriginalNetworkId(), ts.getTransportStreamId(), 0, 0);
00179                            if (Channel->SetTransponderData(Source, Frequencies[n], SymbolRate, dtp.ToString('S')))
00180                               EITScanner.AddTransponder(Channel);
00181                            else
00182                               delete Channel;
00183                            }
00184                        }
00185                     }
00186                  }
00187                  break;
00188             case SI::CableDeliverySystemDescriptorTag: {
00189                  SI::CableDeliverySystemDescriptor *sd = (SI::CableDeliverySystemDescriptor *)d;
00190                  cDvbTransponderParameters dtp;
00191                  int Source = cSource::FromData(cSource::stCable);
00192                  int Frequency = Frequencies[0] = BCD2INT(sd->getFrequency()) / 10;
00193                  //XXX FEC_outer???
00194                  static int CodeRates[] = { FEC_NONE, FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_8_9, FEC_3_5, FEC_4_5, FEC_9_10, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_NONE };
00195                  dtp.SetCoderateH(CodeRates[sd->getFecInner()]);
00196                  static int Modulations[] = { QPSK, QAM_16, QAM_32, QAM_64, QAM_128, QAM_256, QAM_AUTO };
00197                  dtp.SetModulation(Modulations[min(sd->getModulation(), 6)]);
00198                  int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
00199                  if (ThisNIT >= 0) {
00200                     for (int n = 0; n < NumFrequencies; n++) {
00201                         if (ISTRANSPONDER(Frequencies[n] / 1000, Transponder())) {
00202                            nits[ThisNIT].hasTransponder = true;
00203                            //printf("has transponder %d\n", Transponder());
00204                            break;
00205                            }
00206                         }
00207                     break;
00208                     }
00209                  if (Setup.UpdateChannels >= 5) {
00210                     bool found = false;
00211                     bool forceTransponderUpdate = false;
00212                     for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
00213                         if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
00214                            int transponder = Channel->Transponder();
00215                            found = true;
00216                            if (!ISTRANSPONDER(Frequency / 1000, transponder)) {
00217                               for (int n = 0; n < NumFrequencies; n++) {
00218                                   if (ISTRANSPONDER(Frequencies[n] / 1000, transponder)) {
00219                                      Frequency = Frequencies[n];
00220                                      break;
00221                                      }
00222                                   }
00223                               }
00224                            if (ISTRANSPONDER(Frequency / 1000, Transponder())) // only modify channels if we're actually receiving this transponder
00225                               Channel->SetTransponderData(Source, Frequency, SymbolRate, dtp.ToString('C'));
00226                            else if (Channel->Srate() != SymbolRate || strcmp(Channel->Parameters(), dtp.ToString('C')))
00227                               forceTransponderUpdate = true; // get us receiving this transponder
00228                            }
00229                         }
00230                     if (!found || forceTransponderUpdate) {
00231                         for (int n = 0; n < NumFrequencies; n++) {
00232                            cChannel *Channel = new cChannel;
00233                            Channel->SetId(ts.getOriginalNetworkId(), ts.getTransportStreamId(), 0, 0);
00234                            if (Channel->SetTransponderData(Source, Frequencies[n], SymbolRate, dtp.ToString('C')))
00235                               EITScanner.AddTransponder(Channel);
00236                            else
00237                               delete Channel;
00238                            }
00239                        }
00240                     }
00241                  }
00242                  break;
00243             case SI::TerrestrialDeliverySystemDescriptorTag: {
00244                  SI::TerrestrialDeliverySystemDescriptor *sd = (SI::TerrestrialDeliverySystemDescriptor *)d;
00245                  cDvbTransponderParameters dtp;
00246                  int Source = cSource::FromData(cSource::stTerr);
00247                  int Frequency = Frequencies[0] = sd->getFrequency() * 10;
00248                  static int Bandwidths[] = { 8000000, 7000000, 6000000, 5000000, 0, 0, 0, 0 };
00249                  dtp.SetBandwidth(Bandwidths[sd->getBandwidth()]);
00250                  static int Constellations[] = { QPSK, QAM_16, QAM_64, QAM_AUTO };
00251                  dtp.SetModulation(Constellations[sd->getConstellation()]);
00252                  dtp.SetSystem(DVB_SYSTEM_1);
00253                  static int Hierarchies[] = { HIERARCHY_NONE, HIERARCHY_1, HIERARCHY_2, HIERARCHY_4, HIERARCHY_AUTO, HIERARCHY_AUTO, HIERARCHY_AUTO, HIERARCHY_AUTO };
00254                  dtp.SetHierarchy(Hierarchies[sd->getHierarchy()]);
00255                  static int CodeRates[] = { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_AUTO, FEC_AUTO, FEC_AUTO };
00256                  dtp.SetCoderateH(CodeRates[sd->getCodeRateHP()]);
00257                  dtp.SetCoderateL(CodeRates[sd->getCodeRateLP()]);
00258                  static int GuardIntervals[] = { GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_16, GUARD_INTERVAL_1_8, GUARD_INTERVAL_1_4 };
00259                  dtp.SetGuard(GuardIntervals[sd->getGuardInterval()]);
00260                  static int TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_4K, TRANSMISSION_MODE_AUTO };
00261                  dtp.SetTransmission(TransmissionModes[sd->getTransmissionMode()]);
00262                  if (ThisNIT >= 0) {
00263                     for (int n = 0; n < NumFrequencies; n++) {
00264                         if (ISTRANSPONDER(Frequencies[n] / 1000000, Transponder())) {
00265                            nits[ThisNIT].hasTransponder = true;
00266                            //printf("has transponder %d\n", Transponder());
00267                            break;
00268                            }
00269                         }
00270                     break;
00271                     }
00272                  if (Setup.UpdateChannels >= 5) {
00273                     bool found = false;
00274                     bool forceTransponderUpdate = false;
00275                     for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
00276                         if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
00277                            int transponder = Channel->Transponder();
00278                            found = true;
00279                            if (!ISTRANSPONDER(Frequency / 1000000, transponder)) {
00280                               for (int n = 0; n < NumFrequencies; n++) {
00281                                   if (ISTRANSPONDER(Frequencies[n] / 1000000, transponder)) {
00282                                      Frequency = Frequencies[n];
00283                                      break;
00284                                      }
00285                                   }
00286                               }
00287                            if (ISTRANSPONDER(Frequency / 1000000, Transponder())) // only modify channels if we're actually receiving this transponder
00288                               Channel->SetTransponderData(Source, Frequency, 0, dtp.ToString('T'));
00289                            else if (strcmp(Channel->Parameters(), dtp.ToString('T')))
00290                               forceTransponderUpdate = true; // get us receiving this transponder
00291                            }
00292                         }
00293                     if (!found || forceTransponderUpdate) {
00294                        for (int n = 0; n < NumFrequencies; n++) {
00295                            cChannel *Channel = new cChannel;
00296                            Channel->SetId(ts.getOriginalNetworkId(), ts.getTransportStreamId(), 0, 0);
00297                            if (Channel->SetTransponderData(Source, Frequencies[n], 0, dtp.ToString('T')))
00298                               EITScanner.AddTransponder(Channel);
00299                            else
00300                               delete Channel;
00301                            }
00302                         }
00303                     }
00304                  }
00305                  break;
00306             case SI::ExtensionDescriptorTag: {
00307                  SI::ExtensionDescriptor *sd = (SI::ExtensionDescriptor *)d;
00308                  switch (sd->getExtensionDescriptorTag()) {
00309                    case SI::T2DeliverySystemDescriptorTag: {
00310                         if (Setup.UpdateChannels >= 5) {
00311                            for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
00312                                int Source = cSource::FromData(cSource::stTerr);
00313                                if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
00314                                   SI::T2DeliverySystemDescriptor *td = (SI::T2DeliverySystemDescriptor *)d;
00315                                   int Frequency = Channel->Frequency();
00316                                   int SymbolRate = Channel->Srate();
00317                                   //int SystemId = td->getSystemId();
00318                                   cDvbTransponderParameters dtp(Channel->Parameters());
00319                                   dtp.SetSystem(DVB_SYSTEM_2);
00320                                   dtp.SetPlpId(td->getPlpId());
00321                                   if (td->getExtendedDataFlag()) {
00322                                      static int T2Bandwidths[] = { 8000000, 7000000, 6000000, 5000000, 10000000, 1712000, 0, 0 };
00323                                      dtp.SetBandwidth(T2Bandwidths[td->getBandwidth()]);
00324                                      static int T2GuardIntervals[] = { GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_16, GUARD_INTERVAL_1_8, GUARD_INTERVAL_1_4, GUARD_INTERVAL_1_128, GUARD_INTERVAL_19_128, GUARD_INTERVAL_19_256, 0 };
00325                                      dtp.SetGuard(T2GuardIntervals[td->getGuardInterval()]);
00326                                      static int T2TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_4K, TRANSMISSION_MODE_1K, TRANSMISSION_MODE_16K, TRANSMISSION_MODE_32K, TRANSMISSION_MODE_AUTO, TRANSMISSION_MODE_AUTO };
00327                                      dtp.SetTransmission(T2TransmissionModes[td->getTransmissionMode()]);
00328                                      //TODO add parsing of frequencies
00329                                      }
00330                                   Channel->SetTransponderData(Source, Frequency, SymbolRate, dtp.ToString('T'));
00331                                   }
00332                                }
00333                            }
00334                         }
00335                         break;
00336                    default: ;
00337                    }
00338                  }
00339                  break;
00340             default: ;
00341             }
00342           delete d;
00343           }
00344       }
00345   Channels.Unlock();
00346 }