]> git.vomp.tv Git - vompclient.git/blob - demuxer.cc
Rewritten vomp discovery protocol
[vompclient.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
35 #define DEMUXER_H264_ACCESS_UNIT 0x00000109
36 #define DEMUXER_H264_SEQ_PARAMETER_SET 0x00000107
37
38
39 #define SEEK_THRESHOLD 150000 // About 1.5 seconds
40
41 // Statics
42 const int Demuxer::FrameRates[9] = { 0, 23, 24, 25, 29, 30, 50, 59, 60 };
43 Demuxer* Demuxer::instance = NULL;
44
45 class NALUUnit {
46 public:
47     NALUUnit(const UCHAR* buf,UINT length_buf);
48     ~NALUUnit();
49
50 inline    UINT getBits(UINT num_bits);
51     UINT getUe();
52     int getSe();
53     bool isEonalu() {return eonalu;};
54
55 protected:
56     UCHAR* nalu_buf;
57     UINT nalu_length;
58     UINT pos;
59     UCHAR bit_pos;
60     UCHAR working_byte;
61     UINT last_bytes;
62     bool eonalu;
63 };
64
65 NALUUnit::NALUUnit(const UCHAR *buf, UINT length_buf)
66 {
67     nalu_length=0;
68     nalu_buf=NULL;
69     pos=0;
70     bit_pos=0;
71     working_byte=0;
72     last_bytes=0;
73     eonalu=false;
74
75     UINT nalu_start=0;
76     UINT nalu_end=0;
77     UINT pattern =(((UINT)buf[ 0] << 16) |
78                    ((UINT)buf[1] <<  8) |
79                     (UINT)buf[2]  );
80     nalu_start=3;
81     while (pattern != 0x000001)
82     {
83         if (++nalu_start >= length_buf) return;
84         pattern = ((pattern << 8) | buf[nalu_start])&0x00FFFFFF;
85     }
86     nalu_end=nalu_start+1;
87     pattern = ((pattern << 8) | buf[nalu_end])&0x00FFFFFF;
88
89     while (pattern != 0x000001 && pattern != 0x000000)
90     {
91         if (++nalu_end >= length_buf) { nalu_end+=3;break;};
92         pattern = ((pattern << 8) | buf[nalu_end])&0x00FFFFFF;
93     }
94     nalu_end-=3;
95     nalu_end=min(length_buf-1,nalu_end);
96     nalu_length=nalu_end-nalu_start;
97     nalu_buf=(UCHAR*)malloc(nalu_length);
98     memcpy(nalu_buf,buf+nalu_start,nalu_length);
99     pos=1;
100 }
101
102 NALUUnit::~NALUUnit()
103 {
104     if (nalu_buf) free(nalu_buf);
105 }
106
107 inline UINT NALUUnit::getBits(UINT num_bits)
108 {
109     if (num_bits==0) return 0; //???
110     UINT remain_bits=num_bits;
111     UINT work=0;
112     //May be slow, but should work!
113     while (remain_bits>0) {
114         if (bit_pos==0) {
115             if (pos<nalu_length)
116             {
117                 last_bytes=(last_bytes<<8) & nalu_buf[pos];
118                 if ((last_bytes & 0x00FFFFFF) == 0x000003) pos++; //emulation prevention byte
119                  if (pos<nalu_length)
120                  {
121                      working_byte=nalu_buf[pos];
122                      pos++;
123                  } 
124                  else
125                  {
126                      working_byte=0;
127                      eonalu=true;
128                  }
129             } 
130             else
131             {
132                 working_byte=0;
133                 eonalu=true;
134             }
135
136         }
137         UINT fetch_bits=min(remain_bits,8-bit_pos);
138         work=work <<fetch_bits;
139         //work|=((working_byte>>bit_pos) & (0xFF>>(8-fetch_bits)));
140         work|=(working_byte &(0xFF>>(bit_pos)))>>(8-fetch_bits-bit_pos);
141         remain_bits-=fetch_bits;
142         bit_pos=(bit_pos+fetch_bits)%8;
143     }
144     return work;
145 }
146
147 UINT NALUUnit::getUe()
148 {
149     int leadbits=-1;
150     bool bit;
151     for( bit = 0; !bit && !eonalu; leadbits++ )
152         bit = getBits(1);
153     if (eonalu) return true;
154     return ((1 << leadbits)-1)+getBits(leadbits);
155 }
156
157 int NALUUnit::getSe()
158 {
159     UINT input=getUe();
160     if (input==0) return 0;
161     int output=((input+1)>>1);
162     if (input & 0x1) output*=-1;
163     return output;
164 }
165
166
167
168 static const int PESPacket_initial_size = 2000;
169
170 // PESPacket methods
171 PESPacket::PESPacket()
172 {
173   data_size = PESPacket_initial_size;
174   data = (UCHAR*)malloc(data_size);
175   data[0] = 0x00;
176   data[1] = 0x00;
177   data[2] = 0x01;
178   init(0);
179 }
180
181 PESPacket::PESPacket(const PESPacket& packet)
182 {
183   copyFrom(packet);
184 }
185
186 PESPacket& PESPacket::operator=(const PESPacket& packet)
187 {
188   if (this != &packet)
189   {
190     if (data) free(data);
191     copyFrom(packet);
192   }
193   return *this;
194 }
195
196 PESPacket::~PESPacket()
197 {
198   if (data) free(data);
199 }
200
201 void PESPacket::copyFrom(const PESPacket& packet)
202 {
203   length = packet.length;
204   size = packet.size;
205   packetType = packet.packetType;
206   substream = packet.substream;
207   seq_header = packet.seq_header;
208   data_size = size;
209   data = (UCHAR*)malloc(data_size);
210   memcpy(data, packet.data, data_size);
211 }
212
213 void PESPacket::init(UCHAR type, UCHAR sub)
214 {
215   length = 0; 
216   size = 6;
217   data[4] = data[5] = 0;
218   data[3] = type;
219   packetType = type;
220   substream = sub;
221   seq_header = 1; // Unknown seq_header status
222 }
223
224 void PESPacket::truncate()
225 {
226   init(packetType,substream);
227 }
228
229 int PESPacket::write(const UCHAR *buf, int len)
230 {
231   if (size + len > 0x10000) return 0;
232   if (size + len > data_size)
233   { // Reallocate
234     UINT new_data_size = max(data_size + data_size / 2, data_size + len);
235     if (new_data_size > 0x10000) new_data_size = 0x10000;
236     data_size = new_data_size;
237     data = (UCHAR*)realloc(data, data_size);
238   }
239   memcpy(data + size, buf, len);
240   length += len;
241   size += len;
242   data[4] = (length >> 8);
243   data[5] = (length & 0xFF);
244   // We have added data - reset seq_header indicator if necessary
245   if (seq_header == 0) seq_header = 1; // Reset to 'unknown'
246   return 1;
247 }
248
249 ULLONG PESPacket::getPTS() const
250 {
251   if ( ( (packetType >= Demuxer::PESTYPE_AUD0 &&
252           packetType <= Demuxer::PESTYPE_AUDMAX)
253          ||
254          (packetType >= Demuxer::PESTYPE_VID0 &&
255           packetType <= Demuxer::PESTYPE_VIDMAX)
256    ||
257           packetType == Demuxer::PESTYPE_PRIVATE_1
258        )
259        && size >= 14 && data[7] & 0x80)
260   {
261     return ( (ULLONG)(data[ 9] & 0x0E) << 29) |
262            ( (ULLONG)(data[10])        << 22 ) |
263            ( (ULLONG)(data[11] & 0xFE) << 14 ) |
264            ( (ULLONG)(data[12])        <<  7 ) |
265            ( (ULLONG)(data[13] & 0xFE) >>  1 );
266   }
267   else return PTS_INVALID;
268 }
269
270 UCHAR PESPacket::operator[] (UINT index) const
271 {
272   if (index >= size)
273     return 0;
274   else
275     return data[index];
276 }
277
278 UINT PESPacket::findPictureHeader(bool h264) const
279 {
280   if (size < 12) return 0;
281   UINT pattern = ( ((UINT)data[ 8] << 24) |
282                    ((UINT)data[ 9] << 16) |
283                    ((UINT)data[10] <<  8) |
284                     (UINT)data[11]  );
285   UINT pos = 11;
286   if (h264) {
287           
288           while (pattern != DEMUXER_H264_ACCESS_UNIT)
289           {
290                   if (++pos >= size) return 0;
291                   pattern = (pattern << 8) | data[pos];
292           }
293           return pos-3;
294   } else {
295           while (pattern != DEMUXER_PIC_HEAD)
296           {
297                   if (++pos >= size) return 0;
298                   pattern = (pattern << 8) | data[pos];
299           }
300           return pos-3;
301   }
302 }
303
304 UINT PESPacket::countPictureHeaders(bool h264) const
305 {
306   if (size < 12) return 0;
307   UINT pattern = ( ((UINT)data[ 8] << 24) |
308                    ((UINT)data[ 9] << 16) |
309                    ((UINT)data[10] <<  8) |
310                     (UINT)data[11]  );
311   UINT pos = 11;
312   UINT count=0;
313   if (h264) {
314           
315           while (pos<size)
316           {
317           pos++;
318                   pattern = (pattern << 8) | data[pos];
319           if (pattern==DEMUXER_H264_ACCESS_UNIT) count++;
320           }
321           return count;
322   } else {
323       while (pos<size)
324           {
325           pos++;
326                   pattern = (pattern << 8) | data[pos];
327           if (pattern==DEMUXER_PIC_HEAD) count++;
328           }
329           return count;
330   }
331 }
332
333 UINT PESPacket::findSeqHeader(bool h264) const
334 {
335   if (seq_header != 1) return seq_header;
336   if (size < 12) return 0;
337   UINT pattern = ( ((UINT)data[ 8] << 24) |
338                    ((UINT)data[ 9] << 16) |
339                    ((UINT)data[10] <<  8) |
340                     (UINT)data[11]  );
341   UINT pos = 11;
342   if (h264) {
343       while ((pattern & 0xFFFFFF1F) != DEMUXER_H264_SEQ_PARAMETER_SET)
344           {
345                   if (++pos >= size)
346                   {
347                           seq_header = 0;
348                           return 0;
349                   }
350                   pattern = (pattern << 8) | data[pos];
351           }
352           seq_header = pos - 3;
353   } 
354   else 
355   {
356           while (pattern != DEMUXER_SEQ_HEAD)
357           {
358                   if (++pos >= size)
359                   {
360                           seq_header = 0;
361                           return 0;
362                   }
363                   pattern = (pattern << 8) | data[pos];
364           }
365           seq_header = pos - 3;
366   }
367   return seq_header;
368 }
369
370 // Demuxer methods
371 Demuxer::Demuxer()
372 {
373   if (instance) return;
374   instance = this;
375   initted = false;
376   callback = NULL;
377   arcnt = 0;
378   vid_seeking = aud_seeking = false;
379   video_pts = audio_pts = 0;
380   ispre_1_3_19 = false;
381   packetnum=0;
382   h264 = false;
383   fps = 25.0;
384 }
385
386 Demuxer::~Demuxer()
387 {
388   shutdown();
389   instance = NULL;
390 }
391
392 Demuxer* Demuxer::getInstance()
393 {
394   return instance;
395 }
396
397 int Demuxer::init(Callback* tcallback, DrainTarget* audio, DrainTarget* video, DrainTarget* teletext,
398                   ULONG demuxMemoryV, ULONG demuxMemoryA, ULONG demuxMemoryT,double infps, DVBSubtitles* tsubtitles)
399 {
400   if (!initted)
401   {
402     if ( !videostream.init(video, demuxMemoryV) ||
403          !audiostream.init(audio, demuxMemoryA) ||
404          !teletextstream.init(teletext, demuxMemoryT))
405     {
406       Log::getInstance()->log("Demuxer", Log::CRIT,
407                               "Failed to initialize demuxer");
408       shutdown();
409       return 0;
410     }
411   }
412   if (teletext) {
413       isteletextdecoded = true;
414   } else {
415       isteletextdecoded = false;
416   }
417   fps=infps;
418   reset();
419   initted = true;
420   subtitles = tsubtitles;
421   callback = tcallback;
422   return 1;
423 }
424
425 void Demuxer::reset()
426 {
427   Log::getInstance()->log("Demuxer", Log::DEBUG, "Reset called");
428   flush();
429   video_current = audio_current = teletext_current = subtitle_current = -1;
430   horizontal_size = vertical_size = 0;
431   aspect_ratio = (enum AspectRatio) 0;
432   frame_rate = bit_rate = 0;
433   ispre_1_3_19 = false;
434   h264 = false;
435   packetnum=0;
436
437   for (int i = 0; i <= (PESTYPE_AUDMAX - PESTYPE_AUD0); i++)
438   {
439     avail_mpaudchan[i] = false;
440   }
441   for (int i = 0; i <= (PESTYPE_SUBSTREAM_AC3MAX - PESTYPE_SUBSTREAM_AC30); i++)
442   {
443     avail_ac3audchan[i] = false;
444   }
445   for (int i = 0; i <= (PESTYPE_SUBSTREAM_DVBSUBTITLEMAX - PESTYPE_SUBSTREAM_DVBSUBTITLE0); i++)
446   {
447     avail_dvbsubtitlechan[i] = false;
448   }
449 }
450
451 int Demuxer::shutdown()
452 {
453   videostream.shutdown();
454   audiostream.shutdown();
455   teletextstream.shutdown();
456   initted = false;
457   return 1;
458 }
459
460 void Demuxer::flush()
461 {
462   Log::getInstance()->log("Demuxer", Log::DEBUG, "Flush called");
463
464   videostream.flush();
465   audiostream.flush();
466   teletextstream.flush();
467 }
468
469 void Demuxer::flushAudio()
470 {
471   audiostream.flush();
472 }
473
474 void Demuxer::seek()
475 {
476   vid_seeking = aud_seeking = true;
477   video_pts = audio_pts = teletext_pts = 0;
478 }
479
480 void Demuxer::setAudioStream(int id)
481 {
482   audio_current = id;
483 }
484
485 void Demuxer::setVideoStream(int id)
486 {
487   video_current = id;
488 }
489
490 void Demuxer::setTeletextStream(int id)
491 {
492   teletext_current = id;
493 }
494
495 void Demuxer::setDVBSubtitleStream(int id)
496 {
497   subtitle_current = id;
498 }
499
500 void Demuxer::setAspectRatio(enum AspectRatio ar)
501 {
502   if (aspect_ratio != ar)
503   {
504     Log::getInstance()->log("Demux", Log::DEBUG,
505                             "Aspect ratio difference signalled");
506     if (++arcnt > 3) // avoid changing aspect ratio if glitch in signal
507     {
508       arcnt = 0;
509       aspect_ratio = ar;
510       if (callback) callback->call(this);
511     }
512   }
513   else
514     arcnt = 0;
515 }
516
517 bool Demuxer::writeAudio()
518 {
519   return audiostream.drain();
520 }
521
522 bool Demuxer::writeVideo()
523 {
524   return videostream.drain();
525 }
526
527 bool Demuxer::writeTeletext()
528 {
529    return teletextstream.drain();
530 }
531
532 bool Demuxer::submitPacket(PESPacket& packet)
533 {
534   UINT sent = 0;
535   UCHAR packet_type = packet.getPacketType();
536   const UCHAR* packetdata = packet.getData();
537   if (packet_type >= PESTYPE_VID0 && packet_type <= PESTYPE_VIDMAX)
538   {
539     if (video_current == -1) video_current = packet_type;
540     if (video_current == packet_type && !vid_seeking)
541         {
542         sent = videostream.put(&packetdata[0], packet.getSize(), h264?MPTYPE_VIDEO_H264:MPTYPE_VIDEO_MPEG2,packetnum);
543         if (sent) packetnum++;
544         }
545         else
546       sent = packet.getSize();
547   }
548   else if (packet_type >= PESTYPE_AUD0 && packet_type <= PESTYPE_AUDMAX)
549   {
550     if (audio_current == -1) audio_current = packet_type;
551     avail_mpaudchan[packet_type - PESTYPE_AUD0] = true;
552     if (audio_current == packet_type && !aud_seeking)
553         {
554       sent = audiostream.put(&packetdata[0], packet.getSize(), MPTYPE_MPEG_AUDIO,packetnum);
555           if (sent)  packetnum++;
556         }
557         else
558       sent = packet.getSize();
559   }
560   else if (packet_type == PESTYPE_PRIVATE_1 &&
561            packet.getSubstream() >= PESTYPE_SUBSTREAM_AC30 &&
562            packet.getSubstream() <= PESTYPE_SUBSTREAM_AC3MAX)
563   {
564     avail_ac3audchan[packet.getSubstream() - PESTYPE_SUBSTREAM_AC30] = true;
565     if (packet.getSubstream() == audio_current)
566     {
567       sent = audiostream.put(&packetdata[0], packet.getSize(), (ispre_1_3_19)? MPTYPE_AC3_PRE13 : MPTYPE_AC3,packetnum);
568           if (sent) packetnum++;
569     }
570     else
571     {
572       sent = packet.getSize();
573     }
574   }
575   else if (packet_type == PESTYPE_PRIVATE_1 &&
576            packet.getSubstream() >= PESTYPE_SUBSTREAM_DVBSUBTITLE0 &&
577            packet.getSubstream() <= PESTYPE_SUBSTREAM_DVBSUBTITLEMAX)
578   {
579     avail_dvbsubtitlechan[packet.getSubstream()-PESTYPE_SUBSTREAM_DVBSUBTITLE0]=true;
580     if (subtitle_current == -1) subtitle_current = packet.getSubstream();
581     if (subtitles && packet.getSubstream()==subtitle_current)
582     {
583          subtitles->put(packet);
584     }
585     sent = packet.getSize();
586   }
587   else if (isteletextdecoded  && packet_type == PESTYPE_PRIVATE_1 &&
588            packet.getSubstream() >= PESTYPE_SUBSTREAM_TELETEXT0 &&
589            packet.getSubstream() <= PESTYPE_SUBSTREAM_TELETEXTMAX)
590   {
591
592     if (teletext_current == -1) teletext_current = packet.getSubstream();
593     if (teletext_current == packet.getSubstream() )
594     {
595         sent = teletextstream.put(&packetdata[0], packet.getSize(), MPTYPE_TELETEXT,packetnum);
596     }
597     else 
598     {
599         sent = packet.getSize();
600     }
601   }
602   else
603   {
604     sent = packet.getSize();
605   }
606
607   if (sent < packet.getSize()) // Stream is full.
608     return false;
609   else
610     return true;
611 }
612
613 void Demuxer::parsePacketDetails(PESPacket& packet)
614 {
615     if (packet.getPacketType() >= PESTYPE_AUD0 &&
616         packet.getPacketType() <= PESTYPE_AUDMAX)
617     {
618         // Extract audio PTS if it exists
619         if (packet.hasPTS())
620         {
621             audio_pts = packet.getPTS();
622             // We continue to seek on the audio if the video PTS that we
623             // are trying to match is ahead of the audio PTS by at most
624             // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
625             if (aud_seeking && !vid_seeking &&
626                 !( (video_pts_seek > audio_pts &&
627                 video_pts_seek - audio_pts < SEEK_THRESHOLD)
628                 ||
629                 (video_pts_seek < audio_pts &&
630                 video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
631             {
632                 aud_seeking = 0;
633                 Log::getInstance()->log("Demuxer", Log::DEBUG,
634                     "Leaving  audio sync: Audio PTS = %llu", audio_pts);
635             }
636         }
637     }
638     else if (packet.getPacketType() == PESTYPE_PRIVATE_1) // Private stream
639     {
640         //Inspired by vdr's device.c
641         int payload_begin = packet[8]+9;
642         unsigned char substream_id = packet[payload_begin];
643         unsigned char substream_type = substream_id & 0xF0;
644         unsigned char substream_index = substream_id & 0x1F;
645 pre_1_3_19_Recording: //This is for old recordings stuff and live TV
646         if (ispre_1_3_19)
647         {
648             substream_id = PESTYPE_PRIVATE_1;
649             substream_type = 0x80;
650             substream_index = 0;
651         }
652         switch (substream_type)
653         {
654         case 0x20://SPU
655         case 0x30://SPU
656             packet.setSubstream(substream_id);
657             break;
658         case 0xA0: //LPCM //not supported yet, is there any LPCM transmissio out there?
659             break;
660         case 0x80: //ac3, currently only one ac3 track per recording supported
661             packet.setSubstream(substream_type+substream_index);
662
663             // Extract audio PTS if it exists
664             if (packet.hasPTS())
665             {
666                 audio_pts = packet.getPTS();
667                 // We continue to seek on the audio if the video PTS that we
668                 // are trying to match is ahead of the audio PTS by at most
669                 // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
670                 if (aud_seeking && !vid_seeking &&
671                     !( (video_pts_seek > audio_pts &&
672                     video_pts_seek - audio_pts < SEEK_THRESHOLD)
673                     ||
674                     (video_pts_seek < audio_pts &&
675                     video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
676                 {
677                     aud_seeking = 0;
678                     Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving  audio sync: Audio PTS = %llu", audio_pts);
679                 }
680             }
681             break;
682         case 0x10: //Teletext Is this correct?
683             packet.setSubstream(substream_id);
684             // Extract teletxt PTS if it exists
685             if (packet.hasPTS())
686             {
687                 teletext_pts = packet.getPTS();
688             }
689             break;
690         default:
691             if (!ispre_1_3_19)
692             {
693                 ispre_1_3_19=true; //switching to compat mode and live tv mode
694                 goto pre_1_3_19_Recording;
695             }
696             else
697             {
698                 packet.setSubstream(0);
699             }
700             break;
701         }
702     }
703     else if (packet.getPacketType() >= PESTYPE_VID0 &&
704         packet.getPacketType() <= PESTYPE_VIDMAX)
705     {
706         // Extract video PTS if it exists
707         if (packet.hasPTS()) video_pts = packet.getPTS();
708
709         // If there is a sequence header, extract information
710         UINT pos = packet.findSeqHeader(h264);
711         if (pos > 1)
712         {
713             if (!h264) {
714                 pos += 4;
715                 if (pos+6 >= packet.getSize()) return;
716                 horizontal_size = ((int)packet[pos] << 4) | ((int)packet[pos+1] >> 4);
717                 
718                 vertical_size = (((int)packet[pos+1] & 0xf) << 8) | (int)packet[pos+2];
719
720                 setAspectRatio((enum AspectRatio)(packet[pos+3] >> 4));
721                 frame_rate = packet[pos+3] & 0x0f;
722                 if (frame_rate >= 1 && frame_rate <= 8)
723                     frame_rate = FrameRates[frame_rate];
724                 else
725                     frame_rate = 0;
726                 bit_rate = ((int)packet[pos+4] << 10) |
727                     ((int)packet[pos+5] << 2) |
728                     ((int)packet[pos+6] >> 6);
729             } 
730             else
731             {
732                 /* Chris and Mark I know this is ugly, should we move this to a method  of PESPacket or to NALUUnit what would be better?
733                 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*/
734                 NALUUnit nalu(packet.getData()+pos,packet.getSize()-pos);
735                 profile=nalu.getBits(8);
736                 nalu.getBits(8); //constraints
737                 nalu.getBits(8); //level_idc
738                 nalu.getUe(); //seq_parameter_set_id
739                 int chroma=1;
740                 if (profile==100 || profile==110 || profile==122 || profile==144)
741                 {
742                     chroma=nalu.getUe();
743                     if (chroma==3)
744                     {
745                         nalu.getBits(1);
746                     }
747                     nalu.getUe(); //bit depth lume
748                     nalu.getUe(); //bit depth chrome
749                     nalu.getBits(1);
750                     if (nalu.getBits(1))
751                     {
752                         for (int i=0;i<8;i++){
753                             if (nalu.getBits(1))
754                             {
755                                 if (i<6)
756                                 {
757                                     UINT lastscale=8;
758                                     UINT nextscale=8;
759                                     for (int j=0;j<16;j++) {
760                                         if (nextscale!=0) {
761                                             UINT delta=nalu.getSe();
762                                             nextscale=(lastscale+delta+256)%256;
763                                         }
764                                         lastscale=(nextscale==0)?lastscale:nextscale;
765                                     }
766                                 }
767                                 else
768                                 {
769                                     UINT lastscale=8;
770                                     UINT nextscale=8;
771                                     for (int j=0;j<64;j++) {
772                                         if (nextscale!=0) {
773                                             UINT delta=nalu.getSe();
774                                             nextscale=(lastscale+delta+256)%256;
775                                         }
776                                         lastscale=(nextscale==0)?lastscale:nextscale;
777                                     }
778                                 }
779                             }
780                         }
781                     }
782                 }
783                 int chromunitx=1;
784                 int chromunity=1;
785                 switch (chroma) {
786                 case 0:
787                     chromunitx=chromunity=1; break;
788                 case 1:
789                     chromunitx=chromunity=2; break;
790                 case 2:
791                     chromunitx=2;chromunity=1; break;
792                 case 3:
793                     chromunitx=chromunity=1; break;
794                 };
795
796                 nalu.getUe(); //log2framenum
797                 UINT temp=nalu.getUe();
798                 if (temp==0) //pict order
799                     nalu.getUe();
800                 else if (temp==1) {
801                     nalu.getBits(1);
802                     nalu.getSe();
803                     nalu.getSe();
804                     UINT temp2=nalu.getUe();
805                     for (int i=0;i<temp2;i++)
806                         nalu.getSe();
807                 }
808                 nalu.getUe(); //Num refframes
809                 nalu.getBits(1);
810                 horizontal_size=(nalu.getUe()+1)*16;
811                 
812                 vertical_size=(nalu.getUe()+1)*16;
813                 int interlaced=nalu.getBits(1);
814                 vertical_size*=(2-interlaced);
815                 
816                 if (!interlaced) nalu.getBits(1);
817                 nalu.getBits(1);
818                 if (nalu.getBits(1))
819                 {
820                     horizontal_size-=nalu.getUe()*chromunitx;
821                     horizontal_size-=nalu.getUe()*chromunitx;
822                     vertical_size-=nalu.getUe()*(2-interlaced)*chromunity;
823                     vertical_size-=nalu.getUe()*(2-interlaced)*chromunity;
824                 }
825                 if (nalu.getBits(1))
826                 {
827                     if (nalu.getBits(1))
828                     {
829                         UINT aspectratioidc=nalu.getBits(8);
830                         bool hasaspect=false;
831                         const float aspects[]={1., 1./1.,12./11.,10./11.,16./11.,40./33.,
832                             24./11.,20./11.,32./11.,80./33.,18./11.,15./11.,64./33.,160./99.,4./3.,3./2.,2./1.};
833                       
834                         float aspectratio=((float) horizontal_size)/((float) vertical_size);
835                         if (aspectratioidc<=16) 
836                         {
837                             hasaspect=true;
838                             aspectratio*=aspects[aspectratioidc];
839                            
840                         }
841                         else if (aspectratioidc==255)
842                         {
843                             int t_sar_width=nalu.getBits(16);
844                             int t_sar_height=nalu.getBits(16);
845                             if (t_sar_width!=0 && t_sar_height!=0)
846                             {
847                                 hasaspect=true;
848                                 aspectratio*=((float)t_sar_width)/((float)t_sar_height);
849                             }
850                         }
851                         if (hasaspect)
852                         {
853                             if (fabs(aspectratio-16./9.)<0.1) setAspectRatio(ASPECT_16_9);
854                             else if (fabs(aspectratio-4./3.)<0.1) setAspectRatio(ASPECT_4_3);
855                         }
856                     }
857
858                 }
859
860             }
861            
862             if (vid_seeking)
863             {
864                 vid_seeking = 0;
865                 video_pts_seek = video_pts;
866                 Log::getInstance()->log("Demuxer", Log::DEBUG,
867                     "Entering audio sync: Video PTS = %llu", video_pts);
868                 Log::getInstance()->log("Demuxer", Log::DEBUG,
869                     "Entering audio sync: Audio PTS = %llu", audio_pts);
870             }
871             return;
872         } 
873     }
874 }
875
876 UINT Demuxer::stripAudio(UCHAR* buf, UINT len)
877 {
878   UINT read_pos = 0, write_pos = 0;
879   UINT pattern, packet_length;
880   if (len < 4) return 0;
881   pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
882   while (read_pos + 7 <= len)
883   {
884     pattern = ((pattern & 0xFFFFFF) << 8) | buf[read_pos+3];
885     if (pattern < (0x100|PESTYPE_VID0) || pattern > (0x100|PESTYPE_VIDMAX))
886       read_pos++;
887     else
888     {
889       packet_length = ((buf[read_pos+4] << 8) | (buf[read_pos+5])) + 6;
890       if (read_pos + packet_length > len)
891         read_pos = len;
892       else
893       {
894         if (read_pos != write_pos)
895           memmove(buf+write_pos, buf+read_pos, packet_length);
896         read_pos += packet_length;
897         write_pos += packet_length;
898         pattern = (buf[read_pos] << 16) | (buf[read_pos+1] << 8)
899                                         | (buf[read_pos+2]);
900       }
901     }
902   }
903   return write_pos;
904 }
905
906 bool Demuxer::scanForVideo(UCHAR* buf, UINT len, bool &ish264)
907 {
908   UINT pos = 3;
909   UINT pattern;
910   ish264=false;
911   if (len < 4) return false;
912   pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
913   while (pos < len)
914   {
915     pattern = ((pattern & 0xFFFFFF) << 8) | buf[pos++];
916     if (pattern >= (0x100|PESTYPE_VID0) && pattern <= (0x100|PESTYPE_VIDMAX))
917       return true;
918   }
919   return false;
920 }
921
922 bool* Demuxer::getmpAudioChannels()
923 {
924   return avail_mpaudchan;
925 }
926
927 bool* Demuxer::getac3AudioChannels()
928 {
929   return avail_ac3audchan;
930 }
931
932 bool* Demuxer::getSubtitleChannels()
933 {
934   return avail_dvbsubtitlechan;
935 }
936
937 int Demuxer::getselSubtitleChannel()
938 {
939   return subtitle_current;
940 }
941
942 int Demuxer::getselAudioChannel()
943 {
944   return audio_current;
945 }
946
947