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;
56 doubledframerate=false;
60 void DemuxerTS::flush()
64 havechannelinfo=false;
66 vPacket.init(PESTYPE_VID0);
70 aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
74 aPacket.init(PESTYPE_AUD0);
77 subPacket.init(PESTYPE_PRIVATE_1);
78 tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
85 doubledframerate=false;
89 int DemuxerTS::scan(UCHAR *buf, int len)
94 return PESTYPE_PRIVATE_1;
101 void DemuxerTS::setVID(int p_vID)
104 vPacket.init(PESTYPE_VID0);
108 void DemuxerTS::setAID(int p_aID, int type)
115 aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
116 setAudioStream(PESTYPE_SUBSTREAM_AC30);
120 aPacket.init(PESTYPE_AUD0);
121 setAudioStream(PESTYPE_AUD0);
127 void DemuxerTS::setSubID(int p_subID)
130 subPacket.init(PESTYPE_PRIVATE_1);
135 void DemuxerTS::setTID(int p_tID)
138 tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
146 int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest)
150 while (len >= TS_SIZE)
152 if (*buf != TS_SIG) {buf++;len--; continue;}
154 //Pattern scanning won't work for ts
157 int datalen = TS_SIZE - 4;
158 int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
159 UCHAR payload = buf[1] & 0x40;
161 if (buf[3] & 0x20) // Adaptation field is present
162 datalen -= (buf[4] + 1);
164 UCHAR* curbuf =buf+ (TS_SIZE - datalen);
168 if (pid == 0x00) {//PAT, only take first program number, ignore the rest
169 int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);
170 if ((pmtpid >> 13) != 0x07)
172 Log::getInstance()->log("findPTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));
176 pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
180 } else if (pid == PMTPID) { //PMT
181 int sectionlength = ((*(curbuf+2) << 8) & 0x0F ) | *(buf+3);
182 //sectionlength += 4; //include header but subtract crc in the end...
183 int p = 13; //skip fixed part of pmt
184 while ( p < sectionlength) {
185 int streamtype = *(curbuf+p);
187 int foundpid = (*(curbuf+p)<< 8) | *(curbuf+p+1);
188 p += 2; //skip ES Pid
189 int eslength = ((*(curbuf+p) << 8) & 0x0F ) | *(curbuf+p+1);
190 p += 2; //skip ES length
191 if ((foundpid >> 13) != 0x07)
193 Log::getInstance()->log("findPTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
197 foundpid = foundpid & 0x1FFF; //clear upper 3 bits
199 if (streamtype==3 || streamtype ==4) {
203 p += eslength; //skip es descriptor
205 } else if (pid == scanaid) {
206 // UINT framelength = ((UINT)curbuf[4] << 8) | curbuf[5]; UNUSED?
208 if ( curbuf[7] & 0x80 ) // PTS_DTS_flags indicate that PTS is present
210 *dest = ( (ULLONG)(curbuf[9] & 0x0E) << 29 ) |
211 ( (ULLONG)(curbuf[10]) << 22 ) |
212 ( (ULLONG)(curbuf[11] & 0xFE) << 14 ) |
213 ( (ULLONG)(curbuf[12]) << 7 ) |
214 ( (ULLONG)(curbuf[13] & 0xFE) >> 1 );
226 void DemuxerTS::setFrameNum(ULONG frame)
228 frameCounting = true;
231 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "setFrameNum %d", frame);
234 void DemuxerTS::setPacketNum(ULONG npacket)
236 packetCounting = true;
237 packetNumber = npacket;
238 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "setPacketNum %d", npacket);
242 int DemuxerTS::put(UCHAR* buf, int len)
244 int ret = 0; // return number of bytes consumed
248 if (len >= TS_SIZE + 1 - partPacket)
249 { // Remainder of partial packet is available, plus one
250 memcpy(store+partPacket, buf, TS_SIZE - partPacket);
251 ret += TS_SIZE - partPacket;
252 buf += TS_SIZE - partPacket;
253 len -= TS_SIZE - partPacket;
254 partPacket = TS_SIZE;
256 { // Packet is properly terminated
257 int rc = processTS(store);
259 partPacket = 0; // Successfully processed
261 return ret; // Try again later.
264 { // Packet not terminated. Find another candidate, and shift store
265 Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
267 while (search < partPacket && store[search] != TS_SIG)
269 partPacket -= search;
270 if (partPacket) memcpy(store, store+search, partPacket);
274 { // Still don't have complete packet. Consume what we do have.
275 memcpy(store+partPacket, buf, len);
282 // Position ourselves at a candidate TS packet
283 while (len > 0 && *buf != TS_SIG)
285 Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
291 if (len < TS_SIZE + 1)
292 { // Not enough data. Store what we have.
293 memcpy(store, buf, len);
299 if (buf[TS_SIZE] != TS_SIG)
300 { // Not terminated correctly.
302 while (len > 0 && *buf != TS_SIG)
309 int rc = processTS(buf);
311 { // Successfully processed
312 buf += TS_SIZE; ret += TS_SIZE; len -= TS_SIZE;
315 { // Processing failed.
323 int DemuxerTS::processTS(UCHAR* buf)
325 int datalen = TS_SIZE - 4;
327 int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
328 UCHAR payload = buf[1] & 0x40;
330 if (buf[3] & 0x20) // Adaptation field is present
331 datalen -= (buf[4] + 1);
332 if (datalen < 0) // Error in stream TODO log this
334 if (datalen == 0) // Null packet
336 buf += (TS_SIZE - datalen);
341 if (pid == 0x00) {//PAT, only take first program number, ignore the rest
342 int pmtpid = (*(buf+11)<< 8) | *(buf+12);
343 if ((pmtpid >> 13) != 0x07)
345 Log::getInstance()->log("ProcessTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(buf+11),*(buf+12), (pmtpid >> 13));
349 pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
356 int sectionlength = ((*(buf+2) << 8) & 0x0F ) | *(buf+3);
357 //sectionlength += 4; //include header but subtract crc in the end...
358 int p = 13; //skip fixed part of pmt
359 Channel new_channelinfo;
360 new_channelinfo.numAPids=0;
361 new_channelinfo.numDPids=0;
362 new_channelinfo.numSPids=0;
363 new_channelinfo.number=0;
364 new_channelinfo.type=VDR::RADIO;
365 new_channelinfo.name=NULL;
366 new_channelinfo.tpid=0xFFFFF; //unused, check this
367 new_channelinfo.vpid=0xFFFFF; //unused, check this
368 new_channelinfo.index=0;
370 new_channelinfo.apids.clear();
371 new_channelinfo.dpids.clear();
372 new_channelinfo.spids.clear();
374 while ( p < sectionlength) {
375 int streamtype = *(buf+p);
377 int foundpid = (*(buf+p)<< 8) | *(buf+p+1);
378 p += 2; //skip ES Pid
379 int eslength = ((*(buf+p) << 8) & 0x0F ) | *(buf+p+1);
380 p += 2; //skip ES length
381 if ((foundpid >> 13) != 0x07)
383 Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
387 foundpid = foundpid & 0x1FFF; //clear upper 3 bits
390 // Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDPID is %x", foundpid);
393 case 0x1B: //MPEG 4 for future use
396 if (foundpid != getVID())
398 new_channelinfo.type=VDR::VIDEO;
399 new_channelinfo.vstreamtype=streamtype;
400 new_channelinfo.vpid=foundpid;
401 if (streamtype==0x1b) h264=true;
404 // Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set video PID to %x", foundpid);
409 newapid.pid = foundpid;
410 newapid.name = NULL; //set it in player
411 new_channelinfo.apids.push_back(newapid);
412 new_channelinfo.numAPids++;
413 if (getAID() == 0) { //set unset AID to first audio pid that reports itself
415 Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set audio PID to %x", foundpid);
419 case 6: { //Private Data
421 newapid.pid = foundpid;
422 newapid.name = NULL; //set it in player
426 while (pos< eslength && notfound) {
427 switch (buf[p+pos]) {
428 case 0x6A: {//Ac3 descriptor
429 new_channelinfo.dpids.push_back(newapid);
430 new_channelinfo.numDPids++;
433 case 0x59: {//SubtitlingDescriptor
434 new_channelinfo.spids.push_back(newapid);
435 new_channelinfo.numSPids++;
439 new_channelinfo.tpid=foundpid;
447 default://TODO how about subtitles and second audio pids
452 p += eslength; //skip es descriptor
456 bool audioPIDpresent=false; //Check if pids chnages
458 for (i=0;i<channelinfo.numAPids;i++) {
459 if (aID == (int)channelinfo.apids[i].pid) {
460 audioPIDpresent=true;
463 for (i=0;i<channelinfo.numDPids && (! audioPIDpresent);i++) {
464 if (aID == (int)channelinfo.dpids[i].pid) {
465 audioPIDpresent=true;
468 if (! audioPIDpresent) {
469 if (channelinfo.numAPids>0) {
470 setAID(channelinfo.apids[0].pid,0);
471 } else if (channelinfo.numDPids>0) {
472 setAID(channelinfo.dpids[0].pid,1);
476 channelinfo=new_channelinfo;
477 havechannelinfo=true;
491 parseTSPacketDetails(vPacket);
494 rc = submitPacket(vPacket);
504 parseTSPacketDetails(aPacket);
507 rc = submitPacket(aPacket);
517 parseTSPacketDetails(subPacket);
520 rc = submitPacket(subPacket);
524 if (isteletextdecoded && pid == tID)
530 parseTSPacketDetails(tPacket);
533 rc = submitPacket(tPacket);
537 if (rc == 0) return 0;
542 vPacket.init(PESTYPE_VID0);
543 buf += 6; datalen -= 6;
550 aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
554 aPacket.init(PESTYPE_AUD0);
557 buf += 6; datalen -= 6;
561 subPacket.init(PESTYPE_PRIVATE_1);
562 subLength = (buf[4] << 8) + buf[5];
563 buf += 6; datalen -= 6;
565 if (isteletextdecoded && pid == tID)
567 tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
568 buf += 6; datalen -= 6;
572 if ( (pid == vID && vActive) ||
573 (pid == aID && aActive) ||
574 (pid == tID && tActive) ||
575 (pid == subID && subActive) )
577 PESPacket* packet = NULL;
578 if (pid == vID) packet = &vPacket;
579 if (pid == aID) packet = &aPacket;
583 if (pid == tID) packet = &tPacket;
586 if (packet->write(buf, datalen) == 0)
587 { // Writing to packet failed. It has overflowed.
590 parseTSPacketDetails(*packet);
593 if (submitPacket(*packet) == 0) return 0;
596 packet->write((UCHAR*)"\200\000\000", 3);
597 packet->write(buf, datalen);
602 if (pid == subID && subActive && subPacket.getLength() == subLength)
604 parsePacketDetails(subPacket);
605 Log::getInstance()->log("DEMUXERTS", Log::DEBUG, "SUBMITTING A SUBTITLE PACKET %d %x", subLength, subPacket.getSubstream());
606 submitPacket(subPacket);
613 ULONG DemuxerTS::getPacketNum()
618 ULONG DemuxerTS::getFrameNumFromPTS(ULLONG pts)
620 ULLONG difference = (1LL<<33);
622 int total = 0, actual = 0;
623 if (pts==0) return 0; //we are in startup
624 pts_map_mutex.Lock();
625 PTSMap::iterator iter = pts_map.begin();
626 while (iter != pts_map.end())
629 //Log::getInstance()->log("DemuxerTS", Log::DEBUG, "getFrameNumfromPTS pts1 %lld pts2 %lld", pts, iter->pts);
630 if (PTSDifference(iter->pts, pts) < PTS_ALLOWANCE)
633 ref_frame = iter->frame;
637 ULLONG newdiff = PTSDifference(pts, iter->pts);
638 if (newdiff < difference)
640 difference = newdiff;
641 ref_frame = iter->frame;
646 if (total > 1 && actual == 1) // We are using the most recent PTS ref.
647 { // Delete the rest.
648 iter = pts_map.begin(); iter++;
649 pts_map.erase(iter, pts_map.end());
651 pts_map_mutex.Unlock();
653 //Log::getInstance()->log("DemuxerTS", Log::DEBUG, "getFrameNumfromPTS pts %lld deleted %d difference %lld", pts, total,difference);
655 if (difference == (1LL<<33))
656 return 0; // We cannot make sense of the pts
658 return ref_frame + difference * fps / 90000;
662 void DemuxerTS::parseTSPacketDetails(PESPacket &packet) // Only important stuff for paket counting reminas
664 parsePacketDetails(packet);
665 if (packetCounting && packet.getPacketType() >= PESTYPE_AUD0 &&
666 packet.getPacketType() <= PESTYPE_AUDMAX)
670 UINT pictsinpacket=packet.countPictureHeaders(h264);
673 if (!doubledframerate)
675 numpicts=pictsinpacket;
679 numpicts=(pictsinpacket+framereserve)>>1;
680 framereserve=(pictsinpacket+framereserve)%2;
684 if (frameCounting && numpicts &&
685 packet.getPacketType() >= PESTYPE_VID0 &&
686 packet.getPacketType() <= PESTYPE_VIDMAX)
688 frameNumber+=numpicts;
689 ULONG frame_num = frameNumber;
690 if ((h264 || packet.findSeqHeader(h264) > 1) && packet.hasPTS())
693 pts_map_mutex.Lock();
696 me.pts = packet.getPTS();
697 me.frame = frame_num;
698 pts_map_mutex.Unlock();
699 pts_map_mutex.Lock();
700 pts_map.push_front(me);
702 me = pts_map.front();
703 pts_map_mutex.Unlock();
705 //UINT fps = Video::getInstance()->getFPS();
707 if (doubledframerate) tfps*=2.;
708 ULLONG pts_expected = me.pts + 90000*((int)(((double)(frame_num - me.frame)) / tfps));
709 while (pts_expected > (1LL<<33)) pts_expected -= (1LL<<33);
711 if (!doubledframerate
712 &&(abs((long long)PTSDistance(pts_expected, packet.getPTS())-1800) <= 1
713 || abs((long long)PTSDistance(pts_expected, packet.getPTS())-1501) <= 1)) {
714 doubledframerate=true; //Detected p50 or p60
717 if (PTSDistance(pts_expected, packet.getPTS()) > PTS_JUMP_MARGIN) // PTS jump!
719 me.pts = packet.getPTS();
720 me.frame = frame_num;
721 pts_map_mutex.Lock();
722 pts_map.push_front(me);
723 pts_map_mutex.Unlock();
730 bool DemuxerTS::scanForVideo(UCHAR* buf, UINT len, bool &ish264)
734 while (len >= TS_SIZE)
736 if (*buf != TS_SIG) {buf++;len--; continue;}
738 //Pattern scanning won't work for ts
741 int datalen = TS_SIZE - 4;
742 int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
743 UCHAR payload = buf[1] & 0x40;
745 if (buf[3] & 0x20) // Adaptation field is present
746 datalen -= (buf[4] + 1);
748 UCHAR* curbuf =buf+ (TS_SIZE - datalen);
751 if (pid == 0x00) {//PAT, only take first program number, ignore the rest
752 int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);
753 if ((pmtpid >> 13) != 0x07)
755 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));
759 pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
761 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "PMT pid%02x",pmtpid );
764 } else if (pid == pmtpidy) { //PMT
765 int sectionlength = ((*(curbuf+2) << 8) & 0x0F ) | *(buf+3);
766 //sectionlength += 4; //include header but subtract crc in the end...
767 int p = 13; //skip fixed part of pmt
768 while ( p < sectionlength) {
769 int streamtype = *(curbuf+p);
771 int foundpid = (*(curbuf+p)<< 8) | *(curbuf+p+1);
772 p += 2; //skip ES Pid
773 int eslength = ((*(curbuf+p) << 8) & 0x0F ) | *(curbuf+p+1);
774 p += 2; //skip ES length
775 if ((foundpid >> 13) != 0x07)
777 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
781 foundpid = foundpid & 0x1FFF; //clear upper 3 bits
782 // int pos=0; UNUSED?
783 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Pid found %02x type %02x",foundpid ,streamtype);
784 if (streamtype==1 || streamtype ==2) {
786 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Found Mpeg2 Video");
789 if (streamtype==0x1b) {
791 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Found h264 Video");
795 p += eslength; //skip es descriptor
808 UINT DemuxerTS::stripAudio(UCHAR* buf, UINT len) //it has to be adapted
810 //This function strips all TS Headers and non video payload
815 while (readpos < len ) {
816 if (buf[readpos] != TS_SIG) {readpos++; continue;}
817 UINT oldreadpos=readpos;
819 int datalen = TS_SIZE - 4;
820 int pid = ( (buf[readpos+1] & 0x1F) << 8 ) | buf[readpos+2];
821 UCHAR payload = buf[readpos+1] & 0x40;
822 if (buf[readpos+3] & 0x20) { // Adaptation field is present
823 datalen -= (buf[readpos+4] + 1);
825 if (datalen < 0) {// Error in stream TODO log this
828 if (datalen == 0) {// Null packet
829 readpos=oldreadpos+TS_SIZE;
832 readpos += (TS_SIZE - datalen);
833 UINT towrite=min(datalen,len-readpos);
837 parsePacketDetails(destpaket);
838 memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
839 writepos+=destpaket.getSize();
841 destpaket.init(PESTYPE_VID0);
842 readpos += 6; towrite -= 6;
847 if (!destpaket.write(buf+readpos,towrite)) {
848 parsePacketDetails(destpaket);
849 memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
850 writepos+=destpaket.getSize();
851 destpaket.truncate();
852 destpaket.write((UCHAR*)"\200\000\000", 3);
853 destpaket.write(buf+readpos,towrite);
861 readpos=oldreadpos+TS_SIZE;
863 parsePacketDetails(destpaket);
864 memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
865 writepos+=destpaket.getSize();