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