From 9eda923269f49291317547130d24067cad9cb669 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Tue, 28 Jan 2014 11:26:02 +0100 Subject: [PATCH] Increased MIN_TS_PACKETS_FOR_FRAME_DETECTOR to 100 and introduced counting the number of actual video TS packets in cTsPayload --- CONTRIBUTORS | 2 ++ HISTORY | 4 ++++ remux.c | 54 +++++++++++++++++++++++++++++++++++++++++----------- remux.h | 13 ++++++++++--- 4 files changed, 59 insertions(+), 14 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 2fec0012..865c7a32 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -707,6 +707,8 @@ Oliver Endriss 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 suggesting to eliminate MAXDVBDEVICES + 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 5e9da0bd..f5e74534 100644 --- a/HISTORY +++ b/HISTORY @@ -8175,3 +8175,7 @@ Video Disk Recorder Revision History - 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 + Oliver Endriss). diff --git a/remux.c b/remux.c index fd726017..d0b8e8e2 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 3.1 2014/01/18 11:27:30 kls Exp $ + * $Id: remux.c 3.2 2014/01/28 11:07:59 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 5dd24ebd..ac627371 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 3.1 2014/01/16 10:15:50 kls Exp $ + * $Id: remux.h 3.2 2014/01/28 11:06:37 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;