vdr  2.4.7
pat.c
Go to the documentation of this file.
1 /*
2  * pat.c: PAT section filter
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: pat.c 4.9 2020/12/18 14:51:57 kls Exp $
8  */
9 
10 #include "pat.h"
11 #include <malloc.h>
12 #include "channels.h"
13 #include "libsi/section.h"
14 #include "libsi/descriptor.h"
15 
16 #define PMT_SCAN_TIMEOUT 1000 // ms
17 
18 // --- cCaDescriptor ---------------------------------------------------------
19 
20 class cCaDescriptor : public cListObject {
21 private:
22  int caSystem;
23  int caPid;
24  int esPid;
25  int length;
27 public:
28  cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data);
29  virtual ~cCaDescriptor();
30  bool operator== (const cCaDescriptor &arg) const;
31  int CaSystem(void) { return caSystem; }
32  int CaPid(void) { return caPid; }
33  int EsPid(void) { return esPid; }
34  int Length(void) const { return length; }
35  const uchar *Data(void) const { return data; }
36  };
37 
38 cCaDescriptor::cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data)
39 {
41  caPid = CaPid;
42  esPid = EsPid;
43  length = Length + 6;
44  data = MALLOC(uchar, length);
46  data[1] = length - 2;
47  data[2] = (caSystem >> 8) & 0xFF;
48  data[3] = caSystem & 0xFF;
49  data[4] = ((CaPid >> 8) & 0x1F) | 0xE0;
50  data[5] = CaPid & 0xFF;
51  if (Length)
52  memcpy(&data[6], Data, Length);
53 }
54 
56 {
57  free(data);
58 }
59 
61 {
62  return esPid == arg.esPid && length == arg.length && memcmp(data, arg.data, length) == 0;
63 }
64 
65 // --- cCaDescriptors --------------------------------------------------------
66 
67 class cCaDescriptors : public cListObject {
68 private:
69  int source;
71  int serviceId;
72  int pmtPid; // needed for OctopusNet - otherwise irrelevant!
73  int numCaIds;
74  int caIds[MAXCAIDS + 1];
76  void AddCaId(int CaId);
77 public:
78  cCaDescriptors(int Source, int Transponder, int ServiceId, int PmtPid);
79  bool operator== (const cCaDescriptors &arg) const;
80  bool Is(int Source, int Transponder, int ServiceId);
81  bool Is(cCaDescriptors * CaDescriptors);
82  bool Empty(void) { return caDescriptors.Count() == 0; }
83  void AddCaDescriptor(SI::CaDescriptor *d, int EsPid);
84  void GetCaDescriptors(const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid);
85  int GetCaPids(const int *CaSystemIds, int BufSize, int *Pids);
86  const int GetPmtPid(void) { return pmtPid; };
87  const int *CaIds(void) { return caIds; }
88  };
89 
90 cCaDescriptors::cCaDescriptors(int Source, int Transponder, int ServiceId, int PmtPid)
91 {
92  source = Source;
93  transponder = Transponder;
94  serviceId = ServiceId;
95  pmtPid = PmtPid;
96  numCaIds = 0;
97  caIds[0] = 0;
98 }
99 
101 {
102  const cCaDescriptor *ca1 = caDescriptors.First();
103  const cCaDescriptor *ca2 = arg.caDescriptors.First();
104  while (ca1 && ca2) {
105  if (!(*ca1 == *ca2))
106  return false;
107  ca1 = caDescriptors.Next(ca1);
108  ca2 = arg.caDescriptors.Next(ca2);
109  }
110  return !ca1 && !ca2;
111 }
112 
113 bool cCaDescriptors::Is(int Source, int Transponder, int ServiceId)
114 {
115  return source == Source && transponder == Transponder && serviceId == ServiceId;
116 }
117 
118 bool cCaDescriptors::Is(cCaDescriptors *CaDescriptors)
119 {
120  return Is(CaDescriptors->source, CaDescriptors->transponder, CaDescriptors->serviceId);
121 }
122 
124 {
125  if (numCaIds < MAXCAIDS) {
126  for (int i = 0; i < numCaIds; i++) {
127  if (caIds[i] == CaId)
128  return;
129  }
130  caIds[numCaIds++] = CaId;
131  caIds[numCaIds] = 0;
132  }
133 }
134 
136 {
137  cCaDescriptor *nca = new cCaDescriptor(d->getCaType(), d->getCaPid(), EsPid, d->privateData.getLength(), d->privateData.getData());
138  for (cCaDescriptor *ca = caDescriptors.First(); ca; ca = caDescriptors.Next(ca)) {
139  if (*ca == *nca) {
140  delete nca;
141  return;
142  }
143  }
144  AddCaId(nca->CaSystem());
145  caDescriptors.Add(nca);
146 //#define DEBUG_CA_DESCRIPTORS 1
147 #ifdef DEBUG_CA_DESCRIPTORS
148  char buffer[1024];
149  char *q = buffer;
150  q += sprintf(q, "CAM: %04X %5d %5d %04X %04X -", source, transponder, serviceId, d->getCaType(), EsPid);
151  for (int i = 0; i < nca->Length(); i++)
152  q += sprintf(q, " %02X", nca->Data()[i]);
153  dsyslog("%s", buffer);
154 #endif
155 }
156 
157 // EsPid is to select the "type" of CaDescriptor to be returned
158 // >0 - CaDescriptor for the particular esPid
159 // =0 - common CaDescriptor
160 // <0 - all CaDescriptors regardless of type (old default)
161 
162 void cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid)
163 {
164  Buffer.Clear();
165  if (!CaSystemIds || !*CaSystemIds)
166  return;
167  for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
168  if (EsPid < 0 || d->EsPid() == EsPid) {
169  const int *caids = CaSystemIds;
170  do {
171  if (*caids == 0xFFFF || d->CaSystem() == *caids)
172  Buffer.Append(d->Data(), d->Length());
173  } while (*++caids);
174  }
175  }
176 }
177 
178 int cCaDescriptors::GetCaPids(const int *CaSystemIds, int BufSize, int *Pids)
179 {
180  if (!CaSystemIds || !*CaSystemIds)
181  return 0;
182  if (BufSize > 0 && Pids) {
183  int numPids = 0;
184  for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
185  const int *caids = CaSystemIds;
186  do {
187  if (*caids == 0xFFFF || d->CaSystem() == *caids) {
188  if (numPids + 1 < BufSize) {
189  Pids[numPids++] = d->CaPid();
190  Pids[numPids] = 0;
191  }
192  else
193  return -1;
194  }
195  } while (*++caids);
196  }
197  return numPids;
198  }
199  return -1;
200 }
201 
202 // --- cCaDescriptorHandler --------------------------------------------------
203 
204 class cCaDescriptorHandler : public cList<cCaDescriptors> {
205 private:
207 public:
208  int AddCaDescriptors(cCaDescriptors *CaDescriptors);
209  // Returns 0 if this is an already known descriptor,
210  // 1 if it is an all new descriptor with actual contents,
211  // and 2 if an existing descriptor was changed.
212  void GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid);
213  int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids);
214  int GetPmtPid(int Source, int Transponder, int ServiceId);
215  };
216 
218 {
219  cMutexLock MutexLock(&mutex);
220  for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
221  if (ca->Is(CaDescriptors)) {
222  if (*ca == *CaDescriptors) {
223  delete CaDescriptors;
224  return 0;
225  }
226  Del(ca);
227  Add(CaDescriptors);
228  return 2;
229  }
230  }
231  Add(CaDescriptors);
232  return CaDescriptors->Empty() ? 0 : 1;
233 }
234 
235 void cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid)
236 {
237  cMutexLock MutexLock(&mutex);
238  for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
239  if (ca->Is(Source, Transponder, ServiceId)) {
240  ca->GetCaDescriptors(CaSystemIds, Buffer, EsPid);
241  break;
242  }
243  }
244 }
245 
246 int cCaDescriptorHandler::GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
247 {
248  cMutexLock MutexLock(&mutex);
249  for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
250  if (ca->Is(Source, Transponder, ServiceId))
251  return ca->GetCaPids(CaSystemIds, BufSize, Pids);
252  }
253  return 0;
254 }
255 
256 int cCaDescriptorHandler::GetPmtPid(int Source, int Transponder, int ServiceId)
257 {
258  cMutexLock MutexLock(&mutex);
259  for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
260  if (ca->Is(Source, Transponder, ServiceId))
261  return ca->GetPmtPid();
262  }
263  return 0;
264 }
265 
267 
268 void GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid)
269 {
270  CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, Buffer, EsPid);
271 }
272 
273 int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
274 {
275  return CaDescriptorHandler.GetCaPids(Source, Transponder, ServiceId, CaSystemIds, BufSize, Pids);
276 }
277 
278 int GetPmtPid(int Source, int Transponder, int ServiceId)
279 {
280  return CaDescriptorHandler.GetPmtPid(Source, Transponder, ServiceId);
281 }
282 
283 // --- cPmtPidEntry ----------------------------------------------------------
284 
285 class cPmtPidEntry : public cListObject {
286 private:
287  int pid;
288  bool complete;
289 public:
290  cPmtPidEntry(int Pid);
291  int Pid(void) { return pid; }
292  int Complete(void) { return complete; }
293  void SetComplete(bool State) { complete = State; }
294  };
295 
297 {
298  pid = Pid;
299  complete = false;
300 }
301 
302 // --- cPmtSidEntry ----------------------------------------------------------
303 
304 class cPmtSidEntry : public cListObject {
305 private:
306  int sid;
307  int pid;
309  int version;
310  bool received;
311 public:
313  int Sid(void) { return sid; }
314  int Pid(void) { return pid; }
315  cPmtPidEntry *PidEntry(void) { return pidEntry; }
316  int Version(void) { return version; }
317  int Received(void) { return received; }
319  void SetReceived(bool State) { received = State; }
320  };
321 
322 cPmtSidEntry::cPmtSidEntry(int Sid, int Pid, cPmtPidEntry *PidEntry)
323 {
324  sid = Sid;
325  pid = Pid;
326  pidEntry = PidEntry;
327  version = -1;
328  received = false;
329 }
330 
331 // --- cPatFilter ------------------------------------------------------------
332 
333 //#define DEBUG_PAT_PMT
334 #ifdef DEBUG_PAT_PMT
335 #define DBGLOG(a...) { cString s = cString::sprintf(a); fprintf(stderr, "%s\n", *s); dsyslog("%s", *s); }
336 #else
337 #define DBGLOG(a...) void()
338 #endif
339 
341 {
342  Trigger(0);
343  Set(0x00, 0x00); // PAT
344 }
345 
347 {
348  cMutexLock MutexLock(&mutex);
349  DBGLOG("PAT filter set status %d", On);
350  cFilter::SetStatus(On);
351  Trigger();
352 }
353 
354 void cPatFilter::Trigger(int Sid)
355 {
356  cMutexLock MutexLock(&mutex);
357  patVersion = -1;
359  if (Sid != 0 && activePmt)
361  activePmt = NULL;
362  if (Sid >= 0) {
363  sid = Sid;
364  DBGLOG("PAT filter trigger SID %d", Sid);
365  }
366 }
367 
369 {
370  for (cPmtSidEntry *se = pmtSidList.First(); se; se = pmtSidList.Next(se)) {
371  if (se->Pid() == PmtPid && !se->Received())
372  return false;
373  }
374  return true;
375 }
376 
377 void cPatFilter::PmtPidReset(int PmtPid)
378 {
379  for (cPmtSidEntry *se = pmtSidList.First(); se; se = pmtSidList.Next(se)) {
380  if (se->Pid() == PmtPid)
381  se->SetReceived(false);
382  }
383 }
384 
385 bool cPatFilter::PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNewVersion)
386 {
387  int i = 0;
388  for (cPmtSidEntry *se = pmtSidList.First(); se; se = pmtSidList.Next(se), i++) {
389  if (se->Sid() == Sid && se->Pid() == PmtPid) {
390  if (!se->Received()) {
391  se->SetReceived(true);
392  se->PidEntry()->SetComplete(PmtPidComplete(PmtPid));
393  }
394  if (se->Version() != Version) {
395  if (SetNewVersion)
396  se->SetVersion(Version);
397  else
398  DBGLOG("PMT %d %2d %5d/%d %2d -> %2d", Transponder(), i, PmtPid, Sid, se->Version(), Version);
399  return true;
400  }
401  break;
402  }
403  }
404  return false;
405 }
406 
408 {
409  if (activePmt) {
414  activePmt->SetComplete(false);
416  }
417 }
418 
419 void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
420 {
421  cMutexLock MutexLock(&mutex);
422  if (Pid == 0x00) {
423  if (Tid == SI::TableIdPAT) {
424  SI::PAT pat(Data, false);
425  if (!pat.CheckCRCAndParse())
426  return;
428  DBGLOG("PAT %d %d -> %d %d/%d", Transponder(), patVersion, pat.getVersionNumber(), pat.getSectionNumber(), pat.getLastSectionNumber());
429  if (pat.getVersionNumber() != patVersion) {
430  if (pat.getLastSectionNumber() > 0)
431  DBGLOG(" PAT %d: %d sections", Transponder(), pat.getLastSectionNumber() + 1);
432  if (activePmt) {
434  activePmt = NULL;
435  }
436  pmtSidList.Clear();
437  pmtPidList.Clear();
439  }
440  SI::PAT::Association assoc;
441  for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); ) {
442  if (!assoc.isNITPid()) {
443  int PmtPid = assoc.getPid();
444  cPmtPidEntry *pPid = NULL;
445  int PidIndex = 0;
446  for (pPid = pmtPidList.First(); pPid && pPid->Pid() != PmtPid; pPid = pmtPidList.Next(pPid))
447  PidIndex++;
448  if (!pPid) { // new PMT Pid
449  pPid = new cPmtPidEntry(PmtPid);
450  pmtPidList.Add(pPid);
451  }
452  pmtSidList.Add(new cPmtSidEntry(assoc.getServiceId(), PmtPid, pPid));
453  DBGLOG(" PMT pid %2d/%2d %5d SID %5d", PidIndex, pmtSidList.Count() - 1, PmtPid, assoc.getServiceId());
454  if (sid == assoc.getServiceId()) {
455  activePmt = pPid;
456  DBGLOG("sid = %d pidIndex = %d", sid, PidIndex);
457  }
458  }
459  }
460  if (sectionSyncer.Complete()) { // all PAT sections done
461  if (pmtPidList.Count() != pmtSidList.Count())
462  DBGLOG(" PAT %d: shared PMT PIDs", Transponder());
463  if (pmtSidList.Count() && !activePmt)
465  if (activePmt)
468  }
469  }
470  }
471  }
472  else if (Tid == SI::TableIdPMT && Source() && Transponder()) {
474  SI::PMT pmt(Data, false);
475  if (!pmt.CheckCRCAndParse())
476  return;
477  if (!PmtVersionChanged(Pid, pmt.getTableIdExtension(), pmt.getVersionNumber(), false)) {
478  if (activePmt && activePmt->Complete())
480  return;
481  }
482  cStateKey StateKey;
483  cChannels *Channels = cChannels::GetChannelsWrite(StateKey, 10);
484  if (!Channels)
485  return;
486  PmtVersionChanged(Pid, pmt.getTableIdExtension(), pmt.getVersionNumber(), true);
487  bool ChannelsModified = false;
488  if (activePmt && activePmt->Complete())
490  cChannel *Channel = Channels->GetByServiceID(Source(), Transponder(), pmt.getServiceId());
491  if (Channel) {
492  Channel->SetSeen();
493  SI::CaDescriptor *d;
494  cCaDescriptors *CaDescriptors = new cCaDescriptors(Channel->Source(), Channel->Transponder(), Channel->Sid(), Pid);
495  // Scan the common loop:
497  CaDescriptors->AddCaDescriptor(d, 0);
498  delete d;
499  }
500  // Scan the stream-specific loop:
501  SI::PMT::Stream stream;
502  int Vpid = 0;
503  int Ppid = 0;
504  int Vtype = 0;
505  int Apids[MAXAPIDS + 1] = { 0 }; // these lists are zero-terminated
506  int Atypes[MAXAPIDS + 1] = { 0 };
507  int Dpids[MAXDPIDS + 1] = { 0 };
508  int Dtypes[MAXDPIDS + 1] = { 0 };
509  int Spids[MAXSPIDS + 1] = { 0 };
510  uchar SubtitlingTypes[MAXSPIDS + 1] = { 0 };
511  uint16_t CompositionPageIds[MAXSPIDS + 1] = { 0 };
512  uint16_t AncillaryPageIds[MAXSPIDS + 1] = { 0 };
513  char ALangs[MAXAPIDS][MAXLANGCODE2] = { "" };
514  char DLangs[MAXDPIDS][MAXLANGCODE2] = { "" };
515  char SLangs[MAXSPIDS][MAXLANGCODE2] = { "" };
516  int Tpid = 0;
517  int NumApids = 0;
518  int NumDpids = 0;
519  int NumSpids = 0;
520  for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); ) {
521  bool ProcessCaDescriptors = false;
522  int esPid = stream.getPid();
523  switch (stream.getStreamType()) {
524  case 1: // STREAMTYPE_11172_VIDEO
525  case 2: // STREAMTYPE_13818_VIDEO
526  case 0x1B: // H.264
527  case 0x24: // H.265
528  Vpid = esPid;
529  Ppid = pmt.getPCRPid();
530  Vtype = stream.getStreamType();
531  ProcessCaDescriptors = true;
532  break;
533  case 3: // STREAMTYPE_11172_AUDIO
534  case 4: // STREAMTYPE_13818_AUDIO
535  case 0x0F: // ISO/IEC 13818-7 Audio with ADTS transport syntax
536  case 0x11: // ISO/IEC 14496-3 Audio with LATM transport syntax
537  {
538  if (NumApids < MAXAPIDS) {
539  Apids[NumApids] = esPid;
540  Atypes[NumApids] = stream.getStreamType();
541  SI::Descriptor *d;
542  for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
543  switch (d->getDescriptorTag()) {
547  char *s = ALangs[NumApids];
548  int n = 0;
549  for (SI::Loop::Iterator it; ld->languageLoop.getNext(l, it); ) {
550  if (*ld->languageCode != '-') { // some use "---" to indicate "none"
551  if (n > 0)
552  *s++ = '+';
554  s += strlen(s);
555  if (n++ > 1)
556  break;
557  }
558  }
559  }
560  break;
561  default: ;
562  }
563  delete d;
564  }
565  NumApids++;
566  }
567  ProcessCaDescriptors = true;
568  }
569  break;
570  case 5: // STREAMTYPE_13818_PRIVATE
571  case 6: // STREAMTYPE_13818_PES_PRIVATE
572  //XXX case 8: // STREAMTYPE_13818_DSMCC
573  {
574  int dpid = 0;
575  int dtype = 0;
576  char lang[MAXLANGCODE1] = { 0 };
577  SI::Descriptor *d;
578  for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
579  switch (d->getDescriptorTag()) {
582  dpid = esPid;
583  dtype = d->getDescriptorTag();
584  ProcessCaDescriptors = true;
585  break;
587  if (NumSpids < MAXSPIDS) {
588  Spids[NumSpids] = esPid;
591  char *s = SLangs[NumSpids];
592  int n = 0;
593  for (SI::Loop::Iterator it; sd->subtitlingLoop.getNext(sub, it); ) {
594  if (sub.languageCode[0]) {
595  SubtitlingTypes[NumSpids] = sub.getSubtitlingType();
596  CompositionPageIds[NumSpids] = sub.getCompositionPageId();
597  AncillaryPageIds[NumSpids] = sub.getAncillaryPageId();
598  if (n > 0)
599  *s++ = '+';
601  s += strlen(s);
602  if (n++ > 1)
603  break;
604  }
605  }
606  NumSpids++;
607  }
608  break;
610  Tpid = esPid;
611  break;
615  }
616  break;
617  default: ;
618  }
619  delete d;
620  }
621  if (dpid) {
622  if (NumDpids < MAXDPIDS) {
623  Dpids[NumDpids] = dpid;
624  Dtypes[NumDpids] = dtype;
625  strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
626  NumDpids++;
627  }
628  }
629  }
630  break;
631  case 0x80: // STREAMTYPE_USER_PRIVATE
632  if (Setup.StandardCompliance == STANDARD_ANSISCTE) { // DigiCipher II VIDEO (ANSI/SCTE 57)
633  Vpid = esPid;
634  Ppid = pmt.getPCRPid();
635  Vtype = 0x02; // compression based upon MPEG-2
636  ProcessCaDescriptors = true;
637  break;
638  }
639  // fall through
640  case 0x81: // STREAMTYPE_USER_PRIVATE
641  case 0x87: // eac3
642  if (Setup.StandardCompliance == STANDARD_ANSISCTE) { // ATSC A/53 AUDIO (ANSI/SCTE 57)
643  char lang[MAXLANGCODE1] = { 0 };
644  SI::Descriptor *d;
645  for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
646  switch (d->getDescriptorTag()) {
650  }
651  break;
652  default: ;
653  }
654  delete d;
655  }
656  if (NumDpids < MAXDPIDS) {
657  Dpids[NumDpids] = esPid;
658  Dtypes[NumDpids] = SI::AC3DescriptorTag;
659  strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
660  NumDpids++;
661  }
662  ProcessCaDescriptors = true;
663  break;
664  }
665  // fall through
666  case 0x82: // STREAMTYPE_USER_PRIVATE
667  if (Setup.StandardCompliance == STANDARD_ANSISCTE) { // STANDARD SUBTITLE (ANSI/SCTE 27)
668  //TODO
669  break;
670  }
671  // fall through
672  case 0x83 ... 0x86: // STREAMTYPE_USER_PRIVATE
673  case 0x88 ... 0xFF: // STREAMTYPE_USER_PRIVATE
674  {
675  char lang[MAXLANGCODE1] = { 0 };
676  bool IsAc3 = false;
677  SI::Descriptor *d;
678  for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
679  switch (d->getDescriptorTag()) {
682  // http://www.smpte-ra.org/mpegreg/mpegreg.html
683  switch (rd->getFormatIdentifier()) {
684  case 0x41432D33: // 'AC-3'
685  IsAc3 = true;
686  break;
687  default:
688  //printf("Format identifier: 0x%08X (pid: %d)\n", rd->getFormatIdentifier(), esPid);
689  break;
690  }
691  }
692  break;
696  }
697  break;
698  default: ;
699  }
700  delete d;
701  }
702  if (IsAc3) {
703  if (NumDpids < MAXDPIDS) {
704  Dpids[NumDpids] = esPid;
705  Dtypes[NumDpids] = SI::AC3DescriptorTag;
706  strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
707  NumDpids++;
708  }
709  ProcessCaDescriptors = true;
710  }
711  }
712  break;
713  default: ;//printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());
714  }
715  if (ProcessCaDescriptors) {
717  CaDescriptors->AddCaDescriptor(d, esPid);
718  delete d;
719  }
720  }
721  }
722  if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3)
723  ChannelsModified |= Channel->ClearObsoleteChannel();
724  if (Setup.UpdateChannels >= 2) {
725  ChannelsModified |= Channel->SetPids(Vpid, Ppid, Vtype, Apids, Atypes, ALangs, Dpids, Dtypes, DLangs, Spids, SLangs, Tpid);
726  ChannelsModified |= Channel->SetCaIds(CaDescriptors->CaIds());
727  ChannelsModified |= Channel->SetSubtitlingDescriptors(SubtitlingTypes, CompositionPageIds, AncillaryPageIds);
728  }
729  ChannelsModified |= Channel->SetCaDescriptors(CaDescriptorHandler.AddCaDescriptors(CaDescriptors));
730  }
731  StateKey.Remove(ChannelsModified);
732  }
733  if (timer.TimedOut()) {
734  if (activePmt)
735  DBGLOG("PMT timeout Pid %d", activePmt->Pid());
738  }
739 }
#define MAXLANGCODE2
Definition: channels.h:37
#define MAXDPIDS
Definition: channels.h:32
#define MAXAPIDS
Definition: channels.h:31
#define MAXSPIDS
Definition: channels.h:33
#define MAXCAIDS
Definition: channels.h:34
#define MAXLANGCODE1
Definition: channels.h:36
bool CheckCRCAndParse()
Definition: si.c:65
CharArray privateData
Definition: descriptor.h:147
int getCaPid() const
Definition: descriptor.c:355
int getCaType() const
Definition: descriptor.c:351
int getLength() const
Definition: util.h:58
const unsigned char * getData() const
Definition: util.h:51
Descriptor * getNext(Iterator &it)
Definition: si.c:112
DescriptorTag getDescriptorTag() const
Definition: si.c:100
StructureLoop< Language > languageLoop
Definition: descriptor.h:490
int getTableIdExtension() const
Definition: si.c:72
int getSectionNumber() const
Definition: si.c:88
int getLastSectionNumber() const
Definition: si.c:92
int getVersionNumber() const
Definition: si.c:84
int getPid() const
Definition: section.c:34
int getServiceId() const
Definition: section.c:30
bool isNITPid() const
Definition: section.h:31
StructureLoop< Association > associationLoop
Definition: section.h:39
DescriptorLoop streamDescriptors
Definition: section.h:63
int getPid() const
Definition: section.c:65
int getStreamType() const
Definition: section.c:69
int getServiceId() const
Definition: section.c:57
int getPCRPid() const
Definition: section.c:61
StructureLoop< Stream > streamLoop
Definition: section.h:71
DescriptorLoop commonDescriptors
Definition: section.h:70
int getFormatIdentifier() const
Definition: descriptor.c:1193
StructureLoop< Subtitling > subtitlingLoop
Definition: descriptor.h:332
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
Definition: pat.c:246
int GetPmtPid(int Source, int Transponder, int ServiceId)
Definition: pat.c:256
void GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid)
Definition: pat.c:235
int AddCaDescriptors(cCaDescriptors *CaDescriptors)
Definition: pat.c:217
cMutex mutex
Definition: pat.c:206
const uchar * Data(void) const
Definition: pat.c:35
virtual ~cCaDescriptor()
Definition: pat.c:55
cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data)
Definition: pat.c:38
int caSystem
Definition: pat.c:22
int CaPid(void)
Definition: pat.c:32
int CaSystem(void)
Definition: pat.c:31
uchar * data
Definition: pat.c:26
int EsPid(void)
Definition: pat.c:33
int caPid
Definition: pat.c:23
int length
Definition: pat.c:25
int Length(void) const
Definition: pat.c:34
int esPid
Definition: pat.c:24
bool operator==(const cCaDescriptor &arg) const
Definition: pat.c:60
cCaDescriptors(int Source, int Transponder, int ServiceId, int PmtPid)
Definition: pat.c:90
bool Empty(void)
Definition: pat.c:82
int pmtPid
Definition: pat.c:72
const int GetPmtPid(void)
Definition: pat.c:86
const int * CaIds(void)
Definition: pat.c:87
bool Is(int Source, int Transponder, int ServiceId)
Definition: pat.c:113
void AddCaId(int CaId)
Definition: pat.c:123
int caIds[MAXCAIDS+1]
Definition: pat.c:74
cList< cCaDescriptor > caDescriptors
Definition: pat.c:75
int source
Definition: pat.c:69
int serviceId
Definition: pat.c:71
void AddCaDescriptor(SI::CaDescriptor *d, int EsPid)
Definition: pat.c:135
int GetCaPids(const int *CaSystemIds, int BufSize, int *Pids)
Definition: pat.c:178
bool operator==(const cCaDescriptors &arg) const
Definition: pat.c:100
int numCaIds
Definition: pat.c:73
void GetCaDescriptors(const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid)
Definition: pat.c:162
int transponder
Definition: pat.c:70
bool SetCaIds(const int *CaIds)
Definition: channels.c:454
int Source(void) const
Definition: channels.h:152
bool SetPids(int Vpid, int Ppid, int Vtype, int *Apids, int *Atypes, char ALangs[][MAXLANGCODE2], int *Dpids, int *Dtypes, char DLangs[][MAXLANGCODE2], int *Spids, char SLangs[][MAXLANGCODE2], int Tpid)
Definition: channels.c:341
bool ClearObsoleteChannel(void)
Definition: channels.c:1184
void SetSeen(void)
Definition: channels.c:433
bool SetCaDescriptors(int Level)
Definition: channels.c:476
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
Definition: channels.c:147
int Sid(void) const
Definition: channels.h:176
bool SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *CompositionPageIds, uint16_t *AncillaryPageIds)
Definition: channels.c:409
static cChannels * GetChannelsWrite(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of channels for write access.
Definition: channels.c:855
const cChannel * GetByServiceID(int Source, int Transponder, unsigned short ServiceID) const
Definition: channels.c:1024
void Append(const uchar *Data, int Length)
Definition: tools.c:2334
void Clear(void)
Definition: tools.h:845
void Set(u_short Pid, u_char Tid, u_char Mask=0xFF)
Sets the given filter data by calling Add() with Sticky = true.
Definition: filter.c:162
int Transponder(void)
Returns the transponder of the data delivered to this filter.
Definition: filter.c:119
virtual void SetStatus(bool On)
Turns this filter on or off, depending on the value of On.
Definition: filter.c:129
int Source(void)
Returns the source of the data delivered to this filter.
Definition: filter.c:114
const cChannel * Channel(void)
Returns the channel of the data delivered to this filter.
Definition: filter.c:124
void Del(u_short Pid, u_char Tid, u_char Mask=0xFF)
Deletes the given filter data from this filter.
Definition: filter.c:175
void Add(u_short Pid, u_char Tid, u_char Mask=0xFF, bool Sticky=false)
Adds the given filter data to this filter.
Definition: filter.c:167
virtual void Clear(void)
Definition: tools.c:2235
void Del(cListObject *Object, bool DeleteObject=true)
Definition: tools.c:2190
int Count(void) const
Definition: tools.h:594
void Add(cListObject *Object, cListObject *After=NULL)
Definition: tools.c:2158
const T * Next(const T *Object) const
< Returns the element immediately before Object in this list, or NULL if Object is the first element ...
Definition: tools.h:617
const T * First(void) const
Returns the first element in this list, or NULL if the list is empty.
Definition: tools.h:610
Definition: thread.h:67
cList< cPmtSidEntry > pmtSidList
Definition: pat.h:28
void PmtPidReset(int PmtPid)
Definition: pat.c:377
bool PmtPidComplete(int PmtPid)
Definition: pat.c:368
void SwitchToNextPmtPid(void)
Definition: pat.c:407
virtual void SetStatus(bool On)
Turns this filter on or off, depending on the value of On.
Definition: pat.c:346
int sid
Definition: pat.h:25
bool PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNewVersion=false)
Definition: pat.c:385
cList< cPmtPidEntry > pmtPidList
Definition: pat.h:27
int patVersion
Definition: pat.h:24
cPatFilter(void)
Definition: pat.c:340
cTimeMs timer
Definition: pat.h:23
void Trigger(int Sid=-1)
Definition: pat.c:354
cMutex mutex
Definition: pat.h:22
cPmtPidEntry * activePmt
Definition: pat.h:26
cSectionSyncer sectionSyncer
Definition: pat.h:29
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
Processes the data delivered to this filter.
Definition: pat.c:419
int Pid(void)
Definition: pat.c:291
int Complete(void)
Definition: pat.c:292
bool complete
Definition: pat.c:288
int pid
Definition: pat.c:287
void SetComplete(bool State)
Definition: pat.c:293
cPmtPidEntry(int Pid)
Definition: pat.c:296
bool received
Definition: pat.c:310
int Sid(void)
Definition: pat.c:313
void SetReceived(bool State)
Definition: pat.c:319
cPmtSidEntry(int Sid, int Pid, cPmtPidEntry *PidEntry)
Definition: pat.c:322
int Received(void)
Definition: pat.c:317
int Version(void)
Definition: pat.c:316
cPmtPidEntry * pidEntry
Definition: pat.c:308
int Pid(void)
Definition: pat.c:314
int version
Definition: pat.c:309
int sid
Definition: pat.c:306
void SetVersion(int Version)
Definition: pat.c:318
cPmtPidEntry * PidEntry(void)
Definition: pat.c:315
int pid
Definition: pat.c:307
bool Sync(uchar Version, int Number, int LastNumber)
Definition: filter.c:36
bool Complete(void)
Definition: filter.h:29
void Reset(void)
Definition: filter.c:20
int StandardCompliance
Definition: config.h:283
int UpdateChannels
Definition: config.h:318
void Remove(bool IncState=true)
Removes this key from the lock it was previously used with.
Definition: thread.c:859
void Set(int Ms=0)
Sets the timer.
Definition: tools.c:776
bool TimedOut(void) const
Definition: tools.c:781
cSetup Setup
Definition: config.c:372
#define STANDARD_ANSISCTE
Definition: config.h:71
const char * I18nNormalizeLanguageCode(const char *Code)
Returns a 3 letter language code that may not be zero terminated.
Definition: i18n.c:284
@ TableIdPAT
Definition: si.h:23
@ TableIdPMT
Definition: si.h:25
@ EnhancedAC3DescriptorTag
Definition: si.h:137
@ TeletextDescriptorTag
Definition: si.h:100
@ CaDescriptorTag
Definition: si.h:60
@ SubtitlingDescriptorTag
Definition: si.h:103
@ ISO639LanguageDescriptorTag
Definition: si.h:61
@ AC3DescriptorTag
Definition: si.h:120
@ RegistrationDescriptorTag
Definition: si.h:56
unsigned char u_char
Definition: headers.h:24
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
Gets all CA pids for a given channel.
Definition: pat.c:273
#define DBGLOG(a...)
Definition: pat.c:337
int GetPmtPid(int Source, int Transponder, int ServiceId)
Gets the Pid of the PMT in which the CA descriptors for this channel are defined.
Definition: pat.c:278
void GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid)
Gets all CA descriptors for a given channel.
Definition: pat.c:268
#define PMT_SCAN_TIMEOUT
Definition: pat.c:16
cCaDescriptorHandler CaDescriptorHandler
Definition: pat.c:266
char * strn0cpy(char *dest, const char *src, size_t n)
Definition: tools.c:131
unsigned char uchar
Definition: tools.h:31
#define dsyslog(a...)
Definition: tools.h:37
#define MALLOC(type, size)
Definition: tools.h:47