Example #1
0
void CPmt::MakeCAMap(casys_map_t &camap)
{
	ProgramMapSection pmt(buffer);
	CaProgramMapSection capmt(&pmt, 0x03, 0x01);
	DescriptorConstIterator dit;
	for (dit = capmt.getDescriptors()->begin(); dit != capmt.getDescriptors()->end(); ++dit) {
		if ((*dit)->getTag() == CA_DESCRIPTOR ) {
			CaDescriptor * d = (CaDescriptor*) *dit;
			//printf("%02X: casys %04X capid %04X, ", d->getTag(), d->getCaSystemId(), d->getCaPid());
			camap.insert(d->getCaSystemId());
		}
	}
	const ElementaryStreamInfoList * eslist = pmt.getEsInfo();
	ElementaryStreamInfoConstIterator it;
	for (it = eslist->begin(); it != eslist->end(); ++it) {
		ElementaryStreamInfo *esinfo = *it;
		const DescriptorList * dlist = esinfo->getDescriptors();
		for (dit = dlist->begin(); dit != dlist->end(); ++dit) {
			if ((*dit)->getTag() == CA_DESCRIPTOR ) {
				CaDescriptor * d = (CaDescriptor*) *dit;
				camap.insert(d->getCaSystemId());
			}
		}
	}
}
std::vector < std::vector <Double_t> > readPMTbackgroundRates(Int_t octet) {

  std::vector < std::vector <Double_t> > PMT;

  TString dir = TString::Format("%s/reference_rates/backgroundRatesByAnaChoice/",getenv("ANALYSIS_CODE"));

  TString filename = ( dir + TString("pmtRefSpectra_Octets_") +
		       ( octet<=59 ? TString("0-59") : TString("60-121") ) + TString(".txt") );

  std::ifstream infile(filename.Data());

  Double_t totalRefTime[8];

  std::string label;
  infile >> label >> totalRefTime[0] >> totalRefTime[1] >> totalRefTime[2] >> totalRefTime[3]
	 >> totalRefTime[4] >> totalRefTime[5] >> totalRefTime[6] >> totalRefTime[7];

  double binMid=0.;
  std::vector <Double_t> pmt(8, 0.);

  while ( infile >> binMid >> pmt[0] >> pmt[1] >> pmt[2] >> pmt[3] 
	  >> pmt[4] >> pmt[5] >> pmt[6] >> pmt[7] ) {

    for ( int i=0; i<8; ++i ) {
      pmt[i] = pmt[i]/totalRefTime[i];
      std::cout << pmt[i] << "  ";
    }
    std::cout << std::endl;

    PMT.push_back(pmt);
  }
  
  return PMT;

}
Example #3
0
bool CCam::makeCaPmt(CZapitChannel * channel, bool add_private, uint8_t list, const CaIdVector &caids)
{
        int len;
        unsigned char * buffer = channel->getRawPmt(len);

	INFO("cam %x source %d camask %d list %02x buffer", (int) this, source_demux, camask, list);

	if(!buffer)
		return false;

	ProgramMapSection pmt(buffer);
	CaProgramMapSection capmt(&pmt, list, 0x01, caids);

	if (add_private) {
		uint8_t tmp[10];
		tmp[0] = 0x84;
		tmp[1] = 0x02;
		tmp[2] = channel->getPmtPid() >> 8;
		tmp[3] = channel->getPmtPid() & 0xFF;
		capmt.injectDescriptor(tmp, false);

		tmp[0] = 0x82;
		tmp[1] = 0x02;
		tmp[2] = camask;
		tmp[3] = source_demux;
		capmt.injectDescriptor(tmp, false);

		memset(tmp, 0, sizeof(tmp));
		tmp[0] = 0x81;
		tmp[1] = 0x08;
		tmp[2] = channel->getSatellitePosition() >> 8;
		tmp[3] = channel->getSatellitePosition() & 0xFF;
		tmp[4] = channel->getFreqId() >> 8;
		tmp[5] = channel->getFreqId() & 0xFF;
		tmp[6] = channel->getTransportStreamId() >> 8;
		tmp[7] = channel->getTransportStreamId() & 0xFF;
		tmp[8] = channel->getOriginalNetworkId() >> 8;
		tmp[9] = channel->getOriginalNetworkId() & 0xFF;

		capmt.injectDescriptor(tmp, false);
	}

	calen = capmt.writeToBuffer(cabuf);
#ifdef DEBUG_CAPMT
	printf("CAPMT: ");
	for(int i = 0; i < calen; i++)
		printf("%02X ", cabuf[i]);
	printf("\n");
#endif
	return true;
}
Example #4
0
bool CPmt::Parse(CZapitChannel * const channel)
{
	printf("[zapit] parsing pmt pid 0x%X (%s)\n", channel->getPmtPid(), channel->getName().c_str());

	if (channel->getPmtPid() == 0)
		return false;

	if(!Read(channel->getPmtPid(), channel->getServiceId()))
		return false;

	ProgramMapSection pmt(buffer);

	DBG("pcr pid: old 0x%x new 0x%x\n", channel->getPcrPid(), pmt.getPcrPid());

	channel->resetPids();

	channel->setPmtVersion(pmt.getVersionNumber());
	channel->setPcrPid(pmt.getPcrPid());

	const ElementaryStreamInfoList * eslist = pmt.getEsInfo();
	ElementaryStreamInfoConstIterator it;
	for (it = eslist->begin(); it != eslist->end(); ++it) {
		ElementaryStreamInfo *esinfo = *it;
		ParseEsInfo(esinfo, channel);
	}

	casys_map_t camap;
	MakeCAMap(camap);
	channel->scrambled = !camap.empty();

	if(CServiceScan::getInstance()->Scanning()) {
		channel->setRawPmt(NULL);
	} else {
		channel->camap = camap;
		int pmtlen= pmt.getSectionLength() + 3;
		unsigned char * p = new unsigned char[pmtlen];
		memmove(p, buffer, pmtlen);
		channel->setRawPmt(p, pmtlen);
	}

	channel->setPidsFlag();
	return true;
}
Example #5
0
void cLivePatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
{
  if (Pid == 0x00)
  {
    if (Tid == 0x00)
    {
      SI::PAT pat(Data, false);
      if (!pat.CheckCRCAndParse())
        return;
      SI::PAT::Association assoc;
      for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); )
      {
        if (!assoc.isNITPid())
        {
          const cChannel *Channel =  Channels.GetByServiceID(Source(), Transponder(), assoc.getServiceId());
          if (Channel && (Channel == m_Channel))
          {
            int prevPmtPid = m_pmtPid;
            if (0 != (m_pmtPid = assoc.getPid()))
            {
              if (m_pmtPid != prevPmtPid)
              {
                m_pmtSid = assoc.getServiceId();
                Add(m_pmtPid, 0x02);
                m_pmtVersion = -1;
                break;
              }
              return;
            }
          }
        }
      }
    }
  }
  else if (Pid == m_pmtPid && Tid == SI::TableIdPMT && Source() && Transponder())
  {
    SI::PMT pmt(Data, false);
    if (!pmt.CheckCRCAndParse())
      return;
    if (pmt.getServiceId() != m_pmtSid)
      return; // skip broken PMT records
    if (m_pmtVersion != -1)
    {
      if (m_pmtVersion != pmt.getVersionNumber())
      {
        cFilter::Del(m_pmtPid, 0x02);
        m_pmtPid = 0; // this triggers PAT scan
      }
      return;
    }
    m_pmtVersion = pmt.getVersionNumber();

    cChannel *Channel = Channels.GetByServiceID(Source(), Transponder(), pmt.getServiceId());
    if (Channel) {
       // Scan the stream-specific loop:
       SI::PMT::Stream stream;
       int Vpid = 0;
       int Ppid = 0;
       int Vtype = 0;
       int Apids[MAXAPIDS + 1] = { 0 }; // these lists are zero-terminated
       int Atypes[MAXAPIDS + 1] = { 0 };
       int Dpids[MAXDPIDS + 1] = { 0 };
       int Dtypes[MAXDPIDS + 1] = { 0 };
       int Spids[MAXSPIDS + 1] = { 0 };
       uchar SubtitlingTypes[MAXSPIDS + 1] = { 0 };
       uint16_t CompositionPageIds[MAXSPIDS + 1] = { 0 };
       uint16_t AncillaryPageIds[MAXSPIDS + 1] = { 0 };
       char ALangs[MAXAPIDS][MAXLANGCODE2] = { "" };
       char DLangs[MAXDPIDS][MAXLANGCODE2] = { "" };
       char SLangs[MAXSPIDS][MAXLANGCODE2] = { "" };
       int Tpid = 0;
       int NumApids = 0;
       int NumDpids = 0;
       int NumSpids = 0;
       for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); ) {
           bool ProcessCaDescriptors = false;
           int esPid = stream.getPid();
           switch (stream.getStreamType()) {
             case 1: // STREAMTYPE_11172_VIDEO
             case 2: // STREAMTYPE_13818_VIDEO
             case 0x1B: // MPEG4
                     Vpid = esPid;
                     Ppid = pmt.getPCRPid();
                     Vtype = stream.getStreamType();
                     ProcessCaDescriptors = true;
                     break;
             case 3: // STREAMTYPE_11172_AUDIO
             case 4: // STREAMTYPE_13818_AUDIO
             case 0x0F: // ISO/IEC 13818-7 Audio with ADTS transport syntax
             case 0x11: // ISO/IEC 14496-3 Audio with LATM transport syntax
                     {
                     if (NumApids < MAXAPIDS) {
                        Apids[NumApids] = esPid;
                        Atypes[NumApids] = stream.getStreamType();
                        SI::Descriptor *d;
                        for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
                            switch (d->getDescriptorTag()) {
                              case SI::ISO639LanguageDescriptorTag: {
                                   SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
                                   SI::ISO639LanguageDescriptor::Language l;
                                   char *s = ALangs[NumApids];
                                   int n = 0;
                                   for (SI::Loop::Iterator it; ld->languageLoop.getNext(l, it); ) {
                                       if (*ld->languageCode != '-') { // some use "---" to indicate "none"
                                          if (n > 0)
                                             *s++ = '+';
                                          strn0cpy(s, I18nNormalizeLanguageCode(l.languageCode), MAXLANGCODE1);
                                          s += strlen(s);
                                          if (n++ > 1)
                                             break;
                                          }
                                       }
                                   }
                                   break;
                              default: ;
                              }
                            delete d;
                            }
                        NumApids++;
                        }
                     ProcessCaDescriptors = true;
                     }
                     break;
             case 5: // STREAMTYPE_13818_PRIVATE
             case 6: // STREAMTYPE_13818_PES_PRIVATE
             //XXX case 8: // STREAMTYPE_13818_DSMCC
                     {
                     int dpid = 0;
                     int dtype = 0;
                     char lang[MAXLANGCODE1] = { 0 };
                     SI::Descriptor *d;
                     for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
                         switch (d->getDescriptorTag()) {
                           case SI::AC3DescriptorTag:
                           case SI::EnhancedAC3DescriptorTag:
                                dpid = esPid;
                                dtype = d->getDescriptorTag();
                                ProcessCaDescriptors = true;
                                break;
                           case SI::SubtitlingDescriptorTag:
                                if (NumSpids < MAXSPIDS) {
                                   Spids[NumSpids] = esPid;
                                   SI::SubtitlingDescriptor *sd = (SI::SubtitlingDescriptor *)d;
                                   SI::SubtitlingDescriptor::Subtitling sub;
                                   char *s = SLangs[NumSpids];
                                   int n = 0;
                                   for (SI::Loop::Iterator it; sd->subtitlingLoop.getNext(sub, it); ) {
                                       if (sub.languageCode[0]) {
                                          SubtitlingTypes[NumSpids] = sub.getSubtitlingType();
                                          CompositionPageIds[NumSpids] = sub.getCompositionPageId();
                                          AncillaryPageIds[NumSpids] = sub.getAncillaryPageId();
                                          if (n > 0)
                                             *s++ = '+';
                                          strn0cpy(s, I18nNormalizeLanguageCode(sub.languageCode), MAXLANGCODE1);
                                          s += strlen(s);
                                          if (n++ > 1)
                                             break;
                                          }
                                       }
                                   NumSpids++;
                                   }
                                break;
                           case SI::TeletextDescriptorTag:
                                Tpid = esPid;
                                break;
                           case SI::ISO639LanguageDescriptorTag: {
                                SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
                                strn0cpy(lang, I18nNormalizeLanguageCode(ld->languageCode), MAXLANGCODE1);
                                }
                                break;
                           default: ;
                           }
                         delete d;
                         }
                     if (dpid) {
                        if (NumDpids < MAXDPIDS) {
                           Dpids[NumDpids] = dpid;
                           Dtypes[NumDpids] = dtype;
                           strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
                           NumDpids++;
                           }
                        }
                     }
                     break;
             case 0x80: // STREAMTYPE_USER_PRIVATE
#if APIVERSNUM >= 10728
                     if (Setup.StandardCompliance == STANDARD_ANSISCTE)
#endif
                     { // DigiCipher II VIDEO (ANSI/SCTE 57)
                        Vpid = esPid;
                        Ppid = pmt.getPCRPid();
                        Vtype = 0x02; // compression based upon MPEG-2
                        ProcessCaDescriptors = true;
                        break;
                        }
                     // fall through
             case 0x81: // STREAMTYPE_USER_PRIVATE
#if APIVERSNUM >= 10728
                     if (Setup.StandardCompliance == STANDARD_ANSISCTE)
#endif
                     { // ATSC A/53 AUDIO (ANSI/SCTE 57)
                        char lang[MAXLANGCODE1] = { 0 };
                        SI::Descriptor *d;
                        for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
                            switch (d->getDescriptorTag()) {
                              case SI::ISO639LanguageDescriptorTag: {
                                   SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
                                   strn0cpy(lang, I18nNormalizeLanguageCode(ld->languageCode), MAXLANGCODE1);
                                   }
                                   break;
                              default: ;
                              }
                           delete d;
                           }
                        if (NumDpids < MAXDPIDS) {
                           Dpids[NumDpids] = esPid;
                           Dtypes[NumDpids] = SI::AC3DescriptorTag;
                           strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
                           NumDpids++;
                           }
                        ProcessCaDescriptors = true;
                        break;
                        }
                     // fall through
             case 0x82: // STREAMTYPE_USER_PRIVATE
#if APIVERSNUM >= 10728
                     if (Setup.StandardCompliance == STANDARD_ANSISCTE)
#endif
                     { // STANDARD SUBTITLE (ANSI/SCTE 27)
                        //TODO
                        break;
                        }
                     // fall through
             case 0x83 ... 0xFF: // STREAMTYPE_USER_PRIVATE
                     {
                     char lang[MAXLANGCODE1] = { 0 };
                     bool IsAc3 = false;
                     SI::Descriptor *d;
                     for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
                         switch (d->getDescriptorTag()) {
                           case SI::RegistrationDescriptorTag: {
                                SI::RegistrationDescriptor *rd = (SI::RegistrationDescriptor *)d;
                                // http://www.smpte-ra.org/mpegreg/mpegreg.html
                                switch (rd->getFormatIdentifier()) {
                                  case 0x41432D33: // 'AC-3'
                                       IsAc3 = true;
                                       break;
                                  default:
                                       //printf("Format identifier: 0x%08X (pid: %d)\n", rd->getFormatIdentifier(), esPid);
                                       break;
                                  }
                                }
                                break;
                           case SI::ISO639LanguageDescriptorTag: {
                                SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
                                strn0cpy(lang, I18nNormalizeLanguageCode(ld->languageCode), MAXLANGCODE1);
                                }
                                break;
                           default: ;
                           }
                        delete d;
                        }
                     if (IsAc3) {
                        if (NumDpids < MAXDPIDS) {
                           Dpids[NumDpids] = esPid;
                           Dtypes[NumDpids] = SI::AC3DescriptorTag;
                           strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
                           NumDpids++;
                           }
                        ProcessCaDescriptors = true;
                        }
                     }
                     break;
             default: ;//printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());
             }
           }
       cChannel pmtChannel(*Channel);
       pmtChannel.SetPids(Vpid, Ppid, Vtype, Apids, Atypes, ALangs, Dpids, Dtypes, DLangs, Spids, SLangs, Tpid);
       pmtChannel.SetSubtitlingDescriptors(SubtitlingTypes, CompositionPageIds, AncillaryPageIds);
       m_Streamer->SetTpid(Tpid);
       cPatPmtGenerator patPmtGenerator(&pmtChannel);
       m_Streamer->m_bufferLock.Lock();
       m_Streamer->Put(patPmtGenerator.GetPat(), TS_SIZE);
       int Index = 0;
       while (uchar *pmt = patPmtGenerator.GetPmt(Index))
         m_Streamer->Put(pmt, TS_SIZE);
       m_Streamer->m_bufferLock.Unlock();
       }
  }
Example #6
0
void cLivePatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
{
  if (Pid == 0x00 && Tid == 0x00)
  {
    SI::PAT pat(Data, false);
    if (!pat.CheckCRCAndParse())
      return;

    SI::PAT::Association assoc;
    for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); )
    {
      if (!assoc.isNITPid())
      {
    	XVDRChannels.Lock(false);
        const cChannel *Channel =  XVDRChannels.Get()->GetByServiceID(Source(), Transponder(), assoc.getServiceId());

        if (Channel && (Channel == m_Channel))
        {
          int prevPmtPid = m_pmtPid;
          if (0 != (m_pmtPid = assoc.getPid()))
          {
            m_pmtSid = assoc.getServiceId();
            if (m_pmtPid != prevPmtPid)
            {
              Add(m_pmtPid, 0x02);
              m_pmtVersion = -1;
            }
            XVDRChannels.Unlock();
            return;
          }
        }

        XVDRChannels.Unlock();
      }
    }
  }
  else if (Pid == m_pmtPid && Tid == SI::TableIdPMT && Source() && Transponder())
  {
    SI::PMT pmt(Data, false);
    if (!pmt.CheckCRCAndParse() || pmt.getServiceId() != m_pmtSid)
      return;

    if (m_pmtVersion != -1)
    {
      if (m_pmtVersion != pmt.getVersionNumber())
      {
        cFilter::Del(m_pmtPid, 0x02);
        m_pmtPid = 0; // this triggers PAT scan
      }
      return;
    }
    m_pmtVersion = pmt.getVersionNumber();

    // get cached channel data
    if(m_ChannelCache.size() == 0)
      m_ChannelCache = cChannelCache::GetFromCache(CreateChannelUID(m_Channel));

    // get all streams and check if there are new (currently unknown) streams
    SI::PMT::Stream stream;
    cChannelCache cache;
    for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); )
    {
      cStreamInfo info;
      if (GetStreamInfo(stream, info) && cache.size() < MAXRECEIVEPIDS) {
        info.SetContent();
        cache.AddStream(info);
      }
    }

    // no new streams found -> exit
    if (m_ChannelCache.ismetaof(cache))
      return;

    m_Streamer->m_FilterMutex.Lock();

    // create new stream demuxers
    m_Streamer->Detach();
    cache.CreateDemuxers(m_Streamer);

    m_Streamer->m_ready = false;
    INFOLOG("Currently unknown new streams found, requesting stream change");

    m_Streamer->RequestStreamChange();

    // write changed data back to the cache
    m_ChannelCache = cache;
    cChannelCache::AddToCache(CreateChannelUID(m_Channel), m_ChannelCache);

    // try to attach receiver
    int c = 0;
    for(; c < 3 && !m_Streamer->Attach(); c++) {
      INFOLOG("Unable to attach receiver, retrying ...");
      usleep(100 * 1000);
    }

    // unable to attach receiver
    if(c == 3) {
      ERRORLOG("failed to attach receiver, sending detach ...");
      m_Streamer->sendDetach();
    }

    m_Streamer->m_FilterMutex.Unlock();
  }
}
Example #7
0
void cLivePatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
{
  if (Pid == 0x00 && Tid == 0x00)
  {
    SI::PAT pat(Data, false);
    if (!pat.CheckCRCAndParse())
      return;

    SI::PAT::Association assoc;
    for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); )
    {
      if (!assoc.isNITPid())
      {
        const cChannel *Channel =  Channels.GetByServiceID(Source(), Transponder(), assoc.getServiceId());
        if (Channel && (Channel == m_Channel))
        {
          int prevPmtPid = m_pmtPid;
          if (0 != (m_pmtPid = assoc.getPid()))
          {
            m_pmtSid = assoc.getServiceId();
            if (m_pmtPid != prevPmtPid)
            {
              Add(m_pmtPid, 0x02);
              m_pmtVersion = -1;
            }
            return;
          }
        }
      }
    }
  }
  else if (Pid == m_pmtPid && Tid == SI::TableIdPMT && Source() && Transponder())
  {
    SI::PMT pmt(Data, false);
    if (!pmt.CheckCRCAndParse() || pmt.getServiceId() != m_pmtSid)
      return;

    if (m_pmtVersion != -1)
    {
      if (m_pmtVersion != pmt.getVersionNumber())
      {
        cFilter::Del(m_pmtPid, 0x02);
        m_pmtPid = 0; // this triggers PAT scan
      }
      return;
    }
    m_pmtVersion = pmt.getVersionNumber();

    // get cached channel data
    if(m_ChannelCache.size() == 0)
      m_ChannelCache = cChannelCache::GetFromCache(CreateChannelUID(m_Channel));

    // get all streams and check if there are new (currently unknown) streams
    SI::PMT::Stream stream;
    cChannelCache cache;
    for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); )
    {
      struct StreamInfo info;
      if (GetStreamInfo(stream, info) && cache.size() < MAXRECEIVEPIDS)
        cache.AddStream(info);
    }

    // no new streams found -> exit
    if (cache == m_ChannelCache)
      return;

    m_Streamer->m_FilterMutex.Lock();

    // create new stream demuxers
    cache.CreateDemuxers(m_Streamer);

    INFOLOG("Currently unknown new streams found, requesting stream change");

    // write changed data back to the cache
    m_ChannelCache = cache;
    cChannelCache::AddToCache(CreateChannelUID(m_Channel), m_ChannelCache);

    m_Streamer->RequestStreamChange();
    m_Streamer->m_FilterMutex.Unlock();
  }
}
Example #8
0
void cLivePatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
{
  if (Pid == 0x00)
  {
    if (Tid == 0x00)
    {
      SI::PAT pat(Data, false);
      if (!pat.CheckCRCAndParse())
        return;
      SI::PAT::Association assoc;
      for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); )
      {
        if (!assoc.isNITPid())
        {
          const cChannel *Channel =  Channels.GetByServiceID(Source(), Transponder(), assoc.getServiceId());
          if (Channel && (Channel == m_Channel))
          {
            int prevPmtPid = m_pmtPid;
            if (0 != (m_pmtPid = assoc.getPid()))
            {
              m_pmtSid = assoc.getServiceId();
              if (m_pmtPid != prevPmtPid)
              {
                Add(m_pmtPid, 0x02);
                m_pmtVersion = -1;
              }
              return;
            }
          }
        }
      }
    }
  }
  else if (Pid == m_pmtPid && Tid == SI::TableIdPMT && Source() && Transponder())
  {
    SI::PMT pmt(Data, false);
    if (!pmt.CheckCRCAndParse())
      return;
    if (pmt.getServiceId() != m_pmtSid)
      return; // skip broken PMT records
    if (m_pmtVersion != -1)
    {
      if (m_pmtVersion != pmt.getVersionNumber())
      {
//        printf("cStreamdevPatFilter: PMT version changed, detaching all pids\n");
        cFilter::Del(m_pmtPid, 0x02);
        m_pmtPid = 0; // this triggers PAT scan
      }
      return;
    }
    m_pmtVersion = pmt.getVersionNumber();

    SI::PMT::Stream stream;
    int         pids[MAXRECEIVEPIDS + 1];
    eStreamType types[MAXRECEIVEPIDS + 1];
    char        langs[MAXRECEIVEPIDS + 1][MAXLANGCODE2];
    int         subtitlingType[MAXRECEIVEPIDS + 1];
    int         compositionPageId[MAXRECEIVEPIDS + 1];
    int         ancillaryPageId[MAXRECEIVEPIDS + 1];
    int         streams = 0;
    for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); )
    {
      eStreamType type;
      int pid = GetPid(stream, &type, langs[streams], &subtitlingType[streams], &compositionPageId[streams], &ancillaryPageId[streams]);
      if (0 != pid && streams < MAXRECEIVEPIDS)
      {
        pids[streams]   = pid;
        types[streams]  = type;
        streams++;
      }
    }
    pids[streams] = 0;

    int newstreams = 0;
    for (int i = 0; i < streams; i++)
    {
      if (m_Streamer->HaveStreamDemuxer(pids[i], types[i]) == -1)
        newstreams++;
    }

    if (newstreams > 0)
    {
      m_Streamer->m_FilterMutex.Lock();
      if (m_Streamer->m_Receiver)
      {
        DEBUGLOG("Detaching Live Receiver");
        m_Streamer->m_Device->Detach(m_Streamer->m_Receiver);
        DELETENULL(m_Streamer->m_Receiver);
      }

      for (int idx = 0; idx < MAXRECEIVEPIDS; ++idx)
      {
        if (m_Streamer->m_Streams[idx])
        {
          DELETENULL(m_Streamer->m_Streams[idx]);
          m_Streamer->m_Pids[idx] = 0;
        }
      }
      m_Streamer->m_NumStreams  = 0;
      m_Streamer->m_streamReady = false;
      m_Streamer->m_IFrameSeen  = false;

      for (int i = 0; i < streams; i++)
      {
        switch (types[i])
        {
          case stMPEG2AUDIO:
          {
            m_Streamer->m_Streams[m_Streamer->m_NumStreams] = new cTSDemuxer(m_Streamer, stMPEG2AUDIO, pids[i]);
            m_Streamer->m_Streams[m_Streamer->m_NumStreams]->SetLanguage(langs[i]);
            m_Streamer->m_Pids[m_Streamer->m_NumStreams] = pids[i];
            m_Streamer->m_NumStreams++;
            break;
          }
          case stMPEG2VIDEO:
          {
            m_Streamer->m_Streams[m_Streamer->m_NumStreams] = new cTSDemuxer(m_Streamer, stMPEG2VIDEO, pids[i]);
            m_Streamer->m_Pids[m_Streamer->m_NumStreams] = pids[i];
            m_Streamer->m_NumStreams++;
            break;
          }
          case stH264:
          {
            m_Streamer->m_Streams[m_Streamer->m_NumStreams] = new cTSDemuxer(m_Streamer, stH264, pids[i]);
            m_Streamer->m_Pids[m_Streamer->m_NumStreams] = pids[i];
            m_Streamer->m_NumStreams++;
            break;
          }
          case stAC3:
          {
            m_Streamer->m_Streams[m_Streamer->m_NumStreams] = new cTSDemuxer(m_Streamer, stAC3, pids[i]);
            m_Streamer->m_Streams[m_Streamer->m_NumStreams]->SetLanguage(langs[i]);
            m_Streamer->m_Pids[m_Streamer->m_NumStreams] = pids[i];
            m_Streamer->m_NumStreams++;
            break;
          }
          case stEAC3:
          {
            m_Streamer->m_Streams[m_Streamer->m_NumStreams] = new cTSDemuxer(m_Streamer, stEAC3, pids[i]);
            m_Streamer->m_Streams[m_Streamer->m_NumStreams]->SetLanguage(langs[i]);
            m_Streamer->m_Pids[m_Streamer->m_NumStreams] = pids[i];
            m_Streamer->m_NumStreams++;
            break;
          }
          case stDTS:
          {
            m_Streamer->m_Streams[m_Streamer->m_NumStreams] = new cTSDemuxer(m_Streamer, stDTS, pids[i]);
            m_Streamer->m_Streams[m_Streamer->m_NumStreams]->SetLanguage(langs[i]);
            m_Streamer->m_Pids[m_Streamer->m_NumStreams] = pids[i];
            m_Streamer->m_NumStreams++;
            break;
          }
          case stAAC:
          {
            m_Streamer->m_Streams[m_Streamer->m_NumStreams] = new cTSDemuxer(m_Streamer, stAAC, pids[i]);
            m_Streamer->m_Streams[m_Streamer->m_NumStreams]->SetLanguage(langs[i]);
            m_Streamer->m_Pids[m_Streamer->m_NumStreams] = pids[i];
            m_Streamer->m_NumStreams++;
            break;
          }
          case stLATM:
          {
            m_Streamer->m_Streams[m_Streamer->m_NumStreams] = new cTSDemuxer(m_Streamer, stLATM, pids[i]);
            m_Streamer->m_Streams[m_Streamer->m_NumStreams]->SetLanguage(langs[i]);
            m_Streamer->m_Pids[m_Streamer->m_NumStreams] = pids[i];
            m_Streamer->m_NumStreams++;
            break;
          }
          case stDVBSUB:
          {
            m_Streamer->m_Streams[m_Streamer->m_NumStreams] = new cTSDemuxer(m_Streamer, stDVBSUB, pids[i]);
            m_Streamer->m_Streams[m_Streamer->m_NumStreams]->SetLanguage(langs[i]);
            m_Streamer->m_Streams[m_Streamer->m_NumStreams]->SetSubtitlingDescriptor(subtitlingType[i], compositionPageId[i], ancillaryPageId[i]);
            m_Streamer->m_Pids[m_Streamer->m_NumStreams] = pids[i];
            m_Streamer->m_NumStreams++;
            break;
          }
          case stTELETEXT:
          {
            m_Streamer->m_Streams[m_Streamer->m_NumStreams] = new cTSDemuxer(m_Streamer, stTELETEXT, pids[i]);
            m_Streamer->m_Pids[m_Streamer->m_NumStreams] = pids[i];
            m_Streamer->m_NumStreams++;
            break;
          }
          default:
            break;
        }
      }

      m_Streamer->m_Receiver  = new cLiveReceiver(m_Streamer, m_Channel->GetChannelID(), m_Streamer->m_Priority, m_Streamer->m_Pids);
      m_Streamer->m_Device->AttachReceiver(m_Streamer->m_Receiver);
      INFOLOG("Currently unknown new streams found, requesting stream change");
      m_Streamer->RequestStreamChange();
      m_Streamer->m_FilterMutex.Unlock();
    }
  }
}