]> git.vomp.tv Git - vompclient.git/blob - demuxerts.cc
HDTV for Windows
[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
662   if (frameCounting && packet.findPictureHeader(h264) &&
663       packet.getPacketType() >= PESTYPE_VID0 &&
664       packet.getPacketType() <= PESTYPE_VIDMAX)
665   {
666     ULONG frame_num = (frameNumber)++;
667     if ((h264 || packet.findSeqHeader(h264) > 1) && packet.hasPTS())
668     {
669       PTSMapEntry me;
670       pts_map_mutex.Lock();
671       if (pts_map.empty())
672       {
673         me.pts = packet.getPTS();
674         me.frame = frame_num;
675         pts_map_mutex.Unlock();
676         pts_map_mutex.Lock();
677         pts_map.push_front(me);
678       }
679       me = pts_map.front();
680       pts_map_mutex.Unlock();
681
682       //UINT fps = Video::getInstance()->getFPS();
683       ULLONG pts_expected = me.pts + 90000*((int)(((double)(frame_num - me.frame)) / fps));
684       while (pts_expected > (1LL<<33)) pts_expected -= (1LL<<33);
685
686       if (PTSDistance(pts_expected, packet.getPTS()) > PTS_JUMP_MARGIN) // PTS jump!
687       {
688         me.pts = packet.getPTS();
689         me.frame = frame_num;
690         pts_map_mutex.Lock();
691         pts_map.push_front(me);
692         pts_map_mutex.Unlock();
693       }
694     }
695   }
696 }
697
698
699 bool DemuxerTS::scanForVideo(UCHAR* buf, UINT len, bool &ish264)
700 {
701     int pmtpidy=0;
702
703   while (len >= TS_SIZE)
704   {
705       if (*buf != TS_SIG) {buf++;len--; continue;} 
706
707     //Pattern scanning won't work for ts
708
709       
710       int datalen = TS_SIZE - 4;
711       int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
712       UCHAR payload = buf[1] & 0x40;
713       
714       if (buf[3] & 0x20) // Adaptation field is present
715           datalen -= (buf[4] + 1);
716
717       UCHAR* curbuf =buf+ (TS_SIZE - datalen);
718      
719       if (payload) {
720           if (pid == 0x00) {//PAT, only take first program number, ignore the rest
721               int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);
722               if ((pmtpid >> 13) != 0x07) 
723               {
724                   Log::getInstance()->log("DemuxerTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));
725               } 
726               else 
727               {
728                   pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
729                   pmtpidy = pmtpid;
730                                   Log::getInstance()->log("DemuxerTS", Log::DEBUG, "PMT pid%02x",pmtpid );
731               }
732           
733           } else if (pid == pmtpidy) { //PMT
734               int sectionlength = ((*(curbuf+2) << 8) & 0x0F ) | *(buf+3);
735               //sectionlength += 4; //include header but subtract crc in the end...
736               int p = 13; //skip fixed part of pmt
737               while ( p < sectionlength) {
738                   int streamtype = *(curbuf+p);
739                   p++;
740                   int foundpid = (*(curbuf+p)<< 8) | *(curbuf+p+1);
741                   p += 2; //skip ES Pid
742                   int eslength = ((*(curbuf+p) << 8) & 0x0F ) | *(curbuf+p+1);
743                   p += 2; //skip ES length
744                   if ((foundpid >> 13) != 0x07)
745                   {
746                       Log::getInstance()->log("DemuxerTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
747                   }
748                   else 
749                   {
750                       foundpid = foundpid & 0x1FFF; //clear upper 3 bits
751                    //   int pos=0; UNUSED?
752                                           Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Pid found %02x type %02x",foundpid ,streamtype);
753                       if (streamtype==1 || streamtype ==2) {
754                                                   ish264=false;
755                                                   Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Found Mpeg2 Video");
756                           return true;
757                       }
758                                           if (streamtype==0x1b) {
759                                                   ish264=true;
760                                                   Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Found h264 Video");
761                                                   return true;
762                                           }
763                   }
764                   p += eslength; //skip es descriptor
765               }
766                           ish264=false;
767               return false;
768           } 
769       }
770       len-=TS_SIZE;
771       buf+=TS_SIZE;
772   }
773   ish264=false;
774   return false;
775 }
776
777 UINT DemuxerTS::stripAudio(UCHAR* buf, UINT len) //it has to be adapted
778
779     //This function strips all TS Headers and non video payload
780     UINT readpos=0;
781     UINT writepos=0;
782     PESPacket destpaket;
783     bool started=true;
784     while (readpos < len ) {
785         if (buf[readpos] != TS_SIG) {readpos++; continue;} 
786         UINT oldreadpos=readpos;
787
788         int datalen = TS_SIZE - 4;
789         int pid = ( (buf[readpos+1] & 0x1F) << 8 ) | buf[readpos+2];
790         UCHAR payload = buf[readpos+1] & 0x40;
791         if (buf[readpos+3] & 0x20) { // Adaptation field is present
792            datalen -= (buf[readpos+4] + 1);
793         }
794         if (datalen < 0) {// Error in stream TODO log this
795             return 0;
796         }
797         if (datalen == 0) {// Null packet
798              readpos=oldreadpos+TS_SIZE;
799             continue;
800         }
801         readpos += (TS_SIZE - datalen);
802         UINT towrite=min(datalen,len-readpos);
803         if (pid == vID) {
804             if (payload) {
805                 if (started) {
806                     parsePacketDetails(destpaket);
807                     memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
808                     writepos+=destpaket.getSize();
809                  }
810                  destpaket.init(PESTYPE_VID0);
811                  readpos += 6; towrite -= 6;
812                  started=true;
813             }
814
815             if (started) {
816                 if (!destpaket.write(buf+readpos,towrite)) {
817                     parsePacketDetails(destpaket);
818                     memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
819                     writepos+=destpaket.getSize();
820                     destpaket.truncate();
821                                         destpaket.write((UCHAR*)"\200\000\000", 3);
822                     destpaket.write(buf+readpos,towrite);
823
824                 }
825             }
826             
827        
828
829         }
830         readpos=oldreadpos+TS_SIZE;
831     }
832     parsePacketDetails(destpaket);
833     memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
834     writepos+=destpaket.getSize();
835  
836     return writepos;
837 }    
838
839
840