]> git.vomp.tv Git - vompclient-marten.git/blob - demuxer.cc
dvbsubtitles fixup part 2
[vompclient-marten.git] / demuxer.cc
1 /*
2     Copyright 2005-2008 Mark Calderbank
3     Copyright 2007 Marten Richter (AC3 support)
4
5     This file is part of VOMP.
6
7     VOMP is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11
12     VOMP is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with VOMP; if not, write to the Free Software Foundation, Inc.,
19     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 */
21
22 #include "demuxer.h"
23
24 #include "callback.h"
25 #include "dvbsubtitles.h"
26 #include "log.h"
27
28 #include <cstdlib>
29
30 #include <math.h>
31
32 #define DEMUXER_SEQ_HEAD 0x000001B3
33 #define DEMUXER_PIC_HEAD 0x00000101
34 #define DEMUXER_SEQ_EXT_HEAD 0x000001B5
35
36 #define DEMUXER_H264_ACCESS_UNIT 0x00000109
37 #define DEMUXER_H264_SEQ_PARAMETER_SET 0x00000107
38 #define DEMUXER_H264_SUB_ENHANCEMENT_INF 0x00000106
39
40
41 #define SEEK_THRESHOLD 150000 // About 1.5 seconds
42
43 // Statics
44 const int Demuxer::FrameRates[9] = { 0, 23, 24, 25, 29, 30, 50, 59, 60 };
45 Demuxer* Demuxer::instance = NULL;
46
47 class NALUUnit {
48 public:
49     NALUUnit(const UCHAR* buf,UINT length_buf);
50     ~NALUUnit();
51
52 inline    UINT getBits(UINT num_bits);
53     UINT getUe();
54     int getSe();
55     bool isEonalu() {return eonalu;};
56
57 protected:
58     UCHAR* nalu_buf;
59     UINT nalu_length;
60     UINT pos;
61     UCHAR bit_pos;
62     UCHAR working_byte;
63     UINT last_bytes;
64     bool eonalu;
65 };
66
67 NALUUnit::NALUUnit(const UCHAR *buf, UINT length_buf)
68 {
69     nalu_length=0;
70     nalu_buf=NULL;
71     pos=0;
72     bit_pos=0;
73     working_byte=0;
74     last_bytes=0;
75     eonalu=false;
76
77     UINT nalu_start=0;
78     UINT nalu_end=0;
79     UINT pattern =(((UINT)buf[ 0] << 16) |
80                    ((UINT)buf[1] <<  8) |
81                     (UINT)buf[2]  );
82     nalu_start=3;
83     while (pattern != 0x000001)
84     {
85         if (++nalu_start >= length_buf) return;
86         pattern = ((pattern << 8) | buf[nalu_start])&0x00FFFFFF;
87     }
88     nalu_end=nalu_start+1;
89     pattern = ((pattern << 8) | buf[nalu_end])&0x00FFFFFF;
90
91     while (pattern != 0x000001 && pattern != 0x000000)
92     {
93         if (++nalu_end >= length_buf) { nalu_end+=3;break;};
94         pattern = ((pattern << 8) | buf[nalu_end])&0x00FFFFFF;
95     }
96     nalu_end-=3;
97     nalu_end=min(length_buf-1,nalu_end);
98     nalu_length=nalu_end-nalu_start;
99     nalu_buf=(UCHAR*)malloc(nalu_length);
100     memcpy(nalu_buf,buf+nalu_start,nalu_length);
101     pos=1;
102 }
103
104 NALUUnit::~NALUUnit()
105 {
106     if (nalu_buf) free(nalu_buf);
107 }
108
109 inline UINT NALUUnit::getBits(UINT num_bits)
110 {
111     if (num_bits==0) return 0; //???
112     UINT remain_bits=num_bits;
113     UINT work=0;
114     //May be slow, but should work!
115     while (remain_bits>0) {
116         if (bit_pos==0) {
117             if (pos<nalu_length)
118             {
119                 last_bytes=(last_bytes<<8) & nalu_buf[pos];
120                 if ((last_bytes & 0x00FFFFFF) == 0x000003) pos++; //emulation prevention byte
121                  if (pos<nalu_length)
122                  {
123                      working_byte=nalu_buf[pos];
124                      pos++;
125                  } 
126                  else
127                  {
128                      working_byte=0;
129                      eonalu=true;
130                  }
131             } 
132             else
133             {
134                 working_byte=0;
135                 eonalu=true;
136             }
137
138         }
139         UINT fetch_bits=min(remain_bits,8-bit_pos);
140         work=work <<fetch_bits;
141         //work|=((working_byte>>bit_pos) & (0xFF>>(8-fetch_bits)));
142         work|=(working_byte &(0xFF>>(bit_pos)))>>(8-fetch_bits-bit_pos);
143         remain_bits-=fetch_bits;
144         bit_pos=(bit_pos+fetch_bits)%8;
145     }
146     return work;
147 }
148
149 UINT NALUUnit::getUe()
150 {
151     int leadbits=-1;
152     bool bit;
153     for( bit = 0; !bit && !eonalu; leadbits++ )
154         bit = getBits(1);
155     if (eonalu) return true;
156     return ((1 << leadbits)-1)+getBits(leadbits);
157 }
158
159 int NALUUnit::getSe()
160 {
161     UINT input=getUe();
162     if (input==0) return 0;
163     int output=((input+1)>>1);
164     if (input & 0x1) output*=-1;
165     return output;
166 }
167
168
169
170 static const int PESPacket_initial_size = 2000;
171
172 // PESPacket methods
173 PESPacket::PESPacket()
174 {
175   data_size = PESPacket_initial_size;
176   data = (UCHAR*)malloc(data_size);
177   data[0] = 0x00;
178   data[1] = 0x00;
179   data[2] = 0x01;
180   init(0);
181 }
182
183 PESPacket::PESPacket(const PESPacket& packet)
184 {
185   copyFrom(packet);
186 }
187
188 PESPacket& PESPacket::operator=(const PESPacket& packet)
189 {
190   if (this != &packet)
191   {
192     if (data) free(data);
193     copyFrom(packet);
194   }
195   return *this;
196 }
197
198 PESPacket::~PESPacket()
199 {
200   if (data) free(data);
201 }
202
203 void PESPacket::copyFrom(const PESPacket& packet)
204 {
205   length = packet.length;
206   size = packet.size;
207   packetType = packet.packetType;
208   substream = packet.substream;
209   seq_header = packet.seq_header;
210   data_size = size;
211   data = (UCHAR*)malloc(data_size);
212   memcpy(data, packet.data, data_size);
213 }
214
215 void PESPacket::init(UCHAR type, UCHAR sub)
216 {
217   length = 0; 
218   size = 6;
219   data[4] = data[5] = 0;
220   data[3] = type;
221   packetType = type;
222   substream = sub;
223   seq_header = 1; // Unknown seq_header status
224
225 }
226
227 void PESPacket::truncate()
228 {
229   init(packetType,substream);
230 }
231
232
233
234 int PESPacket::write(const UCHAR *buf, int len)
235 {
236
237
238   if (size + len > 0x10000) return 0;
239   if (size + len > data_size)
240   { // Reallocate
241     UINT new_data_size = max(data_size + data_size / 2, data_size + len);
242     if (new_data_size > 0x10000) new_data_size = 0x10000;
243     data_size = new_data_size;
244     data = (UCHAR*)realloc(data, data_size);
245   }
246   memcpy(data + size, buf, len);
247   length += len;
248   size += len;
249   data[4] = (length >> 8);
250   data[5] = (length & 0xFF);
251   // We have added data - reset seq_header indicator if necessary
252   if (seq_header == 0) seq_header = 1; // Reset to 'unknown'
253   return 1;
254 }
255
256 ULLONG PESPacket::getPTS() const
257 {
258   if ( ( (packetType >= Demuxer::PESTYPE_AUD0 &&
259           packetType <= Demuxer::PESTYPE_AUDMAX)
260          ||
261          (packetType >= Demuxer::PESTYPE_VID0 &&
262           packetType <= Demuxer::PESTYPE_VIDMAX)
263    ||
264           packetType == Demuxer::PESTYPE_PRIVATE_1
265        )
266        && size >= 14 && data[7] & 0x80)
267   {
268     return ( (ULLONG)(data[ 9] & 0x0E) << 29) |
269            ( (ULLONG)(data[10])        << 22 ) |
270            ( (ULLONG)(data[11] & 0xFE) << 14 ) |
271            ( (ULLONG)(data[12])        <<  7 ) |
272            ( (ULLONG)(data[13] & 0xFE) >>  1 );
273   }
274   else return PTS_INVALID;
275 }
276
277 UCHAR PESPacket::operator[] (UINT index) const
278 {
279   if (index >= size)
280     return 0;
281   else
282     return data[index];
283 }
284
285 UINT PESPacket::findPictureHeader(bool h264) const
286 {
287   if (size < 12) return 0;
288   UINT pattern = ( ((UINT)data[ 8] << 24) |
289                    ((UINT)data[ 9] << 16) |
290                    ((UINT)data[10] <<  8) |
291                     (UINT)data[11]  );
292   UINT pos = 11;
293   if (h264) {
294           
295           while (pattern != DEMUXER_H264_ACCESS_UNIT)
296           {
297                   if (++pos >= size) return 0;
298                   pattern = (pattern << 8) | data[pos];
299           }
300           return pos-3;
301   } else {
302           while (pattern != DEMUXER_PIC_HEAD)
303           {
304                   if (++pos >= size) return 0;
305                   pattern = (pattern << 8) | data[pos];
306           }
307           return pos-3;
308   }
309 }
310
311 UINT PESPacket::countPictureHeaders(bool h264) const
312 {
313   if (size < 12) return 0;
314   UINT pattern = ( ((UINT)data[ 8] << 24) |
315                    ((UINT)data[ 9] << 16) |
316                    ((UINT)data[10] <<  8) |
317                     (UINT)data[11]  );
318   UINT pos = 11;
319   UINT count=0;
320   if (h264) {
321           
322           while (pos<size)
323           {
324           pos++;
325                   pattern = (pattern << 8) | data[pos];
326           if (pattern==DEMUXER_H264_ACCESS_UNIT) count++;
327           }
328           return count;
329   } else {
330       while (pos<size)
331           {
332           pos++;
333                   pattern = (pattern << 8) | data[pos];
334           if (pattern==DEMUXER_PIC_HEAD) count++;
335           }
336           return count;
337   }
338 }
339
340 UINT PESPacket::findSeqHeader(bool h264) const
341 {
342   if (seq_header != 1) return seq_header;
343   if (size < 12) return 0;
344   UINT pattern = ( ((UINT)data[ 8] << 24) |
345                    ((UINT)data[ 9] << 16) |
346                    ((UINT)data[10] <<  8) |
347                     (UINT)data[11]  );
348   UINT pos = 11;
349   if (h264) {
350       while ((pattern & 0xFFFFFF1F) != DEMUXER_H264_SEQ_PARAMETER_SET)
351           {
352                   if (++pos >= size)
353                   {
354                           seq_header = 0;
355                           return 0;
356                   }
357                   pattern = (pattern << 8) | data[pos];
358           }
359           seq_header = pos - 3;
360   } 
361   else 
362   {
363           while (pattern != DEMUXER_SEQ_HEAD)
364           {
365                   if (++pos >= size)
366                   {
367                           seq_header = 0;
368                           return 0;
369                   }
370                   pattern = (pattern << 8) | data[pos];
371           }
372           seq_header = pos - 3;
373   }
374   return seq_header;
375 }
376
377 UINT PESPacket::findSeqExtHeader(bool h264) const
378 {
379   if (seq_header != 1) return seq_header;
380   if (size < 12) return 0;
381   UINT pattern = ( ((UINT)data[ 8] << 24) |
382                    ((UINT)data[ 9] << 16) |
383                    ((UINT)data[10] <<  8) |
384                     (UINT)data[11]  );
385   UINT pos = 11;
386   if (h264) {
387       while ((pattern & 0xFFFFFF1F) != DEMUXER_H264_SUB_ENHANCEMENT_INF)
388           {
389                   if (++pos >= size)
390                   {
391                           seq_header = 0;
392                           return 0;
393                   }
394                   pattern = (pattern << 8) | data[pos];
395           }
396           seq_header = pos - 3;
397   }
398   else
399   {
400           while (pattern != DEMUXER_SEQ_EXT_HEAD && (data[pos+1]&0xf0)!=0x10)
401           {
402                   if (++pos >= (size-1))
403                   {
404                           seq_header = 0;
405                           return 0;
406                   }
407                   pattern = (pattern << 8) | data[pos];
408           }
409           seq_header = pos - 3;
410   }
411   return seq_header;
412 }
413
414 // Demuxer methods
415 Demuxer::Demuxer()
416 {
417   if (instance) return;
418   instance = this;
419   initted = false;
420   callback = NULL;
421   arcnt = 0;
422   vid_seeking = aud_seeking = false;
423   video_pts = audio_pts = 0;
424   ispre_1_3_19 = false;
425   packetnum=0;
426   h264 = false;
427   fps = 25.0;
428   astreamtype=4;
429   livetv=false;
430 }
431
432 Demuxer::~Demuxer()
433 {
434   shutdown();
435   instance = NULL;
436 }
437
438 Demuxer* Demuxer::getInstance()
439 {
440   return instance;
441 }
442
443 int Demuxer::init(Callback* tcallback, DrainTarget* audio, DrainTarget* video, DrainTarget* teletext,
444                   ULONG demuxMemoryV, ULONG demuxMemoryA, ULONG demuxMemoryT,double infps, DVBSubtitles* tsubtitles)
445 {
446   if (!initted)
447   {
448     if ( !videostream.init(video, demuxMemoryV) ||
449          !audiostream.init(audio, demuxMemoryA) ||
450          !teletextstream.init(teletext, demuxMemoryT))
451     {
452       Log::getInstance()->log("Demuxer", Log::CRIT,
453                               "Failed to initialize demuxer");
454       shutdown();
455       return 0;
456     }
457   }
458   if (teletext) {
459       isteletextdecoded = true;
460   } else {
461       isteletextdecoded = false;
462   }
463   fps=infps;
464   reset();
465   initted = true;
466   subtitles = tsubtitles;
467   callback = tcallback;
468   return 1;
469 }
470
471 void Demuxer::reset()
472 {
473   Log::getInstance()->log("Demuxer", Log::DEBUG, "Reset called");
474   flush();
475   video_current = audio_current = teletext_current = subtitle_current = -1;
476   horizontal_size = vertical_size = 0;
477   interlaced=true; // default is true
478   aspect_ratio = (enum AspectRatio) 0;
479   parx=1;
480   pary=1;
481   frame_rate = bit_rate = 0;
482   ispre_1_3_19 = false;
483   h264 = false;
484   packetnum=0;
485   astreamtype=4;
486   livetv=false;
487
488   for (int i = 0; i <= (PESTYPE_AUDMAX - PESTYPE_AUD0); i++)
489   {
490     avail_mpaudchan[i] = false;
491   }
492   for (int i = 0; i <= (PESTYPE_SUBSTREAM_AC3MAX - PESTYPE_SUBSTREAM_AC30); i++)
493   {
494     avail_ac3audchan[i] = false;
495   }
496   for (int i = 0; i <= (PESTYPE_SUBSTREAM_DVBSUBTITLEMAX - PESTYPE_SUBSTREAM_DVBSUBTITLE0); i++)
497   {
498     avail_dvbsubtitlechan[i] = false;
499   }
500 }
501
502 int Demuxer::shutdown()
503 {
504   videostream.shutdown();
505   audiostream.shutdown();
506   teletextstream.shutdown();
507   initted = false;
508   return 1;
509 }
510
511 void Demuxer::flush()
512 {
513   Log::getInstance()->log("Demuxer", Log::DEBUG, "Flush called");
514
515   videostream.flush();
516   audiostream.flush();
517   teletextstream.flush();
518 }
519
520 void Demuxer::flushAudio()
521 {
522   audiostream.flush();
523 }
524
525 void Demuxer::seek()
526 {
527   vid_seeking = aud_seeking = true;
528   video_pts = audio_pts = teletext_pts = 0;
529 }
530
531 void Demuxer::setAudioStream(int id)
532 {
533   audio_current = id;
534 }
535
536 void Demuxer::setVideoStream(int id)
537 {
538   video_current = id;
539 }
540
541 void Demuxer::setTeletextStream(int id)
542 {
543   teletext_current = id;
544 }
545
546 void Demuxer::setDVBSubtitleStream(int id)
547 {
548   subtitle_current = id;
549 }
550
551 void Demuxer::setAspectRatio(enum AspectRatio ar, int taspectx, int taspecty)
552 {
553   if (aspect_ratio != ar)
554   {
555     Log::getInstance()->log("Demux", Log::DEBUG,
556                             "Aspect ratio difference signalled");
557     if (++arcnt > 3) // avoid changing aspect ratio if glitch in signal
558     {
559       arcnt = 0;
560       aspect_ratio = ar;
561       parx=taspectx;
562       pary=taspecty;
563       if (callback) callback->call(this);
564     }
565   }
566   else
567     arcnt = 0;
568 }
569
570 bool Demuxer::writeAudio(bool * dataavail)
571 {
572   return audiostream.drain(dataavail);
573 }
574
575 bool Demuxer::writeVideo(bool * dataavail)
576 {
577   return videostream.drain(dataavail);
578 }
579
580 bool Demuxer::writeTeletext(bool * dataavail)
581 {
582    return teletextstream.drain(dataavail);
583 }
584
585 bool Demuxer::submitPacket(PESPacket& packet)
586 {
587   UINT sent = 0;
588   UCHAR packet_type = packet.getPacketType();
589   const UCHAR* packetdata = packet.getData();
590   if (packet_type >= PESTYPE_VID0 && packet_type <= PESTYPE_VIDMAX)
591   {
592     if (video_current == -1) video_current = packet_type;
593     if (video_current == packet_type && !vid_seeking)
594         {
595         sent = videostream.put(&packetdata[0], packet.getSize(), h264?MPTYPE_VIDEO_H264:MPTYPE_VIDEO_MPEG2,packetnum);
596         if (sent) packetnum++;
597         }
598         else
599       sent = packet.getSize();
600   }
601   else if (packet_type >= PESTYPE_AUD0 && packet_type <= PESTYPE_AUDMAX)
602   {
603
604     if (audio_current == -1) audio_current = packet_type;
605     avail_mpaudchan[packet_type - PESTYPE_AUD0] = true;
606     if (audio_current == packet_type && !aud_seeking)
607         {
608       UCHAR type=MPTYPE_MPEG_AUDIO;
609       switch (astreamtype)
610       {
611       case 3:
612       case 4:
613           type=MPTYPE_MPEG_AUDIO; break;
614       case 0x11:
615           type=MPTYPE_AAC_LATM; break;
616       };
617       sent = audiostream.put(&packetdata[0], packet.getSize(), type,packetnum);
618           if (sent)  packetnum++;
619         }
620         else
621       sent = packet.getSize();
622   }
623   else if (packet_type == PESTYPE_PRIVATE_1 &&
624            packet.getSubstream() >= PESTYPE_SUBSTREAM_AC30 &&
625            packet.getSubstream() <= PESTYPE_SUBSTREAM_AC3MAX)
626   {
627     avail_ac3audchan[packet.getSubstream() - PESTYPE_SUBSTREAM_AC30] = true;
628     if (packet.getSubstream() == audio_current)
629     {
630       sent = audiostream.put(&packetdata[0], packet.getSize(), (ispre_1_3_19 || livetv)? MPTYPE_AC3_PRE13 : MPTYPE_AC3,packetnum);
631           if (sent) packetnum++;
632     }
633     else
634     {
635       sent = packet.getSize();
636     }
637   }
638   else if (packet_type == PESTYPE_PRIVATE_1 &&
639            packet.getSubstream() >= PESTYPE_SUBSTREAM_DVBSUBTITLE0 &&
640            packet.getSubstream() <= PESTYPE_SUBSTREAM_DVBSUBTITLEMAX)
641   {
642     avail_dvbsubtitlechan[packet.getSubstream()-PESTYPE_SUBSTREAM_DVBSUBTITLE0]=true;
643     if (subtitle_current == -1) subtitle_current = packet.getSubstream();
644     if (subtitles && packet.getSubstream()==subtitle_current)
645     {
646          subtitles->put(packet);
647     }
648     sent = packet.getSize();
649   }
650   else if (isteletextdecoded  && packet_type == PESTYPE_PRIVATE_1 &&
651            packet.getSubstream() >= PESTYPE_SUBSTREAM_TELETEXT0 &&
652            packet.getSubstream() <= PESTYPE_SUBSTREAM_TELETEXTMAX)
653   {
654
655     if (teletext_current == -1) teletext_current = packet.getSubstream();
656     if (teletext_current == packet.getSubstream())
657     {
658         sent = teletextstream.put(&packetdata[0], packet.getSize(), MPTYPE_TELETEXT,packetnum);
659     }
660     else 
661     {
662         sent = packet.getSize();
663     }
664   }
665   else
666   {
667     sent = packet.getSize();
668   }
669
670   if (sent < packet.getSize()) // Stream is full.
671     return false;
672   else
673     return true;
674 }
675
676 void Demuxer::parsePacketDetails(PESPacket& packet)
677 {
678     if (packet.getPacketType() >= PESTYPE_AUD0 &&
679         packet.getPacketType() <= PESTYPE_AUDMAX)
680     {
681         // Extract audio PTS if it exists
682         if (packet.hasPTS())
683         {
684             audio_pts = packet.getPTS();
685             // We continue to seek on the audio if the video PTS that we
686             // are trying to match is ahead of the audio PTS by at most
687             // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
688             if (aud_seeking && !vid_seeking &&
689                 !( (video_pts_seek > audio_pts &&
690                 video_pts_seek - audio_pts < SEEK_THRESHOLD)
691                 ||
692                 (video_pts_seek < audio_pts &&
693                 video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
694             {
695                 aud_seeking = 0;
696                 Log::getInstance()->log("Demuxer", Log::DEBUG,
697                     "Leaving  audio sync: Audio PTS = %llu", audio_pts);
698             }
699         }
700     }
701     else if (packet.getPacketType() == PESTYPE_PRIVATE_1) // Private stream
702     {
703         if (!livetv) {
704                 //Inspired by vdr's device.c
705                 int payload_begin = packet[8]+9;
706                 unsigned char substream_id = packet[payload_begin];
707                 unsigned char substream_type = substream_id & 0xF0;
708                 unsigned char substream_index = substream_id & 0x1F;
709                 pre_1_3_19_Recording: //This is for old recordings stuff and live TV
710                 if (ispre_1_3_19)
711                 {
712                         int old_substream=packet.getSubstream();
713                         if (old_substream){ //someone else already set it, this is live tv
714                                 substream_id = old_substream;
715                                 substream_type = substream_id & 0xF0;
716                                 substream_index = substream_id & 0x1F;
717                         } else {
718                                 substream_id = PESTYPE_PRIVATE_1;
719                                 substream_type = 0x80;
720                                 substream_index = 0;
721                         }
722
723                 }
724                 switch (substream_type)
725                 {
726                 case 0x20://SPU
727                 case 0x30://SPU
728                         packet.setSubstream(substream_id);
729                         break;
730                 case 0xA0: //LPCM //not supported yet, is there any LPCM transmissio out there?
731                         break;
732                 case 0x80: //ac3, currently only one ac3 track per recording supported
733                         packet.setSubstream(substream_type+substream_index);
734
735                         // Extract audio PTS if it exists
736                         if (packet.hasPTS())
737                         {
738                                 audio_pts = packet.getPTS();
739                                 // We continue to seek on the audio if the video PTS that we
740                                 // are trying to match is ahead of the audio PTS by at most
741                                 // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
742                                 if (aud_seeking && !vid_seeking &&
743                                                 !( (video_pts_seek > audio_pts &&
744                                                                 video_pts_seek - audio_pts < SEEK_THRESHOLD)
745                                                                 ||
746                                                                 (video_pts_seek < audio_pts &&
747                                                                                 video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
748                                 {
749                                         aud_seeking = 0;
750                                         Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving  audio sync: Audio PTS = %llu", audio_pts);
751                                 }
752                         }
753                         break;
754                 case 0x10: //Teletext Is this correct?
755                         packet.setSubstream(substream_id);
756                         // Extract teletxt PTS if it exists
757                         if (packet.hasPTS())
758                         {
759                                 teletext_pts = packet.getPTS();
760                         }
761                         break;
762                 default:
763                         if (!ispre_1_3_19)
764                         {
765                                 ispre_1_3_19=true; //switching to compat mode and live tv mode
766                                 goto pre_1_3_19_Recording;
767                         }
768                         else
769                         {
770                                 packet.setSubstream(0);
771                         }
772                         break;
773                 }
774         }
775     }
776     else if (packet.getPacketType() >= PESTYPE_VID0 &&
777         packet.getPacketType() <= PESTYPE_VIDMAX)
778     {
779         // Extract video PTS if it exists
780         if (packet.hasPTS()) video_pts = packet.getPTS();
781
782         // If there is a sequence header, extract information
783         UINT pos = packet.findSeqHeader(h264);
784         if (pos > 1)
785         {
786             if (!h264) {
787                 pos += 4;
788                 if (pos+6 >= packet.getSize()) return;
789                 horizontal_size = ((int)packet[pos] << 4) | ((int)packet[pos+1] >> 4);
790                 
791                 vertical_size = (((int)packet[pos+1] & 0xf) << 8) | (int)packet[pos+2];
792
793                 enum AspectRatio aspect=(enum AspectRatio)(packet[pos+3] >> 4);
794                 int aspectx=1;
795                 int aspecty=1;
796                 const int aspectDAR[]={0,1,1,1,4,3,16,9,221,100};
797                 int aspectDARx=aspectDAR[aspect*2];
798                 int aspectDARy=aspectDAR[aspect*2+1];
799
800                 aspectx=aspectDARx*vertical_size;
801                 aspecty=aspectDARy*horizontal_size;
802
803                 int commona;
804                 int commonb;
805                // Log::getInstance()->log("Demuxer", Log::DEBUG, "PAR test1 %d %d %d %d ", aspectx,aspecty,commona,commonb);
806                 commona=aspectx;
807                 commonb=aspecty;
808
809                 while (commonb) {
810                         int temp=commonb;
811                         commonb=commona%commonb;
812                         commona=temp;
813                 }
814                 aspectx=aspectx/commona;
815                 aspecty=aspecty/commona;
816                 //Log::getInstance()->log("Demuxer", Log::DEBUG, "PAR test2 %d %d %d %d %d %d %d", aspectx,aspecty,aspectDARx,aspectDARy,horizontal_size,vertical_size,commona);
817
818                 setAspectRatio(aspect,aspectx,aspecty);
819                 frame_rate = packet[pos+3] & 0x0f;
820                 if (frame_rate >= 1 && frame_rate <= 8)
821                     frame_rate = FrameRates[frame_rate];
822                 else
823                     frame_rate = 0;
824                 bit_rate = ((int)packet[pos+4] << 10) |
825                     ((int)packet[pos+5] << 2) |
826                     ((int)packet[pos+6] >> 6);
827             } 
828             else
829             {
830                 /* Chris and Mark I know this is ugly, should we move this to a method  of PESPacket or to NALUUnit what would be better?
831                 This looks so ugly since the header includes variable length parts and I have to parse through the whole header to get the wanted information*/
832                 NALUUnit nalu(packet.getData()+pos,packet.getSize()-pos);
833                 profile=nalu.getBits(8);
834                 nalu.getBits(8); //constraints
835                 nalu.getBits(8); //level_idc
836                 nalu.getUe(); //seq_parameter_set_id
837                 int chroma=1;
838                 if (profile==100 || profile==110 || profile==122 || profile==144)
839                 {
840                     chroma=nalu.getUe();
841                     if (chroma==3)
842                     {
843                         nalu.getBits(1);
844                     }
845                     nalu.getUe(); //bit depth lume
846                     nalu.getUe(); //bit depth chrome
847                     nalu.getBits(1);
848                     if (nalu.getBits(1))
849                     {
850                         for (int i=0;i<8;i++){
851                             if (nalu.getBits(1))
852                             {
853                                 if (i<6)
854                                 {
855                                     UINT lastscale=8;
856                                     UINT nextscale=8;
857                                     for (int j=0;j<16;j++) {
858                                         if (nextscale!=0) {
859                                             UINT delta=nalu.getSe();
860                                             nextscale=(lastscale+delta+256)%256;
861                                         }
862                                         lastscale=(nextscale==0)?lastscale:nextscale;
863                                     }
864                                 }
865                                 else
866                                 {
867                                     UINT lastscale=8;
868                                     UINT nextscale=8;
869                                     for (int j=0;j<64;j++) {
870                                         if (nextscale!=0) {
871                                             UINT delta=nalu.getSe();
872                                             nextscale=(lastscale+delta+256)%256;
873                                         }
874                                         lastscale=(nextscale==0)?lastscale:nextscale;
875                                     }
876                                 }
877                             }
878                         }
879                     }
880                 }
881                 int chromunitx=1;
882                 int chromunity=1;
883                 switch (chroma) {
884                 case 0:
885                     chromunitx=chromunity=1; break;
886                 case 1:
887                     chromunitx=chromunity=2; break;
888                 case 2:
889                     chromunitx=2;chromunity=1; break;
890                 case 3:
891                     chromunitx=chromunity=1; break;
892                 };
893
894                 nalu.getUe(); //log2framenum
895                 UINT temp=nalu.getUe();
896                 if (temp==0) //pict order
897                     nalu.getUe();
898                 else if (temp==1) {
899                     nalu.getBits(1);
900                     nalu.getSe();
901                     nalu.getSe();
902                     UINT temp2=nalu.getUe();
903                     for (int i=0;i<temp2;i++)
904                         nalu.getSe();
905                 }
906                 nalu.getUe(); //Num refframes
907                 nalu.getBits(1);
908                 horizontal_size=(nalu.getUe()+1)*16;
909                 
910                 vertical_size=(nalu.getUe()+1)*16;
911                 int tinterlaced=nalu.getBits(1);
912                 vertical_size*=(2-tinterlaced);
913                 interlaced=!tinterlaced;
914                 
915                 if (!tinterlaced) nalu.getBits(1);
916                 nalu.getBits(1);
917                 if (nalu.getBits(1))
918                 {
919                     horizontal_size-=nalu.getUe()*chromunitx;
920                     horizontal_size-=nalu.getUe()*chromunitx;
921                     vertical_size-=nalu.getUe()*(2-tinterlaced)*chromunity;
922                     vertical_size-=nalu.getUe()*(2-tinterlaced)*chromunity;
923                 }
924                 if (nalu.getBits(1))
925                 {
926                     if (nalu.getBits(1))
927                     {
928                         UINT aspectratioidc=nalu.getBits(8);
929                         bool hasaspect=false;
930                         int aspectx,aspecty;
931                         const float aspects[]={1., 1./1.,12./11.,10./11.,16./11.,40./33.,
932                             24./11.,20./11.,32./11.,80./33.,18./11.,15./11.,64./33.,160./99.,4./3.,3./2.,2./1.};
933                         const int aspectsx[]={1, 1,12,10,16,40,
934                                                     24,20,32,80,18,15,64,160,4,3,2};
935                         const int aspectsy[]={1, 1,11,11,11,33,11,11,11,33,11,11,33,99,3,2,1};
936                       
937                         float aspectratio=((float) horizontal_size)/((float) vertical_size);
938                         if (aspectratioidc<=16) 
939                         {
940                             hasaspect=true;
941                             aspectratio*=aspects[aspectratioidc];
942                             aspectx=aspectsx[aspectratioidc];
943                             aspecty=aspectsy[aspectratioidc];
944                            
945                         }
946                         else if (aspectratioidc==255)
947                         {
948                             int t_sar_width=nalu.getBits(16);
949                             int t_sar_height=nalu.getBits(16);
950                             if (t_sar_width!=0 && t_sar_height!=0)
951                             {
952                                 hasaspect=true;
953                                 aspectratio*=((float)t_sar_width)/((float)t_sar_height);
954                                 aspectx=t_sar_width;
955                                 aspecty=t_sar_height;
956                             }
957                         }
958                         if (hasaspect)
959                         {
960                             if (fabs(aspectratio-16./9.)<0.1) setAspectRatio(ASPECT_16_9,aspectx,aspecty);
961                             else if (fabs(aspectratio-4./3.)<0.1) setAspectRatio(ASPECT_4_3,aspectx,aspecty);
962                             else  setAspectRatio(ASPECT_1_1,aspectx,aspecty);
963                         }
964                     }
965
966                 }
967
968             }
969             UINT posext = packet.findSeqExtHeader(h264);
970             if (posext>1) {
971                 if (!h264) {
972                         interlaced=!(packet[pos+1] & 0x08); //really simple
973                         // if more than full hd is coming we need to add additional parsers here
974                 } else {
975                 /*      NALUUnit nalu(packet.getData()+posext,packet.getSize()-posext);
976                         while (!nalu.isEonalu()) {
977                                 unsigned int payloadtype=0;
978                                 unsigned int payloadadd=0xFF;
979                                 while (payloadadd==0xFF && !nalu.isEonalu()) {
980                                         payloadadd=nalu.getBits(8);
981                                         payloadtype+=payloadadd;
982                                 }
983                                 unsigned int payloadsize=0;
984                                 payloadadd=0xff;
985                                 while (payloadadd==0xFF && !nalu.isEonalu()) {
986                                        payloadadd=nalu.getBits(8);
987                                        payloadsize+=payloadadd;
988                             }
989                                 switch (payloadtype) {
990                                 case 1: { // picture timing SEI
991
992                                 } break;
993                                 default: {
994                                         while (payloadsize) { // not handled skip
995                                                 nalu.getBits(8);
996                                                 payloadsize--;
997                                         }
998                                 } break;
999                                 }
1000
1001
1002
1003                         }*/
1004
1005
1006                 }
1007             }
1008            
1009             if (vid_seeking)
1010             {
1011                 vid_seeking = 0;
1012                 video_pts_seek = video_pts;
1013                 Log::getInstance()->log("Demuxer", Log::DEBUG,
1014                     "Entering audio sync: Video PTS = %llu", video_pts);
1015                 Log::getInstance()->log("Demuxer", Log::DEBUG,
1016                     "Entering audio sync: Audio PTS = %llu", audio_pts);
1017             }
1018             return;
1019         } 
1020     }
1021 }
1022
1023 UINT Demuxer::stripAudio(UCHAR* buf, UINT len)
1024 {
1025   UINT read_pos = 0, write_pos = 0;
1026   UINT pattern, packet_length;
1027   if (len < 4) return 0;
1028   pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
1029   while (read_pos + 7 <= len)
1030   {
1031     pattern = ((pattern & 0xFFFFFF) << 8) | buf[read_pos+3];
1032     if (pattern < (0x100|PESTYPE_VID0) || pattern > (0x100|PESTYPE_VIDMAX))
1033       read_pos++;
1034     else
1035     {
1036       packet_length = ((buf[read_pos+4] << 8) | (buf[read_pos+5])) + 6;
1037       if (read_pos + packet_length > len)
1038         read_pos = len;
1039       else
1040       {
1041         if (read_pos != write_pos)
1042           memmove(buf+write_pos, buf+read_pos, packet_length);
1043         read_pos += packet_length;
1044         write_pos += packet_length;
1045         pattern = (buf[read_pos] << 16) | (buf[read_pos+1] << 8)
1046                                         | (buf[read_pos+2]);
1047       }
1048     }
1049   }
1050   return write_pos;
1051 }
1052
1053 void Demuxer::changeTimes(UCHAR* buf, UINT len,UINT playtime)
1054 {
1055         UINT pattern, packet_length;
1056         UINT read_pos = 0;
1057         if (len < 4) return;
1058         pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
1059         while (read_pos + 7 <= len)
1060         {
1061            pattern = ((pattern & 0xFFFFFF) << 8) | buf[read_pos+3];
1062            if (pattern < (0x100|PESTYPE_VID0) || pattern > (0x100|PESTYPE_VIDMAX))
1063               read_pos++;
1064            else
1065            {
1066               packet_length = ((buf[read_pos+4] << 8) | (buf[read_pos+5])) + 6;
1067               // ok we have a packet figure out if pts and dts are present and replace them
1068               if (read_pos + 19 > len) return;
1069               ULLONG new_ts=playtime*90; //play time is on ms so multiply it by 90
1070               if (buf[read_pos+7] & 0x80) { // pts is here, replace it
1071                   buf[read_pos+9]=0x21 | (( new_ts>>29)& 0xde );
1072                   buf[read_pos+10]=0x00 |(( new_ts>>22)& 0xff );
1073                   buf[read_pos+11]=0x01 | (( new_ts>>14)& 0xfe );
1074                   buf[read_pos+12]=0x00 | (( new_ts>>7)& 0xff );
1075                   buf[read_pos+13]=0x01 | (( new_ts<<1)& 0xfe );
1076               }
1077
1078               if (buf[read_pos+7] & 0x40) { // pts is here, replace it
1079                    buf[read_pos+14]=0x21 | (( new_ts>>29)& 0xde );
1080                    buf[read_pos+15]=0x00 | (( new_ts>>22)& 0xff );
1081                    buf[read_pos+16]=0x01 | (( new_ts>>14)& 0xfe );
1082                    buf[read_pos+17]=0x00 | (( new_ts>>7)& 0xff );
1083                    buf[read_pos+18]=0x01 | (( new_ts<<1)& 0xfe );
1084               }
1085               read_pos += packet_length;
1086               pattern = (buf[read_pos] << 16) | (buf[read_pos+1] << 8)
1087                                                 | (buf[read_pos+2]);
1088               }
1089           }
1090
1091 }
1092
1093 bool Demuxer::scanForVideo(UCHAR* buf, UINT len, bool &ish264)
1094 {
1095   UINT pos = 3;
1096   UINT pattern;
1097   ish264=false;
1098   if (len < 4) return false;
1099   pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
1100   while (pos < len)
1101   {
1102     pattern = ((pattern & 0xFFFFFF) << 8) | buf[pos++];
1103     if (pattern >= (0x100|PESTYPE_VID0) && pattern <= (0x100|PESTYPE_VIDMAX))
1104       return true;
1105   }
1106   return false;
1107 }
1108
1109 bool* Demuxer::getmpAudioChannels()
1110 {
1111   return avail_mpaudchan;
1112 }
1113
1114 bool* Demuxer::getac3AudioChannels()
1115 {
1116   return avail_ac3audchan;
1117 }
1118
1119 bool* Demuxer::getSubtitleChannels()
1120 {
1121   return avail_dvbsubtitlechan;
1122 }
1123
1124 int Demuxer::getselSubtitleChannel()
1125 {
1126   return subtitle_current;
1127 }
1128
1129 int Demuxer::getselAudioChannel()
1130 {
1131   return audio_current;
1132 }
1133
1134