From 9e9219d8fba26ffa997cac98315e899fa0e53e7c Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Tue, 28 Jan 2014 12:40:04 +0100 Subject: Increased MIN_TS_PACKETS_FOR_FRAME_DETECTOR to 100 and introduced counting the number of actual video TS packets in cTsPayload --- CONTRIBUTORS | 2 ++ HISTORY | 9 +++++---- remux.c | 54 +++++++++++++++++++++++++++++++++++++++++++----------- remux.h | 13 ++++++++++--- 4 files changed, 60 insertions(+), 18 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index e6dce486..c7f5d0de 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -706,6 +706,8 @@ Oliver Endriss for reporting a problem with resuming replay of PES recordings for suggesting to make all bonded devices (except for the master) turn off their LNB power completely to avoid problems when receiving vertically polarized transponders + for reporting that there are channels that need even more than 10 TS packets in order + to detect the frame type Reinhard Walter Buchner for adding some satellites to 'sources.conf' diff --git a/HISTORY b/HISTORY index b82827c6..c69c35b8 100644 --- a/HISTORY +++ b/HISTORY @@ -7870,17 +7870,18 @@ Video Disk Recorder Revision History and also to use the correct directory with --edit (the latter reported by Marko Mäkelä). -2014-01-26: Version 2.0.6 +2014-01-28: Version 2.0.6 - Updated 'sources.conf' (thanks to Antti Hartikainen). - cFont::CreateFont() now returns a dummy font in case there are no fonts installed. This prevents a crash with the LCARS skin on a system that has no fonts. -- Increased MIN_TS_PACKETS_FOR_FRAME_DETECTOR to 10 in order to be able to record - channels that need more than 5 TS packets for detecting frame borders (reported by - Eike Sauer). - Fixed detecting frame borders in MPEG-2 streams that have "bottom fields" or varying GOP structures (reported by Christian Paulick, with help from Helmut Auer). - Fixed a wrong alignment in cCiDateTime::SendDateTime(). - Now checking whether the primary device actually has a decoder before retuning the current channel after a change in its parameters. This fixes broken recordings on the primary device on "headless" systems. +- Increased MIN_TS_PACKETS_FOR_FRAME_DETECTOR to 100 and introduced counting the number + of actual video TS packets in cTsPayload in order to be able to record channels that + sometimes need even more than 10 TS packets for detecting frame borders (reported by + Eike Sauer and Oliver Endriss). diff --git a/remux.c b/remux.c index 15a5e44b..5bf57fd8 100644 --- a/remux.c +++ b/remux.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: remux.c 2.75.1.1 2014/01/25 14:37:05 kls Exp $ + * $Id: remux.c 2.75.1.2 2014/01/28 12:36:57 kls Exp $ */ #include "remux.h" @@ -23,6 +23,10 @@ static bool DebugFrames = false; #define dbgpatpmt(a...) if (DebugPatPmt) fprintf(stderr, a) #define dbgframes(a...) if (DebugFrames) fprintf(stderr, a) +#define MAX_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION 6 +#define WRN_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION (MAX_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION / 2) +#define WRN_TS_PACKETS_FOR_FRAME_DETECTOR (MIN_TS_PACKETS_FOR_FRAME_DETECTOR / 2) + #define EMPTY_SCANNER (0xFFFFFFFF) ePesHeader AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader) @@ -231,7 +235,7 @@ cTsPayload::cTsPayload(void) data = NULL; length = 0; pid = -1; - index = 0; + Reset(); } cTsPayload::cTsPayload(uchar *Data, int Length, int Pid) @@ -239,12 +243,25 @@ cTsPayload::cTsPayload(uchar *Data, int Length, int Pid) Setup(Data, Length, Pid); } +uchar cTsPayload::SetEof(void) +{ + length = index; // triggers EOF + return 0x00; +} + +void cTsPayload::Reset(void) +{ + index = 0; + numPacketsPid = 0; + numPacketsOther = 0; +} + void cTsPayload::Setup(uchar *Data, int Length, int Pid) { data = Data; length = Length; pid = Pid >= 0 ? Pid : TsPid(Data); - index = 0; + Reset(); } uchar cTsPayload::GetByte(void) @@ -255,20 +272,20 @@ uchar cTsPayload::GetByte(void) if (data[index] == TS_SYNC_BYTE && index + TS_SIZE <= length) { // to make sure we are at a TS header start and drop incomplete TS packets at the end uchar *p = data + index; if (TsPid(p) == pid) { // only handle TS packets for the initial PID + if (numPacketsPid++ > MAX_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION) + return SetEof(); if (TsHasPayload(p)) { - if (index > 0 && TsPayloadStart(p)) { // checking index to not skip the very first TS packet - length = index; // triggers EOF - return 0x00; - } + if (index > 0 && TsPayloadStart(p)) // checking index to not skip the very first TS packet + return SetEof(); index += TsPayloadOffset(p); break; } } + else + numPacketsOther++; } - else { - length = index; // triggers EOF - return 0x00; - } + else + return SetEof(); } } return data[index++]; @@ -302,6 +319,8 @@ void cTsPayload::SetByte(uchar Byte, int Index) bool cTsPayload::Find(uint32_t Code) { int OldIndex = index; + int OldNumPacketsPid = numPacketsPid; + int OldNumPacketsOther = numPacketsOther; uint32_t Scanner = EMPTY_SCANNER; while (!Eof()) { Scanner = (Scanner << 8) | GetByte(); @@ -309,9 +328,19 @@ bool cTsPayload::Find(uint32_t Code) return true; } index = OldIndex; + numPacketsPid = OldNumPacketsPid; + numPacketsOther = OldNumPacketsOther; return false; } +void cTsPayload::Statistics(void) const +{ + if (numPacketsPid + numPacketsOther > WRN_TS_PACKETS_FOR_FRAME_DETECTOR) + dsyslog("WARNING: required (%d+%d) TS packets to determine frame type", numPacketsOther, numPacketsPid); + if (numPacketsPid > WRN_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION) + dsyslog("WARNING: required %d video TS packets to determine frame type", numPacketsPid); +} + // --- cPatPmtGenerator ------------------------------------------------------ cPatPmtGenerator::cPatPmtGenerator(const cChannel *Channel) @@ -1120,6 +1149,7 @@ int cMpeg2Parser::Parse(const uchar *Data, int Length, int Pid) dbgframes("%c", FrameTypes[FrameType]); } } + tsPayload.Statistics(); break; } if (tsPayload.AtPayloadStart() // stop at any new payload start to have the buffer refilled if necessary @@ -1266,6 +1296,8 @@ int cH264Parser::Parse(const uchar *Data, int Length, int Pid) case nutCodedSliceIdr: if (gotAccessUnitDelimiter && gotSequenceParameterSet) { ParseSliceHeader(); gotAccessUnitDelimiter = false; + if (newFrame) + tsPayload.Statistics(); return tsPayload.Used(); } break; diff --git a/remux.h b/remux.h index 10aeed7f..12ee9700 100644 --- a/remux.h +++ b/remux.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: remux.h 2.37.1.1 2014/01/16 10:33:35 kls Exp $ + * $Id: remux.h 2.37.1.2 2014/01/28 12:36:26 kls Exp $ */ #ifndef __REMUX_H @@ -217,8 +217,11 @@ private: int length; int pid; int index; // points to the next byte to process + int numPacketsPid; // the number of TS packets with the given PID (for statistical purposes) + int numPacketsOther; // the number of TS packets with other PIDs (for statistical purposes) + uchar SetEof(void); protected: - void Reset(void) { index = 0; } + void Reset(void); public: cTsPayload(void); cTsPayload(uchar *Data, int Length, int Pid = -1); @@ -246,6 +249,10 @@ public: ///< is counted with its full size. bool Eof(void) const { return index >= length; } ///< Returns true if all available bytes of the TS payload have been processed. + void Statistics(void) const; + ///< May be called after a new frame has been detected, and will log a warning + ///< if the number of TS packets required to determine the frame type exceeded + ///< some safety limits. uchar GetByte(void); ///< Gets the next byte of the TS payload, skipping any intermediate TS header data. bool SkipBytes(int Bytes); @@ -462,7 +469,7 @@ void PesDump(const char *Name, const u_char *Data, int Length); // Frame detector: -#define MIN_TS_PACKETS_FOR_FRAME_DETECTOR 10 +#define MIN_TS_PACKETS_FOR_FRAME_DETECTOR 100 class cFrameParser; -- cgit v1.2.3