From patchwork Thu Nov 15 22:29:40 2007 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reinhard Nissl X-Patchwork-Id: 12550 Received: from mail.gmx.net ([213.165.64.20]) by www.linuxtv.org with smtp (Exim 4.63) (envelope-from ) id 1IsnDw-0007RW-1k for vdr@linuxtv.org; Thu, 15 Nov 2007 23:30:12 +0100 Received: (qmail invoked by alias); 15 Nov 2007 22:29:41 -0000 Received: from p5493309E.dip0.t-ipconnect.de (EHLO [192.168.101.15]) [84.147.48.158] by mail.gmx.net (mp047) with SMTP; 15 Nov 2007 23:29:41 +0100 X-Authenticated: #527675 X-Provags-ID: V01U2FsdGVkX1+dXZAK+Ded+UNbWd64ZtuDo2PiELy7CMkgODyHGm sLoNBOlnAjhwTN Message-ID: <473CC854.7020805@gmx.de> Date: Thu, 15 Nov 2007 23:29:40 +0100 From: Reinhard Nissl User-Agent: Mozilla/5.0 (X11; U; Linux i686; de; rv:1.8.1.6) Gecko/20070801 SUSE/2.0.0.6-22 Thunderbird/2.0.0.6 Mnenhy/0.7.5.666 MIME-Version: 1.0 To: vdr@linuxtv.org References: <47385FF4.8080006@iki.fi> <4738C232.4020205@gmx.de> <4738C67C.7000909@iki.fi> <4738CB54.5050904@iki.fi> <47399073.8000200@iki.fi> In-Reply-To: <47399073.8000200@iki.fi> X-Y-GMX-Trusted: 0 Cc: tri@iki.fi Subject: Re: [vdr] vdr-1.5.11 & subtitling problems X-BeenThere: vdr@linuxtv.org X-Mailman-Version: 2.1.9 Precedence: list Reply-To: VDR Mailing List List-Id: VDR Mailing List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 15 Nov 2007 22:30:12 -0000 Status: O X-Status: X-Keywords: X-UID: 14578 Hi, Timo J. Rinne schrieb: >> Anyways, it's been on for 25 minutes so far and has worked perfectly. >> If I notice something in contrary to this, I'll report further. > > Nope, it still doesn't quite work. In live mode it seems to skip > subtitles every now and then. It even seems to depend on the program. > Today I watched something and saw maybe one subtitle of ten. Sometimes > it seems to work more or less perfectly. > > When I recorded the program that in live mode didn't work too well, the > subtitles were fine in playback. > > I have ff card and I think the problems are present mainly (if not only) > in direct live mode. When I forced it to transport mode by > simultaneously recording an encrypted channel and watching fta channel > live (transport mode), subtitles showed OK. Please try the attached patch on a vanilla VDR-1.5.11. It should write the subtitle TS and PES packets to separate files at /video. The additionally recorded timestamps of your system time and the primary device's STC should allow us to determine whether the packets arrive in time and get properly remuxed. Once you've seen enough anomalies, please provide us (a link to) the files. BTW: the patch is almost untested as there are currently no subtitles running. Bye. 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-15 23:02:54.000000000 +0100 @@ -1387,6 +1387,51 @@ int cDolbyRepacker::BreakAt(const uchar return -1; } +class cLogger { + static int instance; + FILE *logFileTS; + FILE *logFilePES; + static void Store(FILE *LogFile, const uchar *Data, int Count); +public: + cLogger(void); + ~cLogger(); + void PutTS(const uchar *Data) { Store(logFileTS, Data, 188); } + void PutPES(const uchar *Data, int Count) { Store(logFilePES, Data, Count); } + }; + +int cLogger::instance = 0; + +cLogger::cLogger(void) +{ + int Instance = instance++; + char FileNameTS[200]; + sprintf(FileNameTS, "/video/subtitle_log_%d_%02d.ts", getpid(), Instance); + logFileTS = fopen(FileNameTS, "wb"); + char FileNamePES[200]; + sprintf(FileNamePES, "/video/subtitle_log_%d_%02d.pes", getpid(), Instance); + logFilePES = fopen(FileNamePES, "wb"); +} + +cLogger::~cLogger() +{ + fclose(logFileTS); + fclose(logFilePES); +} + +#include +#include "device.h" + +void cLogger::Store(FILE *LogFile, const uchar *Data, int Count) +{ + timeval tv; + gettimeofday(&tv, 0); + int64_t stc = cDevice::PrimaryDevice()->GetSTC(); + fwrite(&tv, sizeof (tv), 1, LogFile); + fwrite(&stc, sizeof (stc), 1, LogFile); + fwrite(Data, Count, 1, LogFile); + fflush(LogFile); +} + // --- cTS2PES --------------------------------------------------------------- #include @@ -1474,12 +1519,14 @@ public: int Pid(void) { return pid; } void ts_to_pes(const uint8_t *Buf); // don't need count (=188) void Clear(void); +cLogger *logger; }; uint8_t cTS2PES::headr[] = { 0x00, 0x00, 0x01 }; cTS2PES::cTS2PES(int Pid, cRingBufferLinear *ResultBuffer, int Size, uint8_t RewriteCid, uint8_t SubStreamId, cRepacker *Repacker) { +logger = (Repacker ? 0 : new cLogger); pid = Pid; resultBuffer = ResultBuffer; size = Size; @@ -1504,6 +1551,7 @@ cTS2PES::cTS2PES(int Pid, cRingBufferLin cTS2PES::~cTS2PES() { +delete logger; if (tsErrors || ccErrors) dsyslog("cTS2PES got %d TS errors, %d TS continuity errors", tsErrors, ccErrors); free(buf); @@ -1519,6 +1567,7 @@ void cTS2PES::Clear(void) void cTS2PES::store(uint8_t *Data, int Count) { +if (logger) logger->PutPES(Data, Count); if (repacker) repacker->Repack(resultBuffer, Data, Count); else @@ -1749,14 +1798,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); @@ -1826,7 +1876,7 @@ void cTS2PES::ts_to_pes(const uint8_t *B { if (!Buf) return; - +if (logger) logger->PutTS(Buf); if (Buf[1] & TS_ERROR) tsErrors++; @@ -1883,7 +1933,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 +1962,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; }