index.vdr misses pictures

Message ID 4380B3CB.9070504@gmx.de
State New
Headers

Commit Message

Reinhard Nissl Nov. 20, 2005, 5:35 p.m. UTC
  Hi,

Werner wrote:

>>>in recent recording from premiere i saw that not all pictures in
>>>the data stream are indexed in index.vdr. The displayed movie lenghts are
>>>slightly to short and the cutmarks in marks.vdr are wrong. I use
>>>marks.vdr in an external program. The resulting cutted movies are
>>>sometimes about 1-2 minutes too short. This does not affect normal
>>>vdr users too much because vdr cutted movies have the right len.
>>>
>>>Im not an mpeg expert, so only some speculations:
>>>It looks that every index.vdr entry points to an "packet start code"
>>>(0x000001). Vdr assumes that every packet has mostly one picture start
>>>code. The difference i saw between old recordings and new recordings
>>>is that in new recordings are sometimes two picture start codes in a
>>>packet. The second one is dropped by vdr.
>>>I have no idea of how to fix this assuming that vdr can only resume
>>>on a packet start code. Anyone any idea?
>>
>>If you were right, then cVideoRepacker is buggy. Are you shure that you
>>see two picture start codes (0x00000100) in one PES-Packet?
> 
> yes, thats what i saw. My app demuxes the data stream (with the help
> of some libmpeg2 code) and two printfs show that sometimes (<5%) there are
> two picture start codes in a packet.

In the sample you sent me, there really are two picture start codes in 
one PES packet. You've already got the attached patch which records a 
snipplet of the TS stream in such a case.

Do you already have some test material, as I'm ready to replay and debug it?

Bye.
  

Patch

--- ../vdr-1.3.36-orig/remux.h	2005-08-26 15:22:19.000000000 +0200
+++ remux.h	2005-11-07 22:29:05.000000000 +0100
@@ -33,9 +33,11 @@  ePesHeader AnalyzePesHeader(const uchar 
 #define MAXTRACKS 64
 
 class cTS2PES;
+class cTSLogger;
 
 class cRemux {
 private:
+cTSLogger *tsLogger;
   bool exitOnFailure;
   bool isRadio;
   int numUPTerrors;
@@ -65,6 +67,7 @@  public:
   int Put(const uchar *Data, int Count);
        ///< Puts at most Count bytes of Data into the remuxer.
        ///< \return Returns the number of bytes actually consumed from Data.
+  uchar *Get0(int &Count, uchar *PictureType = NULL);
   uchar *Get(int &Count, uchar *PictureType = NULL);
        ///< Gets all currently available data from the remuxer.
        ///< \return Count contains the number of bytes the result points to, and
--- ../vdr-1.3.36-orig/remux.c	2005-09-11 15:26:50.000000000 +0200
+++ remux.c	2005-11-07 22:36:52.000000000 +0100
@@ -86,6 +86,60 @@  ePesHeader AnalyzePesHeader(const uchar 
   return phMPEG1; // MPEG 1
 }
 
+// --- cTSLogger -------------------------------------------------------------
+
+class cTSLogger
+{
+  uchar *buffer;
+  int size;
+  int fill;
+  int64_t count;
+  int dumps;
+  int cid;
+
+public:
+  cTSLogger(int Cid);
+  ~cTSLogger();
+  void Put(const uchar *Data);
+  void Dump();
+};
+
+cTSLogger::cTSLogger(int Cid)
+{
+  size = 1000; // number of TS packets to log
+  buffer = new uchar[size * 188];
+  fill = 0;
+  count = 0;
+  dumps = 0;
+  cid = Cid;
+}
+
+cTSLogger::~cTSLogger()
+{
+  delete [] buffer;
+}
+
+void cTSLogger::Put(const uchar *Data)
+{
+  memcpy(&buffer[(count++ % size) * 188], Data, 188);
+  if (fill < size)
+     fill++;
+}
+
+void cTSLogger::Dump()
+{
+  char name[200];
+  sprintf(name, "/video/ts_%d_%ld_0x%02X_%03d_%lld_%d.log", getpid(), pthread_self(), cid, dumps++, count, fill);
+  esyslog("cTSLogger: dumping to file '%s'", name);
+
+  FILE *f = fopen(name, "wb");
+  for (int64_t n = count - fill; n < count; n++)
+      fwrite(&buffer[(n % size) * 188], 188, 1, f);
+  fclose(f);
+
+  fill = 0;
+}
+
 // --- cRepacker -------------------------------------------------------------
 
 class cRepacker {
@@ -1675,6 +1731,7 @@  void cTS2PES::ts_to_pes(const uint8_t *B
 
 cRemux::cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure)
 {
+tsLogger = new cTSLogger(0xe0);
   exitOnFailure = ExitOnFailure;
   isRadio = VPid == 0 || VPid == 1 || VPid == 0x1FFF;
   numUPTerrors = 0;
@@ -1722,6 +1779,7 @@  cRemux::~cRemux()
   for (int t = 0; t < numTracks; t++)
       delete ts2pes[t];
   delete resultBuffer;
+delete tsLogger;
 }
 
 int cRemux::GetPid(const uchar *Data)
@@ -1793,6 +1851,7 @@  int cRemux::Put(const uchar *Data, int C
       if (Data[i + 3] & 0x10) { // got payload
          for (int t = 0; t < numTracks; t++) {
              if (ts2pes[t]->Pid() == pid) {
+if (t == 0) tsLogger->Put(Data + i);
                 ts2pes[t]->ts_to_pes(Data + i);
                 break;
                 }
@@ -1818,6 +1877,52 @@  int cRemux::Put(const uchar *Data, int C
 
 uchar *cRemux::Get(int &Count, uchar *PictureType)
 {
+  uchar *r = Get0(Count, PictureType);
+  
+  int n = 0;
+  while (r && n < Count)
+  {
+    if (r[ n + 0 ] != 0x00
+      || r[ n + 1 ] != 0x00
+      || r[ n + 2 ] != 0x01)
+    {
+      esyslog("out of sync ======================");
+      break;
+    }
+
+    int l = 6 + r[ n + 4 ] * 256 + r[ n + 5 ];
+    if ((r[ n + 3 ] & 0xf0) != 0xe0)
+    {
+      n += l;
+      continue;
+    }
+
+    ulong scanner = 0xffffffff;
+    int k = 0;
+
+    int o = 6 + 3 + r[ n + 8 ];
+    for (int i = o; i < l; i++)
+    {
+      scanner <<= 8;
+      scanner |= r[ n + i ];
+
+      if (scanner == 0x00000100)
+      {
+        k++;
+
+        if (k > 1)
+          tsLogger->Dump();
+      }
+    }
+
+    n += l;
+  }
+
+  return r;
+}
+
+uchar *cRemux::Get0(int &Count, uchar *PictureType)
+{
   // Remove any previously skipped data from the result buffer:
 
   if (resultSkipped > 0) {