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