--- ../vdr-1.5.10-orig/remux.h	2007-09-02 12:19:06.000000000 +0200
+++ remux.h	2007-10-24 23:45:55.000000000 +0200
@@ -33,6 +33,7 @@ ePesHeader AnalyzePesHeader(const uchar 
 #define MAXTRACKS 64
 
 class cTS2PES;
+class cAudioIndexer;
 
 class cRemux {
 private:
@@ -45,6 +46,7 @@ private:
   int numTracks;
   cRingBufferLinear *resultBuffer;
   int resultSkipped;
+  cAudioIndexer *audioIndexer;
   int GetPid(const uchar *Data);
 public:
   cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure = false);
@@ -79,6 +81,7 @@ public:
   static void SetBrokenLink(uchar *Data, int Length);
   static int GetPacketLength(const uchar *Data, int Count, int Offset);
   static int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType);
+  static int GetAudioFrameDuration(const uchar *Data, int Count, int *TrackIndex = NULL);
   };
 
 #endif // __REMUX_H
--- ../vdr-1.5.10-orig/remux.c	2007-09-22 14:08:22.000000000 +0200
+++ remux.c	2007-10-24 23:45:55.000000000 +0200
@@ -19,6 +19,7 @@
 #include "channels.h"
 #include "shutdown.h"
 #include "tools.h"
+#include "recording.h"
 
 ePesHeader AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader)
 {
@@ -690,12 +691,13 @@ private:
   int frameTodo;
   int frameSize;
   int cid;
-  static bool IsValidAudioHeader(uint32_t Header, bool Mpeg2, int *FrameSize = NULL);
+  static bool IsValidAudioHeader(uint32_t Header, bool Mpeg2, int *FrameSize = NULL, int *FrameDuration = NULL);
 public:
   cAudioRepacker(int Cid);
   virtual void Reset(void);
   virtual void Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count);
   virtual int BreakAt(const uchar *Data, int Count);
+  static int GetFrameDuration(const uchar *Data, int Count, int *TrackIndex = NULL);
   };
 
 int cAudioRepacker::bitRates[2][3][16] = { // all values are specified as kbits/s
@@ -711,6 +713,25 @@ int cAudioRepacker::bitRates[2][3][16] =
   }
   };
 
+int cAudioRepacker::GetFrameDuration(const uchar *Data, int Count, int *TrackIndex)
+{
+  int PesPayloadOffset = 0;
+  ePesHeader PH = AnalyzePesHeader(Data, Count, PesPayloadOffset);
+  if (PH < phMPEG1)
+     return -1;
+
+  const uchar *Payload = Data + PesPayloadOffset;
+  const int PayloadCount = Count - PesPayloadOffset;
+
+  int FrameDuration = -1;
+  if ((Data[3] & 0xE0) == 0xC0 && PayloadCount >= 4) {
+     if (IsValidAudioHeader(((Payload[0] << 8 | Payload[1]) << 8 | Payload[2]) << 8 | Payload[3], PH == phMPEG2, NULL, &FrameDuration) && TrackIndex)
+        *TrackIndex = Data[3] - 0xC0;
+     }
+
+  return FrameDuration;
+}
+
 cAudioRepacker::cAudioRepacker(int Cid)
 {
   cid = Cid;
@@ -726,7 +747,7 @@ void cAudioRepacker::Reset(void)
   frameSize = 0;
 }
 
-bool cAudioRepacker::IsValidAudioHeader(uint32_t Header, bool Mpeg2, int *FrameSize)
+bool cAudioRepacker::IsValidAudioHeader(uint32_t Header, bool Mpeg2, int *FrameSize, int *FrameDuration)
 {
   int syncword           = (Header & 0xFFF00000) >> 20;
   int id                 = (Header & 0x00080000) >> 19;
@@ -760,32 +781,36 @@ bool cAudioRepacker::IsValidAudioHeader(
   if (emphasis == 2) // reserved
      return false;
 
-  if (FrameSize) {
-     if (bitrate_index == 0)
-        *FrameSize = 0;
-     else {
-        static int samplingFrequencies[2][4] = { // all values are specified in Hz
-          { 44100, 48000, 32000, -1 }, // MPEG 1
-          { 22050, 24000, 16000, -1 }  // MPEG 2
-          };
-
-        static int slots_per_frame[2][3] = {
-          { 12, 144, 144 }, // MPEG 1, Layer I, II, III
-          { 12, 144,  72 }  // MPEG 2, Layer I, II, III
-          };
-
-        int mpegIndex = 1 - id;
-        int layerIndex = 3 - layer;
-
-        // Layer I (i. e., layerIndex == 0) has a larger slot size
-        int slotSize = (layerIndex == 0) ? 4 : 1; // bytes
-
-        int br = 1000 * bitRates[mpegIndex][layerIndex][bitrate_index]; // bits/s
-        int sf = samplingFrequencies[mpegIndex][sampling_frequency];
-
-        int N = slots_per_frame[mpegIndex][layerIndex] * br / sf; // slots
+  if (FrameSize || FrameDuration) {
+     static int samplingFrequencies[2][4] = { // all values are specified in Hz
+       { 44100, 48000, 32000, -1 }, // MPEG 1
+       { 22050, 24000, 16000, -1 }  // MPEG 2
+       };
+
+     static int slots_per_frame[2][3] = {
+       { 12, 144, 144 }, // MPEG 1, Layer I, II, III
+       { 12, 144,  72 }  // MPEG 2, Layer I, II, III
+       };
+
+     int mpegIndex = 1 - id;
+     int layerIndex = 3 - layer;
+
+     // Layer I (i. e., layerIndex == 0) has a larger slot size
+     int slotSize = (layerIndex == 0) ? 4 : 1; // bytes
+     int sf = samplingFrequencies[mpegIndex][sampling_frequency];
+
+     if (FrameDuration)
+        *FrameDuration = 90000 * 8 * slotSize * slots_per_frame[mpegIndex][layerIndex] / sf;
+
+     if (FrameSize) {
+        if (bitrate_index == 0)
+           *FrameSize = 0;
+        else {
+           int br = 1000 * bitRates[mpegIndex][layerIndex][bitrate_index]; // bits/s
+           int N = slots_per_frame[mpegIndex][layerIndex] * br / sf; // slots
 
-        *FrameSize = (N + padding_bit) * slotSize; // bytes
+           *FrameSize = (N + padding_bit) * slotSize; // bytes
+           }
         }
      }
 
@@ -1086,6 +1111,7 @@ public:
   virtual void Reset(void);
   virtual void Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count);
   virtual int BreakAt(const uchar *Data, int Count);
+  static int GetFrameDuration(const uchar *Data, int Count, int *TrackIndex = NULL);
   };
 
 // frameSizes are in words, i. e. multiply them by 2 to get bytes
@@ -1112,6 +1138,30 @@ int cDolbyRepacker::frameSizes[] = {
      0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
   };
 
+int cDolbyRepacker::GetFrameDuration(const uchar *Data, int Count, int *TrackIndex)
+{
+  int PesPayloadOffset = 0;
+  ePesHeader PH = AnalyzePesHeader(Data, Count, PesPayloadOffset);
+  if (PH < phMPEG1)
+     return -1;
+
+  const uchar *Payload = Data + PesPayloadOffset;
+  const int PayloadCount = Count - PesPayloadOffset;
+
+  if (Data[3] == 0xBD && PayloadCount >= 9 && ((Payload[0] & 0xF0) == 0x80) && Payload[4] == 0x0B && Payload[5] == 0x77 && frameSizes[Payload[8]] > 0) {
+     if (TrackIndex)
+        *TrackIndex = Payload[0] - 0x80;
+
+     static int samplingFrequencies[4] = { // all values are specified in Hz
+       48000, 44100, 32000, -1
+       };
+
+     return 90000 * 1536 / samplingFrequencies[Payload[8] >> 6];
+     }
+
+  return -1;
+}
+
 cDolbyRepacker::cDolbyRepacker(void)
 {
   pesHeader[0] = 0x00;
@@ -1869,6 +1919,58 @@ void cTS2PES::ts_to_pes(const uint8_t *B
      instant_repack(Buf + 4 + off, TS_SIZE - 4 - off);
 }
 
+// --- cAudioIndexer ---------------------------------------------------------
+
+class cAudioIndexer {
+private:
+  int frameTrack;
+  int frameDuration;
+  int64_t trackTime[MAXAPIDS + MAXDPIDS];
+  int64_t nextIndexTime;
+  
+public:
+  cAudioIndexer(void);
+  void Clear(void);
+  void PrepareFrame(const uchar *Data, int Count, int Offset, uchar &PictureType);
+  void ProcessFrame(void);
+  };
+
+cAudioIndexer::cAudioIndexer(void)
+{
+  Clear();
+}
+
+void cAudioIndexer::Clear(void)
+{
+  memset(trackTime, 0, sizeof (trackTime));
+  nextIndexTime = 0;
+  frameTrack = -1;
+}
+
+void cAudioIndexer::PrepareFrame(const uchar *Data, int Count, int Offset, uchar &PictureType)
+{
+  frameDuration = cRemux::GetAudioFrameDuration(Data + Offset, Count - Offset, &frameTrack);
+  if (frameDuration <= 0)
+     return;
+
+  if (Data[Offset + 3] == 0xBD)
+     frameTrack += MAXAPIDS;
+
+  PictureType = (trackTime[frameTrack] >= nextIndexTime) ? I_FRAME : NO_PICTURE;
+}
+
+void cAudioIndexer::ProcessFrame(void)
+{
+  if (frameTrack < 0)
+     return;
+
+  if (trackTime[frameTrack] >= nextIndexTime)
+     nextIndexTime += 90000 / FRAMESPERSEC;
+
+  trackTime[frameTrack] += frameDuration;
+  frameTrack = -1;
+}
+
 // --- cRemux ----------------------------------------------------------------
 
 #define RESULTBUFFERSIZE KILOBYTE(256)
@@ -1913,6 +2015,8 @@ cRemux::cRemux(int VPid, const int *APid
      while (*SPids && numTracks < MAXTRACKS && n < MAXSPIDS)
            ts2pes[numTracks++] = new cTS2PES(*SPids++, resultBuffer, IPACKS, 0x00, 0x20 + n++);
      }
+  if (noVideo)
+     audioIndexer = new cAudioIndexer;
 }
 
 cRemux::~cRemux()
@@ -1920,6 +2024,18 @@ cRemux::~cRemux()
   for (int t = 0; t < numTracks; t++)
       delete ts2pes[t];
   delete resultBuffer;
+  delete audioIndexer;
+}
+
+int cRemux::GetAudioFrameDuration(const uchar *Data, int Count, int *TrackIndex)
+{
+  if (Count <= 4)
+     return -1;
+
+  if (Data[3] == 0xBD)
+     return cDolbyRepacker::GetFrameDuration(Data, Count, TrackIndex);
+
+  return cAudioRepacker::GetFrameDuration(Data, Count, TrackIndex);
 }
 
 int cRemux::GetPid(const uchar *Data)
@@ -2099,16 +2215,19 @@ uchar *cRemux::Get(int &Count, uchar *Pi
                if (l < 0)
                   return resultData;
                if (noVideo) {
+                  uchar pt = NO_PICTURE;
+                  if (audioIndexer && !Count)
+                     audioIndexer->PrepareFrame(data, resultCount, i, pt); 
                   if (!synced) {
                      if (PictureType)
-                        *PictureType = I_FRAME;
+                        *PictureType = pt;
                      resultSkipped = i; // will drop everything before this position
                      synced = true;
                      }
                   else if (Count)
                      return resultData;
                   else if (PictureType)
-                     *PictureType = I_FRAME;
+                     *PictureType = pt;
                   }
                }
             if (synced) {
@@ -2129,6 +2248,8 @@ uchar *cRemux::Get(int &Count, uchar *Pi
 void cRemux::Del(int Count)
 {
   resultBuffer->Del(Count);
+  if (audioIndexer && Count > 0)
+     audioIndexer->ProcessFrame();
 }
 
 void cRemux::Clear(void)
@@ -2136,6 +2257,7 @@ void cRemux::Clear(void)
   for (int t = 0; t < numTracks; t++)
       ts2pes[t]->Clear();
   resultBuffer->Clear();
+  audioIndexer->Clear();
   synced = false;
   skipped = 0;
   resultSkipped = 0;
