]> git.vomp.tv Git - vompclient-marten.git/commitdiff
Fix bug in pts_expected (Thanks to hondansx for spotting this)
authorMarten Richter <marten.richter@freenet.de>
Mon, 5 Nov 2012 07:30:39 +0000 (08:30 +0100)
committerMarten Richter <marten.richter@freenet.de>
Mon, 5 Nov 2012 07:30:39 +0000 (08:30 +0100)
demuxerts.cc

index 97ab760b40ebef47c8b6e5a8470bc2d3c8763f4a..70375b4a476bac3db744810f0c56253acfc1cd30 100644 (file)
-/*\r
-    Copyright 2006-2008 Mark Calderbank\r
-\r
-    This file is part of VOMP.\r
-\r
-    VOMP is free software; you can redistribute it and/or modify\r
-    it under the terms of the GNU General Public License as published by\r
-    the Free Software Foundation; either version 2 of the License, or\r
-    (at your option) any later version.\r
-\r
-    VOMP is distributed in the hope that it will be useful,\r
-    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-    GNU General Public License for more details.\r
-\r
-    You should have received a copy of the GNU General Public License\r
-    along with VOMP; if not, write to the Free Software Foundation, Inc.,\r
-    51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
-*/\r
-\r
-#include "demuxerts.h"\r
-#include "log.h"\r
-#include "video.h"\r
-#include "vdr.h"\r
-#include "audio.h"\r
-\r
-#define PTS_JUMP_MARGIN   10000\r
-#define PTS_ALLOWANCE 90000\r
-\r
-// TODO: PTS class to handle wrapping arithmetic & comparisons?\r
-static ULLONG PTSDistance(ULLONG pts1, ULLONG pts2)\r
-{\r
-  // Assume pts1, pts2 < 2^33; calculate shortest distance between\r
-  ULLONG ret = (pts1 > pts2) ? pts1 - pts2 : pts2 - pts1;\r
-  if (ret > (1LL<<32)) ret = (1LL<<33) - ret;\r
-  return ret;\r
-}\r
-\r
-static ULLONG PTSDifference(ULLONG pts1, ULLONG pts2)\r
-{\r
-  // Assume pts1, pts2 < 2^33; calculate pts1 - pts2\r
-  if (pts1 > pts2)\r
-    return pts1 - pts2;\r
-  else\r
-    return (1LL<<33) + pts1 - pts2;\r
-}\r
-\r
-DemuxerTS::DemuxerTS(int p_vID, int p_aID, int p_subID, int p_tID)\r
-{\r
-  vID = p_vID; vActive = false;\r
-  aID = p_aID; aActive = false;\r
-  subID = p_subID; subActive = false;\r
-  atype = 0;\r
-  subLength = 0;\r
-  tID = p_tID;\r
-  havechannelinfo=false;\r
-  //doubledframerate=false;\r
-  framereserve=0;\r
-}\r
-\r
-void DemuxerTS::flush()\r
-{\r
-  partPacket = 0;\r
-  parsed = false;\r
-  havechannelinfo=false;\r
-  Demuxer::flush();\r
-  vPacket.init(PESTYPE_VID0);\r
-  switch (atype)\r
-  {\r
-  case 1:\r
-    aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);\r
-    break;\r
-  default:\r
-  case 0:\r
-    aPacket.init(PESTYPE_AUD0);\r
-    break;\r
-  }\r
-  subPacket.init(PESTYPE_PRIVATE_1);\r
-tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);\r
-\r
-  vActive = false;\r
-  aActive = false;\r
-  subActive = false;\r
-  subLength = 0;\r
-  tActive = false;\r
- // doubledframerate=false;\r
-  framereserve=0;\r
-}\r
-\r
-int DemuxerTS::scan(UCHAR *buf, int len)\r
-{\r
-  switch (atype)\r
-  {\r
-  case 1:\r
-    return PESTYPE_PRIVATE_1;\r
-  default:\r
-  case 0:\r
-    return PESTYPE_AUD0;\r
-  }\r
-}\r
-\r
-void DemuxerTS::setVID(int p_vID)\r
-{\r
-  vID = p_vID;\r
-  vPacket.init(PESTYPE_VID0);\r
-  vActive = false;\r
-}\r
-\r
-void DemuxerTS::setAID(int p_aID, int type, int streamtype)\r
-{\r
-  aID = p_aID;\r
-  atype = type;\r
-  astreamtype = streamtype;\r
-  switch (atype)\r
-  {\r
-  case 1:\r
-    aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);\r
-    setAudioStream(PESTYPE_SUBSTREAM_AC30);\r
-    break;\r
-  default:\r
-  case 0:\r
-    aPacket.init(PESTYPE_AUD0);\r
-    setAudioStream(PESTYPE_AUD0);\r
-    break;\r
-  }\r
-  aActive = false;\r
-}\r
-\r
-void DemuxerTS::setSubID(int p_subID)\r
-{\r
-  subID = p_subID;\r
-  subPacket.init(PESTYPE_PRIVATE_1);\r
-  subActive = false;\r
-  subLength = 0;\r
-}\r
-\r
-void DemuxerTS::setTID(int p_tID)\r
-{\r
-  tID = p_tID;\r
-  tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);\r
-  tActive = false;\r
-\r
-}\r
-\r
-\r
-\r
-\r
-int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest)\r
-{\r
-  int scanaid=0;\r
-\r
-  while (len >= TS_SIZE)\r
-  {\r
-      if (*buf != TS_SIG) {buf++;len--; continue;} \r
-\r
-    //Pattern scanning won't work for ts\r
-\r
-      \r
-      int datalen = TS_SIZE - 4;\r
-      int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];\r
-      UCHAR payload = buf[1] & 0x40;\r
-      \r
-      if (buf[3] & 0x20) // Adaptation field is present\r
-          datalen -= (buf[4] + 1);\r
-\r
-      UCHAR* curbuf =buf+ (TS_SIZE - datalen);\r
-     \r
-\r
-      if (payload) {\r
-          if (pid == 0x00) {//PAT, only take first program number, ignore the rest\r
-              int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);\r
-              if ((pmtpid >> 13) != 0x07) \r
-              {\r
-                  Log::getInstance()->log("findPTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));\r
-              } \r
-              else \r
-              {\r
-                  pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits\r
-                  PMTPID = pmtpid;\r
-              }\r
-          \r
-          } else if (pid == PMTPID) { //PMT\r
-              int sectionlength = ((*(curbuf+2) << 8) & 0x0F ) | *(buf+3);\r
-              //sectionlength += 4; //include header but subtract crc in the end...\r
-              int p = 13; //skip fixed part of pmt\r
-              while ( p < sectionlength) {\r
-                  int streamtype = *(curbuf+p);\r
-                  p++;\r
-                  int foundpid = (*(curbuf+p)<< 8) | *(curbuf+p+1);\r
-                  p += 2; //skip ES Pid\r
-                  int eslength = ((*(curbuf+p) << 8) & 0x0F ) | *(curbuf+p+1);\r
-                  p += 2; //skip ES length\r
-                  if ((foundpid >> 13) != 0x07)\r
-                  {\r
-                      Log::getInstance()->log("findPTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));\r
-                  }\r
-                  else \r
-                  {\r
-                      foundpid = foundpid & 0x1FFF; //clear upper 3 bits\r
-                      //int pos=0; UNUSED?\r
-                      if (streamtype==3 || streamtype ==4) {\r
-                          scanaid=foundpid;\r
-                      }\r
-                  }\r
-                  p += eslength; //skip es descriptor\r
-              }\r
-          } else if (pid == scanaid) {     \r
-           //   UINT framelength = ((UINT)curbuf[4] << 8) | curbuf[5];  UNUSED?\r
-              \r
-              if ( curbuf[7] & 0x80 ) // PTS_DTS_flags indicate that PTS is present\r
-              {\r
-                  *dest = ( (ULLONG)(curbuf[9] & 0x0E) << 29 ) |\r
-                  ( (ULLONG)(curbuf[10])        << 22 ) |\r
-                  ( (ULLONG)(curbuf[11] & 0xFE) << 14 ) |\r
-                  ( (ULLONG)(curbuf[12])        <<  7 ) |\r
-                  ( (ULLONG)(curbuf[13] & 0xFE) >>  1 );\r
-                  return 1;\r
-              }\r
-          }\r
-      }\r
-      len-=TS_SIZE;\r
-      buf+=TS_SIZE;\r
-  }\r
-  // No PTS found.\r
-  return 0;\r
-}\r
-\r
-void DemuxerTS::setFrameNum(ULONG frame)\r
-{\r
-  frameCounting = true;\r
-  frameNumber = frame;\r
-  framereserve=0;\r
-  Log::getInstance()->log("DemuxerTS", Log::DEBUG, "setFrameNum %d", frame);\r
-}\r
-\r
-void DemuxerTS::setPacketNum(ULONG npacket)\r
-{\r
-  packetCounting = true;\r
-  packetNumber = npacket;\r
-  Log::getInstance()->log("DemuxerTS", Log::DEBUG, "setPacketNum %d", npacket);\r
-}\r
-\r
-int DemuxerTS::put(UCHAR* buf, int len)\r
-{\r
-  int ret = 0;    // return number of bytes consumed\r
-\r
-  bool misaligned_mess=false;\r
-  while (partPacket)\r
-  {\r
-    if (len >= TS_SIZE + 1 - partPacket)\r
-    { // Remainder of partial packet is available, plus one\r
-      memcpy(store+partPacket, buf, TS_SIZE - partPacket);\r
-      ret += TS_SIZE - partPacket;\r
-      buf += TS_SIZE - partPacket;\r
-      len -= TS_SIZE - partPacket;\r
-      partPacket = TS_SIZE;\r
-      if (*buf == TS_SIG)\r
-      { // Packet is properly terminated\r
-        int rc = processTS(store);\r
-        if (rc)\r
-          partPacket = 0; // Successfully processed\r
-        else\r
-          return ret;     // Try again later.\r
-      }\r
-      else\r
-      { // Packet not terminated. Find another candidate, and shift store\r
-        if (!misaligned_mess) {\r
-               Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!A");\r
-               misaligned_mess=true; // do not alarm more than once\r
-        }\r
-        int search = 1;\r
-        while (search < partPacket && store[search] != TS_SIG)\r
-          search++;\r
-        partPacket -= search;\r
-        if (partPacket) memcpy(store, store+search, partPacket);\r
-      }\r
-    }\r
-    else\r
-    { // Still don't have complete packet. Consume what we do have.\r
-      memcpy(store+partPacket, buf, len);\r
-      partPacket += len;\r
-      ret += len;\r
-      return ret;\r
-    }\r
-  }\r
-\r
-  // Position ourselves at a candidate TS packet\r
-  while (len > 0 && *buf != TS_SIG)\r
-  {\r
-         if (!misaligned_mess) {\r
-                 Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!B");\r
-             misaligned_mess=true; // do not alarm more than once\r
-          }\r
-    buf++; ret++; len--;\r
-  }\r
-\r
-  while (len)\r
-  {\r
-    if (len < TS_SIZE + 1)\r
-    { // Not enough data. Store what we have.\r
-      memcpy(store, buf, len);\r
-      partPacket = len;\r
-      ret += len;\r
-      return ret;\r
-    }\r
-\r
-    if (buf[TS_SIZE] != TS_SIG)\r
-    { // Not terminated correctly.\r
-      buf++; ret++; len--;\r
-      while (len > 0 && *buf != TS_SIG)\r
-      {\r
-        buf++; ret++; len--;\r
-      }\r
-    }\r
-    else\r
-    {\r
-      int rc = processTS(buf);\r
-      if (rc)\r
-      { // Successfully processed\r
-        buf += TS_SIZE; ret += TS_SIZE; len -= TS_SIZE;\r
-      }\r
-      else\r
-      { // Processing failed.\r
-        return ret;\r
-      }\r
-    }\r
-  }\r
-  return ret;\r
-}\r
-\r
-\r
-int DemuxerTS::processTS(UCHAR* buf)\r
-{\r
-  int datalen = TS_SIZE - 4;\r
-\r
-  int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];\r
-  UCHAR payload = buf[1] & 0x40;\r
-\r
-\r
-  if (buf[3] & 0x20) // Adaptation field is present\r
-    datalen -= (buf[4] + 1);\r
-  if (datalen < 0) // Error in stream TODO log this\r
-    return 1;\r
-  if (datalen == 0) // Null packet\r
-    return 1;\r
- // if (!(buf[3] &0x10)) return 1; // no payload\r
-  buf += (TS_SIZE - datalen);\r
-\r
-  if (payload)\r
-  {\r
-      int rc = 1;\r
-      if (pid == 0x00) {//PAT, only take first program number, ignore the rest\r
-          int pmtpid = (*(buf+11)<< 8) | *(buf+12);\r
-          if ((pmtpid >> 13) != 0x07) \r
-          {\r
-              Log::getInstance()->log("ProcessTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(buf+11),*(buf+12), (pmtpid >> 13));\r
-          } \r
-          else \r
-          {\r
-              pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits\r
-              PMTPID = pmtpid;\r
-          }\r
-           return 1;\r
-    }\r
-    if (pid == PMTPID) \r
-    { //PMT\r
-        int sectionlength = ((*(buf+2) << 8) & 0x0F ) | *(buf+3);\r
-        //sectionlength += 4; //include header but subtract crc in the end...\r
-        int p = 13; //skip fixed part of pmt\r
-        Channel new_channelinfo;\r
-        new_channelinfo.numAPids=0;\r
-        new_channelinfo.numDPids=0;\r
-        new_channelinfo.numSPids=0;\r
-        new_channelinfo.number=0;\r
-        new_channelinfo.type=VDR::RADIO;\r
-        new_channelinfo.name=NULL;\r
-        new_channelinfo.tpid=0xFFFFF; //unused, check this\r
-        new_channelinfo.vpid=0xFFFFF; //unused, check this\r
-        new_channelinfo.index=0;\r
-\r
-        new_channelinfo.apids.clear();\r
-        new_channelinfo.dpids.clear();\r
-        new_channelinfo.spids.clear();\r
-        \r
-        while ( p < sectionlength) {\r
-            int streamtype = *(buf+p);\r
-            p++;\r
-            int foundpid = (*(buf+p)<< 8) | *(buf+p+1);\r
-            p += 2; //skip ES Pid\r
-            int eslength = ((*(buf+p) << 8) & 0x0F ) | *(buf+p+1);\r
-            p += 2; //skip ES length\r
-            if ((foundpid >> 13) != 0x07)\r
-            {\r
-              Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));\r
-            }\r
-            else \r
-            {\r
-                foundpid = foundpid & 0x1FFF; //clear upper 3 bits\r
-                bool notfound=false;\r
-                bool nolang=true;\r
-                int pos=0;\r
-           // Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDPID is %x %x", foundpid,streamtype);\r
-                switch (streamtype)\r
-                {\r
-                case 0x1B: //MPEG 4 for future use\r
-                case 1:\r
-                case 2: { //video\r
-                    if (foundpid != getVID())  \r
-                        setVID(foundpid);\r
-                    new_channelinfo.type=VDR::VIDEO;\r
-                                       new_channelinfo.vstreamtype=streamtype;\r
-                    new_channelinfo.vpid=foundpid;\r
-                                       if (streamtype==0x1b) h264=true;\r
-                                       else h264=false;\r
-\r
-                //  Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set video PID to %x", foundpid);\r
-                        }break;\r
-                case 0x0F: //AAC ADTS packaging\r
-                case 0x11: // LATM packaging\r
-                case 3:\r
-                case 4: { //audio\r
-                    apid newapid;\r
-                    newapid.pid = foundpid;\r
-                    newapid.desc[0]=0;\r
-                    newapid.type=streamtype;\r
-                    pos=0;\r
-                    nolang=true;\r
-                    while (pos< eslength && nolang) {\r
-                       switch (buf[p+pos]) {\r
-                       case 0x0A: {\r
-                               newapid.desc[0]=buf[p+pos+2];\r
-                               newapid.desc[1]=buf[p+pos+3];\r
-                               newapid.desc[2]=buf[p+pos+4];\r
-                               newapid.desc[3]=0;\r
-                               nolang=false;\r
-                    //         Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDLANG is %s", newapid.desc);\r
-                       } break;\r
-                       };\r
-\r
-                       pos+=2+buf[p+pos+1];\r
-                    }\r
-\r
-                    new_channelinfo.apids.push_back(newapid);\r
-                    new_channelinfo.numAPids++;\r
-                    if (getAID() == 0 && Audio::getInstance()->streamTypeSupported(streamtype)) { //set unset AID to first audio pid that reports itself\r
-                        setAID(foundpid,0,streamtype);\r
-                        Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set audio PID to %x", foundpid);\r
-                    }\r
-                        } break;\r
-                case 5:\r
-                case 6: { //Private Data \r
-                    apid newapid;\r
-                    newapid.pid = foundpid;\r
-                    newapid.desc[0]=0; //set it in player\r
-                    pos=0;\r
-                    notfound=true;\r
-                    nolang=true;\r
-                    int type=0;\r
-                  \r
-                    while (pos< eslength && (notfound || nolang)) {\r
-                        switch (buf[p+pos]) {\r
-                        case 0x7A: // Enhanced Ac3 Desriptor\r
-                        case 0x6A: {//Ac3 descriptor \r
-                               newapid.type=buf[p+pos];\r
-                               type=1;\r
-\r
-                            notfound=false;\r
-                                   } break; \r
-                       case 0x59: {//SubtitlingDescriptor\r
-                           type=2;\r
-                           newapid.type=buf[p+pos];\r
-                           newapid.desc[0]=buf[p+pos+2];\r
-                           newapid.desc[1]=buf[p+pos+3];\r
-                           newapid.desc[2]=buf[p+pos+4];\r
-                           newapid.desc[3]=0;\r
-                           newapid.data1=(buf[p+pos+5]<<8) |(buf[p+pos+6]);\r
-                           newapid.data2=(buf[p+pos+7]<<8) |(buf[p+pos+8]);\r
-                        //   Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDSUB is %s", newapid.desc);\r
-                            notfound=false;\r
-                            nolang=false;\r
-                                   } break;\r
-                       case 0x0A: {\r
-                          newapid.desc[0]=buf[p+pos+2];\r
-                          newapid.desc[1]=buf[p+pos+3];\r
-                          newapid.desc[2]=buf[p+pos+4];\r
-                          newapid.desc[3]=0;\r
-                          nolang=false;\r
-                        //  Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDLANG is %s", newapid.desc);\r
-                       } break;\r
-                       case 0x56: {\r
-                          type=3;\r
-                           new_channelinfo.tpid=foundpid;\r
-                           notfound=false;\r
-                                  } break;\r
-                        };\r
-                        pos+=2+buf[p+pos+1];\r
-                    }\r
-                    if (type==1) {\r
-                       new_channelinfo.dpids.push_back(newapid);\r
-                       new_channelinfo.numDPids++;\r
-                    } else if (type==2) {\r
-                       new_channelinfo.spids.push_back(newapid);\r
-                       new_channelinfo.numSPids++;\r
-                    }\r
-\r
-                        } break;\r
-                default://TODO how about subtitles and second audio pids\r
-                    break;\r
-                }\r
-               }\r
-           \r
-                p += eslength; //skip es descriptor\r
-        \r
-        \r
-           }\r
-        bool audioPIDpresent=false; //Check if pids chnages\r
-        ULONG i;\r
-        for (i=0;i<channelinfo.numAPids;i++) {\r
-            if (aID == (int)channelinfo.apids[i].pid) {\r
-                audioPIDpresent=true;\r
-            }\r
-        }\r
-        for (i=0;i<channelinfo.numDPids && (! audioPIDpresent);i++) {\r
-            if (aID == (int)channelinfo.dpids[i].pid) {\r
-                audioPIDpresent=true;\r
-            }\r
-        }\r
-        if (! audioPIDpresent) {\r
-               bool found=false;\r
-            if (channelinfo.numAPids>0) {\r
-               int j=0;\r
-               while (j<channelinfo.numAPids && !found) {\r
-                       if (Audio::getInstance()->streamTypeSupported(channelinfo.apids[j].type)) {\r
-                               found =true;\r
-                               setAID(channelinfo.apids[j].pid,0,channelinfo.apids[j].type);\r
-                       }\r
-                       j++;\r
-               }\r
-\r
-            }\r
-            if (channelinfo.numDPids>0 && !found) {\r
-               int j=0;\r
-               while (j<channelinfo.numDPids && !found) {\r
-                       if (Audio::getInstance()->streamTypeSupported(channelinfo.dpids[j].type)) {\r
-                               found =true;\r
-                               setAID(channelinfo.dpids[j].pid,1,channelinfo.dpids[j].type);\r
-                       }\r
-                       i++;\r
-               }\r
-            }\r
-        }\r
-\r
-        channelinfo=new_channelinfo;\r
-\r
-\r
-        havechannelinfo=true;\r
-\r
-        return 1;\r
-    }\r
-    \r
-\r
-    \r
-\r
-    if (pid == vID)\r
-    {\r
-      if (vActive)\r
-      {\r
-        if (!parsed)\r
-        {\r
-          parseTSPacketDetails(vPacket);\r
-          parsed = true;\r
-        }\r
-        rc = submitPacket(vPacket);\r
-      }\r
-      vActive = true;\r
-    }\r
-    if (pid == aID)\r
-    {\r
-      if (aActive)\r
-      {\r
-        if (!parsed)\r
-        {\r
-          parseTSPacketDetails(aPacket);\r
-          parsed = true;\r
-        }\r
-        rc = submitPacket(aPacket);\r
-      }\r
-      aActive = true;\r
-    }\r
-    if (pid == subID)\r
-    {\r
-      if (subActive)\r
-      {\r
-        if (!parsed)\r
-        {\r
-          parseTSPacketDetails(subPacket);\r
-          parsed = true;\r
-        }\r
-        rc = submitPacket(subPacket);\r
-      }\r
-      subActive = true;\r
-    }\r
-    if (isteletextdecoded && pid == tID)\r
-    {\r
-      if (tActive)\r
-      {\r
-        if (!parsed)\r
-        {\r
-          parseTSPacketDetails(tPacket);\r
-          parsed = true;\r
-        }\r
-      rc = submitPacket(tPacket);\r
-      }\r
-      tActive = true;\r
-    }\r
-    if (rc == 0) return 0;\r
-\r
-    parsed = false;\r
-    if (pid == vID)\r
-    {\r
-      vPacket.init(PESTYPE_VID0);\r
-      buf += 6; datalen -= 6;\r
-    }\r
-    if (pid == aID)\r
-    {\r
-      switch (atype)\r
-      {\r
-      case 1:\r
-        aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);\r
-        break;\r
-      default:\r
-      case 0:\r
-        aPacket.init(PESTYPE_AUD0);\r
-        break;\r
-      }\r
-      buf += 6; datalen -= 6;\r
-    }\r
-    if (pid == subID)\r
-    {\r
-      subPacket.init(PESTYPE_PRIVATE_1);\r
-      subLength = (buf[4] << 8) + buf[5];\r
-      buf += 6; datalen -= 6;\r
-    }\r
-    if (isteletextdecoded && pid == tID)\r
-    {\r
-        tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);\r
-      buf += 6; datalen -= 6;\r
-    }\r
-  }\r
-\r
-  if ( (pid == vID && vActive) ||\r
-       (pid == aID && aActive) ||\r
-       (pid == tID && tActive) ||\r
-       (pid == subID && subActive) )\r
-  {\r
-    PESPacket* packet = NULL;\r
-    if (pid == vID) packet = &vPacket;\r
-    if (pid == aID) packet = &aPacket;\r
-    if (pid == subID) {\r
-      packet = &subPacket;\r
-    }\r
-    if (pid == tID) packet = &tPacket;\r
-    if (packet != NULL)\r
-    {\r
-      if (packet->write(buf, datalen) == 0)\r
-      { // Writing to packet failed. It has overflowed.\r
-        if (!parsed)\r
-        {\r
-          parseTSPacketDetails(*packet);\r
-          parsed = true;\r
-        }\r
-        if (submitPacket(*packet) == 0) return 0;\r
-        parsed = false;\r
-        packet->truncate();\r
-        packet->write((UCHAR*)"\200\000\000", 3);\r
-        packet->write(buf, datalen);\r
-      }\r
-    }\r
-  }\r
-\r
-  if (pid == subID && subActive && subPacket.getLength() == subLength)\r
-  {\r
-    parsePacketDetails(subPacket);\r
-Log::getInstance()->log("DEMUXERTS", Log::DEBUG, "SUBMITTING A SUBTITLE PACKET %d %x", subLength, subPacket.getSubstream());\r
-    submitPacket(subPacket);\r
-    subActive = false;\r
-  }\r
-\r
-  return 1;\r
-}\r
-\r
-ULONG DemuxerTS::getPacketNum()\r
-{\r
-  return packetNumber;\r
-}\r
-\r
-ULONG DemuxerTS::getFrameNumFromPTS(ULLONG pts)\r
-{\r
-  ULLONG difference = (1LL<<33);\r
-  ULONG ref_frame = 0;\r
-  int total = 0, actual = 0;\r
-  if (pts==0) return 0; //we are in startup\r
-  pts_map_mutex.Lock();\r
-  PTSMap::iterator iter = pts_map.begin();\r
-  while (iter != pts_map.end())\r
-  {\r
-    ++total;\r
-    //Log::getInstance()->log("DemuxerTS", Log::DEBUG, "getFrameNumfromPTS pts1 %lld pts2 %lld", pts, iter->pts);\r
-    if (PTSDifference(iter->pts, pts) < PTS_ALLOWANCE)\r
-    {\r
-      difference = 0;\r
-      ref_frame = iter->frame;\r
-      actual = total;\r
-      break;\r
-    }\r
-    ULLONG newdiff = PTSDifference(pts, iter->pts);\r
-    if (newdiff < difference)\r
-    {\r
-      difference = newdiff;\r
-      ref_frame = iter->frame;\r
-      actual = total;\r
-    }\r
-    ++iter;\r
-  }\r
-  if (total > 1 && actual == 1) // We are using the most recent PTS ref.\r
-  {                             // Delete the rest.\r
-    iter = pts_map.begin(); iter++;\r
-    pts_map.erase(iter, pts_map.end());\r
-  }\r
-  pts_map_mutex.Unlock();\r
-  \r
- //Log::getInstance()->log("DemuxerTS", Log::DEBUG, "getFrameNumfromPTS pts %lld deleted %d difference %lld", pts, total,difference);\r
-\r
-  if (difference == (1LL<<33))\r
-    return 0; // We cannot make sense of the pts\r
-  else\r
-    return ref_frame + difference * fps / 90000;\r
-}\r
-\r
-\r
-void DemuxerTS::parseTSPacketDetails(PESPacket &packet) // Only important stuff for paket counting reminas\r
-{\r
-    parsePacketDetails(packet);\r
-    if (packetCounting && packet.getPacketType() >= PESTYPE_AUD0 &&\r
-                        packet.getPacketType() <= PESTYPE_AUDMAX)\r
-    {\r
-        packetNumber++;\r
-    }\r
-    UINT pictsinpacket=packet.countPictureHeaders(h264);\r
-    \r
-    UINT numpicts=0;\r
-  /*  if (!doubledframerate)\r
-    {*/\r
-        numpicts=pictsinpacket;\r
-  /*  }\r
-    else\r
-    {\r
-        numpicts=(pictsinpacket+framereserve)>>1;\r
-        framereserve=(pictsinpacket+framereserve)%2;\r
-    }*/\r
-\r
-\r
-  if (frameCounting && numpicts &&\r
-      packet.getPacketType() >= PESTYPE_VID0 &&\r
-      packet.getPacketType() <= PESTYPE_VIDMAX)\r
-  {\r
-    frameNumber+=numpicts;\r
-    ULONG frame_num = frameNumber;\r
-    if ((h264 || packet.findSeqHeader(h264) > 1) && packet.hasPTS())\r
-    {\r
-      PTSMapEntry me;\r
-      pts_map_mutex.Lock();\r
-      if (pts_map.empty())\r
-      {\r
-        me.pts = packet.getPTS();\r
-        me.frame = frame_num;\r
-        pts_map_mutex.Unlock();\r
-        pts_map_mutex.Lock();\r
-        pts_map.push_front(me);\r
-      }\r
-      me = pts_map.front();\r
-      pts_map_mutex.Unlock();\r
-\r
-      //UINT fps = Video::getInstance()->getFPS();\r
-      double tfps=fps;\r
-     // if (doubledframerate) tfps*=2.;\r
-      ULLONG pts_expected = me.pts + 90000*((int)(((double)(frame_num - me.frame)) / tfps));\r
-\r
-      while (pts_expected > (1LL<<33)) pts_expected -= (1LL<<33);\r
-\r
-      // this was a workaround for a vdr bug, now fixed, for older recordings deleter the index file\r
-\r
-      /*\r
-      if (!doubledframerate \r
-          &&(abs((long long)PTSDistance(pts_expected, packet.getPTS())-1800) <= 1 \r
-          || abs((long long)PTSDistance(pts_expected, packet.getPTS())-1501) <= 1)) {\r
-              doubledframerate=true; //Detected  p50 or p60\r
-      }*/\r
-\r
-      if (PTSDistance(pts_expected, packet.getPTS()) > PTS_JUMP_MARGIN) // PTS jump!\r
-      {\r
-        me.pts = packet.getPTS();\r
-        me.frame = frame_num;\r
-        pts_map_mutex.Lock();\r
-        pts_map.push_front(me);\r
-        pts_map_mutex.Unlock();\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-\r
-bool DemuxerTS::scanForVideo(UCHAR* buf, UINT len, bool &ish264)\r
-{\r
-    int pmtpidy=0;\r
-\r
-  while (len >= TS_SIZE)\r
-  {\r
-      if (*buf != TS_SIG) {buf++;len--; continue;} \r
-\r
-    //Pattern scanning won't work for ts\r
-\r
-      \r
-      int datalen = TS_SIZE - 4;\r
-      int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];\r
-      UCHAR payload = buf[1] & 0x40;\r
-      \r
-      if (buf[3] & 0x20) // Adaptation field is present\r
-          datalen -= (buf[4] + 1);\r
-\r
-      UCHAR* curbuf =buf+ (TS_SIZE - datalen);\r
-     \r
-      if (payload) {\r
-          if (pid == 0x00) {//PAT, only take first program number, ignore the rest\r
-              int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);\r
-              if ((pmtpid >> 13) != 0x07) \r
-              {\r
-                  Log::getInstance()->log("DemuxerTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));\r
-              } \r
-              else \r
-              {\r
-                  pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits\r
-                  pmtpidy = pmtpid;\r
-                                 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "PMT pid%02x",pmtpid );\r
-              }\r
-          \r
-          } else if (pid == pmtpidy) { //PMT\r
-              int sectionlength = ((*(curbuf+2) << 8) & 0x0F ) | *(buf+3);\r
-              //sectionlength += 4; //include header but subtract crc in the end...\r
-              int p = 13; //skip fixed part of pmt\r
-              while ( p < sectionlength) {\r
-                  int streamtype = *(curbuf+p);\r
-                  p++;\r
-                  int foundpid = (*(curbuf+p)<< 8) | *(curbuf+p+1);\r
-                  p += 2; //skip ES Pid\r
-                  int eslength = ((*(curbuf+p) << 8) & 0x0F ) | *(curbuf+p+1);\r
-                  p += 2; //skip ES length\r
-                  if ((foundpid >> 13) != 0x07)\r
-                  {\r
-                      Log::getInstance()->log("DemuxerTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));\r
-                  }\r
-                  else \r
-                  {\r
-                      foundpid = foundpid & 0x1FFF; //clear upper 3 bits\r
-                   //   int pos=0; UNUSED?\r
-                                         Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Pid found %02x type %02x",foundpid ,streamtype);\r
-                      if (streamtype==1 || streamtype ==2) {\r
-                                                 ish264=false;\r
-                                                 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Found Mpeg2 Video");\r
-                          return true;\r
-                      }\r
-                                         if (streamtype==0x1b) {\r
-                                                 ish264=true;\r
-                                                 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Found h264 Video");\r
-                                                 return true;\r
-                                         }\r
-                  }\r
-                  p += eslength; //skip es descriptor\r
-              }\r
-                         ish264=false;\r
-              return false;\r
-          } \r
-      }\r
-      len-=TS_SIZE;\r
-      buf+=TS_SIZE;\r
-  }\r
-  ish264=false;\r
-  return false;\r
-}\r
-\r
-UINT DemuxerTS::stripAudio(UCHAR* buf, UINT len) //it has to be adapted\r
-{ \r
-    //This function strips all TS Headers and non video payload\r
-    UINT readpos=0;\r
-    UINT writepos=0;\r
-    PESPacket destpaket;\r
-    bool started=true;\r
-    while (readpos < len ) {\r
-        if (buf[readpos] != TS_SIG) {readpos++; continue;} \r
-        UINT oldreadpos=readpos;\r
-\r
-        int datalen = TS_SIZE - 4;\r
-        int pid = ( (buf[readpos+1] & 0x1F) << 8 ) | buf[readpos+2];\r
-        UCHAR payload = buf[readpos+1] & 0x40;\r
-        if (buf[readpos+3] & 0x20) { // Adaptation field is present\r
-           datalen -= (buf[readpos+4] + 1);\r
-        }\r
-        if (datalen < 0) {// Error in stream TODO log this\r
-            return 0;\r
-        }\r
-        if (datalen == 0) {// Null packet\r
-             readpos=oldreadpos+TS_SIZE;\r
-            continue;\r
-        }\r
-        readpos += (TS_SIZE - datalen);\r
-        UINT towrite=min(datalen,len-readpos);\r
-        if (pid == vID) {\r
-            if (payload) {\r
-                if (started) {\r
-                    parsePacketDetails(destpaket);\r
-                    memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());\r
-                    writepos+=destpaket.getSize();\r
-                 }\r
-                 destpaket.init(PESTYPE_VID0);\r
-                 readpos += 6; towrite -= 6;\r
-                 started=true;\r
-            }\r
-\r
-            if (started) {\r
-                if (!destpaket.write(buf+readpos,towrite)) {\r
-                    parsePacketDetails(destpaket);\r
-                    memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());\r
-                    writepos+=destpaket.getSize();\r
-                    destpaket.truncate();\r
-                                       destpaket.write((UCHAR*)"\200\000\000", 3);\r
-                    destpaket.write(buf+readpos,towrite);\r
-\r
-                }\r
-            }\r
-            \r
-       \r
-\r
-        }\r
-        readpos=oldreadpos+TS_SIZE;\r
-    }\r
-    parsePacketDetails(destpaket);\r
-    memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());\r
-    writepos+=destpaket.getSize();\r
\r
-    return writepos;\r
-}    \r
-\r
-\r
-\r
+/*
+    Copyright 2006-2008 Mark Calderbank
+
+    This file is part of VOMP.
+
+    VOMP is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    VOMP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with VOMP; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+#include "demuxerts.h"
+#include "log.h"
+#include "video.h"
+#include "vdr.h"
+#include "audio.h"
+
+#define PTS_JUMP_MARGIN   10000
+#define PTS_ALLOWANCE 90000
+
+// TODO: PTS class to handle wrapping arithmetic & comparisons?
+static ULLONG PTSDistance(ULLONG pts1, ULLONG pts2)
+{
+  // Assume pts1, pts2 < 2^33; calculate shortest distance between
+  ULLONG ret = (pts1 > pts2) ? pts1 - pts2 : pts2 - pts1;
+  if (ret > (1LL<<32)) ret = (1LL<<33) - ret;
+  return ret;
+}
+
+static ULLONG PTSDifference(ULLONG pts1, ULLONG pts2)
+{
+  // Assume pts1, pts2 < 2^33; calculate pts1 - pts2
+  if (pts1 > pts2)
+    return pts1 - pts2;
+  else
+    return (1LL<<33) + pts1 - pts2;
+}
+
+DemuxerTS::DemuxerTS(int p_vID, int p_aID, int p_subID, int p_tID)
+{
+  vID = p_vID; vActive = false;
+  aID = p_aID; aActive = false;
+  subID = p_subID; subActive = false;
+  atype = 0;
+  subLength = 0;
+  tID = p_tID;
+  havechannelinfo=false;
+  //doubledframerate=false;
+  framereserve=0;
+}
+
+void DemuxerTS::flush()
+{
+  partPacket = 0;
+  parsed = false;
+  havechannelinfo=false;
+  Demuxer::flush();
+  vPacket.init(PESTYPE_VID0);
+  switch (atype)
+  {
+  case 1:
+    aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
+    break;
+  default:
+  case 0:
+    aPacket.init(PESTYPE_AUD0);
+    break;
+  }
+  subPacket.init(PESTYPE_PRIVATE_1);
+tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
+
+  vActive = false;
+  aActive = false;
+  subActive = false;
+  subLength = 0;
+  tActive = false;
+ // doubledframerate=false;
+  framereserve=0;
+}
+
+int DemuxerTS::scan(UCHAR *buf, int len)
+{
+  switch (atype)
+  {
+  case 1:
+    return PESTYPE_PRIVATE_1;
+  default:
+  case 0:
+    return PESTYPE_AUD0;
+  }
+}
+
+void DemuxerTS::setVID(int p_vID)
+{
+  vID = p_vID;
+  vPacket.init(PESTYPE_VID0);
+  vActive = false;
+}
+
+void DemuxerTS::setAID(int p_aID, int type, int streamtype)
+{
+  aID = p_aID;
+  atype = type;
+  astreamtype = streamtype;
+  switch (atype)
+  {
+  case 1:
+    aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
+    setAudioStream(PESTYPE_SUBSTREAM_AC30);
+    break;
+  default:
+  case 0:
+    aPacket.init(PESTYPE_AUD0);
+    setAudioStream(PESTYPE_AUD0);
+    break;
+  }
+  aActive = false;
+}
+
+void DemuxerTS::setSubID(int p_subID)
+{
+  subID = p_subID;
+  subPacket.init(PESTYPE_PRIVATE_1);
+  subActive = false;
+  subLength = 0;
+}
+
+void DemuxerTS::setTID(int p_tID)
+{
+  tID = p_tID;
+  tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
+  tActive = false;
+
+}
+
+
+
+
+int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest)
+{
+  int scanaid=0;
+
+  while (len >= TS_SIZE)
+  {
+      if (*buf != TS_SIG) {buf++;len--; continue;} 
+
+    //Pattern scanning won't work for ts
+
+      
+      int datalen = TS_SIZE - 4;
+      int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
+      UCHAR payload = buf[1] & 0x40;
+      
+      if (buf[3] & 0x20) // Adaptation field is present
+          datalen -= (buf[4] + 1);
+
+      UCHAR* curbuf =buf+ (TS_SIZE - datalen);
+     
+
+      if (payload) {
+          if (pid == 0x00) {//PAT, only take first program number, ignore the rest
+              int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);
+              if ((pmtpid >> 13) != 0x07) 
+              {
+                  Log::getInstance()->log("findPTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));
+              } 
+              else 
+              {
+                  pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
+                  PMTPID = pmtpid;
+              }
+          
+          } else if (pid == PMTPID) { //PMT
+              int sectionlength = ((*(curbuf+2) << 8) & 0x0F ) | *(buf+3);
+              //sectionlength += 4; //include header but subtract crc in the end...
+              int p = 13; //skip fixed part of pmt
+              while ( p < sectionlength) {
+                  int streamtype = *(curbuf+p);
+                  p++;
+                  int foundpid = (*(curbuf+p)<< 8) | *(curbuf+p+1);
+                  p += 2; //skip ES Pid
+                  int eslength = ((*(curbuf+p) << 8) & 0x0F ) | *(curbuf+p+1);
+                  p += 2; //skip ES length
+                  if ((foundpid >> 13) != 0x07)
+                  {
+                      Log::getInstance()->log("findPTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
+                  }
+                  else 
+                  {
+                      foundpid = foundpid & 0x1FFF; //clear upper 3 bits
+                      //int pos=0; UNUSED?
+                      if (streamtype==3 || streamtype ==4) {
+                          scanaid=foundpid;
+                      }
+                  }
+                  p += eslength; //skip es descriptor
+              }
+          } else if (pid == scanaid) {     
+           //   UINT framelength = ((UINT)curbuf[4] << 8) | curbuf[5];  UNUSED?
+              
+              if ( curbuf[7] & 0x80 ) // PTS_DTS_flags indicate that PTS is present
+              {
+                  *dest = ( (ULLONG)(curbuf[9] & 0x0E) << 29 ) |
+                  ( (ULLONG)(curbuf[10])        << 22 ) |
+                  ( (ULLONG)(curbuf[11] & 0xFE) << 14 ) |
+                  ( (ULLONG)(curbuf[12])        <<  7 ) |
+                  ( (ULLONG)(curbuf[13] & 0xFE) >>  1 );
+                  return 1;
+              }
+          }
+      }
+      len-=TS_SIZE;
+      buf+=TS_SIZE;
+  }
+  // No PTS found.
+  return 0;
+}
+
+void DemuxerTS::setFrameNum(ULONG frame)
+{
+  frameCounting = true;
+  frameNumber = frame;
+  framereserve=0;
+  Log::getInstance()->log("DemuxerTS", Log::DEBUG, "setFrameNum %d", frame);
+}
+
+void DemuxerTS::setPacketNum(ULONG npacket)
+{
+  packetCounting = true;
+  packetNumber = npacket;
+  Log::getInstance()->log("DemuxerTS", Log::DEBUG, "setPacketNum %d", npacket);
+}
+
+int DemuxerTS::put(UCHAR* buf, int len)
+{
+  int ret = 0;    // return number of bytes consumed
+
+  bool misaligned_mess=false;
+  while (partPacket)
+  {
+    if (len >= TS_SIZE + 1 - partPacket)
+    { // Remainder of partial packet is available, plus one
+      memcpy(store+partPacket, buf, TS_SIZE - partPacket);
+      ret += TS_SIZE - partPacket;
+      buf += TS_SIZE - partPacket;
+      len -= TS_SIZE - partPacket;
+      partPacket = TS_SIZE;
+      if (*buf == TS_SIG)
+      { // Packet is properly terminated
+        int rc = processTS(store);
+        if (rc)
+          partPacket = 0; // Successfully processed
+        else
+          return ret;     // Try again later.
+      }
+      else
+      { // Packet not terminated. Find another candidate, and shift store
+        if (!misaligned_mess) {
+               Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!A");
+               misaligned_mess=true; // do not alarm more than once
+        }
+        int search = 1;
+        while (search < partPacket && store[search] != TS_SIG)
+          search++;
+        partPacket -= search;
+        if (partPacket) memcpy(store, store+search, partPacket);
+      }
+    }
+    else
+    { // Still don't have complete packet. Consume what we do have.
+      memcpy(store+partPacket, buf, len);
+      partPacket += len;
+      ret += len;
+      return ret;
+    }
+  }
+
+  // Position ourselves at a candidate TS packet
+  while (len > 0 && *buf != TS_SIG)
+  {
+         if (!misaligned_mess) {
+                 Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!B");
+             misaligned_mess=true; // do not alarm more than once
+          }
+    buf++; ret++; len--;
+  }
+
+  while (len)
+  {
+    if (len < TS_SIZE + 1)
+    { // Not enough data. Store what we have.
+      memcpy(store, buf, len);
+      partPacket = len;
+      ret += len;
+      return ret;
+    }
+
+    if (buf[TS_SIZE] != TS_SIG)
+    { // Not terminated correctly.
+      buf++; ret++; len--;
+      while (len > 0 && *buf != TS_SIG)
+      {
+        buf++; ret++; len--;
+      }
+    }
+    else
+    {
+      int rc = processTS(buf);
+      if (rc)
+      { // Successfully processed
+        buf += TS_SIZE; ret += TS_SIZE; len -= TS_SIZE;
+      }
+      else
+      { // Processing failed.
+        return ret;
+      }
+    }
+  }
+  return ret;
+}
+
+
+int DemuxerTS::processTS(UCHAR* buf)
+{
+  int datalen = TS_SIZE - 4;
+
+  int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
+  UCHAR payload = buf[1] & 0x40;
+
+
+  if (buf[3] & 0x20) // Adaptation field is present
+    datalen -= (buf[4] + 1);
+  if (datalen < 0) // Error in stream TODO log this
+    return 1;
+  if (datalen == 0) // Null packet
+    return 1;
+ // if (!(buf[3] &0x10)) return 1; // no payload
+  buf += (TS_SIZE - datalen);
+
+  if (payload)
+  {
+      int rc = 1;
+      if (pid == 0x00) {//PAT, only take first program number, ignore the rest
+          int pmtpid = (*(buf+11)<< 8) | *(buf+12);
+          if ((pmtpid >> 13) != 0x07) 
+          {
+              Log::getInstance()->log("ProcessTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(buf+11),*(buf+12), (pmtpid >> 13));
+          } 
+          else 
+          {
+              pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
+              PMTPID = pmtpid;
+          }
+           return 1;
+    }
+    if (pid == PMTPID) 
+    { //PMT
+        int sectionlength = ((*(buf+2) << 8) & 0x0F ) | *(buf+3);
+        //sectionlength += 4; //include header but subtract crc in the end...
+        int p = 13; //skip fixed part of pmt
+        Channel new_channelinfo;
+        new_channelinfo.numAPids=0;
+        new_channelinfo.numDPids=0;
+        new_channelinfo.numSPids=0;
+        new_channelinfo.number=0;
+        new_channelinfo.type=VDR::RADIO;
+        new_channelinfo.name=NULL;
+        new_channelinfo.tpid=0xFFFFF; //unused, check this
+        new_channelinfo.vpid=0xFFFFF; //unused, check this
+        new_channelinfo.index=0;
+
+        new_channelinfo.apids.clear();
+        new_channelinfo.dpids.clear();
+        new_channelinfo.spids.clear();
+        
+        while ( p < sectionlength) {
+            int streamtype = *(buf+p);
+            p++;
+            int foundpid = (*(buf+p)<< 8) | *(buf+p+1);
+            p += 2; //skip ES Pid
+            int eslength = ((*(buf+p) << 8) & 0x0F ) | *(buf+p+1);
+            p += 2; //skip ES length
+            if ((foundpid >> 13) != 0x07)
+            {
+              Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
+            }
+            else 
+            {
+                foundpid = foundpid & 0x1FFF; //clear upper 3 bits
+                bool notfound=false;
+                bool nolang=true;
+                int pos=0;
+           // Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDPID is %x %x", foundpid,streamtype);
+                switch (streamtype)
+                {
+                case 0x1B: //MPEG 4 for future use
+                case 1:
+                case 2: { //video
+                    if (foundpid != getVID())  
+                        setVID(foundpid);
+                    new_channelinfo.type=VDR::VIDEO;
+                                       new_channelinfo.vstreamtype=streamtype;
+                    new_channelinfo.vpid=foundpid;
+                                       if (streamtype==0x1b) h264=true;
+                                       else h264=false;
+
+                //  Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set video PID to %x", foundpid);
+                        }break;
+                case 0x0F: //AAC ADTS packaging
+                case 0x11: // LATM packaging
+                case 3:
+                case 4: { //audio
+                    apid newapid;
+                    newapid.pid = foundpid;
+                    newapid.desc[0]=0;
+                    newapid.type=streamtype;
+                    pos=0;
+                    nolang=true;
+                    while (pos< eslength && nolang) {
+                       switch (buf[p+pos]) {
+                       case 0x0A: {
+                               newapid.desc[0]=buf[p+pos+2];
+                               newapid.desc[1]=buf[p+pos+3];
+                               newapid.desc[2]=buf[p+pos+4];
+                               newapid.desc[3]=0;
+                               nolang=false;
+                    //         Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDLANG is %s", newapid.desc);
+                       } break;
+                       };
+
+                       pos+=2+buf[p+pos+1];
+                    }
+
+                    new_channelinfo.apids.push_back(newapid);
+                    new_channelinfo.numAPids++;
+                    if (getAID() == 0 && Audio::getInstance()->streamTypeSupported(streamtype)) { //set unset AID to first audio pid that reports itself
+                        setAID(foundpid,0,streamtype);
+                        Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set audio PID to %x", foundpid);
+                    }
+                        } break;
+                case 5:
+                case 6: { //Private Data 
+                    apid newapid;
+                    newapid.pid = foundpid;
+                    newapid.desc[0]=0; //set it in player
+                    pos=0;
+                    notfound=true;
+                    nolang=true;
+                    int type=0;
+                  
+                    while (pos< eslength && (notfound || nolang)) {
+                        switch (buf[p+pos]) {
+                        case 0x7A: // Enhanced Ac3 Desriptor
+                        case 0x6A: {//Ac3 descriptor 
+                               newapid.type=buf[p+pos];
+                               type=1;
+
+                            notfound=false;
+                                   } break; 
+                       case 0x59: {//SubtitlingDescriptor
+                           type=2;
+                           newapid.type=buf[p+pos];
+                           newapid.desc[0]=buf[p+pos+2];
+                           newapid.desc[1]=buf[p+pos+3];
+                           newapid.desc[2]=buf[p+pos+4];
+                           newapid.desc[3]=0;
+                           newapid.data1=(buf[p+pos+5]<<8) |(buf[p+pos+6]);
+                           newapid.data2=(buf[p+pos+7]<<8) |(buf[p+pos+8]);
+                        //   Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDSUB is %s", newapid.desc);
+                            notfound=false;
+                            nolang=false;
+                                   } break;
+                       case 0x0A: {
+                          newapid.desc[0]=buf[p+pos+2];
+                          newapid.desc[1]=buf[p+pos+3];
+                          newapid.desc[2]=buf[p+pos+4];
+                          newapid.desc[3]=0;
+                          nolang=false;
+                        //  Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDLANG is %s", newapid.desc);
+                       } break;
+                       case 0x56: {
+                          type=3;
+                           new_channelinfo.tpid=foundpid;
+                           notfound=false;
+                                  } break;
+                        };
+                        pos+=2+buf[p+pos+1];
+                    }
+                    if (type==1) {
+                       new_channelinfo.dpids.push_back(newapid);
+                       new_channelinfo.numDPids++;
+                    } else if (type==2) {
+                       new_channelinfo.spids.push_back(newapid);
+                       new_channelinfo.numSPids++;
+                    }
+
+                        } break;
+                default://TODO how about subtitles and second audio pids
+                    break;
+                }
+               }
+           
+                p += eslength; //skip es descriptor
+        
+        
+           }
+        bool audioPIDpresent=false; //Check if pids chnages
+        ULONG i;
+        for (i=0;i<channelinfo.numAPids;i++) {
+            if (aID == (int)channelinfo.apids[i].pid) {
+                audioPIDpresent=true;
+            }
+        }
+        for (i=0;i<channelinfo.numDPids && (! audioPIDpresent);i++) {
+            if (aID == (int)channelinfo.dpids[i].pid) {
+                audioPIDpresent=true;
+            }
+        }
+        if (! audioPIDpresent) {
+               bool found=false;
+            if (channelinfo.numAPids>0) {
+               int j=0;
+               while (j<channelinfo.numAPids && !found) {
+                       if (Audio::getInstance()->streamTypeSupported(channelinfo.apids[j].type)) {
+                               found =true;
+                               setAID(channelinfo.apids[j].pid,0,channelinfo.apids[j].type);
+                       }
+                       j++;
+               }
+
+            }
+            if (channelinfo.numDPids>0 && !found) {
+               int j=0;
+               while (j<channelinfo.numDPids && !found) {
+                       if (Audio::getInstance()->streamTypeSupported(channelinfo.dpids[j].type)) {
+                               found =true;
+                               setAID(channelinfo.dpids[j].pid,1,channelinfo.dpids[j].type);
+                       }
+                       i++;
+               }
+            }
+        }
+
+        channelinfo=new_channelinfo;
+
+
+        havechannelinfo=true;
+
+        return 1;
+    }
+    
+
+    
+
+    if (pid == vID)
+    {
+      if (vActive)
+      {
+        if (!parsed)
+        {
+          parseTSPacketDetails(vPacket);
+          parsed = true;
+        }
+        rc = submitPacket(vPacket);
+      }
+      vActive = true;
+    }
+    if (pid == aID)
+    {
+      if (aActive)
+      {
+        if (!parsed)
+        {
+          parseTSPacketDetails(aPacket);
+          parsed = true;
+        }
+        rc = submitPacket(aPacket);
+      }
+      aActive = true;
+    }
+    if (pid == subID)
+    {
+      if (subActive)
+      {
+        if (!parsed)
+        {
+          parseTSPacketDetails(subPacket);
+          parsed = true;
+        }
+        rc = submitPacket(subPacket);
+      }
+      subActive = true;
+    }
+    if (isteletextdecoded && pid == tID)
+    {
+      if (tActive)
+      {
+        if (!parsed)
+        {
+          parseTSPacketDetails(tPacket);
+          parsed = true;
+        }
+      rc = submitPacket(tPacket);
+      }
+      tActive = true;
+    }
+    if (rc == 0) return 0;
+
+    parsed = false;
+    if (pid == vID)
+    {
+      vPacket.init(PESTYPE_VID0);
+      buf += 6; datalen -= 6;
+    }
+    if (pid == aID)
+    {
+      switch (atype)
+      {
+      case 1:
+        aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
+        break;
+      default:
+      case 0:
+        aPacket.init(PESTYPE_AUD0);
+        break;
+      }
+      buf += 6; datalen -= 6;
+    }
+    if (pid == subID)
+    {
+      subPacket.init(PESTYPE_PRIVATE_1);
+      subLength = (buf[4] << 8) + buf[5];
+      buf += 6; datalen -= 6;
+    }
+    if (isteletextdecoded && pid == tID)
+    {
+        tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
+      buf += 6; datalen -= 6;
+    }
+  }
+
+  if ( (pid == vID && vActive) ||
+       (pid == aID && aActive) ||
+       (pid == tID && tActive) ||
+       (pid == subID && subActive) )
+  {
+    PESPacket* packet = NULL;
+    if (pid == vID) packet = &vPacket;
+    if (pid == aID) packet = &aPacket;
+    if (pid == subID) {
+      packet = &subPacket;
+    }
+    if (pid == tID) packet = &tPacket;
+    if (packet != NULL)
+    {
+      if (packet->write(buf, datalen) == 0)
+      { // Writing to packet failed. It has overflowed.
+        if (!parsed)
+        {
+          parseTSPacketDetails(*packet);
+          parsed = true;
+        }
+        if (submitPacket(*packet) == 0) return 0;
+        parsed = false;
+        packet->truncate();
+        packet->write((UCHAR*)"\200\000\000", 3);
+        packet->write(buf, datalen);
+      }
+    }
+  }
+
+  if (pid == subID && subActive && subPacket.getLength() == subLength)
+  {
+    parsePacketDetails(subPacket);
+Log::getInstance()->log("DEMUXERTS", Log::DEBUG, "SUBMITTING A SUBTITLE PACKET %d %x", subLength, subPacket.getSubstream());
+    submitPacket(subPacket);
+    subActive = false;
+  }
+
+  return 1;
+}
+
+ULONG DemuxerTS::getPacketNum()
+{
+  return packetNumber;
+}
+
+ULONG DemuxerTS::getFrameNumFromPTS(ULLONG pts)
+{
+  ULLONG difference = (1LL<<33);
+  ULONG ref_frame = 0;
+  int total = 0, actual = 0;
+  if (pts==0) return 0; //we are in startup
+  pts_map_mutex.Lock();
+  PTSMap::iterator iter = pts_map.begin();
+  while (iter != pts_map.end())
+  {
+    ++total;
+    //Log::getInstance()->log("DemuxerTS", Log::DEBUG, "getFrameNumfromPTS pts1 %lld pts2 %lld", pts, iter->pts);
+    if (PTSDifference(iter->pts, pts) < PTS_ALLOWANCE)
+    {
+      difference = 0;
+      ref_frame = iter->frame;
+      actual = total;
+      break;
+    }
+    ULLONG newdiff = PTSDifference(pts, iter->pts);
+    if (newdiff < difference)
+    {
+      difference = newdiff;
+      ref_frame = iter->frame;
+      actual = total;
+    }
+    ++iter;
+  }
+  if (total > 1 && actual == 1) // We are using the most recent PTS ref.
+  {                             // Delete the rest.
+    iter = pts_map.begin(); iter++;
+    pts_map.erase(iter, pts_map.end());
+  }
+  pts_map_mutex.Unlock();
+  
+ //Log::getInstance()->log("DemuxerTS", Log::DEBUG, "getFrameNumfromPTS pts %lld deleted %d difference %lld", pts, total,difference);
+
+  if (difference == (1LL<<33))
+    return 0; // We cannot make sense of the pts
+  else
+    return ref_frame + difference * fps / 90000;
+}
+
+
+void DemuxerTS::parseTSPacketDetails(PESPacket &packet) // Only important stuff for paket counting reminas
+{
+    parsePacketDetails(packet);
+    if (packetCounting && packet.getPacketType() >= PESTYPE_AUD0 &&
+                        packet.getPacketType() <= PESTYPE_AUDMAX)
+    {
+        packetNumber++;
+    }
+    UINT pictsinpacket=packet.countPictureHeaders(h264);
+    
+    UINT numpicts=0;
+  /*  if (!doubledframerate)
+    {*/
+        numpicts=pictsinpacket;
+  /*  }
+    else
+    {
+        numpicts=(pictsinpacket+framereserve)>>1;
+        framereserve=(pictsinpacket+framereserve)%2;
+    }*/
+
+
+  if (frameCounting && numpicts &&
+      packet.getPacketType() >= PESTYPE_VID0 &&
+      packet.getPacketType() <= PESTYPE_VIDMAX)
+  {
+    frameNumber+=numpicts;
+    ULONG frame_num = frameNumber;
+    if ((h264 || packet.findSeqHeader(h264) > 1) && packet.hasPTS())
+    {
+      PTSMapEntry me;
+      pts_map_mutex.Lock();
+      if (pts_map.empty())
+      {
+        me.pts = packet.getPTS();
+        me.frame = frame_num;
+        pts_map_mutex.Unlock();
+        pts_map_mutex.Lock();
+        pts_map.push_front(me);
+      }
+      me = pts_map.front();
+      pts_map_mutex.Unlock();
+
+      //UINT fps = Video::getInstance()->getFPS();
+      double tfps=fps;
+     // if (doubledframerate) tfps*=2.;
+      long long pts_expected = me.pts + 90000LL*((long long)(((double)(frame_num - me.frame)) / tfps));
+
+      while (pts_expected < 0) pts_expected += (1LL<<33);
+      while (pts_expected > (1LL<<33)) pts_expected -= (1LL<<33);
+
+      // this was a workaround for a vdr bug, now fixed, for older recordings deleter the index file
+
+      /*
+      if (!doubledframerate 
+          &&(abs((long long)PTSDistance(pts_expected, packet.getPTS())-1800) <= 1 
+          || abs((long long)PTSDistance(pts_expected, packet.getPTS())-1501) <= 1)) {
+              doubledframerate=true; //Detected  p50 or p60
+      }*/
+
+      if (PTSDistance(pts_expected, packet.getPTS()) > PTS_JUMP_MARGIN) // PTS jump!
+      {
+        me.pts = packet.getPTS();
+        me.frame = frame_num;
+        pts_map_mutex.Lock();
+        pts_map.push_front(me);
+        pts_map_mutex.Unlock();
+      }
+    }
+  }
+}
+
+
+bool DemuxerTS::scanForVideo(UCHAR* buf, UINT len, bool &ish264)
+{
+    int pmtpidy=0;
+
+  while (len >= TS_SIZE)
+  {
+      if (*buf != TS_SIG) {buf++;len--; continue;} 
+
+    //Pattern scanning won't work for ts
+
+      
+      int datalen = TS_SIZE - 4;
+      int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
+      UCHAR payload = buf[1] & 0x40;
+      
+      if (buf[3] & 0x20) // Adaptation field is present
+          datalen -= (buf[4] + 1);
+
+      UCHAR* curbuf =buf+ (TS_SIZE - datalen);
+     
+      if (payload) {
+          if (pid == 0x00) {//PAT, only take first program number, ignore the rest
+              int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);
+              if ((pmtpid >> 13) != 0x07) 
+              {
+                  Log::getInstance()->log("DemuxerTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));
+              } 
+              else 
+              {
+                  pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
+                  pmtpidy = pmtpid;
+                                 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "PMT pid%02x",pmtpid );
+              }
+          
+          } else if (pid == pmtpidy) { //PMT
+              int sectionlength = ((*(curbuf+2) << 8) & 0x0F ) | *(buf+3);
+              //sectionlength += 4; //include header but subtract crc in the end...
+              int p = 13; //skip fixed part of pmt
+              while ( p < sectionlength) {
+                  int streamtype = *(curbuf+p);
+                  p++;
+                  int foundpid = (*(curbuf+p)<< 8) | *(curbuf+p+1);
+                  p += 2; //skip ES Pid
+                  int eslength = ((*(curbuf+p) << 8) & 0x0F ) | *(curbuf+p+1);
+                  p += 2; //skip ES length
+                  if ((foundpid >> 13) != 0x07)
+                  {
+                      Log::getInstance()->log("DemuxerTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
+                  }
+                  else 
+                  {
+                      foundpid = foundpid & 0x1FFF; //clear upper 3 bits
+                   //   int pos=0; UNUSED?
+                                         Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Pid found %02x type %02x",foundpid ,streamtype);
+                      if (streamtype==1 || streamtype ==2) {
+                                                 ish264=false;
+                                                 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Found Mpeg2 Video");
+                          return true;
+                      }
+                                         if (streamtype==0x1b) {
+                                                 ish264=true;
+                                                 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Found h264 Video");
+                                                 return true;
+                                         }
+                  }
+                  p += eslength; //skip es descriptor
+              }
+                         ish264=false;
+              return false;
+          } 
+      }
+      len-=TS_SIZE;
+      buf+=TS_SIZE;
+  }
+  ish264=false;
+  return false;
+}
+
+UINT DemuxerTS::stripAudio(UCHAR* buf, UINT len) //it has to be adapted
+{ 
+    //This function strips all TS Headers and non video payload
+    UINT readpos=0;
+    UINT writepos=0;
+    PESPacket destpaket;
+    bool started=true;
+    while (readpos < len ) {
+        if (buf[readpos] != TS_SIG) {readpos++; continue;} 
+        UINT oldreadpos=readpos;
+
+        int datalen = TS_SIZE - 4;
+        int pid = ( (buf[readpos+1] & 0x1F) << 8 ) | buf[readpos+2];
+        UCHAR payload = buf[readpos+1] & 0x40;
+        if (buf[readpos+3] & 0x20) { // Adaptation field is present
+           datalen -= (buf[readpos+4] + 1);
+        }
+        if (datalen < 0) {// Error in stream TODO log this
+            return 0;
+        }
+        if (datalen == 0) {// Null packet
+             readpos=oldreadpos+TS_SIZE;
+            continue;
+        }
+        readpos += (TS_SIZE - datalen);
+        UINT towrite=min(datalen,len-readpos);
+        if (pid == vID) {
+            if (payload) {
+                if (started) {
+                    parsePacketDetails(destpaket);
+                    memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
+                    writepos+=destpaket.getSize();
+                 }
+                 destpaket.init(PESTYPE_VID0);
+                 readpos += 6; towrite -= 6;
+                 started=true;
+            }
+
+            if (started) {
+                if (!destpaket.write(buf+readpos,towrite)) {
+                    parsePacketDetails(destpaket);
+                    memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
+                    writepos+=destpaket.getSize();
+                    destpaket.truncate();
+                                       destpaket.write((UCHAR*)"\200\000\000", 3);
+                    destpaket.write(buf+readpos,towrite);
+
+                }
+            }
+            
+       
+
+        }
+        readpos=oldreadpos+TS_SIZE;
+    }
+    parsePacketDetails(destpaket);
+    memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
+    writepos+=destpaket.getSize();
+    return writepos;
+}    
+
+
+