The attached patch increases MIN_TS_PACKETS_FOR_FRAME_DETECTOR to 100 and itroduces 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. While the frame type can typically be detected by processing at most two video TS packets, there may be several TS packets from other PIDs between the first and second video TS packet. Previously cTsPayload counted all TS packets against MIN_TS_PACKETS_FOR_FRAME_DETECTOR, and that number was intentionally kept small in order to keep the actual data processing at a minimum. With this patch, MIN_TS_PACKETS_FOR_FRAME_DETECTOR will be set to a presumably very safe large value, which only has an impact on the ringbuffer and should not increase processing costs there. The new MAX_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION now defines the number of actual video TS packets that will be processed. There are also WRN_... macros in remux.c, which control some debug messages in case the safety margin for these limits is exceeded. You can try setting these to lower values for experimenting. Please try this patch and let me know if the warning is ever triggered with the given values (or, in case you're experimenting with reduced values, what were the highest values that still triggered warnings). Klaus
--- remux.h 2014/01/16 10:15:50 3.1 +++ remux.h 2014/01/28 11:06:37 @@ -217,8 +217,11 @@ 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 @@ ///< 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 @@ // Frame detector: -#define MIN_TS_PACKETS_FOR_FRAME_DETECTOR 10 +#define MIN_TS_PACKETS_FOR_FRAME_DETECTOR 100 class cFrameParser; --- remux.c 2014/01/18 11:27:30 3.1 +++ remux.c 2014/01/28 11:07:59 @@ -23,6 +23,10 @@ #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 @@ data = NULL; length = 0; pid = -1; - index = 0; + Reset(); } cTsPayload::cTsPayload(uchar *Data, int Length, int Pid) @@ -239,12 +243,25 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ case nutCodedSliceIdr: if (gotAccessUnitDelimiter && gotSequenceParameterSet) { ParseSliceHeader(); gotAccessUnitDelimiter = false; + if (newFrame) + tsPayload.Statistics(); return tsPayload.Used(); } break;
_______________________________________________ vdr mailing list vdr@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr