From 4f50c34824f0c717dd52e0ce32497b7f421c1c66 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Mon, 1 Nov 2010 12:31:52 +0100 Subject: [PATCH] Fixed detecting frames on channels that broadcast with 50 or 60 fps --- HISTORY | 7 ++++++- remux.c | 47 ++++++++++++++++------------------------------- remux.h | 10 ++++------ 3 files changed, 26 insertions(+), 38 deletions(-) diff --git a/HISTORY b/HISTORY index 932fd79b..4b8d95ca 100644 --- a/HISTORY +++ b/HISTORY @@ -6481,7 +6481,7 @@ Video Disk Recorder Revision History from Osama Alrawab). See INSTALL for information on how to turn this on. - Added Arabian language texts (thanks to Osama Alrawab). -2010-10-30: Version 1.7.17 +2010-11-01: Version 1.7.17 - Updated the Estonian OSD texts (thanks to Arthur Konovalov). - Fixed following symbolic links in RemoveFileOrDir() (cont'd) (thanks to @@ -6495,3 +6495,8 @@ Video Disk Recorder Revision History - Made 'dist' target dependent on up to date *.po (thanks to Ville Skyttä). - Added Language and fixed Language-Team header of *.po (thanks to Ville Skyttä). - Updated the Lithuanian OSD texts (thanks to Valdemaras Pipiras). +- Fixed detecting frames on channels that broadcast with 50 or 60 fps. + This avoids artifacts during fast forward/rewind when replaying recordings from such + channels. To fix the index of existing recordings from such channels, just delete the + 'index' file of the recording and VDR will generate a new one the next time you play it. + You should also change the line "F 25" to "F 50" in the 'info' file of that recording. diff --git a/remux.c b/remux.c index 52065444..b30b12ca 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.47 2010/06/05 13:32:15 kls Exp $ + * $Id: remux.c 2.48 2010/11/01 12:29:17 kls Exp $ */ #include "remux.h" @@ -780,9 +780,8 @@ cFrameDetector::cFrameDetector(int Pid, int Type) newFrame = independentFrame = false; numPtsValues = 0; numIFrames = 0; - frameDuration = 0; + framesPerSecond = 0; framesInPayloadUnit = framesPerPayloadUnit = 0; - payloadUnitOfFrame = 0; scanning = false; scanner = EMPTY_SCANNER; } @@ -804,7 +803,6 @@ void cFrameDetector::SetPid(int Pid, int Type) void cFrameDetector::Reset(void) { newFrame = independentFrame = false; - payloadUnitOfFrame = 0; scanning = false; scanner = EMPTY_SCANNER; } @@ -831,8 +829,8 @@ int cFrameDetector::Analyze(const uchar *Data, int Length) return Processed; if (Length < MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE) return Processed; // need more data, in case the frame type is not stored in the first TS packet - if (!frameDuration) { - // frame duration unknown, so collect a sequence of PTS values: + if (!framesPerSecond) { + // frame rate unknown, so collect a sequence of PTS values: if (numPtsValues < MaxPtsValues && numIFrames < 2) { // collect a sequence containing at least two I-frames const uchar *Pes = Data + TsPayloadOffset(Data); if (PesHasPts(Pes)) { @@ -857,28 +855,22 @@ int cFrameDetector::Analyze(const uchar *Data, int Length) uint32_t Delta = ptsValues[0]; // determine frame info: if (isVideo) { - if (Delta % 3600 == 0) - frameDuration = 3600; // PAL, 25 fps, exact timing - else if (abs(Delta % 3600) == 3599 || abs(Delta % 3600) == 1) - frameDuration = 3600; // PAL, 25 fps, timing with jitter + if (abs(Delta - 3600) <= 1) + framesPerSecond = 25.0; else if (Delta % 3003 == 0) - frameDuration = 3003; // NTSC, 29.97 fps - else if (abs(Delta - 1800) <= 1) { - frameDuration = 3600; // PAL, 25 fps - framesPerPayloadUnit = -2; - } - else if (Delta == 1501) { - frameDuration = 3003; // NTSC, 29.97 fps - framesPerPayloadUnit = -2; - } + framesPerSecond = 30.0 / 1.001; + else if (abs(Delta - 1800) <= 1) + framesPerSecond = 50.0; + else if (Delta == 1501) + framesPerSecond = 60.0 / 1.001; else { - frameDuration = 3600; // unknown, assuming 25 fps - dsyslog("unknown frame duration (%d), assuming 25 fps", Delta); + framesPerSecond = 25.0; + dsyslog("unknown frame delta (%d), assuming 25 fps", Delta); } } else // audio - frameDuration = Delta; // PTS of audio frames is always increasing - dbgframes("\nframe duration = %d FPS = %5.2f FPPU = %d\n", frameDuration, 90000.0 / frameDuration, framesPerPayloadUnit); + framesPerSecond = 90000.0 / Delta; // PTS of audio frames is always increasing + dbgframes("\nDelta = %d FPS = %5.2f FPPU = %d\n", Delta, framesPerSecond, framesPerPayloadUnit); } } scanner = EMPTY_SCANNER; @@ -927,13 +919,6 @@ int cFrameDetector::Analyze(const uchar *Data, int Length) newFrame = true; independentFrame = Data[i + 1] == 0x10; if (synced) { - if (framesPerPayloadUnit < 0) { - payloadUnitOfFrame = (payloadUnitOfFrame + 1) % -framesPerPayloadUnit; - if (payloadUnitOfFrame != 0 && independentFrame) - payloadUnitOfFrame = 0; - if (payloadUnitOfFrame) - newFrame = false; - } if (framesPerPayloadUnit <= 1) scanning = false; } @@ -964,7 +949,7 @@ int cFrameDetector::Analyze(const uchar *Data, int Length) pid = 0; // let's just ignore any further data } } - if (!synced && frameDuration && independentFrame) { + if (!synced && framesPerSecond && independentFrame) { synced = true; dbgframes("*"); Reset(); diff --git a/remux.h b/remux.h index 7b621878..7140aaf0 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.26 2010/06/05 13:27:55 kls Exp $ + * $Id: remux.h 2.27 2010/11/01 11:24:20 kls Exp $ */ #ifndef __REMUX_H @@ -347,12 +347,10 @@ private: int numPtsValues; int numIFrames; bool isVideo; - int frameDuration; + double framesPerSecond; int framesInPayloadUnit; int framesPerPayloadUnit; // Some broadcasters send one frame per payload unit (== 1), - // some put an entire GOP into one payload unit (> 1), and - // some spread a single frame over several payload units (< 0). - int payloadUnitOfFrame; + // while others put an entire GOP into one payload unit (> 1). bool scanning; uint32_t scanner; public: @@ -380,7 +378,7 @@ public: ///< Returns true if a new frame was detected and this is an independent frame ///< (i.e. one that can be displayed by itself, without using data from any ///< other frames). - double FramesPerSecond(void) { return frameDuration ? 90000.0 / frameDuration : 0; } + double FramesPerSecond(void) { return framesPerSecond; } ///< Returns the number of frames per second, or 0 if this information is not ///< available. };