vdr-1.5.11 & subtitling problems

Message ID 4738C232.4020205@gmx.de
State New
Headers

Commit Message

Reinhard Nissl Nov. 12, 2007, 9:14 p.m. UTC
  Hi,

Timo J. Rinne schrieb:

> Posting to the mailing list seems to be for subscribers only and I'm
> reading it only through archive.  However ...
> 
>> Reinhard Nissl schrieb:
>>
>> >>> Though, a cleaner solution would be to fix the result buffer to
>> allow
>>>>> retrieving any packet as soon as it is completely available in the
>>>>> buffer (final subtitle packets are about 100 bytes in size).
>>>>
>>>> That sounds like the right thing to do.
>>>> Can you suggest a patch for this?
>>>
>>> I hope to get something ready till tomorrow 12:00.
>> See attachment. Tested in transfer mode with audio packets only (=
>> radio), as there is no broadcast running which would provide
>> subtitles.
> 
> The picture doesn't freeze any longer.  But after a while (5-10 minutes)
> subtitles disappear.

You'll have to provide some more information. Do you use subtitles with
a FF card?
Can you reproduce the issue in a recording?
Did you apply all the posted fixes?

Attached you'll find a single patch against vanilla VDR-1.5.11. It
contains the remuxer fix and the ringbuffer extension, but also reverts
some changes from 1.5.10 to 1.5.11 which should be addressed by the
other two parts.

I've just watched subtitles now for almost 2 hours on ZDF (ASTRA 19.2E)
with vdr-xine without any issues. But vdr-xine works different (transfer
mode) and may not see issues which happen with FF cards.

Bye.
  

Patch

diff -Nurp ../vdr-1.5.11-orig/device.c ./device.c
--- ../vdr-1.5.11-orig/device.c	2007-11-03 14:30:09.000000000 +0100
+++ ./device.c	2007-11-12 21:57:36.000000000 +0100
@@ -210,7 +210,7 @@  int cPesAssembler::PacketSize(const ucha
 #define DEFAULTPRIORITY  -1
 
 // The minimum number of unknown PS1 packets to consider this a "pre 1.3.19 private stream":
-#define MIN_PRE_1_3_19_PRIVATESTREAM 10
+#define MIN_PRE_1_3_19_PRIVATESTREAM 0 /*10*/
 
 int cDevice::numDevices = 0;
 int cDevice::useDevice = 0;
diff -Nurp ../vdr-1.5.11-orig/remux.c ./remux.c
--- ../vdr-1.5.11-orig/remux.c	2007-11-03 15:18:07.000000000 +0100
+++ ./remux.c	2007-11-12 21:50:41.000000000 +0100
@@ -1749,14 +1749,15 @@  void cTS2PES::instant_repack(const uint8
        case AUDIO_STREAM_S ... AUDIO_STREAM_E:
        case VIDEO_STREAM_S ... VIDEO_STREAM_E:
        case PRIVATE_STREAM1:
-
-            if (mpeg == 2 && found == 9) {
+            /* make sure to not write the data twice by looking at count */
+            if (mpeg == 2 && found == 9 && count < found) {
                write_ipack(&flag1, 1);
                write_ipack(&flag2, 1);
                write_ipack(&hlength, 1);
                }
 
-            if (mpeg == 1 && found == mpeg1_required) {
+            /* make sure to not write the data twice by looking at count */
+            if (mpeg == 1 && found == mpeg1_required && count < found) {
                write_ipack(&flag1, 1);
                if (mpeg1_required > 7) {
                   write_ipack(&flag2, 1);
@@ -1883,7 +1884,7 @@  cRemux::cRemux(int VPid, const int *APid
   skipped = 0;
   numTracks = 0;
   resultSkipped = 0;
-  resultBuffer = new cRingBufferLinear(RESULTBUFFERSIZE, IPACKS, false, "Result");
+  resultBuffer = new cRingBufferLinear(RESULTBUFFERSIZE, IPACKS, false, "Result", true);
   resultBuffer->SetTimeouts(0, 100);
   if (VPid)
 #define TEST_cVideoRepacker
@@ -1912,7 +1913,7 @@  cRemux::cRemux(int VPid, const int *APid
   if (SPids) {
      int n = 0;
      while (*SPids && numTracks < MAXTRACKS && n < MAXSPIDS)
-           ts2pes[numTracks++] = new cTS2PES(*SPids++, resultBuffer, SUBTITLE_PACKS, 0x00, 0x20 + n++);
+           ts2pes[numTracks++] = new cTS2PES(*SPids++, resultBuffer, IPACKS /*SUBTITLE_PACKS*/, 0x00, 0x20 + n++);
      }
 }
 
diff -Nurp ../vdr-1.5.11-orig/ringbuffer.c ./ringbuffer.c
--- ../vdr-1.5.11-orig/ringbuffer.c	2006-06-16 11:32:13.000000000 +0200
+++ ./ringbuffer.c	2007-11-10 21:05:47.000000000 +0100
@@ -151,9 +151,10 @@  void cRingBufferLinear::PrintDebugRBL(vo
   }
 #endif
 
-cRingBufferLinear::cRingBufferLinear(int Size, int Margin, bool Statistics, const char *Description)
+cRingBufferLinear::cRingBufferLinear(int Size, int Margin, bool Statistics, const char *Description, bool AssumePesContent)
 :cRingBuffer(Size, Statistics)
 {
+  assumePesContent = AssumePesContent;
   description = Description ? strdup(Description) : NULL;
   tail = head = margin = Margin;
   gotten = 0;
@@ -299,7 +300,7 @@  uchar *cRingBufferLinear::Get(int &Count
   int cont = (diff >= 0) ? diff : Size() + diff - margin;
   if (cont > rest)
      cont = rest;
-  if (cont >= margin) {
+  if (cont >= margin || assumePesContent && HasPesPacket(cont)) {
      p = buffer + tail;
      Count = gotten = cont;
      }
@@ -308,6 +309,19 @@  uchar *cRingBufferLinear::Get(int &Count
   return p;
 }
 
+bool cRingBufferLinear::HasPesPacket(int &Count)
+{
+  uchar *p = buffer + tail;
+  if (Count >= 6 && !p[0] && !p[1] && p[2] == 0x01) {
+     int Length = 6 + p[4] * 256 + p[5];
+     if (Length <= Count) {
+        Count = Length;
+        return true;
+        }
+     }
+  return false;
+}
+
 void cRingBufferLinear::Del(int Count)
 {
   if (Count > gotten) {
diff -Nurp ../vdr-1.5.11-orig/ringbuffer.h ./ringbuffer.h
--- ../vdr-1.5.11-orig/ringbuffer.h	2005-12-10 11:54:51.000000000 +0100
+++ ./ringbuffer.h	2007-11-10 21:05:47.000000000 +0100
@@ -60,12 +60,17 @@  private:
   int gotten;
   uchar *buffer;
   char *description;
+  bool assumePesContent;
+  bool HasPesPacket(int &Count);
 public:
-  cRingBufferLinear(int Size, int Margin = 0, bool Statistics = false, const char *Description = NULL);
+  cRingBufferLinear(int Size, int Margin = 0, bool Statistics = false, const char *Description = NULL, bool AssumePesContent = false);
     ///< Creates a linear ring buffer.
     ///< The buffer will be able to hold at most Size-Margin-1 bytes of data, and will
     ///< be guaranteed to return at least Margin bytes in one consecutive block.
     ///< The optional Description is used for debugging only.
+    ///< AssumePesContent specializes the buffer and changes its behavior when less
+    ///< than Margin bytes are available. The buffer is then allowed to return at
+    ///< least a complete PES packet.
   virtual ~cRingBufferLinear();
   virtual int Available(void);
   virtual int Free(void) { return Size() - Available() - 1 - margin; }