]> git.vomp.tv Git - vompclient.git/blob - src/demuxerts.cc
Remove obsolete min(). But...
[vompclient.git] / src / demuxerts.cc
1 /*
2     Copyright 2006-2008 Mark Calderbank
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "demuxerts.h"
21 #include "log.h"
22 #include "video.h"
23 #include "vdr.h"
24 #include "audio.h"
25
26 #define PTS_JUMP_MARGIN   10000
27 #define PTS_ALLOWANCE 90000
28
29 // TODO: PTS class to handle wrapping arithmetic & comparisons?
30 static u8 PTSDistance(u8 pts1, u8 pts2)
31 {
32   // Assume pts1, pts2 < 2^33; calculate shortest distance between
33   u8 ret = (pts1 > pts2) ? pts1 - pts2 : pts2 - pts1;
34   if (ret > (1LL<<32)) ret = (1LL<<33) - ret;
35   return ret;
36 }
37
38 static u8 PTSDifference(u8 pts1, u8 pts2)
39 {
40   // Assume pts1, pts2 < 2^33; calculate pts1 - pts2
41   if (pts1 > pts2)
42     return pts1 - pts2;
43   else
44     return (1LL<<33) + pts1 - pts2;
45 }
46
47 DemuxerTS::DemuxerTS(int p_vID, int p_aID, int p_subID, int p_tID)
48 {
49   vID = p_vID; vActive = false;
50   aID = p_aID; aActive = false;
51   subID = p_subID; subActive = false;
52   atype = 0;
53   subLength = 0;
54   tID = p_tID;
55   havechannelinfo=false;
56   //doubledframerate=false;
57   framereserve=0;
58
59   pinfo.hassps=false;
60   pinfo.hasaccessunit=false;
61 }
62
63 void DemuxerTS::flush()
64 {
65   partPacket = 0;
66   parsed = false;
67   havechannelinfo=false;
68   Demuxer::flush();
69   vPacket.init(PESTYPE_VID0);
70   switch (atype)
71   {
72   case 1:
73     aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
74     break;
75   default:
76   case 0:
77     aPacket.init(PESTYPE_AUD0);
78     break;
79   }
80   subPacket.init(PESTYPE_PRIVATE_1);
81 tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
82
83   vActive = false;
84   aActive = false;
85   subActive = false;
86   subLength = 0;
87   tActive = false;
88  // doubledframerate=false;
89   framereserve=0;
90   pinfo.hassps=false;
91   pinfo.hasaccessunit=false;
92 }
93
94 int DemuxerTS::scan(u1* /*buf*/, int /*len*/)
95 {
96   switch (atype)
97   {
98   case 1:
99     return PESTYPE_PRIVATE_1;
100   default:
101   case 0:
102     return PESTYPE_AUD0;
103   }
104 }
105
106 void DemuxerTS::setVID(int p_vID)
107 {
108   vID = p_vID;
109   vPacket.init(PESTYPE_VID0);
110   vActive = false;
111 }
112
113 void DemuxerTS::setAID(int p_aID, int type, int streamtype, bool slivetv)
114 {
115   aID = p_aID;
116   atype = type;
117   astreamtype = streamtype;
118   livetv=slivetv;
119   switch (atype)
120   {
121   case 1:
122     aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
123     setAudioStream(PESTYPE_SUBSTREAM_AC30);
124     break;
125   default:
126   case 0:
127     aPacket.init(PESTYPE_AUD0);
128     setAudioStream(PESTYPE_AUD0);
129     break;
130   }
131   aActive = false;
132 }
133
134 void DemuxerTS::setSubID(int p_subID)
135 {
136   subID = p_subID;
137   subPacket.init(PESTYPE_PRIVATE_1);
138   subActive = false;
139   subLength = 0;
140 }
141
142 void DemuxerTS::setTID(int p_tID)
143 {
144   tID = p_tID;
145   tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
146   tActive = false;
147
148 }
149
150
151
152
153 int DemuxerTS::findPTS(u1* buf, int len, u8* dest)
154 {
155   int scanaid=0;
156
157   while (len >= TS_SIZE)
158   {
159       if (*buf != TS_SIG) {buf++;len--; continue;} 
160
161     //Pattern scanning won't work for ts
162
163       
164       int datalen = TS_SIZE - 4;
165       int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
166       u1 payload = buf[1] & 0x40;
167       
168       if (buf[3] & 0x20) // Adaptation field is present
169           datalen -= (buf[4] + 1);
170
171       u1* curbuf =buf+ (TS_SIZE - datalen);
172      
173
174       if (payload) {
175           if (pid == 0x00) {//PAT, only take first program number, ignore the rest
176               int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);
177               if ((pmtpid >> 13) != 0x07) 
178               {
179                   LogNT::getInstance()->debug("findPTS", "PMTPID={:#x} {:#x} TRAILING 111 not set but {:#x}", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));
180               } 
181               else 
182               {
183                   pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
184                   PMTPID = pmtpid;
185               }
186           
187           } else if (pid == PMTPID) { //PMT
188               int sectionlength = ((*(curbuf+2) << 8) & 0x0F ) | *(buf+3);
189               //sectionlength += 4; //include header but subtract crc in the end...
190               int p = 13; //skip fixed part of pmt
191               while ( p < sectionlength) {
192                   int streamtype = *(curbuf+p);
193                   p++;
194                   int foundpid = (*(curbuf+p)<< 8) | *(curbuf+p+1);
195                   p += 2; //skip ES Pid
196                   int eslength = ((*(curbuf+p) << 8) & 0x0F ) | *(curbuf+p+1);
197                   p += 2; //skip ES length
198                   if ((foundpid >> 13) != 0x07)
199                   {
200                       LogNT::getInstance()->debug("findPTS", "FOUNDPID={:#x} {:#x} TRAILING 111 not set but {:#x}", *(buf+p),*(buf+p+1), (foundpid >> 13));
201                   }
202                   else 
203                   {
204                       foundpid = foundpid & 0x1FFF; //clear upper 3 bits
205                       //int pos=0; UNUSED?
206                       if (streamtype==3 || streamtype ==4) {
207                           scanaid=foundpid;
208                       }
209                   }
210                   p += eslength; //skip es descriptor
211               }
212           } else if (pid == scanaid) {     
213            //   u4 framelength = ((u4)curbuf[4] << 8) | curbuf[5];  UNUSED?
214               
215               if ( curbuf[7] & 0x80 ) // PTS_DTS_flags indicate that PTS is present
216               {
217                   *dest = ( (u8)(curbuf[9] & 0x0E) << 29 ) |
218                   ( (u8)(curbuf[10])        << 22 ) |
219                   ( (u8)(curbuf[11] & 0xFE) << 14 ) |
220                   ( (u8)(curbuf[12])        <<  7 ) |
221                   ( (u8)(curbuf[13] & 0xFE) >>  1 );
222                   return 1;
223               }
224           }
225       }
226       len-=TS_SIZE;
227       buf+=TS_SIZE;
228   }
229   // No PTS found.
230   return 0;
231 }
232
233 void DemuxerTS::setFrameNum(u4 frame)
234 {
235   frameCounting = true;
236   frameNumber = frame;
237   framereserve=0;
238   LogNT::getInstance()->debug("DemuxerTS", "setFrameNum {}", frame);
239 }
240
241 void DemuxerTS::setPacketNum(u4 npacket)
242 {
243   packetCounting = true;
244   packetNumber = npacket;
245   LogNT::getInstance()->debug("DemuxerTS", "setPacketNum {}", npacket);
246 }
247
248 int DemuxerTS::put(u1* buf, int len)
249 {
250   int ret = 0;    // return number of bytes consumed
251
252   bool misaligned_mess=false;
253   while (partPacket)
254   {
255     if (len >= TS_SIZE + 1 - partPacket)
256     { // Remainder of partial packet is available, plus one
257       memcpy(store+partPacket, buf, TS_SIZE - partPacket);
258       ret += TS_SIZE - partPacket;
259       buf += TS_SIZE - partPacket;
260       len -= TS_SIZE - partPacket;
261       partPacket = TS_SIZE;
262       if (*buf == TS_SIG)
263       { // Packet is properly terminated
264         int rc = processTS(store);
265         if (rc)
266           partPacket = 0; // Successfully processed
267         else
268           return ret;     // Try again later.
269       }
270       else
271       { // Packet not terminated. Find another candidate, and shift store
272         if (!misaligned_mess) {
273                 LogNT::getInstance()->error("TS Demuxer", "TS Misaligned!A");
274                 misaligned_mess=true; // do not alarm more than once
275         }
276         int search = 1;
277         while (search < partPacket && store[search] != TS_SIG)
278           search++;
279         partPacket -= search;
280         if (partPacket) memcpy(store, store+search, partPacket);
281       }
282     }
283     else
284     { // Still don't have complete packet. Consume what we do have.
285       memcpy(store+partPacket, buf, len);
286       partPacket += len;
287       ret += len;
288       return ret;
289     }
290   }
291
292   // Position ourselves at a candidate TS packet
293   while (len > 0 && *buf != TS_SIG)
294   {
295           if (!misaligned_mess) {
296                   LogNT::getInstance()->error("TS Demuxer", "TS Misaligned!B");
297               misaligned_mess=true; // do not alarm more than once
298            }
299     buf++; ret++; len--;
300   }
301
302   while (len)
303   {
304     if (len < TS_SIZE + 1)
305     { // Not enough data. Store what we have.
306       memcpy(store, buf, len);
307       partPacket = len;
308       ret += len;
309       return ret;
310     }
311
312     if (buf[TS_SIZE] != TS_SIG)
313     { // Not terminated correctly.
314       buf++; ret++; len--;
315       while (len > 0 && *buf != TS_SIG)
316       {
317         buf++; ret++; len--;
318       }
319     }
320     else
321     {
322       int rc = processTS(buf);
323       if (rc)
324       { // Successfully processed
325         buf += TS_SIZE; ret += TS_SIZE; len -= TS_SIZE;
326       }
327       else
328       { // Processing failed.
329         return ret;
330       }
331     }
332   }
333   return ret;
334 }
335
336
337 int DemuxerTS::processTS(u1* buf)
338 {
339   int datalen = TS_SIZE - 4;
340
341   int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
342   u1 payload = buf[1] & 0x40;
343
344
345   if (buf[3] & 0x20) // Adaptation field is present
346     datalen -= (buf[4] + 1);
347   if (datalen < 0) // Error in stream TODO log this
348     return 1;
349   if (datalen == 0) // Null packet
350     return 1;
351  // if (!(buf[3] &0x10)) return 1; // no payload
352   buf += (TS_SIZE - datalen);
353
354   if (payload)
355   {
356       int rc = 1;
357       if (pid == 0x00) {//PAT, only take first program number, ignore the rest
358           int pmtpid = (*(buf+11)<< 8) | *(buf+12);
359           if ((pmtpid >> 13) != 0x07) 
360           {
361               LogNT::getInstance()->debug("ProcessTS", "PMTPID={:#x} {:#x} TRAILING 111 not set but {:#x}", *(buf+11),*(buf+12), (pmtpid >> 13));
362           } 
363           else 
364           {
365               pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
366               PMTPID = pmtpid;
367           }
368             return 1;
369     }
370     if (pid == PMTPID) 
371     { //PMT
372         int sectionlength = ((*(buf+2) << 8) & 0x0F ) | *(buf+3);
373         //sectionlength += 4; //include header but subtract crc in the end...
374         int p = 13; //skip fixed part of pmt
375         Channel new_channelinfo;
376         new_channelinfo.numAPids=0;
377         new_channelinfo.numDPids=0;
378         new_channelinfo.numSPids=0;
379         new_channelinfo.number=0;
380         new_channelinfo.type=VDR::RADIO;
381         new_channelinfo.tpid=0xFFFFF; //unused, check this
382         new_channelinfo.vpid=0xFFFFF; //unused, check this
383         new_channelinfo.index=0;
384
385         new_channelinfo.apids.clear();
386         new_channelinfo.dpids.clear();
387         new_channelinfo.spids.clear();
388         
389         while ( p < sectionlength) {
390             int streamtype = *(buf+p);
391             p++;
392             int foundpid = (*(buf+p)<< 8) | *(buf+p+1);
393             p += 2; //skip ES Pid
394             int eslength = ((*(buf+p) << 8) & 0x0F ) | *(buf+p+1);
395             p += 2; //skip ES length
396             if ((foundpid >> 13) != 0x07)
397             {
398               LogNT::getInstance()->debug("ProcessTS", "FOUNDPID={:#x} {:#x} TRAILING 111 not set but {:#x}", *(buf+p),*(buf+p+1), (foundpid >> 13));
399             }
400             else 
401             {
402                 foundpid = foundpid & 0x1FFF; //clear upper 3 bits
403                 bool notfound=false;
404                 bool nolang=true;
405                 int pos=0;
406            // LogNT::getInstance()->debug("ProcessTS", "FOUNDPID is {:#x} {:#x}", foundpid,streamtype);
407                 switch (streamtype)
408                 {
409                 case 0x1B: //MPEG 4 for future use
410                 case 1:
411                 case 2: { //video
412                     if (foundpid != getVID())   
413                         setVID(foundpid);
414                     new_channelinfo.type=VDR::VIDEO;
415                                         new_channelinfo.vstreamtype=streamtype;
416                     new_channelinfo.vpid=foundpid;
417                                         if (streamtype==0x1b) h264=true;
418                                         else h264=false;
419
420                 //  LogNT::getInstance()->debug("ProcessTS", "Set video PID to {:#x}", foundpid);
421                         }break;
422                 case 0x0F: //AAC ADTS packaging
423                 case 0x11: // LATM packaging
424                 case 3:
425                 case 4: { //audio
426                     apid newapid;
427                     newapid.pid = foundpid;
428                     newapid.desc[0]=0;
429                     newapid.type=streamtype;
430                     pos=0;
431                     nolang=true;
432                     while (pos< eslength && nolang) {
433                         switch (buf[p+pos]) {
434                         case 0x0A: {
435                                 newapid.desc[0]=buf[p+pos+2];
436                                 newapid.desc[1]=buf[p+pos+3];
437                                 newapid.desc[2]=buf[p+pos+4];
438                                 newapid.desc[3]=0;
439                                 nolang=false;
440                     //          LogNT::getInstance()->debug("ProcessTS", "FOUNDLANG is {}", newapid.desc);
441                         } break;
442                         };
443
444                         pos+=2+buf[p+pos+1];
445                     }
446
447                     new_channelinfo.apids.push_back(newapid);
448                     new_channelinfo.numAPids++;
449
450                         } break;
451                 case 5:
452                 case 6: { //Private Data 
453                     apid newapid;
454                     newapid.pid = foundpid;
455                     newapid.desc[0]=0; //set it in player
456                     pos=0;
457                     notfound=true;
458                     nolang=true;
459                     int type=0;
460                   
461                     while (pos< eslength && (notfound || nolang)) {
462                         switch (buf[p+pos]) {
463                         case 0x7A: // Enhanced Ac3 Desriptor
464                         case 0x6A: {//Ac3 descriptor 
465                                 newapid.type=buf[p+pos];
466                                 type=1;
467
468                             notfound=false;
469                                    } break; 
470                        case 0x59: {//SubtitlingDescriptor
471                             type=2;
472                             newapid.type=buf[p+pos];
473                             newapid.desc[0]=buf[p+pos+2];
474                             newapid.desc[1]=buf[p+pos+3];
475                             newapid.desc[2]=buf[p+pos+4];
476                             newapid.desc[3]=0;
477                             newapid.data1=(buf[p+pos+5]<<8) |(buf[p+pos+6]);
478                             newapid.data2=(buf[p+pos+7]<<8) |(buf[p+pos+8]);
479                          //   LogNT::getInstance()->debug("ProcessTS", "FOUNDSUB is {}", newapid.desc);
480                             notfound=false;
481                             nolang=false;
482                                    } break;
483                        case 0x0A: {
484                            newapid.desc[0]=buf[p+pos+2];
485                            newapid.desc[1]=buf[p+pos+3];
486                            newapid.desc[2]=buf[p+pos+4];
487                            newapid.desc[3]=0;
488                            nolang=false;
489                          //  LogNT::getInstance()->debug("ProcessTS", "FOUNDLANG is {}", newapid.desc);
490                        } break;
491                        case 0x56: {
492                            type=3;
493                            new_channelinfo.tpid=foundpid;
494                            notfound=false;
495                                   } break;
496                         };
497                         pos+=2+buf[p+pos+1];
498                     }
499                     if (type==1) {
500                         new_channelinfo.dpids.push_back(newapid);
501                         new_channelinfo.numDPids++;
502                     } else if (type==2) {
503                         new_channelinfo.spids.push_back(newapid);
504                         new_channelinfo.numSPids++;
505                     }
506
507                         } break;
508                 default://TODO how about subtitles and second audio pids
509                     break;
510                 }
511                 }
512             
513                  p += eslength; //skip es descriptor
514         
515         
516             }
517
518         bool audioPIDpresent=false; //Check if pids chnages
519         u4 i;
520         for (i=0;i<channelinfo.numAPids;i++) {
521             if (aID == (int)channelinfo.apids[i].pid) {
522                 audioPIDpresent=true;
523             }
524         }
525         for (i=0;i<channelinfo.numDPids && (! audioPIDpresent);i++) {
526             if (aID == (int)channelinfo.dpids[i].pid) {
527                 audioPIDpresent=true;
528             }
529         }
530         if (! audioPIDpresent || getAID() == 0) {
531
532             bool dolby=false;
533             int selected=-1;
534             int prefered=-1;
535             Control* control = Control::getInstance();
536
537             if (channelinfo.numDPids > 0 && Audio::getInstance()->maysupportAc3())
538             {
539                 u4 j = 0;
540                 while (j < channelinfo.numDPids)
541                 {
542                         int newpref = control->getLangPref(false, channelinfo.dpids[j].desc);
543                         if (Audio::getInstance()->streamTypeSupported(channelinfo.dpids[j].type)
544                                         && (prefered < 0 || newpref < prefered))
545                         {
546                                 selected = j;
547                                 dolby=true;
548                                 prefered = newpref;
549                         }
550                         j++;
551                 }
552             }
553
554             if (channelinfo.numAPids > 0)
555             {
556                 u4 j = 0;
557                 while (j < channelinfo.numAPids)
558                 {
559                         int newpref = control->getLangPref(false, channelinfo.apids[j].desc);
560                         if (Audio::getInstance()->streamTypeSupported(channelinfo.apids[j].type)
561                                         && (prefered < 0 || newpref < prefered))
562                         {
563                                 selected = j;
564                                 dolby=false;
565                                 prefered = newpref;
566                         }
567                         j++;
568                 }
569             }
570             if (selected >= 0) {
571                 if (dolby) {
572                         setAID(channelinfo.dpids[selected].pid,1,channelinfo.dpids[selected].type,false);
573                         Audio::getInstance()->setStreamType(Audio::MPEG2_PES);
574                 } else {
575                         setAID(channelinfo.apids[selected].pid,0,channelinfo.apids[selected].type,false);
576                         Audio::getInstance()->setStreamType(Audio::MPEG2_PES);
577                 }
578             }
579
580
581             selected = -1;
582             prefered=-1;
583             if (channelinfo.numSPids) {
584                 u4 j = 0;
585                 while (j < channelinfo.numSPids)
586                 {
587                         int newpref = control->getLangPref(true, channelinfo.spids[j].desc);
588                         if ( (prefered < 0 || newpref < prefered))
589                         {
590                                 selected = j;
591                                 prefered = newpref;
592                         }
593                         j++;
594                 }
595             }
596
597             if (selected >= 0) {
598                 setSubID(channelinfo.spids[selected].pid);
599
600             }
601         }
602
603         channelinfo=new_channelinfo;
604
605
606         havechannelinfo=true;
607
608          return 1;
609     }
610     
611
612     
613
614     if (pid == vID)
615     {
616       if (vActive)
617       {
618         if (!parsed)
619         {
620           parseTSPacketDetails(vPacket);
621           parsed = true;
622         }
623         rc = submitPacket(vPacket);
624       }
625       vActive = true;
626     }
627     if (pid == aID)
628     {
629       if (aActive)
630       {
631         if (!parsed)
632         {
633           parseTSPacketDetails(aPacket);
634           parsed = true;
635         }
636         rc = submitPacket(aPacket);
637       }
638       aActive = true;
639     }
640     if (pid == subID)
641     {
642       if (subActive)
643       {
644         if (!parsed)
645         {
646           parseTSPacketDetails(subPacket);
647           parsed = true;
648         }
649         rc = submitPacket(subPacket);
650       }
651       subActive = true;
652     }
653     if (isteletextdecoded && pid == tID)
654     {
655       if (tActive)
656       {
657         if (!parsed)
658         {
659           parseTSPacketDetails(tPacket);
660           parsed = true;
661         }
662       rc = submitPacket(tPacket);
663       }
664       tActive = true;
665     }
666     if (rc == 0) return 0;
667
668     parsed = false;
669     if (pid == vID)
670     {
671       vPacket.init(PESTYPE_VID0);
672       buf += 6; datalen -= 6;
673     }
674     if (pid == aID)
675     {
676       switch (atype)
677       {
678       case 1:
679         aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
680         break;
681       default:
682       case 0:
683         aPacket.init(PESTYPE_AUD0);
684         break;
685       }
686       buf += 6; datalen -= 6;
687     }
688     if (pid == subID)
689     {
690       subPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_DVBSUBTITLE0);
691       subLength = (buf[4] << 8) + buf[5];
692       buf += 6; datalen -= 6;
693     }
694     if (isteletextdecoded && pid == tID)
695     {
696         tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
697       buf += 6; datalen -= 6;
698     }
699   }
700
701   if ( (pid == vID && vActive) ||
702        (pid == aID && aActive) ||
703        (pid == tID && tActive) ||
704        (pid == subID && subActive) )
705   {
706     PESPacket* packet = NULL;
707     if (pid == vID) packet = &vPacket;
708     if (pid == aID) packet = &aPacket;
709     if (pid == subID) {
710       packet = &subPacket;
711     }
712     if (pid == tID) packet = &tPacket;
713     if (packet != NULL)
714     {
715       if (packet->write(buf, datalen) == 0)
716       { // Writing to packet failed. It has overflowed.
717         if (!parsed)
718         {
719           parseTSPacketDetails(*packet);
720           parsed = true;
721         }
722         if (submitPacket(*packet) == 0) return 0;
723         parsed = false;
724         packet->truncate();
725         packet->write((u1*)"\200\000\000", 3);
726         packet->write(buf, datalen);
727       }
728     }
729   }
730
731   if (pid == subID && subActive && subPacket.getLength() == subLength)
732   {
733     parsePacketDetails(subPacket);
734 //LogNT::getInstance()->debug("DEMUXERTS", "SUBMITTING A SUBTITLE PACKET {} {:#x}", subLength, subPacket.getSubstream());
735     submitPacket(subPacket);
736     subActive = false;
737   }
738
739   return 1;
740 }
741
742 u4 DemuxerTS::getPacketNum()
743 {
744   return packetNumber;
745 }
746
747 u4 DemuxerTS::getFrameNumFromPTS(u8 pts)
748 {
749   u8 difference = (1LL<<33);
750   u4 ref_frame = 0;
751   int total = 0, actual = 0;
752   if (pts==0) return 0; //we are in startup
753   pts_map_mutex.lock();
754   PTSMap::iterator iter = pts_map.begin();
755   while (iter != pts_map.end())
756   {
757     ++total;
758     //LogNT::getInstance()->debug("DemuxerTS", "getFrameNumfromPTS pts1 {} pts2 {}", pts, iter->pts);
759     if (PTSDifference(iter->pts, pts) < PTS_ALLOWANCE)
760     {
761       difference = 0;
762       ref_frame = iter->frame;
763       actual = total;
764       break;
765     }
766     u8 newdiff = PTSDifference(pts, iter->pts);
767     if (newdiff < difference)
768     {
769       difference = newdiff;
770       ref_frame = iter->frame;
771       actual = total;
772     }
773     ++iter;
774   }
775   if (total > 1 && actual == 1) // We are using the most recent PTS ref.
776   {                             // Delete the rest.
777     iter = pts_map.begin(); iter++;
778     pts_map.erase(iter, pts_map.end());
779   }
780   pts_map_mutex.unlock();
781   
782  //LogNT::getInstance()->debug("DemuxerTS", "getFrameNumfromPTS pts {} deleted {} difference {}", pts, total,difference);
783
784   if (difference == (1LL<<33))
785     return 0; // We cannot make sense of the pts
786   else
787     return ref_frame + difference * fps / 90000;
788 }
789
790
791 void DemuxerTS::parseTSPacketDetails(PESPacket &packet) // Only important stuff for paket counting reminas
792 {
793     parsePacketDetails(packet);
794     if (packetCounting && packet.getPacketType() >= PESTYPE_AUD0 &&
795                         packet.getPacketType() <= PESTYPE_AUDMAX)
796     {
797         packetNumber++;
798     }
799     u4 pictsinpacket=packet.countPictureHeaders(h264,pinfo);
800     
801     u4 numpicts=0;
802   /*  if (!doubledframerate)
803     {*/
804         numpicts=pictsinpacket;
805   /*  }
806     else
807     {
808         numpicts=(pictsinpacket+framereserve)>>1;
809         framereserve=(pictsinpacket+framereserve)%2;
810     }*/
811
812
813   if (frameCounting && numpicts &&
814       packet.getPacketType() >= PESTYPE_VID0 &&
815       packet.getPacketType() <= PESTYPE_VIDMAX)
816   {
817     frameNumber+=numpicts;
818     u4 frame_num = frameNumber;
819     if ((h264 || packet.findSeqHeader(h264) > 1) && packet.hasPTS())
820     {
821       PTSMapEntry me;
822       pts_map_mutex.lock();
823       if (pts_map.empty())
824       {
825         me.pts = packet.getPTS();
826         me.frame = frame_num;
827         pts_map_mutex.unlock();
828         pts_map_mutex.lock();
829         pts_map.push_front(me);
830       }
831       me = pts_map.front();
832       pts_map_mutex.unlock();
833
834       //u4 fps = Video::getInstance()->getFPS();
835       double tfps=fps;
836      // if (doubledframerate) tfps*=2.;
837       long long pts_expected = me.pts + 90000LL*((long long)(((double)(frame_num - me.frame)) / tfps));
838
839       while (pts_expected < 0) pts_expected += (1LL<<33);
840       while (pts_expected > (1LL<<33)) pts_expected -= (1LL<<33);
841
842       // this was a workaround for a vdr bug, now fixed, for older recordings deleter the index file
843
844       /*
845       if (!doubledframerate 
846           &&(abs((long long)PTSDistance(pts_expected, packet.getPTS())-1800) <= 1 
847           || abs((long long)PTSDistance(pts_expected, packet.getPTS())-1501) <= 1)) {
848               doubledframerate=true; //Detected  p50 or p60
849       }*/
850
851       if (PTSDistance(pts_expected, packet.getPTS()) > PTS_JUMP_MARGIN) // PTS jump!
852       {
853         me.pts = packet.getPTS();
854         me.frame = frame_num;
855         pts_map_mutex.lock();
856         pts_map.push_front(me);
857         pts_map_mutex.unlock();
858       }
859     }
860   }
861 }
862
863
864 bool DemuxerTS::scanForVideo(u1* buf, u4 len, bool &ish264)
865 {
866     int pmtpidy=0;
867
868   while (len >= TS_SIZE)
869   {
870       if (*buf != TS_SIG) {buf++;len--; continue;} 
871
872     //Pattern scanning won't work for ts
873
874       
875       int datalen = TS_SIZE - 4;
876       int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
877       u1 payload = buf[1] & 0x40;
878       
879       if (buf[3] & 0x20) // Adaptation field is present
880           datalen -= (buf[4] + 1);
881
882       u1* curbuf =buf+ (TS_SIZE - datalen);
883      
884       if (payload) {
885           if (pid == 0x00) {//PAT, only take first program number, ignore the rest
886               int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);
887               if ((pmtpid >> 13) != 0x07) 
888               {
889                   LogNT::getInstance()->debug("DemuxerTS", "PMTPID={:#x} {:#x} TRAILING 111 not set but {:#x}", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));
890               } 
891               else 
892               {
893                   pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
894                   pmtpidy = pmtpid;
895                                   LogNT::getInstance()->debug("DemuxerTS", "PMT pid {:#x}", pmtpid);
896               }
897           
898           } else if (pid == pmtpidy) { //PMT
899               int sectionlength = ((*(curbuf+2) << 8) & 0x0F ) | *(buf+3);
900               //sectionlength += 4; //include header but subtract crc in the end...
901               int p = 13; //skip fixed part of pmt
902               while ( p < sectionlength) {
903                   int streamtype = *(curbuf+p);
904                   p++;
905                   int foundpid = (*(curbuf+p)<< 8) | *(curbuf+p+1);
906                   p += 2; //skip ES Pid
907                   int eslength = ((*(curbuf+p) << 8) & 0x0F ) | *(curbuf+p+1);
908                   p += 2; //skip ES length
909                   if ((foundpid >> 13) != 0x07)
910                   {
911                       LogNT::getInstance()->debug("DemuxerTS", "FOUNDPID={:#x} {:#x} TRAILING 111 not set but {:#x}", *(buf+p),*(buf+p+1), (foundpid >> 13));
912                   }
913                   else 
914                   {
915                       foundpid = foundpid & 0x1FFF; //clear upper 3 bits
916                    //   int pos=0; UNUSED?
917                                           LogNT::getInstance()->debug("DemuxerTS", "Pid found {:#x} type {:#x}",foundpid ,streamtype);
918                       if (streamtype==1 || streamtype ==2) {
919                                                   ish264=false;
920                                                   LogNT::getInstance()->debug("DemuxerTS", "Found Mpeg2 Video");
921                           return true;
922                       }
923                                           if (streamtype==0x1b) {
924                                                   ish264=true;
925                                                   LogNT::getInstance()->debug("DemuxerTS", "Found h264 Video");
926                                                   return true;
927                                           }
928                   }
929                   p += eslength; //skip es descriptor
930               }
931                           ish264=false;
932               return false;
933           } 
934       }
935       len-=TS_SIZE;
936       buf+=TS_SIZE;
937   }
938   ish264=false;
939   return false;
940 }
941
942 u4 DemuxerTS::stripAudio(u1* buf, u4 len) //it has to be adapted
943
944     //This function strips all TS Headers and non video payload
945     u4 readpos=0;
946     u4 writepos=0;
947     PESPacket destpaket;
948     bool started=true;
949     while (readpos < len ) {
950         if (buf[readpos] != TS_SIG) {readpos++; continue;} 
951         u4 oldreadpos=readpos;
952
953         int datalen = TS_SIZE - 4;
954         int pid = ( (buf[readpos+1] & 0x1F) << 8 ) | buf[readpos+2];
955         u1 payload = buf[readpos+1] & 0x40;
956         if (buf[readpos+3] & 0x20) { // Adaptation field is present
957            datalen -= (buf[readpos+4] + 1);
958         }
959         if (datalen < 0) {// Error in stream TODO log this
960             return 0;
961         }
962         if (datalen == 0) {// Null packet
963              readpos=oldreadpos+TS_SIZE;
964             continue;
965         }
966         readpos += (TS_SIZE - datalen);
967         u4 towrite=std::min(datalen,toi4(len-readpos));
968         if (pid == vID) {
969             if (payload) {
970                 if (started) {
971                     parsePacketDetails(destpaket);
972                     memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
973                     writepos+=destpaket.getSize();
974                  }
975                  destpaket.init(PESTYPE_VID0);
976                  readpos += 6; towrite -= 6;
977                  started=true;
978             }
979
980             if (started) {
981                 if (!destpaket.write(buf+readpos,towrite)) {
982                     parsePacketDetails(destpaket);
983                     memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
984                     writepos+=destpaket.getSize();
985                     destpaket.truncate();
986                                         destpaket.write((u1*)"\200\000\000", 3);
987                     destpaket.write(buf+readpos,towrite);
988
989                 }
990             }
991             
992        
993
994         }
995         readpos=oldreadpos+TS_SIZE;
996     }
997     parsePacketDetails(destpaket);
998     memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
999     writepos+=destpaket.getSize();
1000  
1001     return writepos;
1002 }    
1003
1004
1005