2 Copyright 2005-2008 Mark Calderbank
3 Copyright 2007 Marten Richter (AC3 support)
5 This file is part of VOMP.
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.
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.
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.
25 #include "dvbsubtitles.h"
32 #define DEMUXER_SEQ_HEAD 0x000001B3
33 #define DEMUXER_PIC_HEAD 0x00000101
34 #define DEMUXER_SEQ_EXT_HEAD 0x000001B5
36 #define DEMUXER_H264_ACCESS_UNIT 0x00000109
37 #define DEMUXER_H264_SEQ_PARAMETER_SET 0x00000107
38 #define DEMUXER_H264_SUB_ENHANCEMENT_INF 0x00000106
41 #define SEEK_THRESHOLD 150000 // About 1.5 seconds
44 const int Demuxer::FrameRates[9] = { 0, 23, 24, 25, 29, 30, 50, 59, 60 };
45 Demuxer* Demuxer::instance = NULL;
49 NALUUnit(const UCHAR* buf,UINT length_buf);
52 inline UINT getBits(UINT num_bits);
55 bool isEonalu() {return eonalu;};
67 NALUUnit::NALUUnit(const UCHAR *buf, UINT length_buf)
79 UINT pattern =(((UINT)buf[ 0] << 16) |
83 while (pattern != 0x000001)
85 if (++nalu_start >= length_buf) return;
86 pattern = ((pattern << 8) | buf[nalu_start])&0x00FFFFFF;
88 nalu_end=nalu_start+1;
89 pattern = ((pattern << 8) | buf[nalu_end])&0x00FFFFFF;
91 while (pattern != 0x000001 && pattern != 0x000000)
93 if (++nalu_end >= length_buf) { nalu_end+=3;break;};
94 pattern = ((pattern << 8) | buf[nalu_end])&0x00FFFFFF;
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);
104 NALUUnit::~NALUUnit()
106 if (nalu_buf) free(nalu_buf);
109 inline UINT NALUUnit::getBits(UINT num_bits)
111 if (num_bits==0) return 0; //???
112 UINT remain_bits=num_bits;
114 //May be slow, but should work!
115 while (remain_bits>0) {
119 last_bytes=(last_bytes<<8) & nalu_buf[pos];
120 if ((last_bytes & 0x00FFFFFF) == 0x000003) pos++; //emulation prevention byte
123 working_byte=nalu_buf[pos];
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;
149 UINT NALUUnit::getUe()
153 for( bit = 0; !bit && !eonalu; leadbits++ )
155 if (eonalu) return true;
156 return ((1 << leadbits)-1)+getBits(leadbits);
159 int NALUUnit::getSe()
162 if (input==0) return 0;
163 int output=((input+1)>>1);
164 if (input & 0x1) output*=-1;
170 static const int PESPacket_initial_size = 2000;
173 PESPacket::PESPacket()
175 data_size = PESPacket_initial_size;
176 data = (UCHAR*)malloc(data_size);
183 PESPacket::PESPacket(const PESPacket& packet)
188 PESPacket& PESPacket::operator=(const PESPacket& packet)
192 if (data) free(data);
198 PESPacket::~PESPacket()
200 if (data) free(data);
203 void PESPacket::copyFrom(const PESPacket& packet)
205 length = packet.length;
207 packetType = packet.packetType;
208 substream = packet.substream;
209 seq_header = packet.seq_header;
211 data = (UCHAR*)malloc(data_size);
212 memcpy(data, packet.data, data_size);
215 void PESPacket::init(UCHAR type, UCHAR sub)
219 data[4] = data[5] = 0;
223 seq_header = 1; // Unknown seq_header status
227 void PESPacket::truncate()
229 init(packetType,substream);
234 int PESPacket::write(const UCHAR *buf, int len)
238 if (size + len > 0x10000) return 0;
239 if (size + len > data_size)
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);
246 memcpy(data + size, buf, 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'
256 ULLONG PESPacket::getPTS() const
258 if ( ( (packetType >= Demuxer::PESTYPE_AUD0 &&
259 packetType <= Demuxer::PESTYPE_AUDMAX)
261 (packetType >= Demuxer::PESTYPE_VID0 &&
262 packetType <= Demuxer::PESTYPE_VIDMAX)
264 packetType == Demuxer::PESTYPE_PRIVATE_1
266 && size >= 14 && data[7] & 0x80)
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 );
274 else return PTS_INVALID;
277 UCHAR PESPacket::operator[] (UINT index) const
285 UINT PESPacket::findPictureHeader(bool h264) const
287 if (size < 12) return 0;
288 UINT pattern = ( ((UINT)data[ 8] << 24) |
289 ((UINT)data[ 9] << 16) |
290 ((UINT)data[10] << 8) |
295 while (pattern != DEMUXER_H264_ACCESS_UNIT)
297 if (++pos >= size) return 0;
298 pattern = (pattern << 8) | data[pos];
302 while (pattern != DEMUXER_PIC_HEAD)
304 if (++pos >= size) return 0;
305 pattern = (pattern << 8) | data[pos];
311 UINT PESPacket::countPictureHeaders(bool h264) const
313 if (size < 12) return 0;
314 UINT pattern = ( ((UINT)data[ 8] << 24) |
315 ((UINT)data[ 9] << 16) |
316 ((UINT)data[10] << 8) |
325 pattern = (pattern << 8) | data[pos];
326 if (pattern==DEMUXER_H264_ACCESS_UNIT) count++;
333 pattern = (pattern << 8) | data[pos];
334 if (pattern==DEMUXER_PIC_HEAD) count++;
340 UINT PESPacket::findSeqHeader(bool h264) const
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) |
350 while ((pattern & 0xFFFFFF1F) != DEMUXER_H264_SEQ_PARAMETER_SET)
357 pattern = (pattern << 8) | data[pos];
359 seq_header = pos - 3;
363 while (pattern != DEMUXER_SEQ_HEAD)
370 pattern = (pattern << 8) | data[pos];
372 seq_header = pos - 3;
377 UINT PESPacket::findSeqExtHeader(bool h264) const
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) |
387 while ((pattern & 0xFFFFFF1F) != DEMUXER_H264_SUB_ENHANCEMENT_INF)
394 pattern = (pattern << 8) | data[pos];
396 seq_header = pos - 3;
400 while (pattern != DEMUXER_SEQ_EXT_HEAD && (data[pos+1]&0xf0)!=0x10)
402 if (++pos >= (size-1))
407 pattern = (pattern << 8) | data[pos];
409 seq_header = pos - 3;
417 if (instance) return;
422 vid_seeking = aud_seeking = false;
423 video_pts = audio_pts = 0;
424 ispre_1_3_19 = false;
437 Demuxer* Demuxer::getInstance()
442 int Demuxer::init(Callback* tcallback, DrainTarget* audio, DrainTarget* video, DrainTarget* teletext,
443 ULONG demuxMemoryV, ULONG demuxMemoryA, ULONG demuxMemoryT,double infps, DVBSubtitles* tsubtitles)
447 if ( !videostream.init(video, demuxMemoryV) ||
448 !audiostream.init(audio, demuxMemoryA) ||
449 !teletextstream.init(teletext, demuxMemoryT))
451 Log::getInstance()->log("Demuxer", Log::CRIT,
452 "Failed to initialize demuxer");
458 isteletextdecoded = true;
460 isteletextdecoded = false;
465 subtitles = tsubtitles;
466 callback = tcallback;
470 void Demuxer::reset()
472 Log::getInstance()->log("Demuxer", Log::DEBUG, "Reset called");
474 video_current = audio_current = teletext_current = subtitle_current = -1;
475 horizontal_size = vertical_size = 0;
476 interlaced=true; // default is true
477 aspect_ratio = (enum AspectRatio) 0;
478 frame_rate = bit_rate = 0;
479 ispre_1_3_19 = false;
484 for (int i = 0; i <= (PESTYPE_AUDMAX - PESTYPE_AUD0); i++)
486 avail_mpaudchan[i] = false;
488 for (int i = 0; i <= (PESTYPE_SUBSTREAM_AC3MAX - PESTYPE_SUBSTREAM_AC30); i++)
490 avail_ac3audchan[i] = false;
492 for (int i = 0; i <= (PESTYPE_SUBSTREAM_DVBSUBTITLEMAX - PESTYPE_SUBSTREAM_DVBSUBTITLE0); i++)
494 avail_dvbsubtitlechan[i] = false;
498 int Demuxer::shutdown()
500 videostream.shutdown();
501 audiostream.shutdown();
502 teletextstream.shutdown();
507 void Demuxer::flush()
509 Log::getInstance()->log("Demuxer", Log::DEBUG, "Flush called");
513 teletextstream.flush();
516 void Demuxer::flushAudio()
523 vid_seeking = aud_seeking = true;
524 video_pts = audio_pts = teletext_pts = 0;
527 void Demuxer::setAudioStream(int id)
532 void Demuxer::setVideoStream(int id)
537 void Demuxer::setTeletextStream(int id)
539 teletext_current = id;
542 void Demuxer::setDVBSubtitleStream(int id)
544 subtitle_current = id;
547 void Demuxer::setAspectRatio(enum AspectRatio ar)
549 if (aspect_ratio != ar)
551 Log::getInstance()->log("Demux", Log::DEBUG,
552 "Aspect ratio difference signalled");
553 if (++arcnt > 3) // avoid changing aspect ratio if glitch in signal
557 if (callback) callback->call(this);
564 bool Demuxer::writeAudio(bool * dataavail)
566 return audiostream.drain(dataavail);
569 bool Demuxer::writeVideo(bool * dataavail)
571 return videostream.drain(dataavail);
574 bool Demuxer::writeTeletext(bool * dataavail)
576 return teletextstream.drain(dataavail);
579 bool Demuxer::submitPacket(PESPacket& packet)
582 UCHAR packet_type = packet.getPacketType();
583 const UCHAR* packetdata = packet.getData();
584 if (packet_type >= PESTYPE_VID0 && packet_type <= PESTYPE_VIDMAX)
586 if (video_current == -1) video_current = packet_type;
587 if (video_current == packet_type && !vid_seeking)
589 sent = videostream.put(&packetdata[0], packet.getSize(), h264?MPTYPE_VIDEO_H264:MPTYPE_VIDEO_MPEG2,packetnum);
590 if (sent) packetnum++;
593 sent = packet.getSize();
595 else if (packet_type >= PESTYPE_AUD0 && packet_type <= PESTYPE_AUDMAX)
598 if (audio_current == -1) audio_current = packet_type;
599 avail_mpaudchan[packet_type - PESTYPE_AUD0] = true;
600 if (audio_current == packet_type && !aud_seeking)
602 UCHAR type=MPTYPE_MPEG_AUDIO;
607 type=MPTYPE_MPEG_AUDIO; break;
609 type=MPTYPE_AAC_LATM; break;
611 sent = audiostream.put(&packetdata[0], packet.getSize(), type,packetnum);
612 if (sent) packetnum++;
615 sent = packet.getSize();
617 else if (packet_type == PESTYPE_PRIVATE_1 &&
618 packet.getSubstream() >= PESTYPE_SUBSTREAM_AC30 &&
619 packet.getSubstream() <= PESTYPE_SUBSTREAM_AC3MAX)
621 avail_ac3audchan[packet.getSubstream() - PESTYPE_SUBSTREAM_AC30] = true;
622 if (packet.getSubstream() == audio_current)
624 sent = audiostream.put(&packetdata[0], packet.getSize(), (ispre_1_3_19)? MPTYPE_AC3_PRE13 : MPTYPE_AC3,packetnum);
625 if (sent) packetnum++;
629 sent = packet.getSize();
632 else if (packet_type == PESTYPE_PRIVATE_1 &&
633 packet.getSubstream() >= PESTYPE_SUBSTREAM_DVBSUBTITLE0 &&
634 packet.getSubstream() <= PESTYPE_SUBSTREAM_DVBSUBTITLEMAX)
636 avail_dvbsubtitlechan[packet.getSubstream()-PESTYPE_SUBSTREAM_DVBSUBTITLE0]=true;
637 if (subtitle_current == -1) subtitle_current = packet.getSubstream();
638 if (subtitles && packet.getSubstream()==subtitle_current)
640 subtitles->put(packet);
642 sent = packet.getSize();
644 else if (isteletextdecoded && packet_type == PESTYPE_PRIVATE_1 &&
645 packet.getSubstream() >= PESTYPE_SUBSTREAM_TELETEXT0 &&
646 packet.getSubstream() <= PESTYPE_SUBSTREAM_TELETEXTMAX)
649 if (teletext_current == -1) teletext_current = packet.getSubstream();
650 if (teletext_current == packet.getSubstream())
652 sent = teletextstream.put(&packetdata[0], packet.getSize(), MPTYPE_TELETEXT,packetnum);
656 sent = packet.getSize();
661 sent = packet.getSize();
664 if (sent < packet.getSize()) // Stream is full.
670 void Demuxer::parsePacketDetails(PESPacket& packet)
672 if (packet.getPacketType() >= PESTYPE_AUD0 &&
673 packet.getPacketType() <= PESTYPE_AUDMAX)
675 // Extract audio PTS if it exists
678 audio_pts = packet.getPTS();
679 // We continue to seek on the audio if the video PTS that we
680 // are trying to match is ahead of the audio PTS by at most
681 // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
682 if (aud_seeking && !vid_seeking &&
683 !( (video_pts_seek > audio_pts &&
684 video_pts_seek - audio_pts < SEEK_THRESHOLD)
686 (video_pts_seek < audio_pts &&
687 video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
690 Log::getInstance()->log("Demuxer", Log::DEBUG,
691 "Leaving audio sync: Audio PTS = %llu", audio_pts);
695 else if (packet.getPacketType() == PESTYPE_PRIVATE_1) // Private stream
697 //Inspired by vdr's device.c
698 int payload_begin = packet[8]+9;
699 unsigned char substream_id = packet[payload_begin];
700 unsigned char substream_type = substream_id & 0xF0;
701 unsigned char substream_index = substream_id & 0x1F;
702 pre_1_3_19_Recording: //This is for old recordings stuff and live TV
705 int old_substream=packet.getSubstream();
706 if (old_substream){ //someone else already set it, this is live tv
707 substream_id = old_substream;
708 substream_type = substream_id & 0xF0;
709 substream_index = substream_id & 0x1F;
711 substream_id = PESTYPE_PRIVATE_1;
712 substream_type = 0x80;
717 switch (substream_type)
721 packet.setSubstream(substream_id);
723 case 0xA0: //LPCM //not supported yet, is there any LPCM transmissio out there?
725 case 0x80: //ac3, currently only one ac3 track per recording supported
726 packet.setSubstream(substream_type+substream_index);
728 // Extract audio PTS if it exists
731 audio_pts = packet.getPTS();
732 // We continue to seek on the audio if the video PTS that we
733 // are trying to match is ahead of the audio PTS by at most
734 // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
735 if (aud_seeking && !vid_seeking &&
736 !( (video_pts_seek > audio_pts &&
737 video_pts_seek - audio_pts < SEEK_THRESHOLD)
739 (video_pts_seek < audio_pts &&
740 video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
743 Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving audio sync: Audio PTS = %llu", audio_pts);
747 case 0x10: //Teletext Is this correct?
748 packet.setSubstream(substream_id);
749 // Extract teletxt PTS if it exists
752 teletext_pts = packet.getPTS();
758 ispre_1_3_19=true; //switching to compat mode and live tv mode
759 goto pre_1_3_19_Recording;
763 packet.setSubstream(0);
768 else if (packet.getPacketType() >= PESTYPE_VID0 &&
769 packet.getPacketType() <= PESTYPE_VIDMAX)
771 // Extract video PTS if it exists
772 if (packet.hasPTS()) video_pts = packet.getPTS();
774 // If there is a sequence header, extract information
775 UINT pos = packet.findSeqHeader(h264);
780 if (pos+6 >= packet.getSize()) return;
781 horizontal_size = ((int)packet[pos] << 4) | ((int)packet[pos+1] >> 4);
783 vertical_size = (((int)packet[pos+1] & 0xf) << 8) | (int)packet[pos+2];
785 setAspectRatio((enum AspectRatio)(packet[pos+3] >> 4));
786 frame_rate = packet[pos+3] & 0x0f;
787 if (frame_rate >= 1 && frame_rate <= 8)
788 frame_rate = FrameRates[frame_rate];
791 bit_rate = ((int)packet[pos+4] << 10) |
792 ((int)packet[pos+5] << 2) |
793 ((int)packet[pos+6] >> 6);
797 /* Chris and Mark I know this is ugly, should we move this to a method of PESPacket or to NALUUnit what would be better?
798 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*/
799 NALUUnit nalu(packet.getData()+pos,packet.getSize()-pos);
800 profile=nalu.getBits(8);
801 nalu.getBits(8); //constraints
802 nalu.getBits(8); //level_idc
803 nalu.getUe(); //seq_parameter_set_id
805 if (profile==100 || profile==110 || profile==122 || profile==144)
812 nalu.getUe(); //bit depth lume
813 nalu.getUe(); //bit depth chrome
817 for (int i=0;i<8;i++){
824 for (int j=0;j<16;j++) {
826 UINT delta=nalu.getSe();
827 nextscale=(lastscale+delta+256)%256;
829 lastscale=(nextscale==0)?lastscale:nextscale;
836 for (int j=0;j<64;j++) {
838 UINT delta=nalu.getSe();
839 nextscale=(lastscale+delta+256)%256;
841 lastscale=(nextscale==0)?lastscale:nextscale;
852 chromunitx=chromunity=1; break;
854 chromunitx=chromunity=2; break;
856 chromunitx=2;chromunity=1; break;
858 chromunitx=chromunity=1; break;
861 nalu.getUe(); //log2framenum
862 UINT temp=nalu.getUe();
863 if (temp==0) //pict order
869 UINT temp2=nalu.getUe();
870 for (int i=0;i<temp2;i++)
873 nalu.getUe(); //Num refframes
875 horizontal_size=(nalu.getUe()+1)*16;
877 vertical_size=(nalu.getUe()+1)*16;
878 int tinterlaced=nalu.getBits(1);
879 vertical_size*=(2-tinterlaced);
880 interlaced=!tinterlaced;
882 if (!tinterlaced) nalu.getBits(1);
886 horizontal_size-=nalu.getUe()*chromunitx;
887 horizontal_size-=nalu.getUe()*chromunitx;
888 vertical_size-=nalu.getUe()*(2-tinterlaced)*chromunity;
889 vertical_size-=nalu.getUe()*(2-tinterlaced)*chromunity;
895 UINT aspectratioidc=nalu.getBits(8);
896 bool hasaspect=false;
897 const float aspects[]={1., 1./1.,12./11.,10./11.,16./11.,40./33.,
898 24./11.,20./11.,32./11.,80./33.,18./11.,15./11.,64./33.,160./99.,4./3.,3./2.,2./1.};
900 float aspectratio=((float) horizontal_size)/((float) vertical_size);
901 if (aspectratioidc<=16)
904 aspectratio*=aspects[aspectratioidc];
907 else if (aspectratioidc==255)
909 int t_sar_width=nalu.getBits(16);
910 int t_sar_height=nalu.getBits(16);
911 if (t_sar_width!=0 && t_sar_height!=0)
914 aspectratio*=((float)t_sar_width)/((float)t_sar_height);
919 if (fabs(aspectratio-16./9.)<0.1) setAspectRatio(ASPECT_16_9);
920 else if (fabs(aspectratio-4./3.)<0.1) setAspectRatio(ASPECT_4_3);
927 UINT posext = packet.findSeqExtHeader(h264);
930 interlaced=!(packet[pos+1] & 0x08); //really simple
931 // if more than full hd is coming we need to add additional parsers here
933 /* NALUUnit nalu(packet.getData()+posext,packet.getSize()-posext);
934 while (!nalu.isEonalu()) {
935 unsigned int payloadtype=0;
936 unsigned int payloadadd=0xFF;
937 while (payloadadd==0xFF && !nalu.isEonalu()) {
938 payloadadd=nalu.getBits(8);
939 payloadtype+=payloadadd;
941 unsigned int payloadsize=0;
943 while (payloadadd==0xFF && !nalu.isEonalu()) {
944 payloadadd=nalu.getBits(8);
945 payloadsize+=payloadadd;
947 switch (payloadtype) {
948 case 1: { // picture timing SEI
952 while (payloadsize) { // not handled skip
970 video_pts_seek = video_pts;
971 Log::getInstance()->log("Demuxer", Log::DEBUG,
972 "Entering audio sync: Video PTS = %llu", video_pts);
973 Log::getInstance()->log("Demuxer", Log::DEBUG,
974 "Entering audio sync: Audio PTS = %llu", audio_pts);
981 UINT Demuxer::stripAudio(UCHAR* buf, UINT len)
983 UINT read_pos = 0, write_pos = 0;
984 UINT pattern, packet_length;
985 if (len < 4) return 0;
986 pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
987 while (read_pos + 7 <= len)
989 pattern = ((pattern & 0xFFFFFF) << 8) | buf[read_pos+3];
990 if (pattern < (0x100|PESTYPE_VID0) || pattern > (0x100|PESTYPE_VIDMAX))
994 packet_length = ((buf[read_pos+4] << 8) | (buf[read_pos+5])) + 6;
995 if (read_pos + packet_length > len)
999 if (read_pos != write_pos)
1000 memmove(buf+write_pos, buf+read_pos, packet_length);
1001 read_pos += packet_length;
1002 write_pos += packet_length;
1003 pattern = (buf[read_pos] << 16) | (buf[read_pos+1] << 8)
1004 | (buf[read_pos+2]);
1011 void Demuxer::changeTimes(UCHAR* buf, UINT len,UINT playtime)
1013 UINT pattern, packet_length;
1015 if (len < 4) return;
1016 pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
1017 while (read_pos + 7 <= len)
1019 pattern = ((pattern & 0xFFFFFF) << 8) | buf[read_pos+3];
1020 if (pattern < (0x100|PESTYPE_VID0) || pattern > (0x100|PESTYPE_VIDMAX))
1024 packet_length = ((buf[read_pos+4] << 8) | (buf[read_pos+5])) + 6;
1025 // ok we have a packet figure out if pts and dts are present and replace them
1026 if (read_pos + 19 > len) return;
1027 ULLONG new_ts=playtime*90; //play time is on ms so multiply it by 90
1028 if (buf[read_pos+7] & 0x80) { // pts is here, replace it
1029 buf[read_pos+9]=0x21 | (( new_ts>>29)& 0xde );
1030 buf[read_pos+10]=0x00 |(( new_ts>>22)& 0xff );
1031 buf[read_pos+11]=0x01 | (( new_ts>>14)& 0xfe );
1032 buf[read_pos+12]=0x00 | (( new_ts>>7)& 0xff );
1033 buf[read_pos+13]=0x01 | (( new_ts<<1)& 0xfe );
1036 if (buf[read_pos+7] & 0x40) { // pts is here, replace it
1037 buf[read_pos+14]=0x21 | (( new_ts>>29)& 0xde );
1038 buf[read_pos+15]=0x00 | (( new_ts>>22)& 0xff );
1039 buf[read_pos+16]=0x01 | (( new_ts>>14)& 0xfe );
1040 buf[read_pos+17]=0x00 | (( new_ts>>7)& 0xff );
1041 buf[read_pos+18]=0x01 | (( new_ts<<1)& 0xfe );
1043 read_pos += packet_length;
1044 pattern = (buf[read_pos] << 16) | (buf[read_pos+1] << 8)
1045 | (buf[read_pos+2]);
1051 bool Demuxer::scanForVideo(UCHAR* buf, UINT len, bool &ish264)
1056 if (len < 4) return false;
1057 pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
1060 pattern = ((pattern & 0xFFFFFF) << 8) | buf[pos++];
1061 if (pattern >= (0x100|PESTYPE_VID0) && pattern <= (0x100|PESTYPE_VIDMAX))
1067 bool* Demuxer::getmpAudioChannels()
1069 return avail_mpaudchan;
1072 bool* Demuxer::getac3AudioChannels()
1074 return avail_ac3audchan;
1077 bool* Demuxer::getSubtitleChannels()
1079 return avail_dvbsubtitlechan;
1082 int Demuxer::getselSubtitleChannel()
1084 return subtitle_current;
1087 int Demuxer::getselAudioChannel()
1089 return audio_current;