vdr  2.2.0
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 3.5 2015/01/04 13:14:01 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 #include "vdrttxtsubshooks.h"
16 
17 #define PMT_SCAN_TIMEOUT 1000 // ms
18 
19 // --- cCaDescriptor ---------------------------------------------------------
20 
21 class cCaDescriptor : public cListObject {
22 private:
23  int caSystem;
24  int caPid;
25  int esPid;
26  int length;
28 public:
29  cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data);
30  virtual ~cCaDescriptor();
31  bool operator== (const cCaDescriptor &arg) const;
32  int CaSystem(void) { return caSystem; }
33  int CaPid(void) { return caPid; }
34  int EsPid(void) { return esPid; }
35  int Length(void) const { return length; }
36  const uchar *Data(void) const { return data; }
37  };
38 
40 {
42  caPid = CaPid;
43  esPid = EsPid;
44  length = Length + 6;
45  data = MALLOC(uchar, length);
47  data[1] = length - 2;
48  data[2] = (caSystem >> 8) & 0xFF;
49  data[3] = caSystem & 0xFF;
50  data[4] = ((CaPid >> 8) & 0x1F) | 0xE0;
51  data[5] = CaPid & 0xFF;
52  if (Length)
53  memcpy(&data[6], Data, Length);
54 }
55 
57 {
58  free(data);
59 }
60 
62 {
63  return esPid == arg.esPid && length == arg.length && memcmp(data, arg.data, length) == 0;
64 }
65 
66 // --- cCaDescriptors --------------------------------------------------------
67 
68 class cCaDescriptors : public cListObject {
69 private:
70  int source;
72  int serviceId;
73  int pmtPid; // needed for OctopusNet - otherwise irrelevant!
74  int numCaIds;
75  int caIds[MAXCAIDS + 1];
77  void AddCaId(int CaId);
78 public:
79  cCaDescriptors(int Source, int Transponder, int ServiceId, int PmtPid);
80  bool operator== (const cCaDescriptors &arg) const;
81  bool Is(int Source, int Transponder, int ServiceId);
82  bool Is(cCaDescriptors * CaDescriptors);
83  bool Empty(void) { return caDescriptors.Count() == 0; }
84  void AddCaDescriptor(SI::CaDescriptor *d, int EsPid);
85  int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
86  int GetCaPids(const int *CaSystemIds, int BufSize, int *Pids);
87  const int GetPmtPid(void) { return pmtPid; };
88  const int *CaIds(void) { return caIds; }
89  };
90 
91 cCaDescriptors::cCaDescriptors(int Source, int Transponder, int ServiceId, int PmtPid)
92 {
93  source = Source;
94  transponder = Transponder;
95  serviceId = ServiceId;
96  pmtPid = PmtPid;
97  numCaIds = 0;
98  caIds[0] = 0;
99 }
100 
102 {
103  cCaDescriptor *ca1 = caDescriptors.First();
104  cCaDescriptor *ca2 = arg.caDescriptors.First();
105  while (ca1 && ca2) {
106  if (!(*ca1 == *ca2))
107  return false;
108  ca1 = caDescriptors.Next(ca1);
109  ca2 = arg.caDescriptors.Next(ca2);
110  }
111  return !ca1 && !ca2;
112 }
113 
114 bool cCaDescriptors::Is(int Source, int Transponder, int ServiceId)
115 {
116  return source == Source && transponder == Transponder && serviceId == ServiceId;
117 }
118 
119 bool cCaDescriptors::Is(cCaDescriptors *CaDescriptors)
120 {
121  return Is(CaDescriptors->source, CaDescriptors->transponder, CaDescriptors->serviceId);
122 }
123 
125 {
126  if (numCaIds < MAXCAIDS) {
127  for (int i = 0; i < numCaIds; i++) {
128  if (caIds[i] == CaId)
129  return;
130  }
131  caIds[numCaIds++] = CaId;
132  caIds[numCaIds] = 0;
133  }
134 }
135 
137 {
139  for (cCaDescriptor *ca = caDescriptors.First(); ca; ca = caDescriptors.Next(ca)) {
140  if (*ca == *nca) {
141  delete nca;
142  return;
143  }
144  }
145  AddCaId(nca->CaSystem());
146  caDescriptors.Add(nca);
147 //#define DEBUG_CA_DESCRIPTORS 1
148 #ifdef DEBUG_CA_DESCRIPTORS
149  char buffer[1024];
150  char *q = buffer;
151  q += sprintf(q, "CAM: %04X %5d %5d %04X %04X -", source, transponder, serviceId, d->getCaType(), EsPid);
152  for (int i = 0; i < nca->Length(); i++)
153  q += sprintf(q, " %02X", nca->Data()[i]);
154  dsyslog("%s", buffer);
155 #endif
156 }
157 
158 // EsPid is to select the "type" of CaDescriptor to be returned
159 // >0 - CaDescriptor for the particular esPid
160 // =0 - common CaDescriptor
161 // <0 - all CaDescriptors regardless of type (old default)
162 
163 int cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
164 {
165  if (!CaSystemIds || !*CaSystemIds)
166  return 0;
167  if (BufSize > 0 && Data) {
168  int length = 0;
169  for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
170  if (EsPid < 0 || d->EsPid() == EsPid) {
171  const int *caids = CaSystemIds;
172  do {
173  if (*caids == 0xFFFF || d->CaSystem() == *caids) {
174  if (length + d->Length() <= BufSize) {
175  memcpy(Data + length, d->Data(), d->Length());
176  length += d->Length();
177  }
178  else
179  return -1;
180  }
181  } while (*++caids);
182  }
183  }
184  return length;
185  }
186  return -1;
187 }
188 
189 int cCaDescriptors::GetCaPids(const int *CaSystemIds, int BufSize, int *Pids)
190 {
191  if (!CaSystemIds || !*CaSystemIds)
192  return 0;
193  if (BufSize > 0 && Pids) {
194  int numPids = 0;
195  for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
196  const int *caids = CaSystemIds;
197  do {
198  if (*caids == 0xFFFF || d->CaSystem() == *caids) {
199  if (numPids + 1 < BufSize) {
200  Pids[numPids++] = d->CaPid();
201  Pids[numPids] = 0;
202  }
203  else
204  return -1;
205  }
206  } while (*++caids);
207  }
208  return numPids;
209  }
210  return -1;
211 }
212 
213 // --- cCaDescriptorHandler --------------------------------------------------
214 
215 class cCaDescriptorHandler : public cList<cCaDescriptors> {
216 private:
218 public:
219  int AddCaDescriptors(cCaDescriptors *CaDescriptors);
220  // Returns 0 if this is an already known descriptor,
221  // 1 if it is an all new descriptor with actual contents,
222  // and 2 if an existing descriptor was changed.
223  int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
224  int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids);
225  int GetPmtPid(int Source, int Transponder, int ServiceId);
226  };
227 
229 {
230  cMutexLock MutexLock(&mutex);
231  for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
232  if (ca->Is(CaDescriptors)) {
233  if (*ca == *CaDescriptors) {
234  delete CaDescriptors;
235  return 0;
236  }
237  Del(ca);
238  Add(CaDescriptors);
239  return 2;
240  }
241  }
242  Add(CaDescriptors);
243  return CaDescriptors->Empty() ? 0 : 1;
244 }
245 
246 int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
247 {
248  cMutexLock MutexLock(&mutex);
249  for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
250  if (ca->Is(Source, Transponder, ServiceId))
251  return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, EsPid);
252  }
253  return 0;
254 }
255 
256 int cCaDescriptorHandler::GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
257 {
258  cMutexLock MutexLock(&mutex);
259  for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
260  if (ca->Is(Source, Transponder, ServiceId))
261  return ca->GetCaPids(CaSystemIds, BufSize, Pids);
262  }
263  return 0;
264 }
265 
266 int cCaDescriptorHandler::GetPmtPid(int Source, int Transponder, int ServiceId)
267 {
268  cMutexLock MutexLock(&mutex);
269  for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
270  if (ca->Is(Source, Transponder, ServiceId))
271  return ca->GetPmtPid();
272  }
273  return 0;
274 }
275 
277 
278 int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
279 {
280  return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, EsPid);
281 }
282 
283 int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
284 {
285  return CaDescriptorHandler.GetCaPids(Source, Transponder, ServiceId, CaSystemIds, BufSize, Pids);
286 }
287 
288 int GetPmtPid(int Source, int Transponder, int ServiceId)
289 {
290  return CaDescriptorHandler.GetPmtPid(Source, Transponder, ServiceId);
291 }
292 
293 // --- cPatFilter ------------------------------------------------------------
294 
295 //#define DEBUG_PAT_PMT
296 #ifdef DEBUG_PAT_PMT
297 #define DBGLOG(a...) { cString s = cString::sprintf(a); fprintf(stderr, "%s\n", *s); dsyslog("%s", *s); }
298 #else
299 #define DBGLOG(a...)
300 #endif
301 
303 {
304  Trigger(0);
305  Set(0x00, 0x00); // PAT
306 }
307 
309 {
310  cMutexLock MutexLock(&mutex);
311  DBGLOG("PAT filter set status %d", On);
312  cFilter::SetStatus(On);
313  Trigger();
314 }
315 
316 void cPatFilter::Trigger(int Sid)
317 {
318  cMutexLock MutexLock(&mutex);
319  patVersion = -1;
320  pmtIndex = -1;
321  numPmtEntries = 0;
322  if (Sid >= 0) {
323  sid = Sid;
324  DBGLOG("PAT filter trigger SID %d", Sid);
325  }
326 }
327 
328 bool cPatFilter::PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNewVersion)
329 {
330  int Id = MakePmtId(PmtPid, Sid);
331  for (int i = 0; i < numPmtEntries; i++) {
332  if (pmtId[i] == Id) {
333  if (pmtVersion[i] != Version) {
334  if (SetNewVersion)
335  pmtVersion[i] = Version;
336  else
337  DBGLOG("PMT %d %2d %5d %2d -> %2d", Transponder(), i, PmtPid, pmtVersion[i], Version);
338  return true;
339  }
340  break;
341  }
342  }
343  return false;
344 }
345 
347 {
348  if (pmtIndex >= 0) {
349  Del(GetPmtPid(pmtIndex), SI::TableIdPMT);
350  pmtIndex = (pmtIndex + 1) % numPmtEntries;
351  Add(GetPmtPid(pmtIndex), SI::TableIdPMT);
352  }
353 }
354 
355 void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
356 {
357  cMutexLock MutexLock(&mutex);
358  if (Pid == 0x00) {
359  if (Tid == SI::TableIdPAT) {
360  SI::PAT pat(Data, false);
361  if (!pat.CheckCRCAndParse())
362  return;
363  if (pat.getVersionNumber() != patVersion) {
364  DBGLOG("PAT %d %d -> %d", Transponder(), patVersion, pat.getVersionNumber());
365  if (pmtIndex >= 0) {
366  Del(GetPmtPid(pmtIndex), SI::TableIdPMT);
367  pmtIndex = -1;
368  }
369  numPmtEntries = 0;
370  SI::PAT::Association assoc;
371  for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); ) {
372  if (!assoc.isNITPid() && numPmtEntries < MAXPMTENTRIES) {
373  DBGLOG(" PMT pid %2d %5d SID %5d", numPmtEntries, assoc.getPid(), assoc.getServiceId());
374  pmtId[numPmtEntries] = MakePmtId(assoc.getPid(), assoc.getServiceId());
375  pmtVersion[numPmtEntries] = -1;
376  if (sid == assoc.getServiceId()) {
377  pmtIndex = numPmtEntries;
378  DBGLOG("sid = %d pmtIndex = %d", sid, pmtIndex);
379  }
380  numPmtEntries++;
381  }
382  }
383  if (numPmtEntries > 0 && pmtIndex < 0)
384  pmtIndex = 0;
385  Add(GetPmtPid(pmtIndex), SI::TableIdPMT);
386  patVersion = pat.getVersionNumber();
387  timer.Set(PMT_SCAN_TIMEOUT);
388  }
389  }
390  }
391  else if (Tid == SI::TableIdPMT && Source() && Transponder()) {
392  timer.Set(PMT_SCAN_TIMEOUT);
393  SI::PMT pmt(Data, false);
394  if (!pmt.CheckCRCAndParse())
395  return;
396  if (!PmtVersionChanged(Pid, pmt.getTableIdExtension(), pmt.getVersionNumber())) {
397  SwitchToNextPmtPid();
398  return;
399  }
400  if (!Channels.Lock(true, 10))
401  return;
402  PmtVersionChanged(Pid, pmt.getTableIdExtension(), pmt.getVersionNumber(), true);
403  SwitchToNextPmtPid();
404  cChannel *Channel = Channels.GetByServiceID(Source(), Transponder(), pmt.getServiceId());
405  if (Channel) {
406  SI::CaDescriptor *d;
407  cCaDescriptors *CaDescriptors = new cCaDescriptors(Channel->Source(), Channel->Transponder(), Channel->Sid(), Pid);
408  // Scan the common loop:
410  CaDescriptors->AddCaDescriptor(d, 0);
411  delete d;
412  }
413  // Scan the stream-specific loop:
414  SI::PMT::Stream stream;
415  int Vpid = 0;
416  int Ppid = 0;
417  int Vtype = 0;
418  int Apids[MAXAPIDS + 1] = { 0 }; // these lists are zero-terminated
419  int Atypes[MAXAPIDS + 1] = { 0 };
420  int Dpids[MAXDPIDS + 1] = { 0 };
421  int Dtypes[MAXDPIDS + 1] = { 0 };
422  int Spids[MAXSPIDS + 1] = { 0 };
423  uchar SubtitlingTypes[MAXSPIDS + 1] = { 0 };
424  uint16_t CompositionPageIds[MAXSPIDS + 1] = { 0 };
425  uint16_t AncillaryPageIds[MAXSPIDS + 1] = { 0 };
426  char ALangs[MAXAPIDS][MAXLANGCODE2] = { "" };
427  char DLangs[MAXDPIDS][MAXLANGCODE2] = { "" };
428  char SLangs[MAXSPIDS][MAXLANGCODE2] = { "" };
429  int Tpid = 0;
430  tTeletextSubtitlePage TeletextSubtitlePages[MAXTXTPAGES];
431  int NumTPages = 0;
432  int NumApids = 0;
433  int NumDpids = 0;
434  int NumSpids = 0;
435  for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); ) {
436  bool ProcessCaDescriptors = false;
437  int esPid = stream.getPid();
438  switch (stream.getStreamType()) {
439  case 1: // STREAMTYPE_11172_VIDEO
440  case 2: // STREAMTYPE_13818_VIDEO
441  case 0x1B: // H.264
442  Vpid = esPid;
443  Ppid = pmt.getPCRPid();
444  Vtype = stream.getStreamType();
445  ProcessCaDescriptors = true;
446  break;
447  case 3: // STREAMTYPE_11172_AUDIO
448  case 4: // STREAMTYPE_13818_AUDIO
449  case 0x0F: // ISO/IEC 13818-7 Audio with ADTS transport syntax
450  case 0x11: // ISO/IEC 14496-3 Audio with LATM transport syntax
451  {
452  if (NumApids < MAXAPIDS) {
453  Apids[NumApids] = esPid;
454  Atypes[NumApids] = stream.getStreamType();
455  SI::Descriptor *d;
456  for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
457  switch (d->getDescriptorTag()) {
461  char *s = ALangs[NumApids];
462  int n = 0;
463  for (SI::Loop::Iterator it; ld->languageLoop.getNext(l, it); ) {
464  if (*ld->languageCode != '-') { // some use "---" to indicate "none"
465  if (n > 0)
466  *s++ = '+';
468  s += strlen(s);
469  if (n++ > 1)
470  break;
471  }
472  }
473  }
474  break;
475  default: ;
476  }
477  delete d;
478  }
479  NumApids++;
480  }
481  ProcessCaDescriptors = true;
482  }
483  break;
484  case 5: // STREAMTYPE_13818_PRIVATE
485  case 6: // STREAMTYPE_13818_PES_PRIVATE
486  //XXX case 8: // STREAMTYPE_13818_DSMCC
487  {
488  int dpid = 0;
489  int dtype = 0;
490  char lang[MAXLANGCODE1] = { 0 };
491  SI::Descriptor *d;
492  for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
493  switch (d->getDescriptorTag()) {
496  dpid = esPid;
497  dtype = d->getDescriptorTag();
498  ProcessCaDescriptors = true;
499  break;
501  if (NumSpids < MAXSPIDS) {
502  Spids[NumSpids] = esPid;
505  char *s = SLangs[NumSpids];
506  int n = 0;
507  for (SI::Loop::Iterator it; sd->subtitlingLoop.getNext(sub, it); ) {
508  if (sub.languageCode[0]) {
509  SubtitlingTypes[NumSpids] = sub.getSubtitlingType();
510  CompositionPageIds[NumSpids] = sub.getCompositionPageId();
511  AncillaryPageIds[NumSpids] = sub.getAncillaryPageId();
512  if (n > 0)
513  *s++ = '+';
515  s += strlen(s);
516  if (n++ > 1)
517  break;
518  }
519  }
520  NumSpids++;
521  }
522  break;
524  Tpid = esPid;
527  for (SI::Loop::Iterator it; sd->teletextLoop.getNext(ttxt, it); ) {
528  bool isSubtitlePage = (ttxt.getTeletextType() == 0x02) || (ttxt.getTeletextType() == 0x05);
529  if ((NumTPages < MAXTXTPAGES) && ttxt.languageCode[0] && isSubtitlePage) {
530  strn0cpy(TeletextSubtitlePages[NumTPages].ttxtLanguage, I18nNormalizeLanguageCode(ttxt.languageCode), MAXLANGCODE1);
531  TeletextSubtitlePages[NumTPages].ttxtPage = ttxt.getTeletextPageNumber();
532  TeletextSubtitlePages[NumTPages].ttxtMagazine = ttxt.getTeletextMagazineNumber();
533  TeletextSubtitlePages[NumTPages].ttxtType = ttxt.getTeletextType();
534  NumTPages++;
535  }
536  }
537  }
538  break;
542  }
543  break;
544  default: ;
545  }
546  delete d;
547  }
548  if (dpid) {
549  if (NumDpids < MAXDPIDS) {
550  Dpids[NumDpids] = dpid;
551  Dtypes[NumDpids] = dtype;
552  strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
553  NumDpids++;
554  }
555  }
556  }
557  break;
558  case 0x80: // STREAMTYPE_USER_PRIVATE
559  if (Setup.StandardCompliance == STANDARD_ANSISCTE) { // DigiCipher II VIDEO (ANSI/SCTE 57)
560  Vpid = esPid;
561  Ppid = pmt.getPCRPid();
562  Vtype = 0x02; // compression based upon MPEG-2
563  ProcessCaDescriptors = true;
564  break;
565  }
566  // fall through
567  case 0x81: // STREAMTYPE_USER_PRIVATE
568  if (Setup.StandardCompliance == STANDARD_ANSISCTE) { // ATSC A/53 AUDIO (ANSI/SCTE 57)
569  char lang[MAXLANGCODE1] = { 0 };
570  SI::Descriptor *d;
571  for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
572  switch (d->getDescriptorTag()) {
576  }
577  break;
578  default: ;
579  }
580  delete d;
581  }
582  if (NumDpids < MAXDPIDS) {
583  Dpids[NumDpids] = esPid;
584  Dtypes[NumDpids] = SI::AC3DescriptorTag;
585  strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
586  NumDpids++;
587  }
588  ProcessCaDescriptors = true;
589  break;
590  }
591  // fall through
592  case 0x82: // STREAMTYPE_USER_PRIVATE
593  if (Setup.StandardCompliance == STANDARD_ANSISCTE) { // STANDARD SUBTITLE (ANSI/SCTE 27)
594  //TODO
595  break;
596  }
597  // fall through
598  case 0x83 ... 0xFF: // STREAMTYPE_USER_PRIVATE
599  {
600  char lang[MAXLANGCODE1] = { 0 };
601  bool IsAc3 = false;
602  SI::Descriptor *d;
603  for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
604  switch (d->getDescriptorTag()) {
607  // http://www.smpte-ra.org/mpegreg/mpegreg.html
608  switch (rd->getFormatIdentifier()) {
609  case 0x41432D33: // 'AC-3'
610  IsAc3 = true;
611  break;
612  default:
613  //printf("Format identifier: 0x%08X (pid: %d)\n", rd->getFormatIdentifier(), esPid);
614  break;
615  }
616  }
617  break;
621  }
622  break;
623  default: ;
624  }
625  delete d;
626  }
627  if (IsAc3) {
628  if (NumDpids < MAXDPIDS) {
629  Dpids[NumDpids] = esPid;
630  Dtypes[NumDpids] = SI::AC3DescriptorTag;
631  strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
632  NumDpids++;
633  }
634  ProcessCaDescriptors = true;
635  }
636  }
637  break;
638  default: ;//printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());
639  }
640  if (ProcessCaDescriptors) {
642  CaDescriptors->AddCaDescriptor(d, esPid);
643  delete d;
644  }
645  }
646  }
647  if (Setup.UpdateChannels >= 2) {
648  Channel->SetPids(Vpid, Ppid, Vtype, Apids, Atypes, ALangs, Dpids, Dtypes, DLangs, Spids, SLangs, Tpid);
649  if (NumTPages < MAXTXTPAGES) {
650  int manualPageNumber = cVDRTtxtsubsHookListener::Hook()->ManualPageNumber(Channel);
651  if (manualPageNumber)
652  TeletextSubtitlePages[NumTPages++] = tTeletextSubtitlePage(manualPageNumber);
653  }
654  Channel->SetTeletextSubtitlePages(TeletextSubtitlePages, NumTPages);
655  Channel->SetCaIds(CaDescriptors->CaIds());
656  Channel->SetSubtitlingDescriptors(SubtitlingTypes, CompositionPageIds, AncillaryPageIds);
657  }
658  Channel->SetCaDescriptors(CaDescriptorHandler.AddCaDescriptors(CaDescriptors));
659  }
660  Channels.Unlock();
661  }
662  if (timer.TimedOut()) {
663  if (pmtIndex >= 0)
664  DBGLOG("PMT timeout %d", pmtIndex);
665  SwitchToNextPmtPid();
666  timer.Set(PMT_SCAN_TIMEOUT);
667  }
668 }
#define DBGLOG(a...)
Definition: pat.c:299
unsigned char uchar
Definition: tools.h:30
#define STANDARD_ANSISCTE
Definition: config.h:71
cChannels Channels
Definition: channels.c:864
#define dsyslog(a...)
Definition: tools.h:36
int StandardCompliance
Definition: config.h:284
int esPid
Definition: pat.c:25
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:355
void AddCaId(int CaId)
Definition: pat.c:124
StructureLoop< Association > associationLoop
Definition: section.h:39
uchar * data
Definition: pat.c:27
StructureLoop< Stream > streamLoop
Definition: section.h:71
int getCaPid() const
Definition: descriptor.c:350
char * strn0cpy(char *dest, const char *src, size_t n)
Definition: tools.c:131
DescriptorLoop commonDescriptors
Definition: section.h:70
CharArray privateData
Definition: descriptor.h:147
#define MAXTXTPAGES
Definition: channels.h:39
cPatFilter(void)
Definition: pat.c:302
DescriptorTag getDescriptorTag() const
Definition: si.c:100
int getServiceId() const
Definition: section.c:57
StructureLoop< Teletext > teletextLoop
Definition: descriptor.h:138
StructureLoop< Subtitling > subtitlingLoop
Definition: descriptor.h:331
int Count(void) const
Definition: tools.h:485
int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
Definition: pat.c:163
void AddCaDescriptor(SI::CaDescriptor *d, int EsPid)
Definition: pat.c:136
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
Definition: channels.c:158
int GetPmtPid(int Source, int Transponder, int ServiceId)
Definition: pat.c:266
cCaDescriptors(int Source, int Transponder, int ServiceId, int PmtPid)
Definition: pat.c:91
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
Definition: pat.c:256
int getPid() const
Definition: section.c:65
int CaSystem(void)
Definition: pat.c:32
#define MALLOC(type, size)
Definition: tools.h:46
int getPid() const
Definition: section.c:34
#define PMT_SCAN_TIMEOUT
Definition: pat.c:17
virtual int ManualPageNumber(const cChannel *channel)
void Unlock(void)
Definition: thread.c:170
int Length(void) const
Definition: pat.c:35
void Trigger(int Sid=-1)
Definition: pat.c:316
T * Next(const T *object) const
Definition: tools.h:495
int getCaType() const
Definition: descriptor.c:346
void SetTeletextSubtitlePages(tTeletextSubtitlePage pages[], int numberOfPages)
Definition: channels.c:425
int Source(void) const
Definition: channels.h:168
#define MAXPMTENTRIES
Definition: pat.h:17
int numCaIds
Definition: pat.c:74
cListObject * Next(void) const
Definition: tools.h:468
int getTableIdExtension() const
Definition: si.c:72
bool Is(int Source, int Transponder, int ServiceId)
Definition: pat.c:114
int getFormatIdentifier() const
Definition: descriptor.c:1179
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
Gets all CA descriptors for a given channel.
Definition: pat.c:278
void SwitchToNextPmtPid(void)
Definition: pat.c:346
void SetCaDescriptors(int Level)
Definition: channels.c:471
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:288
static cVDRTtxtsubsHookListener * Hook(void)
cSetup Setup
Definition: config.c:373
bool Lock(bool Write, int TimeoutMs=0)
Definition: thread.c:155
StructureLoop< Language > languageLoop
Definition: descriptor.h:489
int source
Definition: pat.c:70
int GetCaPids(const int *CaSystemIds, int BufSize, int *Pids)
Definition: pat.c:189
Definition: thread.h:63
cChannel * GetByServiceID(int Source, int Transponder, unsigned short ServiceID)
Definition: channels.c:1010
int AddCaDescriptors(cCaDescriptors *CaDescriptors)
Definition: pat.c:228
#define MAXLANGCODE1
Definition: channels.h:41
void SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *CompositionPageIds, uint16_t *AncillaryPageIds)
Definition: channels.c:409
const int GetPmtPid(void)
Definition: pat.c:87
int getStreamType() const
Definition: section.c:69
#define MAXLANGCODE2
Definition: channels.h:42
bool CheckCRCAndParse()
Definition: si.c:65
virtual void SetStatus(bool On)
Turns this filter on or off, depending on the value of On.
Definition: pat.c:308
bool isNITPid() const
Definition: section.h:31
int getServiceId() const
Definition: section.c:30
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
Definition: pat.c:246
virtual ~cCaDescriptor()
Definition: pat.c:56
virtual void SetStatus(bool On)
Turns this filter on or off, depending on the value of On.
Definition: filter.c:104
#define MAXDPIDS
Definition: channels.h:36
T * First(void) const
Definition: tools.h:492
cList< cCaDescriptor > caDescriptors
Definition: pat.c:76
int getVersionNumber() const
Definition: si.c:84
int caSystem
Definition: pat.c:23
bool Empty(void)
Definition: pat.c:83
unsigned char u_char
Definition: headers.h:24
int getPCRPid() const
Definition: section.c:61
int UpdateChannels
Definition: config.h:314
bool operator==(const cCaDescriptors &arg) const
Definition: pat.c:101
int serviceId
Definition: pat.c:72
DescriptorLoop streamDescriptors
Definition: section.h:63
int EsPid(void)
Definition: pat.c:34
int transponder
Definition: pat.c:71
#define MAXSPIDS
Definition: channels.h:37
int getLength() const
Definition: util.h:58
const int * CaIds(void)
Definition: pat.c:88
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:283
const uchar * Data(void) const
Definition: pat.c:36
cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data)
Definition: pat.c:39
int CaPid(void)
Definition: pat.c:33
bool PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNewVersion=false)
Definition: pat.c:328
#define MAXCAIDS
Definition: channels.h:38
void 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
int Sid(void) const
Definition: channels.h:194
bool operator==(const cCaDescriptor &arg) const
Definition: pat.c:61
int getTeletextMagazineNumber() const
Definition: descriptor.c:338
const char * I18nNormalizeLanguageCode(const char *Code)
Returns a 3 letter language code that may not be zero terminated.
Definition: i18n.c:238
int pmtPid
Definition: pat.c:73
const unsigned char * getData() const
Definition: util.h:51
void SetCaIds(const int *CaIds)
Definition: channels.c:450
Descriptor * getNext(Iterator &it)
Definition: si.c:112
cCaDescriptorHandler CaDescriptorHandler
Definition: pat.c:276
cMutex mutex
Definition: pat.c:217
int caPid
Definition: pat.c:24
int length
Definition: pat.c:26
#define MAXAPIDS
Definition: channels.h:35