diff options
-rw-r--r-- | CONTRIBUTORS | 2 | ||||
-rw-r--r-- | HISTORY | 4 | ||||
-rw-r--r-- | remux.c | 54 | ||||
-rw-r--r-- | 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 <o.endriss@gmx.de> 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 <rw.buchner@freenet.de> for adding some satellites to 'sources.conf' @@ -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). @@ -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; @@ -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; |