From e47d73715b48e182cefbc4f4a728f70873840703 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sat, 17 Nov 2007 13:59:08 +0100 Subject: Fixed handling small PES packets that caused subtitles to be displayed late in live mode --- CONTRIBUTORS | 2 ++ HISTORY | 4 +++- remux.c | 28 ++++++++++++++++++++++++++-- ringbuffer.c | 18 +++++++++++------- ringbuffer.h | 9 ++++++++- 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 5eeff57d..60a99e72 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1150,6 +1150,8 @@ Reinhard Nissl attached to a device for reporting a missing SetVolumeDevice() call in cDevice::SetPrimaryDevice() for fixing assembling PS1 packets in cTS2PES::instant_repack() + for a patch that was used to fix handling small PES packets that caused subtitles + to be displayed late in live mode Richard Robson for reporting freezing replay if a timer starts while in Transfer Mode from the diff --git a/HISTORY b/HISTORY index 89e0614d..40451bd1 100644 --- a/HISTORY +++ b/HISTORY @@ -5519,8 +5519,10 @@ Video Disk Recorder Revision History - Fixed decoding filename characters in case there are not two hex digits after the '#' (reported by Helmut Auer). -2007-11-10: Version 1.5.12 +2007-11-17: Version 1.5.12 - Fixed assembling PS1 packets in cTS2PES::instant_repack() (thanks to Reinhard Nissl). - Updated the Russian OSD texts (thanks to Oleg Roitburd). +- Fixed handling small PES packets that caused subtitles to be displayed late + in live mode (based on a patch from Reinhard Nissl). diff --git a/remux.c b/remux.c index a658e194..416ec1cd 100644 --- a/remux.c +++ b/remux.c @@ -11,7 +11,7 @@ * The cRepacker family's code was originally written by Reinhard Nissl , * and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de. * - * $Id: remux.c 1.61 2007/11/10 13:36:47 kls Exp $ + * $Id: remux.c 1.62 2007/11/17 13:49:34 kls Exp $ */ #include "remux.h" @@ -1870,6 +1870,30 @@ void cTS2PES::ts_to_pes(const uint8_t *Buf) // don't need count (=188) instant_repack(Buf + 4 + off, TS_SIZE - 4 - off); } +// --- cRingBufferLinearPes -------------------------------------------------- + +class cRingBufferLinearPes : public cRingBufferLinear { +protected: + virtual int DataReady(const uchar *Data, int Count); +public: + cRingBufferLinearPes(int Size, int Margin = 0, bool Statistics = false, const char *Description = NULL) + :cRingBufferLinear(Size, Margin, Statistics, Description) {} + }; + +int cRingBufferLinearPes::DataReady(const uchar *Data, int Count) +{ + int c = cRingBufferLinear::DataReady(Data, Count); + if (!c) { + const uchar *p = Data; + if (Count >= 6 && !p[0] && !p[1] && p[2] == 0x01) { + int Length = 6 + p[4] * 256 + p[5]; + if (Length <= Count) + return Length; + } + } + return c; +} + // --- cRemux ---------------------------------------------------------------- #define RESULTBUFFERSIZE KILOBYTE(256) @@ -1883,7 +1907,7 @@ cRemux::cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, b skipped = 0; numTracks = 0; resultSkipped = 0; - resultBuffer = new cRingBufferLinear(RESULTBUFFERSIZE, IPACKS, false, "Result"); + resultBuffer = new cRingBufferLinearPes(RESULTBUFFERSIZE, IPACKS, false, "Result"); resultBuffer->SetTimeouts(0, 100); if (VPid) #define TEST_cVideoRepacker diff --git a/ringbuffer.c b/ringbuffer.c index 0633bd37..d74706ab 100644 --- a/ringbuffer.c +++ b/ringbuffer.c @@ -7,7 +7,7 @@ * Parts of this file were inspired by the 'ringbuffy.c' from the * LinuxDVB driver (see linuxtv.org). * - * $Id: ringbuffer.c 1.24 2006/06/16 09:32:13 kls Exp $ + * $Id: ringbuffer.c 1.25 2007/11/17 13:49:34 kls Exp $ */ #include "ringbuffer.h" @@ -187,6 +187,11 @@ cRingBufferLinear::~cRingBufferLinear() free(description); } +int cRingBufferLinear::DataReady(const uchar *Data, int Count) +{ + return Count >= margin ? Count : 0; +} + int cRingBufferLinear::Available(void) { int diff = head - tail; @@ -284,7 +289,6 @@ int cRingBufferLinear::Put(const uchar *Data, int Count) uchar *cRingBufferLinear::Get(int &Count) { - uchar *p = NULL; int Head = head; if (getThreadTid <= 0) getThreadTid = cThread::ThreadId(); @@ -299,13 +303,13 @@ uchar *cRingBufferLinear::Get(int &Count) int cont = (diff >= 0) ? diff : Size() + diff - margin; if (cont > rest) cont = rest; - if (cont >= margin) { - p = buffer + tail; + uchar *p = buffer + tail; + if ((cont = DataReady(p, cont)) > 0) { Count = gotten = cont; + return p; } - if (!p) - WaitForGet(); - return p; + WaitForGet(); + return NULL; } void cRingBufferLinear::Del(int Count) diff --git a/ringbuffer.h b/ringbuffer.h index dba0e619..f6664cf8 100644 --- a/ringbuffer.h +++ b/ringbuffer.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ringbuffer.h 1.17 2005/12/10 10:54:51 kls Exp $ + * $Id: ringbuffer.h 1.18 2007/11/17 13:49:34 kls Exp $ */ #ifndef __RINGBUFFER_H @@ -60,6 +60,13 @@ private: int gotten; uchar *buffer; char *description; +protected: + virtual int DataReady(const uchar *Data, int Count); + ///< By default a ring buffer has data ready as soon as there are at least + ///< 'margin' bytes available. A derived class can reimplement this function + ///< if it has other conditions that define when data is ready. + ///< The return value is either 0 if there is not yet enough data available, + ///< or the number of bytes from the beginning of Data that are "ready". public: cRingBufferLinear(int Size, int Margin = 0, bool Statistics = false, const char *Description = NULL); ///< Creates a linear ring buffer. -- cgit v1.2.3