]> 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;
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];
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=NULL;
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.vpid=foundpid;
395
396        //           Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set video PID to %x", foundpid);
397                         }break;
398                 case 3:
399                 case 4: { //audio
400                     apid newapid;
401                     newapid.pid = foundpid;
402                     newapid.name = NULL; //set it in player
403                     new_channelinfo.apids.push_back(newapid);
404                     new_channelinfo.numAPids++;
405                     if (getAID() == 0) { //set unset AID to first audio pid that reports itself
406                         setAID(foundpid,0);
407                         Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set audio PID to %x", foundpid);
408                     }
409                         } break;
410                 case 5:
411                 case 6: { //Private Data 
412                     apid newapid;
413                     newapid.pid = foundpid;
414                     newapid.name = NULL; //set it in player
415                     pos=0;
416                     notfound=true;
417                   
418                     while (pos< eslength && notfound) {
419                         switch (buf[p+pos]) {
420                         case 0x6A: {//Ac3 descriptor 
421                             new_channelinfo.dpids.push_back(newapid);
422                             new_channelinfo.numDPids++;
423                             notfound=false;
424                                    } break; 
425                        case 0x59: {//SubtitlingDescriptor
426                             new_channelinfo.spids.push_back(newapid);
427                             new_channelinfo.numSPids++;
428                             notfound=false;
429                                    } break;
430                        case 0x56: {
431                            new_channelinfo.tpid=foundpid;
432                            notfound=false;
433                                   } break;
434                         };
435                         pos+=2+buf[p+pos+1];
436                     }
437
438                         } break;
439                 default://TODO how about subtitles and second audio pids
440                     break;
441                 }
442                 }
443             
444                  p += eslength; //skip es descriptor
445         
446         
447             }
448         bool audioPIDpresent=false; //Check if pids chnages
449         int i;
450         for (i=0;i<channelinfo.numAPids;i++) {
451             if (aID ==channelinfo.apids[i].pid) {
452                 audioPIDpresent=true;
453             }
454         }
455         for (i=0;i<channelinfo.numDPids && (! audioPIDpresent);i++) {
456             if (aID ==channelinfo.dpids[i].pid) {
457                 audioPIDpresent=true;
458             }
459         }
460         if (! audioPIDpresent) {
461             if (channelinfo.numAPids>0) {
462                 setAID(channelinfo.apids[0].pid,0);
463             } else if (channelinfo.numDPids>0) {
464                 setAID(channelinfo.dpids[0].pid,1);
465             }
466         }
467
468         channelinfo=new_channelinfo;
469         havechannelinfo=true;
470
471          return 1;
472     }
473     
474
475     
476
477     if (pid == vID)
478     {
479       if (vActive)
480       {
481         if (!parsed)
482         {
483           parseTSPacketDetails(vPacket);
484           parsed = true;
485         }
486         rc = submitPacket(vPacket);
487       }
488       vActive = true;
489     }
490     if (pid == aID)
491     {
492       if (aActive)
493       {
494         if (!parsed)
495         {
496           parseTSPacketDetails(aPacket);
497           parsed = true;
498         }
499         rc = submitPacket(aPacket);
500       }
501       aActive = true;
502     }
503     if (pid == subID)
504     {
505       if (subActive)
506       {
507         if (!parsed)
508         {
509           parseTSPacketDetails(subPacket);
510           parsed = true;
511         }
512         rc = submitPacket(subPacket);
513       }
514       subActive = true;
515     }
516     if (isteletextdecoded && pid == tID)
517     {
518       if (tActive)
519       {
520         if (!parsed)
521         {
522           parseTSPacketDetails(tPacket);
523           parsed = true;
524         }
525       rc = submitPacket(tPacket);
526       }
527       tActive = true;
528     }
529     if (rc == 0) return 0;
530
531     parsed = false;
532     if (pid == vID)
533     {
534       vPacket.init(PESTYPE_VID0);
535       buf += 6; datalen -= 6;
536     }
537     if (pid == aID)
538     {
539       switch (atype)
540       {
541       case 1:
542         aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
543         break;
544       default:
545       case 0:
546         aPacket.init(PESTYPE_AUD0);
547         break;
548       }
549       buf += 6; datalen -= 6;
550     }
551     if (pid == subID)
552     {
553       subPacket.init(PESTYPE_PRIVATE_1);
554       subLength = (buf[4] << 8) + buf[5];
555       buf += 6; datalen -= 6;
556     }
557     if (isteletextdecoded && pid == tID)
558     {
559         tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
560       buf += 6; datalen -= 6;
561     }
562   }
563
564   if ( (pid == vID && vActive) ||
565        (pid == aID && aActive) ||
566        (pid == tID && tActive) ||
567        (pid == subID && subActive) )
568   {
569     PESPacket* packet = NULL;
570     if (pid == vID) packet = &vPacket;
571     if (pid == aID) packet = &aPacket;
572     if (pid == subID) {
573       packet = &subPacket;
574     }
575     if (pid == tID) packet = &tPacket;
576     if (packet != NULL)
577     {
578       if (packet->write(buf, datalen) == 0)
579       { // Writing to packet failed. It has overflowed.
580         if (!parsed)
581         {
582           parseTSPacketDetails(*packet);
583           parsed = true;
584         }
585         if (submitPacket(*packet) == 0) return 0;
586         parsed = false;
587         packet->truncate();
588         packet->write((UCHAR*)"\200\000\000", 3);
589         packet->write(buf, datalen);
590       }
591     }
592   }
593
594   if (pid == subID && subActive && subPacket.getLength() == subLength)
595   {
596     parsePacketDetails(subPacket);
597 Log::getInstance()->log("DEMUXERTS", Log::DEBUG, "SUBMITTING A SUBTITLE PACKET %d %x", subLength, subPacket.getSubstream());
598     submitPacket(subPacket);
599     subActive = false;
600   }
601
602   return 1;
603 }
604
605 ULONG DemuxerTS::getPacketNum()
606 {
607   return packetNumber;
608 }
609
610 ULONG DemuxerTS::getFrameNumFromPTS(ULLONG pts)
611 {
612   ULLONG difference = (1LL<<33);
613   ULONG ref_frame = 0;
614   int total = 0, actual = 0;
615   pts_map_mutex.Lock();
616   PTSMap::iterator iter = pts_map.begin();
617   while (iter != pts_map.end())
618   {
619     ++total;
620     if (PTSDifference(iter->pts, pts) < PTS_ALLOWANCE)
621     {
622       difference = 0;
623       ref_frame = iter->frame;
624       actual = total;
625       break;
626     }
627     ULLONG newdiff = PTSDifference(pts, iter->pts);
628     if (newdiff < difference)
629     {
630       difference = newdiff;
631       ref_frame = iter->frame;
632       actual = total;
633     }
634     ++iter;
635   }
636   if (total > 1 && actual == 1) // We are using the most recent PTS ref.
637   {                             // Delete the rest.
638     iter = pts_map.begin(); iter++;
639     pts_map.erase(iter, pts_map.end());
640   }
641   pts_map_mutex.Unlock();
642
643   if (difference == (1LL<<33))
644     return 0; // We cannot make sense of the pts
645   else
646     return ref_frame + difference * Video::getInstance()->getFPS() / 90000;
647 }
648
649
650 void DemuxerTS::parseTSPacketDetails(PESPacket packet) // Only important stuff for paket counting reminas
651 {
652     parsePacketDetails(packet);
653     if (packetCounting && packet.getPacketType() >= PESTYPE_AUD0 &&
654                         packet.getPacketType() <= PESTYPE_AUDMAX)
655     {
656         packetNumber++;
657     }
658
659   if (frameCounting && packet.findPictureHeader() &&
660       packet.getPacketType() >= PESTYPE_VID0 &&
661       packet.getPacketType() <= PESTYPE_VIDMAX)
662   {
663     ULONG frame_num = (frameNumber)++;
664     if (packet.findSeqHeader() > 1 && packet.hasPTS())
665     {
666       PTSMapEntry me;
667       pts_map_mutex.Lock();
668       if (pts_map.empty())
669       {
670         me.pts = packet.getPTS();
671         me.frame = frame_num;
672         pts_map_mutex.Unlock();
673         pts_map_mutex.Lock();
674         pts_map.push_front(me);
675       }
676       me = pts_map.front();
677       pts_map_mutex.Unlock();
678
679       UINT fps = Video::getInstance()->getFPS();
680       ULLONG pts_expected = me.pts + 90000*(frame_num - me.frame) / fps;
681       while (pts_expected > (1LL<<33)) pts_expected -= (1LL<<33);
682
683       if (PTSDistance(pts_expected, packet.getPTS()) > PTS_JUMP_MARGIN) // PTS jump!
684       {
685         me.pts = packet.getPTS();
686         me.frame = frame_num;
687         pts_map_mutex.Lock();
688         pts_map.push_front(me);
689         pts_map_mutex.Unlock();
690       }
691     }
692   }
693 }
694
695
696 bool DemuxerTS::scanForVideo(UCHAR* buf, UINT len)
697 {
698     int pmtpidy=0;
699
700   while (len >= TS_SIZE)
701   {
702       if (*buf != TS_SIG) {buf++;len--; continue;} 
703
704     //Pattern scanning won't work for ts
705
706       
707       int datalen = TS_SIZE - 4;
708       int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
709       UCHAR payload = buf[1] & 0x40;
710       
711       if (buf[3] & 0x20) // Adaptation field is present
712           datalen -= (buf[4] + 1);
713
714       UCHAR* curbuf =buf+ (TS_SIZE - datalen);
715      
716       if (payload) {
717           if (pid == 0x00) {//PAT, only take first program number, ignore the rest
718               int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);
719               if ((pmtpid >> 13) != 0x07) 
720               {
721                   Log::getInstance()->log("findPTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));
722               } 
723               else 
724               {
725                   pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
726                   pmtpidy = pmtpid;
727               }
728           
729           } else if (pid == pmtpidy) { //PMT
730               int sectionlength = ((*(curbuf+2) << 8) & 0x0F ) | *(buf+3);
731               //sectionlength += 4; //include header but subtract crc in the end...
732               int p = 13; //skip fixed part of pmt
733               while ( p < sectionlength) {
734                   int streamtype = *(curbuf+p);
735                   p++;
736                   int foundpid = (*(curbuf+p)<< 8) | *(curbuf+p+1);
737                   p += 2; //skip ES Pid
738                   int eslength = ((*(curbuf+p) << 8) & 0x0F ) | *(curbuf+p+1);
739                   p += 2; //skip ES length
740                   if ((foundpid >> 13) != 0x07)
741                   {
742                       Log::getInstance()->log("findPTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
743                   }
744                   else 
745                   {
746                       foundpid = foundpid & 0x1FFF; //clear upper 3 bits
747                       int pos=0;
748                       if (streamtype==1 || streamtype ==2) {
749                           return true;
750                       }
751                   }
752                   p += eslength; //skip es descriptor
753               }
754               return false;
755           } 
756       }
757       len-=TS_SIZE;
758       buf+=TS_SIZE;
759   }
760   return false;
761 }
762
763 UINT DemuxerTS::stripAudio(UCHAR* buf, UINT len) //it has to be adapted
764
765     //This function strips all TS Headers and non video payload
766     UINT readpos=0;
767     UINT writepos=0;
768     PESPacket destpaket;
769     bool started=true;
770     while (readpos < len ) {
771         if (buf[readpos] != TS_SIG) {readpos++; continue;} 
772         UINT oldreadpos=readpos;
773
774         int datalen = TS_SIZE - 4;
775         int pid = ( (buf[readpos+1] & 0x1F) << 8 ) | buf[readpos+2];
776         UCHAR payload = buf[readpos+1] & 0x40;
777         if (buf[readpos+3] & 0x20) { // Adaptation field is present
778            datalen -= (buf[readpos+4] + 1);
779         }
780         if (datalen < 0) {// Error in stream TODO log this
781             return 0;
782         }
783         if (datalen == 0) {// Null packet
784              readpos=oldreadpos+TS_SIZE;
785             continue;
786         }
787         readpos += (TS_SIZE - datalen);
788         UINT towrite=min(datalen,len-readpos);
789         if (pid == vID) {
790             if (payload) {
791                 if (started) {
792                     parsePacketDetails(destpaket);
793                     memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
794                     writepos+=destpaket.getSize();
795                  }
796                  destpaket.init(PESTYPE_VID0);
797                  readpos += 6; towrite -= 6;
798                  started=true;
799             }
800
801             if (started) {
802                 if (!destpaket.write(buf+readpos,towrite)) {
803                     parsePacketDetails(destpaket);
804                     memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
805                     writepos+=destpaket.getSize();
806                     destpaket.truncate();
807                     destpaket.write((UCHAR*)"\200\000\000", 3);
808                     destpaket.write(buf+readpos,towrite);
809
810                 }
811             }
812             
813        
814
815         }
816         readpos=oldreadpos+TS_SIZE;
817     }
818     parsePacketDetails(destpaket);
819     memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
820     writepos+=destpaket.getSize();
821  
822     return writepos;
823 }    
824
825
826