Version 1.7.19
[vdr.git] / remux.c
1 /*
2  * remux.c: Tools for detecting frames and handling PAT/PMT
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: remux.c 2.57 2011/06/12 14:24:09 kls Exp $
8  */
9
10 #include "remux.h"
11 #include "device.h"
12 #include "libsi/si.h"
13 #include "libsi/section.h"
14 #include "libsi/descriptor.h"
15 #include "recording.h"
16 #include "shutdown.h"
17 #include "tools.h"
18
19 // Set these to 'true' for debug output:
20 static bool DebugPatPmt = false;
21 static bool DebugFrames = false;
22
23 #define dbgpatpmt(a...) if (DebugPatPmt) fprintf(stderr, a)
24 #define dbgframes(a...) if (DebugFrames) fprintf(stderr, a)
25
26 ePesHeader AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader)
27 {
28   if (Count < 7)
29      return phNeedMoreData; // too short
30
31   if ((Data[6] & 0xC0) == 0x80) { // MPEG 2
32      if (Count < 9)
33         return phNeedMoreData; // too short
34
35      PesPayloadOffset = 6 + 3 + Data[8];
36      if (Count < PesPayloadOffset)
37         return phNeedMoreData; // too short
38
39      if (ContinuationHeader)
40         *ContinuationHeader = ((Data[6] == 0x80) && !Data[7] && !Data[8]);
41
42      return phMPEG2; // MPEG 2
43      }
44
45   // check for MPEG 1 ...
46   PesPayloadOffset = 6;
47
48   // skip up to 16 stuffing bytes
49   for (int i = 0; i < 16; i++) {
50       if (Data[PesPayloadOffset] != 0xFF)
51          break;
52
53       if (Count <= ++PesPayloadOffset)
54          return phNeedMoreData; // too short
55       }
56
57   // skip STD_buffer_scale/size
58   if ((Data[PesPayloadOffset] & 0xC0) == 0x40) {
59      PesPayloadOffset += 2;
60
61      if (Count <= PesPayloadOffset)
62         return phNeedMoreData; // too short
63      }
64
65   if (ContinuationHeader)
66      *ContinuationHeader = false;
67
68   if ((Data[PesPayloadOffset] & 0xF0) == 0x20) {
69      // skip PTS only
70      PesPayloadOffset += 5;
71      }
72   else if ((Data[PesPayloadOffset] & 0xF0) == 0x30) {
73      // skip PTS and DTS
74      PesPayloadOffset += 10;
75      }
76   else if (Data[PesPayloadOffset] == 0x0F) {
77      // continuation header
78      PesPayloadOffset++;
79
80      if (ContinuationHeader)
81         *ContinuationHeader = true;
82      }
83   else
84      return phInvalid; // unknown
85
86   if (Count < PesPayloadOffset)
87      return phNeedMoreData; // too short
88
89   return phMPEG1; // MPEG 1
90 }
91
92 #define VIDEO_STREAM_S   0xE0
93
94 // --- cRemux ----------------------------------------------------------------
95
96 void cRemux::SetBrokenLink(uchar *Data, int Length)
97 {
98   int PesPayloadOffset = 0;
99   if (AnalyzePesHeader(Data, Length, PesPayloadOffset) >= phMPEG1 && (Data[3] & 0xF0) == VIDEO_STREAM_S) {
100      for (int i = PesPayloadOffset; i < Length - 7; i++) {
101          if (Data[i] == 0 && Data[i + 1] == 0 && Data[i + 2] == 1 && Data[i + 3] == 0xB8) {
102             if (!(Data[i + 7] & 0x40)) // set flag only if GOP is not closed
103                Data[i + 7] |= 0x20;
104             return;
105             }
106          }
107      dsyslog("SetBrokenLink: no GOP header found in video packet");
108      }
109   else
110      dsyslog("SetBrokenLink: no video packet in frame");
111 }
112
113 // --- Some TS handling tools ------------------------------------------------
114
115 int64_t TsGetPts(const uchar *p, int l)
116 {
117   // Find the first packet with a PTS and use it:
118   while (l > 0) {
119         const uchar *d = p;
120         if (TsPayloadStart(d) && TsGetPayload(&d) && PesHasPts(d))
121            return PesGetPts(d);
122         p += TS_SIZE;
123         l -= TS_SIZE;
124         }
125   return -1;
126 }
127
128 void TsSetTeiOnBrokenPackets(uchar *p, int l)
129 {
130   bool Processed[MAXPID] = { false };
131   while (l >= TS_SIZE) {
132         if (*p != TS_SYNC_BYTE)
133            break;
134         int Pid = TsPid(p);
135         if (!Processed[Pid]) {
136            if (!TsPayloadStart(p))
137               p[1] |= TS_ERROR;
138            else
139               Processed[Pid] = true;
140            }
141         l -= TS_SIZE;
142         p += TS_SIZE;
143         }
144 }
145
146 // --- cPatPmtGenerator ------------------------------------------------------
147
148 cPatPmtGenerator::cPatPmtGenerator(const cChannel *Channel)
149 {
150   numPmtPackets = 0;
151   patCounter = pmtCounter = 0;
152   patVersion = pmtVersion = 0;
153   pmtPid = 0;
154   esInfoLength = NULL;
155   SetChannel(Channel);
156 }
157
158 void cPatPmtGenerator::IncCounter(int &Counter, uchar *TsPacket)
159 {
160   TsPacket[3] = (TsPacket[3] & 0xF0) | Counter;
161   if (++Counter > 0x0F)
162      Counter = 0x00;
163 }
164
165 void cPatPmtGenerator::IncVersion(int &Version)
166 {
167   if (++Version > 0x1F)
168      Version = 0x00;
169 }
170
171 void cPatPmtGenerator::IncEsInfoLength(int Length)
172 {
173   if (esInfoLength) {
174      Length += ((*esInfoLength & 0x0F) << 8) | *(esInfoLength + 1);
175      *esInfoLength = 0xF0 | (Length >> 8);
176      *(esInfoLength + 1) = Length;
177      }
178 }
179
180 int cPatPmtGenerator::MakeStream(uchar *Target, uchar Type, int Pid)
181 {
182   int i = 0;
183   Target[i++] = Type; // stream type
184   Target[i++] = 0xE0 | (Pid >> 8); // dummy (3), pid hi (5)
185   Target[i++] = Pid; // pid lo
186   esInfoLength = &Target[i];
187   Target[i++] = 0xF0; // dummy (4), ES info length hi
188   Target[i++] = 0x00; // ES info length lo
189   return i;
190 }
191
192 int cPatPmtGenerator::MakeAC3Descriptor(uchar *Target, uchar Type)
193 {
194   int i = 0;
195   Target[i++] = Type;
196   Target[i++] = 0x01; // length
197   Target[i++] = 0x00;
198   IncEsInfoLength(i);
199   return i;
200 }
201
202 int cPatPmtGenerator::MakeSubtitlingDescriptor(uchar *Target, const char *Language, uchar SubtitlingType, uint16_t CompositionPageId, uint16_t AncillaryPageId)
203 {
204   int i = 0;
205   Target[i++] = SI::SubtitlingDescriptorTag;
206   Target[i++] = 0x08; // length
207   Target[i++] = *Language++;
208   Target[i++] = *Language++;
209   Target[i++] = *Language++;
210   Target[i++] = SubtitlingType;
211   Target[i++] = CompositionPageId >> 8;
212   Target[i++] = CompositionPageId & 0xFF;
213   Target[i++] = AncillaryPageId >> 8;
214   Target[i++] = AncillaryPageId & 0xFF;
215   IncEsInfoLength(i);
216   return i;
217 }
218
219 int cPatPmtGenerator::MakeLanguageDescriptor(uchar *Target, const char *Language)
220 {
221   int i = 0;
222   Target[i++] = SI::ISO639LanguageDescriptorTag;
223   int Length = i++;
224   Target[Length] = 0x00; // length
225   for (const char *End = Language + strlen(Language); Language < End; ) {
226       Target[i++] = *Language++;
227       Target[i++] = *Language++;
228       Target[i++] = *Language++;
229       Target[i++] = 0x00;     // audio type
230       Target[Length] += 0x04; // length
231       if (*Language == '+')
232          Language++;
233       }
234   IncEsInfoLength(i);
235   return i;
236 }
237
238 int cPatPmtGenerator::MakeCRC(uchar *Target, const uchar *Data, int Length)
239 {
240   int crc = SI::CRC32::crc32((const char *)Data, Length, 0xFFFFFFFF);
241   int i = 0;
242   Target[i++] = crc >> 24;
243   Target[i++] = crc >> 16;
244   Target[i++] = crc >> 8;
245   Target[i++] = crc;
246   return i;
247 }
248
249 #define P_TSID    0x8008 // pseudo TS ID
250 #define P_PMT_PID 0x0084 // pseudo PMT pid
251 #define MAXPID    0x2000 // the maximum possible number of pids
252
253 void cPatPmtGenerator::GeneratePmtPid(const cChannel *Channel)
254 {
255   bool Used[MAXPID] = { false };
256 #define SETPID(p) { if ((p) >= 0 && (p) < MAXPID) Used[p] = true; }
257 #define SETPIDS(l) { const int *p = l; while (*p) { SETPID(*p); p++; } }
258   SETPID(Channel->Vpid());
259   SETPID(Channel->Ppid());
260   SETPID(Channel->Tpid());
261   SETPIDS(Channel->Apids());
262   SETPIDS(Channel->Dpids());
263   SETPIDS(Channel->Spids());
264   for (pmtPid = P_PMT_PID; Used[pmtPid]; pmtPid++)
265       ;
266 }
267
268 void cPatPmtGenerator::GeneratePat(void)
269 {
270   memset(pat, 0xFF, sizeof(pat));
271   uchar *p = pat;
272   int i = 0;
273   p[i++] = TS_SYNC_BYTE; // TS indicator
274   p[i++] = TS_PAYLOAD_START | (PATPID >> 8); // flags (3), pid hi (5)
275   p[i++] = PATPID & 0xFF; // pid lo
276   p[i++] = 0x10; // flags (4), continuity counter (4)
277   p[i++] = 0x00; // pointer field (payload unit start indicator is set)
278   int PayloadStart = i;
279   p[i++] = 0x00; // table id
280   p[i++] = 0xB0; // section syntax indicator (1), dummy (3), section length hi (4)
281   int SectionLength = i;
282   p[i++] = 0x00; // section length lo (filled in later)
283   p[i++] = P_TSID >> 8;   // TS id hi
284   p[i++] = P_TSID & 0xFF; // TS id lo
285   p[i++] = 0xC1 | (patVersion << 1); // dummy (2), version number (5), current/next indicator (1)
286   p[i++] = 0x00; // section number
287   p[i++] = 0x00; // last section number
288   p[i++] = pmtPid >> 8;   // program number hi
289   p[i++] = pmtPid & 0xFF; // program number lo
290   p[i++] = 0xE0 | (pmtPid >> 8); // dummy (3), PMT pid hi (5)
291   p[i++] = pmtPid & 0xFF; // PMT pid lo
292   pat[SectionLength] = i - SectionLength - 1 + 4; // -2 = SectionLength storage, +4 = length of CRC
293   MakeCRC(pat + i, pat + PayloadStart, i - PayloadStart);
294   IncVersion(patVersion);
295 }
296
297 void cPatPmtGenerator::GeneratePmt(const cChannel *Channel)
298 {
299   // generate the complete PMT section:
300   uchar buf[MAX_SECTION_SIZE];
301   memset(buf, 0xFF, sizeof(buf));
302   numPmtPackets = 0;
303   if (Channel) {
304      int Vpid = Channel->Vpid();
305      int Ppid = Channel->Ppid();
306      uchar *p = buf;
307      int i = 0;
308      p[i++] = 0x02; // table id
309      int SectionLength = i;
310      p[i++] = 0xB0; // section syntax indicator (1), dummy (3), section length hi (4)
311      p[i++] = 0x00; // section length lo (filled in later)
312      p[i++] = pmtPid >> 8;   // program number hi
313      p[i++] = pmtPid & 0xFF; // program number lo
314      p[i++] = 0xC1 | (pmtVersion << 1); // dummy (2), version number (5), current/next indicator (1)
315      p[i++] = 0x00; // section number
316      p[i++] = 0x00; // last section number
317      p[i++] = 0xE0 | (Ppid >> 8); // dummy (3), PCR pid hi (5)
318      p[i++] = Ppid; // PCR pid lo
319      p[i++] = 0xF0; // dummy (4), program info length hi (4)
320      p[i++] = 0x00; // program info length lo
321
322      if (Vpid)
323         i += MakeStream(buf + i, Channel->Vtype(), Vpid);
324      for (int n = 0; Channel->Apid(n); n++) {
325          i += MakeStream(buf + i, Channel->Atype(n), Channel->Apid(n));
326          const char *Alang = Channel->Alang(n);
327          i += MakeLanguageDescriptor(buf + i, Alang);
328          }
329      for (int n = 0; Channel->Dpid(n); n++) {
330          i += MakeStream(buf + i, 0x06, Channel->Dpid(n));
331          i += MakeAC3Descriptor(buf + i, Channel->Dtype(n));
332          i += MakeLanguageDescriptor(buf + i, Channel->Dlang(n));
333          }
334      for (int n = 0; Channel->Spid(n); n++) {
335          i += MakeStream(buf + i, 0x06, Channel->Spid(n));
336          i += MakeSubtitlingDescriptor(buf + i, Channel->Slang(n), Channel->SubtitlingType(n), Channel->CompositionPageId(n), Channel->AncillaryPageId(n));
337          }
338
339      int sl = i - SectionLength - 2 + 4; // -2 = SectionLength storage, +4 = length of CRC
340      buf[SectionLength] |= (sl >> 8) & 0x0F;
341      buf[SectionLength + 1] = sl;
342      MakeCRC(buf + i, buf, i);
343      // split the PMT section into several TS packets:
344      uchar *q = buf;
345      bool pusi = true;
346      while (i > 0) {
347            uchar *p = pmt[numPmtPackets++];
348            int j = 0;
349            p[j++] = TS_SYNC_BYTE; // TS indicator
350            p[j++] = (pusi ? TS_PAYLOAD_START : 0x00) | (pmtPid >> 8); // flags (3), pid hi (5)
351            p[j++] = pmtPid & 0xFF; // pid lo
352            p[j++] = 0x10; // flags (4), continuity counter (4)
353            if (pusi) {
354               p[j++] = 0x00; // pointer field (payload unit start indicator is set)
355               pusi = false;
356               }
357            int l = TS_SIZE - j;
358            memcpy(p + j, q, l);
359            q += l;
360            i -= l;
361            }
362      IncVersion(pmtVersion);
363      }
364 }
365
366 void cPatPmtGenerator::SetVersions(int PatVersion, int PmtVersion)
367 {
368   patVersion = PatVersion & 0x1F;
369   pmtVersion = PmtVersion & 0x1F;
370 }
371
372 void cPatPmtGenerator::SetChannel(const cChannel *Channel)
373 {
374   if (Channel) {
375      GeneratePmtPid(Channel);
376      GeneratePat();
377      GeneratePmt(Channel);
378      }
379 }
380
381 uchar *cPatPmtGenerator::GetPat(void)
382 {
383   IncCounter(patCounter, pat);
384   return pat;
385 }
386
387 uchar *cPatPmtGenerator::GetPmt(int &Index)
388 {
389   if (Index < numPmtPackets) {
390      IncCounter(pmtCounter, pmt[Index]);
391      return pmt[Index++];
392      }
393   return NULL;
394 }
395
396 // --- cPatPmtParser ---------------------------------------------------------
397
398 cPatPmtParser::cPatPmtParser(bool UpdatePrimaryDevice)
399 {
400   updatePrimaryDevice = UpdatePrimaryDevice;
401   Reset();
402 }
403
404 void cPatPmtParser::Reset(void)
405 {
406   pmtSize = 0;
407   patVersion = pmtVersion = -1;
408   pmtPid = -1;
409   vpid = vtype = 0;
410   ppid = 0;
411 }
412
413 void cPatPmtParser::ParsePat(const uchar *Data, int Length)
414 {
415   // Unpack the TS packet:
416   int PayloadOffset = TsPayloadOffset(Data);
417   Data += PayloadOffset;
418   Length -= PayloadOffset;
419   // The PAT is always assumed to fit into a single TS packet
420   if ((Length -= Data[0] + 1) <= 0)
421      return;
422   Data += Data[0] + 1; // process pointer_field
423   SI::PAT Pat(Data, false);
424   if (Pat.CheckCRCAndParse()) {
425      dbgpatpmt("PAT: TSid = %d, c/n = %d, v = %d, s = %d, ls = %d\n", Pat.getTransportStreamId(), Pat.getCurrentNextIndicator(), Pat.getVersionNumber(), Pat.getSectionNumber(), Pat.getLastSectionNumber());
426      if (patVersion == Pat.getVersionNumber())
427         return;
428      SI::PAT::Association assoc;
429      for (SI::Loop::Iterator it; Pat.associationLoop.getNext(assoc, it); ) {
430          dbgpatpmt("     isNITPid = %d\n", assoc.isNITPid());
431          if (!assoc.isNITPid()) {
432             pmtPid = assoc.getPid();
433             dbgpatpmt("     service id = %d, pid = %d\n", assoc.getServiceId(), assoc.getPid());
434             }
435          }
436      patVersion = Pat.getVersionNumber();
437      }
438   else
439      esyslog("ERROR: can't parse PAT");
440 }
441
442 void cPatPmtParser::ParsePmt(const uchar *Data, int Length)
443 {
444   // Unpack the TS packet:
445   bool PayloadStart = TsPayloadStart(Data);
446   int PayloadOffset = TsPayloadOffset(Data);
447   Data += PayloadOffset;
448   Length -= PayloadOffset;
449   // The PMT may extend over several TS packets, so we need to assemble them
450   if (PayloadStart) {
451      pmtSize = 0;
452      if ((Length -= Data[0] + 1) <= 0)
453         return;
454      Data += Data[0] + 1; // this is the first packet
455      if (SectionLength(Data, Length) > Length) {
456         if (Length <= int(sizeof(pmt))) {
457            memcpy(pmt, Data, Length);
458            pmtSize = Length;
459            }
460         else
461            esyslog("ERROR: PMT packet length too big (%d byte)!", Length);
462         return;
463         }
464      // the packet contains the entire PMT section, so we run into the actual parsing
465      }
466   else if (pmtSize > 0) {
467      // this is a following packet, so we add it to the pmt storage
468      if (Length <= int(sizeof(pmt)) - pmtSize) {
469         memcpy(pmt + pmtSize, Data, Length);
470         pmtSize += Length;
471         }
472      else {
473         esyslog("ERROR: PMT section length too big (%d byte)!", pmtSize + Length);
474         pmtSize = 0;
475         }
476      if (SectionLength(pmt, pmtSize) > pmtSize)
477         return; // more packets to come
478      // the PMT section is now complete, so we run into the actual parsing
479      Data = pmt;
480      }
481   else
482      return; // fragment of broken packet - ignore
483   SI::PMT Pmt(Data, false);
484   if (Pmt.CheckCRCAndParse()) {
485      dbgpatpmt("PMT: sid = %d, c/n = %d, v = %d, s = %d, ls = %d\n", Pmt.getServiceId(), Pmt.getCurrentNextIndicator(), Pmt.getVersionNumber(), Pmt.getSectionNumber(), Pmt.getLastSectionNumber());
486      dbgpatpmt("     pcr = %d\n", Pmt.getPCRPid());
487      if (pmtVersion == Pmt.getVersionNumber())
488         return;
489      if (updatePrimaryDevice)
490         cDevice::PrimaryDevice()->ClrAvailableTracks(false, true);
491      int NumApids = 0;
492      int NumDpids = 0;
493      int NumSpids = 0;
494      vpid = vtype = 0;
495      ppid = 0;
496      apids[0] = 0;
497      dpids[0] = 0;
498      spids[0] = 0;
499      atypes[0] = 0;
500      dtypes[0] = 0;
501      SI::PMT::Stream stream;
502      for (SI::Loop::Iterator it; Pmt.streamLoop.getNext(stream, it); ) {
503          dbgpatpmt("     stream type = %02X, pid = %d", stream.getStreamType(), stream.getPid());
504          switch (stream.getStreamType()) {
505            case 0x01: // STREAMTYPE_11172_VIDEO
506            case 0x02: // STREAMTYPE_13818_VIDEO
507            case 0x1B: // MPEG4
508                       vpid = stream.getPid();
509                       vtype = stream.getStreamType();
510                       ppid = Pmt.getPCRPid();
511                       break;
512            case 0x03: // STREAMTYPE_11172_AUDIO
513            case 0x04: // STREAMTYPE_13818_AUDIO
514            case 0x0F: // ISO/IEC 13818-7 Audio with ADTS transport sytax
515            case 0x11: // ISO/IEC 14496-3 Audio with LATM transport syntax
516                       {
517                       if (NumApids < MAXAPIDS) {
518                          apids[NumApids] = stream.getPid();
519                          atypes[NumApids] = stream.getStreamType();
520                          *alangs[NumApids] = 0;
521                          SI::Descriptor *d;
522                          for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
523                              switch (d->getDescriptorTag()) {
524                                case SI::ISO639LanguageDescriptorTag: {
525                                     SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
526                                     SI::ISO639LanguageDescriptor::Language l;
527                                     char *s = alangs[NumApids];
528                                     int n = 0;
529                                     for (SI::Loop::Iterator it; ld->languageLoop.getNext(l, it); ) {
530                                         if (*ld->languageCode != '-') { // some use "---" to indicate "none"
531                                            dbgpatpmt(" '%s'", l.languageCode);
532                                            if (n > 0)
533                                               *s++ = '+';
534                                            strn0cpy(s, I18nNormalizeLanguageCode(l.languageCode), MAXLANGCODE1);
535                                            s += strlen(s);
536                                            if (n++ > 1)
537                                               break;
538                                            }
539                                         }
540                                     }
541                                     break;
542                                default: ;
543                                }
544                              delete d;
545                              }
546                          if (updatePrimaryDevice)
547                             cDevice::PrimaryDevice()->SetAvailableTrack(ttAudio, NumApids, apids[NumApids], alangs[NumApids]);
548                          NumApids++;
549                          apids[NumApids]= 0;
550                          }
551                       }
552                       break;
553            case 0x06: // STREAMTYPE_13818_PES_PRIVATE
554                       {
555                       int dpid = 0;
556                       int dtype = 0;
557                       char lang[MAXLANGCODE1] = "";
558                       SI::Descriptor *d;
559                       for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
560                           switch (d->getDescriptorTag()) {
561                             case SI::AC3DescriptorTag:
562                             case SI::EnhancedAC3DescriptorTag:
563                                  dbgpatpmt(" AC3");
564                                  dpid = stream.getPid();
565                                  dtype = d->getDescriptorTag();
566                                  break;
567                             case SI::SubtitlingDescriptorTag:
568                                  dbgpatpmt(" subtitling");
569                                  if (NumSpids < MAXSPIDS) {
570                                     spids[NumSpids] = stream.getPid();
571                                     *slangs[NumSpids] = 0;
572                                     subtitlingTypes[NumSpids] = 0;
573                                     compositionPageIds[NumSpids] = 0;
574                                     ancillaryPageIds[NumSpids] = 0;
575                                     SI::SubtitlingDescriptor *sd = (SI::SubtitlingDescriptor *)d;
576                                     SI::SubtitlingDescriptor::Subtitling sub;
577                                     char *s = slangs[NumSpids];
578                                     int n = 0;
579                                     for (SI::Loop::Iterator it; sd->subtitlingLoop.getNext(sub, it); ) {
580                                         if (sub.languageCode[0]) {
581                                            dbgpatpmt(" '%s'", sub.languageCode);
582                                            subtitlingTypes[NumSpids] = sub.getSubtitlingType();
583                                            compositionPageIds[NumSpids] = sub.getCompositionPageId();
584                                            ancillaryPageIds[NumSpids] = sub.getAncillaryPageId();
585                                            if (n > 0)
586                                               *s++ = '+';
587                                            strn0cpy(s, I18nNormalizeLanguageCode(sub.languageCode), MAXLANGCODE1);
588                                            s += strlen(s);
589                                            if (n++ > 1)
590                                               break;
591                                            }
592                                         }
593                                     if (updatePrimaryDevice)
594                                        cDevice::PrimaryDevice()->SetAvailableTrack(ttSubtitle, NumSpids, spids[NumSpids], slangs[NumSpids]);
595                                     NumSpids++;
596                                     spids[NumSpids]= 0;
597                                     }
598                                  break;
599                             case SI::ISO639LanguageDescriptorTag: {
600                                  SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
601                                  dbgpatpmt(" '%s'", ld->languageCode);
602                                  strn0cpy(lang, I18nNormalizeLanguageCode(ld->languageCode), MAXLANGCODE1);
603                                  }
604                                  break;
605                             default: ;
606                             }
607                           delete d;
608                           }
609                       if (dpid) {
610                          if (NumDpids < MAXDPIDS) {
611                             dpids[NumDpids] = dpid;
612                             dtypes[NumDpids] = dtype;
613                             strn0cpy(dlangs[NumDpids], lang, sizeof(dlangs[NumDpids]));
614                             if (updatePrimaryDevice && Setup.UseDolbyDigital)
615                                cDevice::PrimaryDevice()->SetAvailableTrack(ttDolby, NumDpids, dpid, lang);
616                             NumDpids++;
617                             dpids[NumDpids]= 0;
618                             }
619                          }
620                       }
621                       break;
622            default: ;
623            }
624          dbgpatpmt("\n");
625          if (updatePrimaryDevice) {
626             cDevice::PrimaryDevice()->EnsureAudioTrack(true);
627             cDevice::PrimaryDevice()->EnsureSubtitleTrack();
628             }
629          }
630      pmtVersion = Pmt.getVersionNumber();
631      }
632   else
633      esyslog("ERROR: can't parse PMT");
634   pmtSize = 0;
635 }
636
637 bool cPatPmtParser::GetVersions(int &PatVersion, int &PmtVersion) const
638 {
639   PatVersion = patVersion;
640   PmtVersion = pmtVersion;
641   return patVersion >= 0 && pmtVersion >= 0;
642 }
643
644 // --- cTsToPes --------------------------------------------------------------
645
646 cTsToPes::cTsToPes(void)
647 {
648   data = NULL;
649   size = 0;
650   Reset();
651 }
652
653 cTsToPes::~cTsToPes()
654 {
655   free(data);
656 }
657
658 void cTsToPes::PutTs(const uchar *Data, int Length)
659 {
660   if (TsError(Data)) {
661      Reset();
662      return; // ignore packets with TEI set, and drop any PES data collected so far
663      }
664   if (TsPayloadStart(Data))
665      Reset();
666   else if (!size)
667      return; // skip everything before the first payload start
668   Length = TsGetPayload(&Data);
669   if (length + Length > size) {
670      int NewSize = max(KILOBYTE(2), length + Length);
671      if (uchar *NewData = (uchar *)realloc(data, NewSize)) {
672         data = NewData;
673         size = NewSize;
674         }
675      else {
676         esyslog("ERROR: out of memory");
677         Reset();
678         return;
679         }
680      }
681   memcpy(data + length, Data, Length);
682   length += Length;
683 }
684
685 #define MAXPESLENGTH 0xFFF0
686
687 const uchar *cTsToPes::GetPes(int &Length)
688 {
689   if (repeatLast) {
690      repeatLast = false;
691      Length = lastLength;
692      return lastData;
693      }
694   if (offset < length && PesLongEnough(length)) {
695      if (!PesHasLength(data)) // this is a video PES packet with undefined length
696         offset = 6; // trigger setting PES length for initial slice
697      if (offset) {
698         uchar *p = data + offset - 6;
699         if (p != data) {
700            p -= 3;
701            memmove(p, data, 4);
702            }
703         int l = min(length - offset, MAXPESLENGTH);
704         offset += l;
705         if (p != data) {
706            l += 3;
707            p[6]  = 0x80;
708            p[7]  = 0x00;
709            p[8]  = 0x00;
710            }
711         p[4] = l / 256;
712         p[5] = l & 0xFF;
713         Length = l + 6;
714         lastLength = Length;
715         lastData = p;
716         return p;
717         }
718      else {
719         Length = PesLength(data);
720         if (Length <= length) {
721            offset = Length; // to make sure we break out in case of garbage data
722            lastLength = Length;
723            lastData = data;
724            return data;
725            }
726         }
727      }
728   return NULL;
729 }
730
731 void cTsToPes::SetRepeatLast(void)
732 {
733   repeatLast = true;
734 }
735
736 void cTsToPes::Reset(void)
737 {
738   length = offset = 0;
739   lastData = NULL;
740   lastLength = 0;
741   repeatLast = false;
742 }
743
744 // --- Some helper functions for debugging -----------------------------------
745
746 void BlockDump(const char *Name, const u_char *Data, int Length)
747 {
748   printf("--- %s\n", Name);
749   for (int i = 0; i < Length; i++) {
750       if (i && (i % 16) == 0)
751          printf("\n");
752       printf(" %02X", Data[i]);
753       }
754   printf("\n");
755 }
756
757 void TsDump(const char *Name, const u_char *Data, int Length)
758 {
759   printf("%s: %04X", Name, Length);
760   int n = min(Length, 20);
761   for (int i = 0; i < n; i++)
762       printf(" %02X", Data[i]);
763   if (n < Length) {
764      printf(" ...");
765      n = max(n, Length - 10);
766      for (n = max(n, Length - 10); n < Length; n++)
767          printf(" %02X", Data[n]);
768      }
769   printf("\n");
770 }
771
772 void PesDump(const char *Name, const u_char *Data, int Length)
773 {
774   TsDump(Name, Data, Length);
775 }
776
777 // --- cFrameDetector --------------------------------------------------------
778
779 #define EMPTY_SCANNER (0xFFFFFFFF)
780
781 cFrameDetector::cFrameDetector(int Pid, int Type)
782 {
783   SetPid(Pid, Type);
784   synced = false;
785   newPayload = newFrame = independentFrame = false;
786   frameTypeOffset = -1;
787   numPtsValues = 0;
788   numFrames = 0;
789   numIFrames = 0;
790   framesPerSecond = 0;
791   framesInPayloadUnit = framesPerPayloadUnit = 0;
792   payloadUnitOfFrame = 0;
793   scanning = false;
794   scanner = EMPTY_SCANNER;
795 }
796
797 static int CmpUint32(const void *p1, const void *p2)
798 {
799   if (*(uint32_t *)p1 < *(uint32_t *)p2) return -1;
800   if (*(uint32_t *)p1 > *(uint32_t *)p2) return  1;
801   return 0;
802 }
803
804 void cFrameDetector::SetPid(int Pid, int Type)
805 {
806   pid = Pid;
807   type = Type;
808   isVideo = type == 0x01 || type == 0x02 || type == 0x1B; // MPEG 1, 2 or 4
809 }
810
811 void cFrameDetector::Reset(void)
812 {
813   newPayload = newFrame = independentFrame = false;
814   frameTypeOffset = -1;
815   payloadUnitOfFrame = 0;
816   scanning = false;
817   scanner = EMPTY_SCANNER;
818 }
819
820 int cFrameDetector::Analyze(const uchar *Data, int Length)
821 {
822   int Processed = 0;
823   newPayload = newFrame = independentFrame = false;
824   while (Length >= TS_SIZE) {
825         if (Data[0] != TS_SYNC_BYTE) {
826            int Skipped = 1;
827            while (Skipped < Length && (Data[Skipped] != TS_SYNC_BYTE || Length - Skipped > TS_SIZE && Data[Skipped + TS_SIZE] != TS_SYNC_BYTE))
828                  Skipped++;
829            esyslog("ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
830            return Processed + Skipped;
831            }
832         if (TsHasPayload(Data) && !TsIsScrambled(Data)) {
833            int Pid = TsPid(Data);
834            if (Pid == pid) {
835               if (TsPayloadStart(Data)) {
836                  if (synced && Processed)
837                     return Processed; // flush everything before this new payload
838                  if (framesPerSecond <= 0.0) {
839                     // frame rate unknown, so collect a sequence of PTS values:
840                     if (numPtsValues < MaxPtsValues && numIFrames < 2) { // collect a sequence containing at least two I-frames
841                        const uchar *Pes = Data + TsPayloadOffset(Data);
842                        if (numIFrames && PesHasPts(Pes)) {
843                           ptsValues[numPtsValues] = PesGetPts(Pes);
844                           // check for rollover:
845                           if (numPtsValues && ptsValues[numPtsValues - 1] > 0xF0000000 && ptsValues[numPtsValues] < 0x10000000) {
846                              dbgframes("#");
847                              numPtsValues = 0;
848                              numIFrames = 0;
849                              numFrames = 0;
850                              }
851                           else
852                              numPtsValues++;
853                           }
854                        }
855                     else {
856                        // find the smallest PTS delta:
857                        qsort(ptsValues, numPtsValues, sizeof(uint32_t), CmpUint32);
858                        numPtsValues--;
859                        for (int i = 0; i < numPtsValues; i++)
860                            ptsValues[i] = ptsValues[i + 1] - ptsValues[i];
861                        qsort(ptsValues, numPtsValues, sizeof(uint32_t), CmpUint32);
862                        uint32_t Delta = ptsValues[0];
863                        // determine frame info:
864                        if (isVideo) {
865                           if (abs(Delta - 3600) <= 1)
866                              framesPerSecond = 25.0;
867                           else if (Delta % 3003 == 0)
868                              framesPerSecond = 30.0 / 1.001;
869                           else if (abs(Delta - 1800) <= 1) {
870                              if (numFrames > 50) {
871                                 // this is a "best guess": if there are more than 50 frames between two I-frames, we assume each "frame" actually contains a "field", so two "fields" make one "frame"
872                                 framesPerSecond = 25.0;
873                                 framesPerPayloadUnit = -2;
874                                 }
875                              else
876                                 framesPerSecond = 50.0;
877                              }
878                           else if (Delta == 1501)
879                              if (numFrames > 50) {
880                                 // this is a "best guess": if there are more than 50 frames between two I-frames, we assume each "frame" actually contains a "field", so two "fields" make one "frame"
881                                 framesPerSecond = 30.0 / 1.001;
882                                 framesPerPayloadUnit = -2;
883                                 }
884                              else
885                                 framesPerSecond = 60.0 / 1.001;
886                           else {
887                              framesPerSecond = DEFAULTFRAMESPERSECOND;
888                              dsyslog("unknown frame delta (%d), assuming %5.2f fps", Delta, DEFAULTFRAMESPERSECOND);
889                              }
890                           }
891                        else // audio
892                           framesPerSecond = 90000.0 / Delta; // PTS of audio frames is always increasing
893                        dbgframes("\nDelta = %d  FPS = %5.2f  FPPU = %d NF = %d\n", Delta, framesPerSecond, framesPerPayloadUnit, numFrames);
894                        }
895                     }
896                  scanner = EMPTY_SCANNER;
897                  scanning = true;
898                  }
899               if (scanning) {
900                  int PayloadOffset = TsPayloadOffset(Data);
901                  if (TsPayloadStart(Data)) {
902                     if (synced && Processed)
903                        return Processed; // flush everything before this new payload
904                     newPayload = true;
905                     scanner = EMPTY_SCANNER;
906                     PayloadOffset += PesPayloadOffset(Data + PayloadOffset);
907                     if (!framesPerPayloadUnit)
908                        framesPerPayloadUnit = framesInPayloadUnit;
909                     if (DebugFrames && !synced)
910                        dbgframes("/");
911                     }
912                  for (int i = PayloadOffset; scanning && i < TS_SIZE; i++) {
913                      if (frameTypeOffset < 0) {
914                         scanner <<= 8;
915                         scanner |= Data[i];
916                         }
917                      else
918                         frameTypeOffset += PayloadOffset;
919                      switch (type) {
920                        case 0x01: // MPEG 1 video
921                        case 0x02: // MPEG 2 video
922                             if (scanner == 0x00000100) { // Picture Start Code
923                                if (frameTypeOffset < 0) {
924                                   frameTypeOffset = i + 2;
925                                   if (frameTypeOffset >= TS_SIZE) { // the byte to check is in the next TS packet
926                                      frameTypeOffset -= TS_SIZE;
927                                      if (!synced)
928                                         dbgframes("%d>", frameTypeOffset);
929                                      break;
930                                      }
931                                   }
932                                scanner = EMPTY_SCANNER;
933                                newFrame = true;
934                                uchar FrameType = (Data[frameTypeOffset] >> 3) & 0x07;
935                                frameTypeOffset = -1;
936                                independentFrame = FrameType == 1; // I-Frame
937                                if (synced) {
938                                   if (framesPerPayloadUnit <= 1)
939                                      scanning = false;
940                                   }
941                                else {
942                                   framesInPayloadUnit++;
943                                   if (independentFrame)
944                                      numIFrames++;
945                                   if (numIFrames == 1)
946                                      numFrames++;
947                                   dbgframes("%u ", FrameType);
948                                   }
949                                if (synced)
950                                   return Processed + TS_SIZE; // flag this new frame
951                                }
952                             break;
953                        case 0x1B: // MPEG 4 video
954                             if (scanner == 0x00000109) { // Access Unit Delimiter
955                                if (frameTypeOffset < 0) {
956                                   frameTypeOffset = i + 1;
957                                   if (frameTypeOffset >= TS_SIZE) { // the byte to check is in the next TS packet
958                                      frameTypeOffset -= TS_SIZE;
959                                      if (!synced)
960                                         dbgframes("%d>", frameTypeOffset);
961                                      break;
962                                      }
963                                   }
964                                scanner = EMPTY_SCANNER;
965                                newFrame = true;
966                                uchar FrameType = Data[frameTypeOffset];
967                                frameTypeOffset = -1;
968                                independentFrame = FrameType == 0x10;
969                                if (synced) {
970                                   if (framesPerPayloadUnit < 0) {
971                                      payloadUnitOfFrame = (payloadUnitOfFrame + 1) % -framesPerPayloadUnit;
972                                      if (payloadUnitOfFrame != 0 && independentFrame)
973                                         payloadUnitOfFrame = 0;
974                                      if (payloadUnitOfFrame)
975                                         newFrame = false;
976                                      }
977                                   if (framesPerPayloadUnit <= 1)
978                                      scanning = false;
979                                   }
980                                else {
981                                   framesInPayloadUnit++;
982                                   if (independentFrame)
983                                      numIFrames++;
984                                   if (numIFrames == 1)
985                                      numFrames++;
986                                   dbgframes("%02X ", FrameType);
987                                   }
988                                if (synced)
989                                   return Processed + TS_SIZE; // flag this new frame
990                                }
991                             break;
992                        case 0x04: // MPEG audio
993                        case 0x06: // AC3 audio
994                             if (synced && Processed)
995                                return Processed;
996                             newFrame = true;
997                             independentFrame = true;
998                             if (!synced) {
999                                framesInPayloadUnit = 1;
1000                                if (TsPayloadStart(Data))
1001                                   numIFrames++;
1002                                }
1003                             scanning = false;
1004                             break;
1005                        default: esyslog("ERROR: unknown stream type %d (PID %d) in frame detector", type, pid);
1006                                 pid = 0; // let's just ignore any further data
1007                        }
1008                      }
1009                  if (!synced && framesPerSecond > 0.0 && independentFrame) {
1010                     synced = true;
1011                     dbgframes("*\n");
1012                     Reset();
1013                     return Processed + TS_SIZE;
1014                     }
1015                  }
1016               }
1017            else if (Pid == PATPID && synced && Processed)
1018               return Processed; // allow the caller to see any PAT packets
1019            }
1020         Data += TS_SIZE;
1021         Length -= TS_SIZE;
1022         Processed += TS_SIZE;
1023         }
1024   return Processed;
1025 }