2 Copyright 2006-2008 Mark Calderbank
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "demuxerts.h"
26 #define PTS_JUMP_MARGIN 10000
27 #define PTS_ALLOWANCE 90000
29 // TODO: PTS class to handle wrapping arithmetic & comparisons?
30 static ULLONG PTSDistance(ULLONG pts1, ULLONG pts2)
32 // Assume pts1, pts2 < 2^33; calculate shortest distance between
33 ULLONG ret = (pts1 > pts2) ? pts1 - pts2 : pts2 - pts1;
34 if (ret > (1LL<<32)) ret = (1LL<<33) - ret;
38 static ULLONG PTSDifference(ULLONG pts1, ULLONG pts2)
40 // Assume pts1, pts2 < 2^33; calculate pts1 - pts2
44 return (1LL<<33) + pts1 - pts2;
47 DemuxerTS::DemuxerTS(int p_vID, int p_aID, int p_subID, int p_tID)
49 vID = p_vID; vActive = false;
50 aID = p_aID; aActive = false;
51 subID = p_subID; subActive = false;
55 havechannelinfo=false;
58 void DemuxerTS::flush()
62 havechannelinfo=false;
64 vPacket.init(PESTYPE_VID0);
68 aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
72 aPacket.init(PESTYPE_AUD0);
75 subPacket.init(PESTYPE_PRIVATE_1);
76 tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
85 int DemuxerTS::scan(UCHAR *buf, int len)
90 return PESTYPE_PRIVATE_1;
97 void DemuxerTS::setVID(int p_vID)
100 vPacket.init(PESTYPE_VID0);
104 void DemuxerTS::setAID(int p_aID, int type)
111 aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
112 setAudioStream(PESTYPE_SUBSTREAM_AC30);
116 aPacket.init(PESTYPE_AUD0);
117 setAudioStream(PESTYPE_AUD0);
123 void DemuxerTS::setSubID(int p_subID)
126 subPacket.init(PESTYPE_PRIVATE_1);
131 void DemuxerTS::setTID(int p_tID)
134 tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
142 int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest)
146 while (len >= TS_SIZE)
148 if (*buf != TS_SIG) {buf++;len--; continue;}
150 //Pattern scanning won't work for ts
153 int datalen = TS_SIZE - 4;
154 int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
155 UCHAR payload = buf[1] & 0x40;
157 if (buf[3] & 0x20) // Adaptation field is present
158 datalen -= (buf[4] + 1);
160 UCHAR* curbuf =buf+ (TS_SIZE - datalen);
164 if (pid == 0x00) {//PAT, only take first program number, ignore the rest
165 int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);
166 if ((pmtpid >> 13) != 0x07)
168 Log::getInstance()->log("findPTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));
172 pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
176 } else if (pid == PMTPID) { //PMT
177 int sectionlength = ((*(curbuf+2) << 8) & 0x0F ) | *(buf+3);
178 //sectionlength += 4; //include header but subtract crc in the end...
179 int p = 13; //skip fixed part of pmt
180 while ( p < sectionlength) {
181 int streamtype = *(curbuf+p);
183 int foundpid = (*(curbuf+p)<< 8) | *(curbuf+p+1);
184 p += 2; //skip ES Pid
185 int eslength = ((*(curbuf+p) << 8) & 0x0F ) | *(curbuf+p+1);
186 p += 2; //skip ES length
187 if ((foundpid >> 13) != 0x07)
189 Log::getInstance()->log("findPTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
193 foundpid = foundpid & 0x1FFF; //clear upper 3 bits
195 if (streamtype==3 || streamtype ==4) {
199 p += eslength; //skip es descriptor
201 } else if (pid == scanaid) {
202 // UINT framelength = ((UINT)curbuf[4] << 8) | curbuf[5]; UNUSED?
204 if ( curbuf[7] & 0x80 ) // PTS_DTS_flags indicate that PTS is present
206 *dest = ( (ULLONG)(curbuf[9] & 0x0E) << 29 ) |
207 ( (ULLONG)(curbuf[10]) << 22 ) |
208 ( (ULLONG)(curbuf[11] & 0xFE) << 14 ) |
209 ( (ULLONG)(curbuf[12]) << 7 ) |
210 ( (ULLONG)(curbuf[13] & 0xFE) >> 1 );
222 void DemuxerTS::setFrameNum(ULONG frame)
224 frameCounting = true;
226 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "setFrameNum %d", frame);
229 void DemuxerTS::setPacketNum(ULONG npacket)
231 packetCounting = true;
232 packetNumber = npacket;
233 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "setPacketNum %d", npacket);
237 int DemuxerTS::put(UCHAR* buf, int len)
239 int ret = 0; // return number of bytes consumed
243 if (len >= TS_SIZE + 1 - partPacket)
244 { // Remainder of partial packet is available, plus one
245 memcpy(store+partPacket, buf, TS_SIZE - partPacket);
246 ret += TS_SIZE - partPacket;
247 buf += TS_SIZE - partPacket;
248 len -= TS_SIZE - partPacket;
249 partPacket = TS_SIZE;
251 { // Packet is properly terminated
252 int rc = processTS(store);
254 partPacket = 0; // Successfully processed
256 return ret; // Try again later.
259 { // Packet not terminated. Find another candidate, and shift store
260 Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
262 while (search < partPacket && store[search] != TS_SIG)
264 partPacket -= search;
265 if (partPacket) memcpy(store, store+search, partPacket);
269 { // Still don't have complete packet. Consume what we do have.
270 memcpy(store+partPacket, buf, len);
277 // Position ourselves at a candidate TS packet
278 while (len > 0 && *buf != TS_SIG)
280 Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
286 if (len < TS_SIZE + 1)
287 { // Not enough data. Store what we have.
288 memcpy(store, buf, len);
294 if (buf[TS_SIZE] != TS_SIG)
295 { // Not terminated correctly.
297 while (len > 0 && *buf != TS_SIG)
304 int rc = processTS(buf);
306 { // Successfully processed
307 buf += TS_SIZE; ret += TS_SIZE; len -= TS_SIZE;
310 { // Processing failed.
318 int DemuxerTS::processTS(UCHAR* buf)
320 int datalen = TS_SIZE - 4;
322 int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
323 UCHAR payload = buf[1] & 0x40;
325 if (buf[3] & 0x20) // Adaptation field is present
326 datalen -= (buf[4] + 1);
327 if (datalen < 0) // Error in stream TODO log this
329 if (datalen == 0) // Null packet
331 buf += (TS_SIZE - datalen);
336 if (pid == 0x00) {//PAT, only take first program number, ignore the rest
337 int pmtpid = (*(buf+11)<< 8) | *(buf+12);
338 if ((pmtpid >> 13) != 0x07)
340 Log::getInstance()->log("ProcessTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(buf+11),*(buf+12), (pmtpid >> 13));
344 pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
351 int sectionlength = ((*(buf+2) << 8) & 0x0F ) | *(buf+3);
352 //sectionlength += 4; //include header but subtract crc in the end...
353 int p = 13; //skip fixed part of pmt
354 Channel new_channelinfo;
355 new_channelinfo.numAPids=0;
356 new_channelinfo.numDPids=0;
357 new_channelinfo.numSPids=0;
358 new_channelinfo.number=0;
359 new_channelinfo.type=VDR::RADIO;
360 new_channelinfo.name=NULL;
361 new_channelinfo.tpid=0xFFFFF; //unused, check this
362 new_channelinfo.vpid=0xFFFFF; //unused, check this
363 new_channelinfo.index=0;
365 new_channelinfo.apids.clear();
366 new_channelinfo.dpids.clear();
367 new_channelinfo.spids.clear();
369 while ( p < sectionlength) {
370 int streamtype = *(buf+p);
372 int foundpid = (*(buf+p)<< 8) | *(buf+p+1);
373 p += 2; //skip ES Pid
374 int eslength = ((*(buf+p) << 8) & 0x0F ) | *(buf+p+1);
375 p += 2; //skip ES length
376 if ((foundpid >> 13) != 0x07)
378 Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
382 foundpid = foundpid & 0x1FFF; //clear upper 3 bits
385 // Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDPID is %x", foundpid);
388 case 0x1B: //MPEG 4 for future use
391 if (foundpid != getVID())
393 new_channelinfo.type=VDR::VIDEO;
394 new_channelinfo.vstreamtype=streamtype;
395 new_channelinfo.vpid=foundpid;
396 if (streamtype==0x1b) h264=true;
399 // Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set video PID to %x", foundpid);
404 newapid.pid = foundpid;
405 newapid.name = NULL; //set it in player
406 new_channelinfo.apids.push_back(newapid);
407 new_channelinfo.numAPids++;
408 if (getAID() == 0) { //set unset AID to first audio pid that reports itself
410 Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set audio PID to %x", foundpid);
414 case 6: { //Private Data
416 newapid.pid = foundpid;
417 newapid.name = NULL; //set it in player
421 while (pos< eslength && notfound) {
422 switch (buf[p+pos]) {
423 case 0x6A: {//Ac3 descriptor
424 new_channelinfo.dpids.push_back(newapid);
425 new_channelinfo.numDPids++;
428 case 0x59: {//SubtitlingDescriptor
429 new_channelinfo.spids.push_back(newapid);
430 new_channelinfo.numSPids++;
434 new_channelinfo.tpid=foundpid;
442 default://TODO how about subtitles and second audio pids
447 p += eslength; //skip es descriptor
451 bool audioPIDpresent=false; //Check if pids chnages
453 for (i=0;i<channelinfo.numAPids;i++) {
454 if (aID == (int)channelinfo.apids[i].pid) {
455 audioPIDpresent=true;
458 for (i=0;i<channelinfo.numDPids && (! audioPIDpresent);i++) {
459 if (aID == (int)channelinfo.dpids[i].pid) {
460 audioPIDpresent=true;
463 if (! audioPIDpresent) {
464 if (channelinfo.numAPids>0) {
465 setAID(channelinfo.apids[0].pid,0);
466 } else if (channelinfo.numDPids>0) {
467 setAID(channelinfo.dpids[0].pid,1);
471 channelinfo=new_channelinfo;
472 havechannelinfo=true;
486 parseTSPacketDetails(vPacket);
489 rc = submitPacket(vPacket);
499 parseTSPacketDetails(aPacket);
502 rc = submitPacket(aPacket);
512 parseTSPacketDetails(subPacket);
515 rc = submitPacket(subPacket);
519 if (isteletextdecoded && pid == tID)
525 parseTSPacketDetails(tPacket);
528 rc = submitPacket(tPacket);
532 if (rc == 0) return 0;
537 vPacket.init(PESTYPE_VID0);
538 buf += 6; datalen -= 6;
545 aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
549 aPacket.init(PESTYPE_AUD0);
552 buf += 6; datalen -= 6;
556 subPacket.init(PESTYPE_PRIVATE_1);
557 subLength = (buf[4] << 8) + buf[5];
558 buf += 6; datalen -= 6;
560 if (isteletextdecoded && pid == tID)
562 tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
563 buf += 6; datalen -= 6;
567 if ( (pid == vID && vActive) ||
568 (pid == aID && aActive) ||
569 (pid == tID && tActive) ||
570 (pid == subID && subActive) )
572 PESPacket* packet = NULL;
573 if (pid == vID) packet = &vPacket;
574 if (pid == aID) packet = &aPacket;
578 if (pid == tID) packet = &tPacket;
581 if (packet->write(buf, datalen) == 0)
582 { // Writing to packet failed. It has overflowed.
585 parseTSPacketDetails(*packet);
588 if (submitPacket(*packet) == 0) return 0;
591 packet->write((UCHAR*)"\200\000\000", 3);
592 packet->write(buf, datalen);
597 if (pid == subID && subActive && subPacket.getLength() == subLength)
599 parsePacketDetails(subPacket);
600 Log::getInstance()->log("DEMUXERTS", Log::DEBUG, "SUBMITTING A SUBTITLE PACKET %d %x", subLength, subPacket.getSubstream());
601 submitPacket(subPacket);
608 ULONG DemuxerTS::getPacketNum()
613 ULONG DemuxerTS::getFrameNumFromPTS(ULLONG pts)
615 ULLONG difference = (1LL<<33);
617 int total = 0, actual = 0;
618 pts_map_mutex.Lock();
619 PTSMap::iterator iter = pts_map.begin();
620 while (iter != pts_map.end())
623 if (PTSDifference(iter->pts, pts) < PTS_ALLOWANCE)
626 ref_frame = iter->frame;
630 ULLONG newdiff = PTSDifference(pts, iter->pts);
631 if (newdiff < difference)
633 difference = newdiff;
634 ref_frame = iter->frame;
639 if (total > 1 && actual == 1) // We are using the most recent PTS ref.
640 { // Delete the rest.
641 iter = pts_map.begin(); iter++;
642 pts_map.erase(iter, pts_map.end());
644 pts_map_mutex.Unlock();
646 if (difference == (1LL<<33))
647 return 0; // We cannot make sense of the pts
649 return ref_frame + difference * fps / 90000;
653 void DemuxerTS::parseTSPacketDetails(PESPacket &packet) // Only important stuff for paket counting reminas
655 parsePacketDetails(packet);
656 if (packetCounting && packet.getPacketType() >= PESTYPE_AUD0 &&
657 packet.getPacketType() <= PESTYPE_AUDMAX)
662 if (frameCounting && packet.findPictureHeader(h264) &&
663 packet.getPacketType() >= PESTYPE_VID0 &&
664 packet.getPacketType() <= PESTYPE_VIDMAX)
666 ULONG frame_num = (frameNumber)++;
667 if ((h264 || packet.findSeqHeader(h264) > 1) && packet.hasPTS())
670 pts_map_mutex.Lock();
673 me.pts = packet.getPTS();
674 me.frame = frame_num;
675 pts_map_mutex.Unlock();
676 pts_map_mutex.Lock();
677 pts_map.push_front(me);
679 me = pts_map.front();
680 pts_map_mutex.Unlock();
682 //UINT fps = Video::getInstance()->getFPS();
683 ULLONG pts_expected = me.pts + 90000*((int)(((double)(frame_num - me.frame)) / fps));
684 while (pts_expected > (1LL<<33)) pts_expected -= (1LL<<33);
686 if (PTSDistance(pts_expected, packet.getPTS()) > PTS_JUMP_MARGIN) // PTS jump!
688 me.pts = packet.getPTS();
689 me.frame = frame_num;
690 pts_map_mutex.Lock();
691 pts_map.push_front(me);
692 pts_map_mutex.Unlock();
699 bool DemuxerTS::scanForVideo(UCHAR* buf, UINT len, bool &ish264)
703 while (len >= TS_SIZE)
705 if (*buf != TS_SIG) {buf++;len--; continue;}
707 //Pattern scanning won't work for ts
710 int datalen = TS_SIZE - 4;
711 int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
712 UCHAR payload = buf[1] & 0x40;
714 if (buf[3] & 0x20) // Adaptation field is present
715 datalen -= (buf[4] + 1);
717 UCHAR* curbuf =buf+ (TS_SIZE - datalen);
720 if (pid == 0x00) {//PAT, only take first program number, ignore the rest
721 int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);
722 if ((pmtpid >> 13) != 0x07)
724 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));
728 pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
730 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "PMT pid%02x",pmtpid );
733 } else if (pid == pmtpidy) { //PMT
734 int sectionlength = ((*(curbuf+2) << 8) & 0x0F ) | *(buf+3);
735 //sectionlength += 4; //include header but subtract crc in the end...
736 int p = 13; //skip fixed part of pmt
737 while ( p < sectionlength) {
738 int streamtype = *(curbuf+p);
740 int foundpid = (*(curbuf+p)<< 8) | *(curbuf+p+1);
741 p += 2; //skip ES Pid
742 int eslength = ((*(curbuf+p) << 8) & 0x0F ) | *(curbuf+p+1);
743 p += 2; //skip ES length
744 if ((foundpid >> 13) != 0x07)
746 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
750 foundpid = foundpid & 0x1FFF; //clear upper 3 bits
751 // int pos=0; UNUSED?
752 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Pid found %02x type %02x",foundpid ,streamtype);
753 if (streamtype==1 || streamtype ==2) {
755 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Found Mpeg2 Video");
758 if (streamtype==0x1b) {
760 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Found h264 Video");
764 p += eslength; //skip es descriptor
777 UINT DemuxerTS::stripAudio(UCHAR* buf, UINT len) //it has to be adapted
779 //This function strips all TS Headers and non video payload
784 while (readpos < len ) {
785 if (buf[readpos] != TS_SIG) {readpos++; continue;}
786 UINT oldreadpos=readpos;
788 int datalen = TS_SIZE - 4;
789 int pid = ( (buf[readpos+1] & 0x1F) << 8 ) | buf[readpos+2];
790 UCHAR payload = buf[readpos+1] & 0x40;
791 if (buf[readpos+3] & 0x20) { // Adaptation field is present
792 datalen -= (buf[readpos+4] + 1);
794 if (datalen < 0) {// Error in stream TODO log this
797 if (datalen == 0) {// Null packet
798 readpos=oldreadpos+TS_SIZE;
801 readpos += (TS_SIZE - datalen);
802 UINT towrite=min(datalen,len-readpos);
806 parsePacketDetails(destpaket);
807 memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
808 writepos+=destpaket.getSize();
810 destpaket.init(PESTYPE_VID0);
811 readpos += 6; towrite -= 6;
816 if (!destpaket.write(buf+readpos,towrite)) {
817 parsePacketDetails(destpaket);
818 memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
819 writepos+=destpaket.getSize();
820 destpaket.truncate();
821 destpaket.write((UCHAR*)"\200\000\000", 3);
822 destpaket.write(buf+readpos,towrite);
830 readpos=oldreadpos+TS_SIZE;
832 parsePacketDetails(destpaket);
833 memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
834 writepos+=destpaket.getSize();