]> git.vomp.tv Git - vompclient.git/commitdiff
VDR 1.7.7 compatibility
authorChris Tallon <chris@vomp.tv>
Sat, 30 May 2009 14:30:47 +0000 (14:30 +0000)
committerChris Tallon <chris@vomp.tv>
Sat, 30 May 2009 14:30:47 +0000 (14:30 +0000)
14 files changed:
demuxer.h
demuxerts.cc
demuxerts.h
player.cc
player.h
playerradio.cc
playerradio.h
recording.cc
recording.h
vdr.cc
vdr.h
videowin.cc
vradiorec.cc
vvideorec.cc

index bef9e79458327ee85defab59f60de48bedd6f01d..54cd1b36b5ecdc30acd023ccf1168363798096d9 100644 (file)
--- a/demuxer.h
+++ b/demuxer.h
@@ -88,6 +88,8 @@ class Demuxer
     void flushAudio();
     void seek();
     void setVideoStream(int id);
+    //TODO HANS next virtual necessary?
+    //virtual void setAudioStream(int id);
     void setAudioStream(int id);
     void setTeletextStream(int id);
     void setDVBSubtitleStream(int id);
@@ -125,8 +127,8 @@ class Demuxer
 
     // Remove all data from a buffer apart from video PES packets.
     // Returns the length of the reduced data.
-    // *static function*
-    static UINT stripAudio(UCHAR* buf, UINT len);
+    // removed *static function*, due to DemuxerTS
+    virtual UINT stripAudio(UCHAR* buf, UINT len);
 
     // Scan a buffer to see if video packets are present.
     // Returns true if video exists; false if not.
index 9738e6b469c85cfb349f734d2c75adb6651a4c66..252aa6443ee271d527ecaaeb51797ba3bc505e25 100644 (file)
 
 #include "demuxerts.h"
 #include "log.h"
+#include "video.h"
+#include "vdr.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)
 {
@@ -29,12 +52,14 @@ DemuxerTS::DemuxerTS(int p_vID, int p_aID, int p_subID, int p_tID)
   atype = 0;
   subLength = 0;
   tID = p_tID;
+  havechannelinfo=false;
 }
 
 void DemuxerTS::flush()
 {
   partPacket = 0;
   parsed = false;
+  havechannelinfo=false;
   Demuxer::flush();
   vPacket.init(PESTYPE_VID0);
   switch (atype)
@@ -111,36 +136,104 @@ void DemuxerTS::setTID(int p_tID)
 
 }
 
-int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest)
-{
-  UINT LoPattern = 0x100 | PESTYPE_VID0,
-       HiPattern = 0x100 | PESTYPE_VIDMAX;
 
-  while (len >= 14)
-  {
-    UINT pattern = *(UINT*)buf;
-    buf++; len--;
-    if (pattern < LoPattern || pattern > HiPattern) continue;
 
-    UINT framelength = ((UINT)buf[3] << 8) | buf[4];
-    buf += 5; len -= 5;
 
-    if ( buf[1] & 0x80 ) // PTS_DTS_flags indicate that PTS is present
-    {
-      *dest = ( (ULLONG)(buf[3] & 0x0E) << 29 ) |
-              ( (ULLONG)(buf[4])        << 22 ) |
-              ( (ULLONG)(buf[5] & 0xFE) << 14 ) |
-              ( (ULLONG)(buf[6])        <<  7 ) |
-              ( (ULLONG)(buf[7] & 0xFE) >>  1 );
-      return 1;
-    }
+int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest)
+{
+  int scanaid=0;
 
-    buf += framelength; len -= framelength;
+  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;
+                      if (streamtype==3 || streamtype ==4) {
+                          scanaid=foundpid;
+                      }
+                  }
+                  p += eslength; //skip es descriptor
+              }
+          } else if (pid == scanaid) {     
+              UINT framelength = ((UINT)curbuf[4] << 8) | curbuf[5];
+              
+              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;
+  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
@@ -225,6 +318,7 @@ int DemuxerTS::put(UCHAR* buf, int len)
 int DemuxerTS::processTS(UCHAR* buf)
 {
   int datalen = TS_SIZE - 4;
+
   int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
   UCHAR payload = buf[1] & 0x40;
 
@@ -238,7 +332,147 @@ int DemuxerTS::processTS(UCHAR* buf)
 
   if (payload)
   {
-    int rc = 1;
+      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=NULL;
+
+        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;
+                int pos=0;
+       //     Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDPID is %x", foundpid);
+                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.vpid=foundpid;
+
+       //           Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set video PID to %x", foundpid);
+                        }break;
+                case 3:
+                case 4: { //audio
+                    apid newapid;
+                    newapid.pid = foundpid;
+                    newapid.name = NULL; //set it in player
+                    new_channelinfo.apids.push_back(newapid);
+                    new_channelinfo.numAPids++;
+                    if (getAID() == 0) { //set unset AID to first audio pid that reports itself
+                        setAID(foundpid,0);
+                        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.name = NULL; //set it in player
+                    pos=0;
+                    notfound=true;
+                  
+                    while (pos< eslength && notfound) {
+                        switch (buf[p+pos]) {
+                        case 0x6A: {//Ac3 descriptor 
+                            new_channelinfo.dpids.push_back(newapid);
+                            new_channelinfo.numDPids++;
+                            notfound=false;
+                                   } break; 
+                       case 0x59: {//SubtitlingDescriptor
+                            new_channelinfo.spids.push_back(newapid);
+                            new_channelinfo.numSPids++;
+                            notfound=false;
+                                   } break;
+                       case 0x56: {
+                           new_channelinfo.tpid=foundpid;
+                           notfound=false;
+                                  } break;
+                        };
+                        pos+=2+buf[p+pos+1];
+                    }
+
+                        } break;
+                default://TODO how about subtitles and second audio pids
+                    break;
+                }
+               }
+           
+                p += eslength; //skip es descriptor
+        
+        
+           }
+        bool audioPIDpresent=false; //Check if pids chnages
+        int i;
+        for (i=0;i<channelinfo.numAPids;i++) {
+            if (aID ==channelinfo.apids[i].pid) {
+                audioPIDpresent=true;
+            }
+        }
+        for (i=0;i<channelinfo.numDPids && (! audioPIDpresent);i++) {
+            if (aID ==channelinfo.dpids[i].pid) {
+                audioPIDpresent=true;
+            }
+        }
+        if (! audioPIDpresent) {
+            if (channelinfo.numAPids>0) {
+                setAID(channelinfo.apids[0].pid,0);
+            } else if (channelinfo.numDPids>0) {
+                setAID(channelinfo.dpids[0].pid,1);
+            }
+        }
+
+        channelinfo=new_channelinfo;
+        havechannelinfo=true;
+
+        return 1;
+    }
+    
+
+    
 
     if (pid == vID)
     {
@@ -246,7 +480,7 @@ int DemuxerTS::processTS(UCHAR* buf)
       {
         if (!parsed)
         {
-          parsePacketDetails(vPacket);
+          parseTSPacketDetails(vPacket);
           parsed = true;
         }
         rc = submitPacket(vPacket);
@@ -259,7 +493,7 @@ int DemuxerTS::processTS(UCHAR* buf)
       {
         if (!parsed)
         {
-          parsePacketDetails(aPacket);
+          parseTSPacketDetails(aPacket);
           parsed = true;
         }
         rc = submitPacket(aPacket);
@@ -272,7 +506,7 @@ int DemuxerTS::processTS(UCHAR* buf)
       {
         if (!parsed)
         {
-          parsePacketDetails(subPacket);
+          parseTSPacketDetails(subPacket);
           parsed = true;
         }
         rc = submitPacket(subPacket);
@@ -285,7 +519,7 @@ int DemuxerTS::processTS(UCHAR* buf)
       {
         if (!parsed)
         {
-          parsePacketDetails(tPacket);
+          parseTSPacketDetails(tPacket);
           parsed = true;
         }
       rc = submitPacket(tPacket);
@@ -345,7 +579,7 @@ int DemuxerTS::processTS(UCHAR* buf)
       { // Writing to packet failed. It has overflowed.
         if (!parsed)
         {
-          parsePacketDetails(*packet);
+          parseTSPacketDetails(*packet);
           parsed = true;
         }
         if (submitPacket(*packet) == 0) return 0;
@@ -367,3 +601,226 @@ Log::getInstance()->log("DEMUXERTS", Log::DEBUG, "SUBMITTING A SUBTITLE PACKET %
 
   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;
+  pts_map_mutex.Lock();
+  PTSMap::iterator iter = pts_map.begin();
+  while (iter != pts_map.end())
+  {
+    ++total;
+    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();
+
+  if (difference == (1LL<<33))
+    return 0; // We cannot make sense of the pts
+  else
+    return ref_frame + difference * Video::getInstance()->getFPS() / 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++;
+    }
+
+  if (frameCounting && packet.findPictureHeader() &&
+      packet.getPacketType() >= PESTYPE_VID0 &&
+      packet.getPacketType() <= PESTYPE_VIDMAX)
+  {
+    ULONG frame_num = (frameNumber)++;
+    if (packet.findSeqHeader() > 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();
+      ULLONG pts_expected = me.pts + 90000*(frame_num - me.frame) / fps;
+      while (pts_expected > (1LL<<33)) pts_expected -= (1LL<<33);
+
+      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)
+{
+    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("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
+                  pmtpidy = 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("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;
+                      if (streamtype==1 || streamtype ==2) {
+                          return true;
+                      }
+                  }
+                  p += eslength; //skip es descriptor
+              }
+              return false;
+          } 
+      }
+      len-=TS_SIZE;
+      buf+=TS_SIZE;
+  }
+  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;
+}    
+
+
+
index e1f19237916f129069dfb0848e18186d9f407d19..b65c29ed0e096d66b0f2674bd56d00be3e8f819d 100644 (file)
 #ifndef DEMUXERTS_H
 #define DEMUXERTS_H
 
+#include "mutex.h"
+#include <deque>
+
 #include "demuxer.h"
 #include "defines.h"
+#include "channel.h"
 
 #define TS_SIZE 188
 #define TS_SIG  0x47
@@ -43,6 +47,15 @@ class DemuxerTS : public Demuxer
     int  getAID() { return aID; }
     int  getSubID() { return subID; }
     int put(UCHAR* buf, int len);
+    int PMTPID; //TODO HANS which of these do I Need:
+    void setFrameNum(ULONG frame);
+    void setPacketNum(ULONG npacket);
+    ULONG getFrameNumFromPTS(ULLONG pts);
+    ULONG getPacketNum();
+    UINT stripAudio(UCHAR* buf, UINT len);
+    static bool scanForVideo(UCHAR* buf, UINT len);
+    Channel getChannelInfo() {return channelinfo;};
+
 
   private:
     int processTS(UCHAR* buf);
@@ -58,8 +71,23 @@ class DemuxerTS : public Demuxer
 
     int atype;
     bool subActive;        // Same for subtitles
- UINT subLength;        // Expected length of subtitle packet   
-bool vActive, aActive, tActive; // Whether video/audio is actively being captured
+    UINT subLength;        // Expected length of subtitle packet   
+    bool vActive, aActive, tActive; // Whether video/audio is actively being captured
+
+    bool havechannelinfo;
+    Channel channelinfo;
+    
+
+    //TODO HANS which of next do I need
+    ULONG frameNumber, packetNumber;
+    bool frameCounting, packetCounting;
+    typedef struct { ULLONG pts; ULONG frame; } PTSMapEntry;
+    typedef std::deque<PTSMapEntry> PTSMap;
+    PTSMap pts_map;
+    Mutex pts_map_mutex;
+    void parseTSPacketDetails(PESPacket packet);
+   
+
 };
 
 #endif
index 9400d0e788bcfc3070043ba730e489ce80ce0479..f68ae01bacc29d3f97b0ad03d1d89fe342ca5726 100644 (file)
--- a/player.cc
+++ b/player.cc
@@ -52,6 +52,7 @@ Player::Player(MessageQueue* tmessageQueue, void* tmessageReceiver, OSDReceiver*
   currentFrameNumber = 0;
   state = S_STOP;
   ifactor = 4;
+  is_pesrecording=true;
 
   subtitlesShowing = false;
 
@@ -68,7 +69,7 @@ Player::~Player()
   if (initted) shutdown();
 }
 
-int Player::init()
+int Player::init(bool isPesRecording)
 {
   if (initted) return 0;
 #ifndef WIN32
@@ -76,8 +77,11 @@ int Player::init()
 #else
   mutex=CreateMutex(NULL,FALSE,NULL);
 #endif
-
-  demuxer = new DemuxerVDR();
+  is_pesrecording=isPesRecording;
+  if (isPesRecording)
+    demuxer = new DemuxerVDR();
+  else
+    demuxer = new DemuxerTS();
   if (!demuxer) return 0;
   subtitles = new DVBSubtitles(osdReceiver);
   if (!subtitles) return 0;
@@ -181,17 +185,29 @@ bool* Player::getDemuxerSubtitleChannels()
 
 int Player::getCurrentAudioChannel()
 {
-    return demuxer->getselAudioChannel();
+    if (is_pesrecording) {
+        return demuxer->getselAudioChannel();
+    } else {
+        return ((DemuxerTS*)demuxer)->getAID();
+    }
 }
 
 int Player::getCurrentSubtitleChannel()
 {
-    return demuxer->getselSubtitleChannel();
+    if (is_pesrecording) {
+        return demuxer->getselSubtitleChannel();
+    } else {
+        return ((DemuxerTS*)demuxer)->getSubID();
+    }
 }
 
 void Player::setSubtitleChannel(int newChannel)
 {
-  return demuxer->setDVBSubtitleStream(newChannel);
+    if (is_pesrecording) {
+        return demuxer->setDVBSubtitleStream(newChannel);
+    } else {
+        return ((DemuxerTS*)demuxer)->setSubID(newChannel);
+    }
 }
 
 int *Player::getTeletxtSubtitlePages()
@@ -201,7 +217,13 @@ int *Player::getTeletxtSubtitlePages()
 
 void Player::setAudioChannel(int newChannel, int type)
 {
-    demuxer->setAudioStream(newChannel);
+    if (is_pesrecording) {
+        demuxer->setAudioStream(newChannel);
+        return;
+    } else {
+        ((DemuxerTS*)demuxer)->setAID(newChannel,type);
+        return;
+    }
 }
 
 bool Player::toggleSubtitles()
@@ -233,6 +255,14 @@ void  Player::turnSubtitlesOn(bool ison) {
 
 }
 
+Channel Player::getDemuxerChannel() {
+    if (!is_pesrecording) {
+        return ((DemuxerTS*) demuxer)->getChannelInfo();
+    } 
+    return Channel(); //Should not happen!
+}
+
+
 // ----------------------------------- Externally called events
 
 void Player::play()
@@ -1149,6 +1179,7 @@ void Player::threadFeedScan()
   {
     // Fetch I-frames until we get one that can be displayed in good time
     // Repeat while clock0 + total_msec > clock2 + frameTimeOffset
+
     baseFrameNumber = currentFrameNumber;
     do
     {
index 3db0a11d5b641efcc67a8e72cc07c19e72bc024d..b339e8f6a48d1ce72952556881ce53825e5c5ea7 100644 (file)
--- a/player.h
+++ b/player.h
@@ -50,6 +50,7 @@ class Log;
 class Demuxer;
 class OSDReceiver;
 class DVBSubtitles;
+class Channel;
 
 class Player : public Thread_TYPE, public Callback
 {
@@ -57,7 +58,7 @@ class Player : public Thread_TYPE, public Callback
     Player(MessageQueue* messageQueue, void* messageReceiver, OSDReceiver* osdReceiver);
     virtual ~Player();
 
-    int init();
+    int init(bool IsPesRecording);
     int shutdown();
     void setStartFrame(ULONG frameNum);
     void setLengthBytes(ULLONG length);
@@ -89,6 +90,8 @@ class Player : public Thread_TYPE, public Callback
     int *getTeletxtSubtitlePages();
     int getCurrentAudioChannel();
     int getCurrentSubtitleChannel();
+    bool isPesRecording() {return is_pesrecording;};
+    Channel getDemuxerChannel();
 
    TeletextDecoderVBIEBU * getTeletextDecoder(){return teletext;};
 
@@ -153,6 +156,8 @@ class Player : public Thread_TYPE, public Callback
     bool startup;
     bool videoStartup;
 
+    bool is_pesrecording;
+
 #ifndef WIN32
     pthread_mutex_t mutex;
 #else
index ddd15ba56b29d14b13827664d4725f204b0c5e59..cdb10e31e8ae224e1495661e4ee1f0747c1e3689 100644 (file)
@@ -62,7 +62,7 @@ PlayerRadio::~PlayerRadio()
   if (initted) shutdown();
 }
 
-int PlayerRadio::init(ULLONG tlengthBytes, ULONG tlengthPackets)
+int PlayerRadio::init(ULLONG tlengthBytes, ULONG tlengthPackets, bool isPesRecording)
 {
   if (initted) return 0;
 #ifndef WIN32
@@ -71,7 +71,10 @@ int PlayerRadio::init(ULLONG tlengthBytes, ULONG tlengthPackets)
   mutex=CreateMutex(NULL,FALSE,NULL);
 #endif
 
-  demuxer = new DemuxerVDR();
+  if (isPesRecording)
+    demuxer = new DemuxerVDR();
+  else
+    demuxer = new DemuxerTS();
   if (!demuxer) return 0;
 
   if (!demuxer->init(this, audio, NULL, NULL, 0, 40000, 0))
index 3460a8f495765874e2c7f327d398de53082fedfb..dbfe1bb8b21bdc4252893df6299b19937bed1d29 100644 (file)
@@ -50,7 +50,7 @@ class PlayerRadio : public Thread_TYPE, public Callback
     PlayerRadio(MessageQueue* messageQueue, void* messageReceiver);
     virtual ~PlayerRadio();
 
-    int init(ULLONG lengthBytes, ULONG lengthPackets);
+    int init(ULLONG lengthBytes, ULONG lengthPackets, bool IsPesRecording);
     int shutdown();
     void setStartBytes(ULLONG startBytes);
 
index 9e8bdd3035dcd67d4b7ca9d49a8448ea0545b4a8..c0e2f2a24f3b22697006b18a84dbc1fc997c7ae9 100644 (file)
@@ -24,6 +24,7 @@
 #include "mark.h"
 #include "log.h"
 #include "demuxer.h"
+#include "demuxerts.h"
 #include "command.h"
 
 Recording* Recording::recInfoFor = NULL;
@@ -124,7 +125,7 @@ void Recording::loadMarks()
 bool Recording::isRadio()
 {
   ULONG lengthFrames = 0;
-  ULLONG lengthBytes = vdr->streamRecording(getFileName(), &lengthFrames);
+  ULLONG lengthBytes = vdr->streamRecording(getFileName(), &lengthFrames, &IsPesRecording);
   if (!lengthBytes || !lengthFrames) return false;
 
   UINT thisRead;
@@ -137,7 +138,11 @@ bool Recording::isRadio()
     return false;
   }
 
-  bool hasVideo = Demuxer::scanForVideo(buffer, thisRead);
+  bool hasVideo = false;
+  if (IsPesRecording)
+    hasVideo = Demuxer::scanForVideo(buffer, thisRead);
+  else
+    hasVideo = DemuxerTS::scanForVideo(buffer, thisRead);
 
   free(buffer);
 
index a79dc263f9580717964050262194a2909bdebbc6..e11428196df6e990dc0d61cd4b33ede9c7caf531 100644 (file)
@@ -48,6 +48,7 @@ class Recording
     void dropRecInfo();
 
     bool isRadio();
+    bool IsPesRecording;
 
     void loadMarks();
     int getPrevMark(int currentFrame);
diff --git a/vdr.cc b/vdr.cc
index 126b044fe21ccc8f1193f40ed1a78176d5d53918..5bd4fdd9d1ccbd34c5cff564a1661e81db8ddc6f 100644 (file)
--- a/vdr.cc
+++ b/vdr.cc
@@ -819,7 +819,7 @@ UCHAR* VDR::getBlock(ULLONG position, UINT maxAmount, UINT* amountReceived)
   return toReturn;
 }
 
-ULLONG VDR::streamRecording(char* fileName, ULONG* totalFrames)
+ULLONG VDR::streamRecording(char* fileName, ULONG* totalFrames, bool* IsPesRecording)
 {
   VDR_RequestPacket vrp;
   if (!vrp.init(VDR_STREAMRECORDING, true, strlen(fileName) + 1)) return 0;
@@ -830,11 +830,14 @@ ULLONG VDR::streamRecording(char* fileName, ULONG* totalFrames)
   
   ULLONG lengthBytes = vresp->extractULLONG();
   ULONG lengthFrames = vresp->extractULONG();
+  UCHAR isPesRecording = vresp->extractUCHAR();
   delete vresp;
 
-  logger->log("VDR", Log::DEBUG, "VDR said length is: %llu %lu", lengthBytes, lengthFrames);
-
   *totalFrames = lengthFrames;
+  *IsPesRecording = (isPesRecording);//convert Uchar to bool
+
+  logger->log("VDR", Log::DEBUG, "VDR said length is: %llu %lu, IsPesRecording %x", lengthBytes, lengthFrames, *IsPesRecording);
+
   return lengthBytes;
 }
 
@@ -895,7 +898,7 @@ bool VDR::getNextIFrame(ULONG frameNumber, ULONG direction, ULLONG* rfilePositio
 
   delete vresp;
 
-//  logger->log("VDR", Log::DEBUG, "VDR GNIF said %llu %lu %lu", *rfilePosition, *rframeNumber, *rframeLength);
+  logger->log("VDR", Log::DEBUG, "VDR GNIF said %llu %lu %lu", *rfilePosition, *rframeNumber, *rframeLength);
 
   return true;
 }
diff --git a/vdr.h b/vdr.h
index 8e9313a62a83c38a7b65a7a49e836b9ad7ef53f3..8bed05e7fb34d38405ab7b1c66cc9df57bfd2edd 100644 (file)
--- a/vdr.h
+++ b/vdr.h
@@ -158,7 +158,7 @@ class VDR : public Thread_TYPE, public EventDispatcher, public MediaProvider
     RecInfo*      getRecInfo(char* fileName);
     int           deleteRecording(char* fileName);
     char*         moveRecording(char* fileName, char* newPath);
-    ULLONG        streamRecording(char* fileName, ULONG* lengthFrames);
+    ULLONG        streamRecording(char* fileName, ULONG* lengthFrames, bool* IsPesRecording);
     ULLONG        positionFromFrameNumber(ULONG frameNumber);
     ULONG         frameNumberFromPosition(ULLONG position);
     bool          getNextIFrame(ULONG frameNumber, ULONG direction, ULLONG* rfilePosition, ULONG* rframeNumber, ULONG* rframeLength);
index 7834751ce4e3443362bc967ffd11a26882897c45..1f1b6358013a079ecdeecdecd0c4b0432472a2d5 100644 (file)
@@ -1405,7 +1405,6 @@ void VideoWin::SetAudioVolume(long volume)
 void VideoWin::displayIFrame(const UCHAR* buffer, UINT length)
 {
        if (!iframemode) EnterIframePlayback();
-
        if (!isdsinited()) return ;
 #ifdef DO_VIDEO
   IMediaSample* ms=NULL;
@@ -1433,8 +1432,10 @@ void VideoWin::displayIFrame(const UCHAR* buffer, UINT length)
   while (read_pos + 7 <= length)
   {
     pattern = ((pattern << 8) & 0xFFFFFFFF) | buffer[read_pos+3];
-    if (pattern < 0x000001E0 || pattern > 0x000001EF)
+    if (pattern < 0x000001E0 || pattern > 0x000001EF) {
       read_pos++;
+      continue;
+    }
     else
     {
          headerstrip=buffer[read_pos+8]+9/*is this right*/;
@@ -1443,7 +1444,8 @@ void VideoWin::displayIFrame(const UCHAR* buffer, UINT length)
         read_pos = length;
       else
       {
-                 if ((write_pos+packet_length-headerstrip)>ms_length) {
+                 if ( (headerstrip < packet_length) &&
+              (write_pos+packet_length-headerstrip)>ms_length) {
                          if (first) {
                   ms->SetSyncPoint(TRUE);
                   ms->SetDiscontinuity(TRUE);
index 9077665238f5e759d41d5b3614bcb92e53241fba..3308bb4439cb5952f253304c5d8364b98a6ad6d8 100644 (file)
@@ -119,12 +119,14 @@ void VRadioRec::go()
 {
   Log::getInstance()->log("VRadioRec", Log::DEBUG, "Starting stream: %s", myRec->getFileName());
   ULONG lengthFrames = 0;
-  ULLONG lengthBytes = vdr->streamRecording(myRec->getFileName(), &lengthFrames);
+  bool isPesRecording;
+  ULLONG lengthBytes = vdr->streamRecording(myRec->getFileName(), &lengthFrames, &isPesRecording);
+  myRec->IsPesRecording = isPesRecording;
 
   bool cantStart = false;
 
   if (!lengthBytes) cantStart = true;
-  else if (!player->init(lengthBytes, lengthFrames)) cantStart = true;
+  else if (!player->init(lengthBytes, lengthFrames, myRec->IsPesRecording)) cantStart = true;
   else
   {
     doBar(0);
index e5c1bc0b48e263504fbd32bc9644fea1a3d22bea..eaea08b9501aca55d293c427f272adfb4e87c7b7 100644 (file)
@@ -39,6 +39,7 @@
 #include "bitmap.h"
 #include "recinfo.h"
 #include "log.h"
+#include "channel.h"
  
 VVideoRec::VVideoRec(Recording* rec)
 {
@@ -49,12 +50,12 @@ VVideoRec::VVideoRec(Recording* rec)
   vas = NULL;
   vsummary = NULL;
 
-  player = new Player(Command::getInstance(), this, this);
-  player->init();
-
   videoMode = video->getMode();
   myRec = rec;
 
+  player = new Player(Command::getInstance(), this, this);
+  player->init(myRec->IsPesRecording);
+
   playing = false;
 
   startMargin = 0;
@@ -165,7 +166,9 @@ void VVideoRec::go(bool resume)
 
   Log::getInstance()->log("VVideoRec", Log::DEBUG, "Starting stream: %s at frame: %lu", myRec->getFileName(), startFrameNum);
   ULONG lengthFrames = 0;
-  ULLONG lengthBytes = vdr->streamRecording(myRec->getFileName(), &lengthFrames);
+  bool isPesRecording;
+  ULLONG lengthBytes = vdr->streamRecording(myRec->getFileName(), &lengthFrames, &isPesRecording);
+  myRec->IsPesRecording = isPesRecording;
   if (lengthBytes)
   {
     player->setLengthBytes(lengthBytes);
@@ -629,33 +632,129 @@ void VVideoRec::toggleChopSides()
 
 void VVideoRec::doAudioSelector()
 {
-  bool* availableMpegAudioChannels = player->getDemuxerMpegAudioChannels();
-  bool* availableAc3AudioChannels = NULL;
-  bool* availableSubtitleChannels = player->getDemuxerSubtitleChannels();
-  int *availableTTxtpages = player->getTeletxtSubtitlePages();
-  int currentAudioChannel = player->getCurrentAudioChannel();
-  if (Audio::getInstance()->supportsAc3())
-  {
-      availableAc3AudioChannels = player->getDemuxerAc3AudioChannels();
-  }
-  int subtitleChannel=player->getCurrentSubtitleChannel();
-  int subtitleType=0x10;
-  if (!(player)->isSubtitlesOn()) {
-      if ((player)->getTeletextDecoder()->getTeletxtView() &&
-          (player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode() 
-          ) {
-              subtitleChannel=(player)->getTeletextDecoder()->getPage();
-              subtitleType=0x11;
-          
-      } else {
-          subtitleType=0xFF; //turnedOff
-          subtitleChannel=0;
-      }
-  }
+    int subtitleChannel=player->getCurrentSubtitleChannel();
+    int subtitleType=0x10;
+    if (!(player)->isSubtitlesOn()) {
+        if ((player)->getTeletextDecoder()->getTeletxtView() &&
+            (player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode() 
+            ) {
+                subtitleChannel=(player)->getTeletextDecoder()->getPage();
+                subtitleType=0x11;
+      
+           } else {
+                subtitleType=0xFF; //turnedOff
+                subtitleChannel=0;
+          }
+    }
+    if (player->isPesRecording()) {
+        bool* availableMpegAudioChannels = player->getDemuxerMpegAudioChannels();
+        bool* availableAc3AudioChannels = NULL;
+        bool* availableSubtitleChannels = player->getDemuxerSubtitleChannels();
+        int *availableTTxtpages = player->getTeletxtSubtitlePages();
+        int currentAudioChannel = player->getCurrentAudioChannel();
+        if (Audio::getInstance()->supportsAc3())
+        {
+            availableAc3AudioChannels = player->getDemuxerAc3AudioChannels();
+        }
+        
+        vas = new VAudioSelector(this, availableMpegAudioChannels, availableAc3AudioChannels, currentAudioChannel,availableSubtitleChannels, availableTTxtpages,
+            subtitleChannel, subtitleType, myRec->recInfo);
+    } else {
+        // Draw the selector
+        Channel temp_channel=player->getDemuxerChannel();
+        RecInfo *cur_info= myRec->recInfo;
+        unsigned char numchan_recinfo = cur_info->numComponents;
+        unsigned char numchan_subtitles_siz = temp_channel.numSPids;
+        int mp_audcounter = 0;
+        int ac3_counter = 0;
+        int dvb_subcounter = 1;
+        
+        unsigned char type;
+        char* lang;
+        char* description;
+        int i;
+        for (i = 0; i < numchan_recinfo; i++)
+        {   
+            apid *ac=NULL;
+            type = cur_info->types[i];
+            lang = cur_info->languages[i];
+            description = cur_info->descriptions[i];
+            
+
+            if (cur_info->streams[i] == 2) {
+                switch (type)
+                {
+                case 1: //mpaudio mono
+                case 3: //mpaudio stereo
+                    if (mp_audcounter < temp_channel.numAPids) ac = &temp_channel.apids[mp_audcounter];
+                    
+                    mp_audcounter++;
+                    break;
+                case 5: //ac3
+                    if (ac3_counter < temp_channel.numDPids) ac = &temp_channel.dpids[ac3_counter];
+                    ac3_counter++;
+                    break;
+                }
+            } else if (cur_info->streams[i] == 3){
+                if (dvb_subcounter < numchan_subtitles_siz) ac = &temp_channel.spids[dvb_subcounter];
+            } else continue; //neither audio nor subtitle
+            if (ac)
+            {
+                if (description && (strlen(description) > 0))
+                {
+                    ac->name = new char[strlen(description) + 1];
+                    strcpy(ac->name, description);
+                    
+                } else if (lang && strlen(lang) > 0)
+                {
+                    ac->name = new char[strlen(lang) + 1];
+                    strcpy(ac->name, lang);
+                    
+                }
+            }
+        }
+        for (i=0;i<temp_channel.numAPids;i++) {
+            apid *ac=&temp_channel.apids[i];
+            if (ac->name==NULL) {
+                ac->name = new char[strlen(tr("unknown")) + 1];
+                strcpy(ac->name, tr("unknown"));
+            }
+        }
+        for (i=0;i<temp_channel.numDPids;i++) {
+            apid *ac=&temp_channel.dpids[i];
+            if (ac->name==NULL) {
+                ac->name = new char[strlen(tr("unknown")) + 1];
+                strcpy(ac->name, tr("unknown"));
+            }
+        }
+        for (i=0;i<temp_channel.numSPids;i++) {
+            apid *ac=&temp_channel.spids[i];
+            if (ac->name==NULL) {
+                ac->name = new char[strlen(tr("unknown")) + 1];
+                strcpy(ac->name, tr("unknown"));
+            }
+        }
+
+        vas = new VAudioSelector(this,&temp_channel , (player)->getCurrentAudioChannel(),
+            subtitleType,subtitleChannel,player->getTeletxtSubtitlePages());  
+         for (i=0;i<temp_channel.numAPids;i++) {
+            apid *ac=&temp_channel.apids[i];
+            delete[] ac->name;
+            ac->name=NULL;
+        }
+        for (i=0;i<temp_channel.numDPids;i++) {
+            apid *ac=&temp_channel.dpids[i];
+            delete[] ac->name;
+            ac->name=NULL;
+        }
+        for (i=0;i<temp_channel.numSPids;i++) {
+            apid *ac=&temp_channel.spids[i];
+            delete[] ac->name;
+            ac->name=NULL;
+        }
+    }
 
 
-  vas = new VAudioSelector(this, availableMpegAudioChannels, availableAc3AudioChannels, currentAudioChannel,availableSubtitleChannels, availableTTxtpages,
-      subtitleChannel, subtitleType, myRec->recInfo);
   vas->setBackgroundColour(barBlue);
   vas->setPosition(0, barRegion.y - 120);