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