]> git.vomp.tv Git - vompclient.git/commitdiff
Demuxer/stream changes, phase I: Make PESPacket independent from Demuxer
authorMark Calderbank <mark@vomp.tv>
Sat, 11 Aug 2007 16:30:16 +0000 (16:30 +0000)
committerMark Calderbank <mark@vomp.tv>
Sat, 11 Aug 2007 16:30:16 +0000 (16:30 +0000)
demuxer.cc
demuxer.h
demuxerts.cc
demuxerts.h
demuxervdr.cc
demuxervdr.h

index e925834cc372d9191a34d5c1e16d18cee7c48aee..5054dfb72e34cc3954cbc1f92a7fcd3e66e09245 100644 (file)
@@ -1,5 +1,6 @@
 /*
-    Copyright 2005-2006 Mark Calderbank
+    Copyright 2005-2007 Mark Calderbank
+    Copyright 2007 Marten Richter (AC3 support)
 
     This file is part of VOMP.
 
 #define __BYTE_ORDER __LITTLE_ENDIAN
 #endif
 
-#if __BYTE_ORDER == __BIG_ENDIAN
 #define DEMUXER_SEQ_HEAD 0x000001B3
-#else
-#define DEMUXER_SEQ_HEAD 0xB3010000
-#endif
-
 #define DEMUXER_PIC_HEAD 0x00000101
 
 #define SEEK_THRESHOLD 150000 // About 1.5 seconds
 
+// Statics
 const int Demuxer::FrameRates[9] = { 0, 23, 24, 25, 29, 30, 50, 59, 60 };
-const ULLONG Demuxer::PESPacket::PTS_INVALID = (1LL << 33);
-
+const ULLONG PESPacket::PTS_INVALID = (1LL << 33);
 Demuxer* Demuxer::instance = NULL;
 
+// PESPacket methods
+PESPacket::PESPacket()
+{
+  data[0] = 0x00;
+  data[1] = 0x00;
+  data[2] = 0x01;
+  init(0);
+}
+
+void PESPacket::init(UCHAR type)
+{
+  length = 0; size = 6;
+  data[3] = type;
+  data[4] = data[5] = 0;
+  packetType = type;
+  pts = PTS_INVALID;
+  seq_header = 1; // Unknown seq_header status
+}
+
+void PESPacket::truncate()
+{
+  init(packetType);
+}
+
+int PESPacket::write(UCHAR *buf, int len)
+{
+  if (length + len > 0xFFFA) return 0;
+  memcpy(data+length+6, buf, len);
+  length += len;
+  size += len;
+  data[4] = (length >> 8);
+  data[5] = (length & 0xFF);
+  // We have added data - reset seq_header indicator if necessary
+  if (seq_header == 0) seq_header = 1; // Reset to 'unknown'
+  // Extract PTS if this is the first write to reach 14 bytes
+  if (size - len < 14 && size >= 14 && data[7] & 0x80 &&
+       ( (packetType >= Demuxer::PESTYPE_AUD0 &&
+          packetType <= Demuxer::PESTYPE_AUDMAX)
+         ||
+         (packetType >= Demuxer::PESTYPE_VID0 &&
+          packetType <= Demuxer::PESTYPE_VIDMAX)
+       ))
+  {
+    // 14 bytes are now in, and PTS_DTS_flags indicate PTS
+    pts = ( (ULLONG)(data[ 9] & 0x0E) << 29 ) |
+          ( (ULLONG)(data[10])        << 22 ) |
+          ( (ULLONG)(data[11] & 0xFE) << 14 ) |
+          ( (ULLONG)(data[12])        <<  7 ) |
+          ( (ULLONG)(data[13] & 0xFE) >>  1 );
+  }
+  return 1;
+}
+
+UCHAR PESPacket::operator[] (UINT index)
+{
+  if (index >= size)
+    return 0;
+  else
+    return data[index];
+}
+
+UINT PESPacket::findPictureHeader()
+{
+  if (size < 12) return 0;
+  UINT pattern = ( ((UINT)data[ 8] << 24) |
+                   ((UINT)data[ 9] << 16) |
+                   ((UINT)data[10] <<  8) |
+                    (UINT)data[11]  );
+  UINT pos = 11;
+  while (pattern != DEMUXER_PIC_HEAD)
+  {
+    if (++pos >= size) return 0;
+    pattern = (pattern << 8) | data[pos];
+  }
+  return pos-3;
+}
+
+UINT PESPacket::findSeqHeader()
+{
+  if (seq_header != 1) return seq_header;
+  if (size < 12) return 0;
+  UINT pattern = ( ((UINT)data[ 8] << 24) |
+                   ((UINT)data[ 9] << 16) |
+                   ((UINT)data[10] <<  8) |
+                    (UINT)data[11]  );
+  UINT pos = 11;
+  while (pattern != DEMUXER_SEQ_HEAD)
+  {
+    if (++pos >= size)
+    {
+      seq_header = 0;
+      return 0;
+    }
+    pattern = (pattern << 8) | data[pos];
+  }
+  seq_header = pos - 3;
+  return seq_header;
+}
+
+// Demuxer methods
 Demuxer::Demuxer()
 {
   if (instance) return;
@@ -166,136 +262,89 @@ bool Demuxer::writeVideo()
   return videostream.drain();
 }
 
-Demuxer::PESPacket::PESPacket()
-{
-  data[0] = 0x00;
-  data[1] = 0x00;
-  data[2] = 0x01;
-  init(0);
-}
-
-void Demuxer::PESPacket::init(UCHAR type)
-{
-  length = submitted = 0;
-  size = 6; closed = false;
-  data[3] = type;
-  data[4] = data[5] = 0;
-  packetType = type;
-  pts = PTS_INVALID;
-  seq_header = false;
-}
-
-void Demuxer::PESPacket::truncate()
-{
-  init(packetType);
-}
-
-int Demuxer::PESPacket::write(UCHAR *buf, int len)
-{
-  if (closed) return 0;
-  if (length + len > 0xFFFA) return 0;
-  memcpy(data+length+6, buf, len);
-  length += len;
-  size += len;
-  data[4] = (length >> 8);
-  data[5] = (length & 0xFF);
-  return 1;
-}
-
-int Demuxer::PESPacket::submit()
+bool Demuxer::submitPacket(PESPacket& packet)
 {
-  if (submitted >= size) return 0;
-  if (!closed) parseDetails();
+  UINT sent = 0;
+  UCHAR packet_type = packet.getPacketType();
 
-  closed = true;
-  Demuxer* dx = Demuxer::getInstance();
-  int sent = 0;
-  if (packetType >= PESTYPE_VID0 && packetType <= PESTYPE_VIDMAX)
+  if (packet_type >= PESTYPE_VID0 && packet_type <= PESTYPE_VIDMAX)
   {
-    if (dx->video_current == -1) dx->video_current = packetType;
-    if (dx->video_current == packetType && !dx->vid_seeking)
-      sent = dx->videostream.put(data+submitted, size-submitted, MPTYPE_VIDEO);
+    if (video_current == -1) video_current = packet_type;
+    if (video_current == packet_type && !vid_seeking)
+      sent = videostream.put(packet.getData(), packet.getSize(), MPTYPE_VIDEO);
     else
-      sent = size-submitted;
+      sent = packet.getSize();
   }
-  else if (packetType >= PESTYPE_AUD0 && packetType <= PESTYPE_AUDMAX)
+  else if (packet_type >= PESTYPE_AUD0 && packet_type <= PESTYPE_AUDMAX)
   {
-    if (dx->audio_current == -1) dx->audio_current = packetType;
-
-    dx->avail_mpaudchan[packetType-PESTYPE_AUD0]=true;
-
-    if (dx->audio_current == packetType && !dx->aud_seeking)
-      sent = dx->audiostream.put(data+submitted, size-submitted, MPTYPE_MPEG_AUDIO);
+    if (audio_current == -1) audio_current = packet_type;
+    avail_mpaudchan[packet_type - PESTYPE_AUD0] = true;
+    if (audio_current == packet_type && !aud_seeking)
+      sent = audiostream.put(packet.getData(), packet.getSize(), MPTYPE_MPEG_AUDIO);
     else
-      sent = size-submitted;
+      sent = packet.getSize();
   }
-  else if (packetType == PESTYPE_PRIVATE_1)
+  else if (packet_type == PESTYPE_PRIVATE_1)
   {
-    if (substream >= PESTYPE_SUBSTREAM_AC30 && substream <= PESTYPE_SUBSTREAM_AC3MAX)
+    if (packet.getSubstream() >= PESTYPE_SUBSTREAM_AC30 &&
+        packet.getSubstream() <= PESTYPE_SUBSTREAM_AC3MAX)
     {
-      dx->avail_ac3audchan[substream-PESTYPE_SUBSTREAM_AC30]=true;
-      if (substream == dx->audio_current)
+      avail_ac3audchan[packet.getSubstream() - PESTYPE_SUBSTREAM_AC30] = true;
+      if (packet.getSubstream() == audio_current)
       {
-        sent = dx->audiostream.put(data+submitted,size-submitted,(dx->ispre_1_3_19)?MPTYPE_AC3_PRE13:MPTYPE_AC3);
+        sent = audiostream.put(packet.getData(), packet.getSize(), (ispre_1_3_19)? MPTYPE_AC3_PRE13 : MPTYPE_AC3);
       }
       else
       {
-        sent = size-submitted;
+        sent = packet.getSize();
       }
     }
   }
   else
   {
-    sent = size-submitted;
+    sent = packet.getSize();
   }
 
-  submitted += sent;
-  if (submitted < size) // Stream is full.
-    return 0;
+  if (sent < packet.getSize()) // Stream is full.
+    return false;
   else
-    return 1;
+    return true;
 }
 
-void Demuxer::PESPacket::parseDetails()
+void Demuxer::parsePacketDetails(PESPacket& packet)
 {
-  Demuxer* dx = Demuxer::getInstance();
-  if (packetType >= PESTYPE_AUD0 && packetType <= PESTYPE_AUDMAX)
+  if (packet.getPacketType() >= PESTYPE_AUD0 &&
+      packet.getPacketType() <= PESTYPE_AUDMAX)
   {
     // Extract audio PTS if it exists
-    if ( size >= 14 && (data[7] & 0x80) ) // PTS_DTS_flags indicate PTS
+    if (packet.hasPTS())
     {
-      dx->audio_pts = pts = ( (ULLONG)(data[9] & 0x0E)  << 29 ) |
-                            ( (ULLONG)(data[10])        << 22 ) |
-                            ( (ULLONG)(data[11] & 0xFE) << 14 ) |
-                            ( (ULLONG)(data[12])        <<  7 ) |
-                            ( (ULLONG)(data[13] & 0xFE) >>  1 );
-
+      audio_pts = packet.getPTS();
       // We continue to seek on the audio if the video PTS that we
       // are trying to match is ahead of the audio PTS by at most
       // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
-      if (dx->aud_seeking && !dx->vid_seeking &&
-          !( (dx->video_pts_seek > dx->audio_pts &&
-              dx->video_pts_seek - dx->audio_pts < SEEK_THRESHOLD)
+      if (aud_seeking && !vid_seeking &&
+          !( (video_pts_seek > audio_pts &&
+              video_pts_seek - audio_pts < SEEK_THRESHOLD)
               ||
-             (dx->video_pts_seek < dx->audio_pts &&
-              dx->video_pts_seek + (1LL<<33) -
-                                   dx->audio_pts < SEEK_THRESHOLD) ))
+             (video_pts_seek < audio_pts &&
+              video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
       {
-        dx->aud_seeking = 0;
+        aud_seeking = 0;
         Log::getInstance()->log("Demuxer", Log::DEBUG,
-            "Leaving  audio sync: Audio PTS = %llu", dx->audio_pts);
+            "Leaving  audio sync: Audio PTS = %llu", audio_pts);
       }
     }
   }
-  else if (packetType == PESTYPE_PRIVATE_1) //Private Stream
+  else if (packet.getPacketType() == PESTYPE_PRIVATE_1) // Private stream
   {
     //Inspired by vdr's device.c
-    int payload_begin = data[8]+9;
-    unsigned char substream_id = data[payload_begin];
+    int payload_begin = packet[8]+9;
+    unsigned char substream_id = packet[payload_begin];
     unsigned char substream_type = substream_id & 0xF0;
     unsigned char substream_index = substream_id & 0x1F;
 pre_1_3_19_Recording: //This is for old recordings stuff
-    if (dx->ispre_1_3_19)
+    if (ispre_1_3_19)
     {
       substream_id = PESTYPE_PRIVATE_1;
       substream_type = 0x80;
@@ -309,107 +358,77 @@ pre_1_3_19_Recording: //This is for old recordings stuff
       case 0xA0: //LPCM //not supported yet, is there any LPCM transmissio out there?
         break;
       case 0x80: //ac3, currently only one ac3 track per recording supported
-        substream=substream_type+substream_index;
+        packet.setSubstream(substream_type+substream_index);
 
         // Extract audio PTS if it exists
-        if ( size >= 14 && (data[7] & 0x80) ) // PTS_DTS_flags indicate PTS
+        if (packet.hasPTS())
         {
-          dx->audio_pts = pts = ( (ULLONG)(data[9] & 0x0E)  << 29 ) |
-                        ( (ULLONG)(data[10])        << 22 ) |
-                        ( (ULLONG)(data[11] & 0xFE) << 14 ) |
-                        ( (ULLONG)(data[12])        <<  7 ) |
-                        ( (ULLONG)(data[13] & 0xFE) >>  1 );
+          audio_pts = packet.getPTS();
           // We continue to seek on the audio if the video PTS that we
           // are trying to match is ahead of the audio PTS by at most
           // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
-          if (dx->aud_seeking && !dx->vid_seeking &&
-              !( (dx->video_pts_seek > dx->audio_pts &&
-              dx->video_pts_seek - dx->audio_pts < SEEK_THRESHOLD)
+          if (aud_seeking && !vid_seeking &&
+              !( (video_pts_seek > audio_pts &&
+                  video_pts_seek - audio_pts < SEEK_THRESHOLD)
               ||
-              (dx->video_pts_seek < dx->audio_pts &&
-                    dx->video_pts_seek + (1LL<<33) -
-                    dx->audio_pts < SEEK_THRESHOLD) ))
+              (video_pts_seek < audio_pts &&
+                    video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
           {
-            dx->aud_seeking = 0;
-            Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving  audio sync: Audio PTS = %llu", dx->audio_pts);
+            aud_seeking = 0;
+            Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving  audio sync: Audio PTS = %llu", audio_pts);
           }
         }
         break;
       default:
-        if (!dx->ispre_1_3_19)
+        if (!ispre_1_3_19)
         {
-          dx->ispre_1_3_19=true; //switching to compat mode
+          ispre_1_3_19=true; //switching to compat mode
           goto pre_1_3_19_Recording;
         }
         else
         {
-          substream=0;
+          packet.setSubstream(0);
         }
         break;
     }
   }
-  else if (packetType >= PESTYPE_VID0 && packetType <= PESTYPE_VIDMAX)
+  else if (packet.getPacketType() >= PESTYPE_VID0 &&
+           packet.getPacketType() <= PESTYPE_VIDMAX)
   {
     // Extract video PTS if it exists
-    if ( size >= 14 && (data[7] & 0x80) ) // PTS_DTS_flags indicate PTS
-    {
-      dx->video_pts = pts = ( (ULLONG)(data[9] & 0x0E)  << 29 ) |
-                            ( (ULLONG)(data[10])        << 22 ) |
-                            ( (ULLONG)(data[11] & 0xFE) << 14 ) |
-                            ( (ULLONG)(data[12])        <<  7 ) |
-                            ( (ULLONG)(data[13] & 0xFE) >>  1 );
-    }
+    if (packet.hasPTS()) video_pts = packet.getPTS();
 
-    // Now, scan for a sequence header and extract information
-    UINT pos = 9; // Start searching from byte 9
-    while (pos < size - 5)
+    // If there is a sequence header, extract information
+    UINT pos = packet.findSeqHeader();
+    if (pos > 1)
     {
-      UINT pattern = *(UINT*)(data+pos);
-      if (pattern == DEMUXER_SEQ_HEAD)
+      pos += 4;
+      if (pos+6 >= packet.getSize()) return;
+      horizontal_size = ((int)packet[pos] << 4) | ((int)packet[pos+1] >> 4);
+      vertical_size = (((int)packet[pos+1] & 0xf) << 8) | (int)packet[pos+2];
+      setAspectRatio((enum AspectRatio)(packet[pos+3] >> 4));
+      frame_rate = packet[pos+3] & 0x0f;
+      if (frame_rate >= 1 && frame_rate <= 8)
+        frame_rate = FrameRates[frame_rate];
+      else
+        frame_rate = 0;
+      bit_rate = ((int)packet[pos+4] << 10) |
+                 ((int)packet[pos+5] << 2) |
+                 ((int)packet[pos+6] >> 6);
+      if (vid_seeking)
       {
-        seq_header = true;
-        pos += 4;
-        if (pos+6 >= size) return;
-        dx->horizontal_size = ((int)data[pos] << 4) | ((int)data[pos+1] >> 4);
-        dx->vertical_size = (((int)data[pos+1] & 0xf) << 8) | (int)data[pos+2];
-        dx->setAspectRatio((enum AspectRatio)(data[pos+3] >> 4));
-        dx->frame_rate = data[pos+3] & 0x0f;
-        if (dx->frame_rate >= 1 && dx->frame_rate <= 8)
-          dx->frame_rate = FrameRates[dx->frame_rate];
-        else
-          dx->frame_rate = 0;
-        dx->bit_rate = ((int)data[pos+4] << 10) |
-                   ((int)data[pos+5] << 2) |
-                   ((int)data[pos+6] >> 6);
-        if (dx->vid_seeking)
-        {
-          dx->vid_seeking = 0;
-          dx->video_pts_seek = dx->video_pts;
-          Log::getInstance()->log("Demuxer", Log::DEBUG,
-              "Entering audio sync: Video PTS = %llu", dx->video_pts);
-          Log::getInstance()->log("Demuxer", Log::DEBUG,
-              "Entering audio sync: Audio PTS = %llu", dx->audio_pts);
-        }
-        return;
+        vid_seeking = 0;
+        video_pts_seek = video_pts;
+        Log::getInstance()->log("Demuxer", Log::DEBUG,
+            "Entering audio sync: Video PTS = %llu", video_pts);
+        Log::getInstance()->log("Demuxer", Log::DEBUG,
+            "Entering audio sync: Audio PTS = %llu", audio_pts);
       }
-      else pos++;
+      return;
     }
   }
 }
 
-UINT Demuxer::PESPacket::findPictureHeader()
-{
-  if (size < 12) return 0;
-  UINT pattern = *(UINT*)(data+8);
-  UINT pos = 11;
-  while (pattern != DEMUXER_PIC_HEAD)
-  {
-    if (++pos >= size) return 0;
-    pattern = (pattern << 8) | data[pos];
-  }
-  return pos-3;
-}
-
 UINT Demuxer::stripAudio(UCHAR* buf, UINT len)
 {
   UINT read_pos = 0, write_pos = 0;
index 104ed9665f9cd0f89367d7c31afd8f8a55a8d249..10ffee4f4695c0dda899b898b56dc66b8150b85f 100644 (file)
--- a/demuxer.h
+++ b/demuxer.h
@@ -1,5 +1,6 @@
 /*
-    Copyright 2005-2006 Mark Calderbank
+    Copyright 2005-2007 Mark Calderbank
+    Copyright 2007 Marten Richter (AC3 support)
 
     This file is part of VOMP.
 
@@ -20,8 +21,8 @@
 
 /*
 
-Thanks goes to Jon Gettler of the MVPMC project and Stephen Rice for
-the demuxer in mvpmc. It was used in the creation of this Demuxer,
+Thanks go to Jon Gettler of the MVPMC project and Stephen Rice for
+the demuxer in mvpmc. It was used in the creation of this demuxer;
 however, no code was copied verbatim.
 
 */
@@ -37,37 +38,39 @@ however, no code was copied verbatim.
 #include "callback.h"
 #include "draintarget.h"
 
-#define PES_AUDIO_START 0xc0
-#define PES_AUDIO_END 0xcf
+class PESPacket
+{
+  public:
+    PESPacket();
+    void init(UCHAR type);
+    void truncate();
+    int  write(UCHAR* buf, int len);
+
+    UCHAR operator[] (UINT index); // return data[index] if in bounds, else 0
+                       // so no proper error condition but never mind for now
+    const UCHAR* getData() { return data; }
+    UINT getLength() { return length; }
+    UINT getSize() { return size; }
+    UCHAR getPacketType() { return packetType; }
+    void setSubstream(UCHAR s) { substream = s; }
+    UCHAR getSubstream() { return substream; }
+    bool hasPTS() { return (pts != PTS_INVALID); }
+    ULLONG getPTS() { return pts; }
+
+    UINT findPictureHeader();
+    UINT findSeqHeader();
+    static const ULLONG PTS_INVALID;
+  protected:
+    UCHAR data[0x10000];
+    UINT length, size;
+    UCHAR packetType;
+    UCHAR substream;
+    ULLONG pts;
+    UINT seq_header; // 0 = no, 1 = unknown, else = header offset
+};
 
 class Demuxer
 {
-protected:
-  class PESPacket
-  {
-    public:
-      PESPacket();
-      void init(UCHAR type);
-      void truncate();
-      int  write(UCHAR* buf, int len);
-      int  submit();
-    protected:
-      UCHAR data[0x10000];
-      UINT length, size;
-      bool closed;
-      UCHAR packetType;
-      UCHAR substream; //for ac3
-      ULLONG pts;
-      bool seq_header;
-      UINT submitted;
-      virtual void parseDetails();
-      UINT findPictureHeader();
-
-
-      static const ULLONG PTS_INVALID;
-  };
-  friend class PESPacket;
-
   public:
     Demuxer();
     virtual ~Demuxer();
@@ -119,34 +122,6 @@ protected:
     // *static function*
     static bool scanForVideo(UCHAR* buf, UINT len);
 
-  protected:
-    // General demuxer objects and status indicators
-    static Demuxer* instance;
-    Stream videostream;
-    Stream audiostream;
-    int shutdown();
-    bool initted;
-    bool vid_seeking;
-    bool aud_seeking;
-    int video_current, audio_current;
-
-    // Video stream information
-    void setAspectRatio(enum AspectRatio);
-    Callback* callback;
-
-    int horizontal_size;
-    int vertical_size;
-    enum AspectRatio aspect_ratio;
-    int arcnt;
-    int frame_rate;
-    int bit_rate;
-    ULLONG video_pts;
-    ULLONG video_pts_seek;
-    ULLONG audio_pts;
-
-    // Constants
-    static const int FrameRates[9];
-
     enum PESTYPE
     {
       PESTYPE_PRIVATE_1 = 0xBD,
@@ -178,6 +153,38 @@ protected:
       PESTYPE_SUBSTREAM_AC3MAX = PESTYPE_SUBSTREAM_AC37
     };
 
+  protected:
+    // Operations on PES packets
+    bool submitPacket(PESPacket&);
+    void parsePacketDetails(PESPacket&);
+
+    // General demuxer objects and status indicators
+    static Demuxer* instance;
+    Stream videostream;
+    Stream audiostream;
+    int shutdown();
+    bool initted;
+    bool vid_seeking;
+    bool aud_seeking;
+    int video_current, audio_current;
+
+    // Video stream information
+    void setAspectRatio(enum AspectRatio);
+    Callback* callback;
+
+    int horizontal_size;
+    int vertical_size;
+    enum AspectRatio aspect_ratio;
+    int arcnt;
+    int frame_rate;
+    int bit_rate;
+    ULLONG video_pts;
+    ULLONG video_pts_seek;
+    ULLONG audio_pts;
+
+    // Constants
+    static const int FrameRates[9];
+
     bool ispre_1_3_19;
     bool avail_mpaudchan[PESTYPE_AUDMAX-PESTYPE_AUD0+1];
     bool avail_ac3audchan[PESTYPE_SUBSTREAM_AC3MAX-PESTYPE_SUBSTREAM_AC30+1];
index da454f3d34b5216a518eaa9103cdfe7f6095fac5..f139d56123f7c7b0ba5c322e863bf22b8ecb650e 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2006 Mark Calderbank
+    Copyright 2006-2007 Mark Calderbank
 
     This file is part of VOMP.
 
@@ -29,6 +29,7 @@ DemuxerTS::DemuxerTS(int p_vID, int p_aID)
 void DemuxerTS::flush()
 {
   partPacket = 0;
+  parsed = false;
   Demuxer::flush();
   vPacket.init(0xE0);
   aPacket.init(0xC0);
@@ -177,10 +178,27 @@ int DemuxerTS::processTS(UCHAR* buf)
   {
     int rc = 1;
 
-    if (pid == vID) rc = vPacket.submit();
-    if (pid == aID) rc = aPacket.submit();
+    if (pid == vID)
+    {
+      if (!parsed)
+      {
+        parsePacketDetails(vPacket);
+        parsed = true;
+      }
+      rc = submitPacket(vPacket);
+    }
+    if (pid == aID)
+    {
+      if (!parsed)
+      {
+        parsePacketDetails(aPacket);
+        parsed = true;
+      }
+      rc = submitPacket(aPacket);
+    }
     if (rc == 0) return 0;
 
+    parsed = false;
     if (pid == vID)
     {
       vPacket.init(0xE0);
@@ -200,8 +218,13 @@ int DemuxerTS::processTS(UCHAR* buf)
   {
     if (packet->write(buf, datalen) == 0)
     { // Writing to packet failed. It has overflowed.
-      if (packet->submit() == 0)
-        return 0;
+      if (!parsed)
+      {
+        parsePacketDetails(*packet);
+        parsed = true;
+      }
+      if (submitPacket(*packet) == 0) return 0;
+      parsed = false;
       packet->truncate();
       packet->write((UCHAR*)"\200\000\000", 3);
       packet->write(buf, datalen);
index 0303917bf23a44b830c464d9ed6835c8f94582c6..9a6ede00bdb499910a7084fb866d20016dc245a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2006 Mark Calderbank
+    Copyright 2006-2007 Mark Calderbank
 
     This file is part of VOMP.
 
@@ -43,6 +43,7 @@ class DemuxerTS : public Demuxer
 
     UCHAR store[TS_SIZE]; // Storage for partial packets
     int partPacket;    // Length of partial packet stored from previous put()
+    bool parsed;       // Whether PES packet to be submitted has been parsed yet
     PESPacket vPacket; // Video PES packet under construction
     PESPacket aPacket; // Audio PES packet under construction
     int vID, aID;      // TS IDs for video/audio
index 12ccbaa093477cbfd31ae582755d217cb383b2d5..715433aa72fb359ab364ffd6341a0fb935041c6e 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2005-2006 Mark Calderbank
+    Copyright 2005-2007 Mark Calderbank
 
     This file is part of VOMP.
 
@@ -155,7 +155,7 @@ int DemuxerVDR::put(UCHAR* buf, int len)
   int ret = 0;    // return number of bytes consumed
   if (submitting)
   {
-    if (packet.submit() == 0) // Still full!
+    if (submitPacket(packet) == 0) // Still full!
       return ret;
     else
       submitting = false;
@@ -168,7 +168,8 @@ int DemuxerVDR::put(UCHAR* buf, int len)
       packet.write(buf, state);
       buf += state; len -= state; ret += state;
       state = 0;
-      if (packet.submit() == 0) // Stream is full
+      parseVDRPacketDetails();
+      if (submitPacket(packet) == 0) // Stream is full
       {
         submitting = true;
         return ret;
@@ -228,7 +229,8 @@ int DemuxerVDR::put(UCHAR* buf, int len)
         packet.write(buf, packetLength);
         buf += packetLength; len -= packetLength; ret += packetLength;
         state = 0;
-        if (packet.submit() == 0) // Stream is full
+        parseVDRPacketDetails();
+        if (submitPacket(packet) == 0) // Stream is full
         {
           submitting = true;
           return ret;
@@ -294,49 +296,49 @@ Log::getInstance()->log("Demuxer", Log::DEBUG, "STILL USING OLD REF");
     return ref_frame + difference * Video::getInstance()->getFPS() / 90000;
 }
 
-void DemuxerVDR::PESPacketVDR::parseDetails()
+void DemuxerVDR::parseVDRPacketDetails()
 {
-  DemuxerVDR* dx = (DemuxerVDR*)(DemuxerVDR::getInstance());
-  PESPacket::parseDetails();
+  parsePacketDetails(packet);
 
-  if (dx->packetCounting &&
-      packetType >= PESTYPE_AUD0 && packetType <= PESTYPE_AUDMAX)
+  if (packetCounting && packet.getPacketType() >= PESTYPE_AUD0 &&
+                        packet.getPacketType() <= PESTYPE_AUDMAX)
   {
-    dx->packetNumber++;
+    packetNumber++;
   }
 
-  if (dx->frameCounting && findPictureHeader() &&
-      packetType >= PESTYPE_VID0 && packetType <= PESTYPE_VIDMAX)
+  if (frameCounting && packet.findPictureHeader() &&
+      packet.getPacketType() >= PESTYPE_VID0 &&
+      packet.getPacketType() <= PESTYPE_VIDMAX)
   {
-    ULONG frame_num = (dx->frameNumber)++;
-    if (seq_header && pts != PTS_INVALID)
+    ULONG frame_num = (frameNumber)++;
+    if (packet.findSeqHeader() > 1 && packet.hasPTS())
     {
       PTSMapEntry me;
-      dx->pts_map_mutex.Lock();
-      if (dx->pts_map.empty())
+      pts_map_mutex.Lock();
+      if (pts_map.empty())
       {
-        me.pts = pts;
+        me.pts = packet.getPTS();
         me.frame = frame_num;
-        dx->pts_map_mutex.Unlock();
+        pts_map_mutex.Unlock();
 Log::getInstance()->log("Demuxer", Log::DEBUG, "+* PTS INIT *+ %llu %u", me.pts, me.frame);
-        dx->pts_map_mutex.Lock();
-        dx->pts_map.push_front(me);
+        pts_map_mutex.Lock();
+        pts_map.push_front(me);
       }
-      me = dx->pts_map.front();
-      dx->pts_map_mutex.Unlock();
+      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, pts) > PTS_JUMP_MARGIN) // PTS jump!
+      if (PTSDistance(pts_expected, packet.getPTS()) > PTS_JUMP_MARGIN) // PTS jump!
       {
-Log::getInstance()->log("Demuxer", Log::DEBUG, "+* PTS JUMP *+ %llu %u", pts, frame_num);
-        me.pts = pts;
+Log::getInstance()->log("Demuxer", Log::DEBUG, "+* PTS JUMP *+ %llu %u", packet.getPTS(), frame_num);
+        me.pts = packet.getPTS();
         me.frame = frame_num;
-        dx->pts_map_mutex.Lock();
-        dx->pts_map.push_front(me);
-        dx->pts_map_mutex.Unlock();
+        pts_map_mutex.Lock();
+        pts_map.push_front(me);
+        pts_map_mutex.Unlock();
       }
     }
   }
index cdfa9149871b8502ad3607d16398bdb2747139fc..27230e7c982cdb11f9848e0322e1774e5175d116 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2005-2006 Mark Calderbank
+    Copyright 2005-2007 Mark Calderbank
 
     This file is part of VOMP.
 
 
 class DemuxerVDR : public Demuxer
 {
-  class PESPacketVDR : public PESPacket
-  {
-    void parseDetails();
-  };
-  friend class PESPacketVDR;
-
   public:
     DemuxerVDR();
     void reset();
@@ -50,7 +44,7 @@ class DemuxerVDR : public Demuxer
     int state;
     bool submitting;
     int packetLength;
-    PESPacketVDR packet;
+    PESPacket packet;
 
     ULONG frameNumber, packetNumber;
     bool frameCounting, packetCounting;
@@ -58,6 +52,8 @@ class DemuxerVDR : public Demuxer
     typedef std::deque<PTSMapEntry> PTSMap;
     PTSMap pts_map;
     Mutex pts_map_mutex;
+
+    void parseVDRPacketDetails();
 };
 
 #endif