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