Fixed detecting frames on channels that broadcast with 50 or 60 fps

This commit is contained in:
Klaus Schmidinger 2010-11-01 12:31:52 +01:00
parent 55d0d8f9ba
commit 4f50c34824
3 changed files with 26 additions and 38 deletions

View File

@ -6481,7 +6481,7 @@ Video Disk Recorder Revision History
from Osama Alrawab). See INSTALL for information on how to turn this on. from Osama Alrawab). See INSTALL for information on how to turn this on.
- Added Arabian language texts (thanks to Osama Alrawab). - 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). - Updated the Estonian OSD texts (thanks to Arthur Konovalov).
- Fixed following symbolic links in RemoveFileOrDir() (cont'd) (thanks to - 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ä). - 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ä). - Added Language and fixed Language-Team header of *.po (thanks to Ville Skyttä).
- Updated the Lithuanian OSD texts (thanks to Valdemaras Pipiras). - 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.

47
remux.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "remux.h"
@ -780,9 +780,8 @@ cFrameDetector::cFrameDetector(int Pid, int Type)
newFrame = independentFrame = false; newFrame = independentFrame = false;
numPtsValues = 0; numPtsValues = 0;
numIFrames = 0; numIFrames = 0;
frameDuration = 0; framesPerSecond = 0;
framesInPayloadUnit = framesPerPayloadUnit = 0; framesInPayloadUnit = framesPerPayloadUnit = 0;
payloadUnitOfFrame = 0;
scanning = false; scanning = false;
scanner = EMPTY_SCANNER; scanner = EMPTY_SCANNER;
} }
@ -804,7 +803,6 @@ void cFrameDetector::SetPid(int Pid, int Type)
void cFrameDetector::Reset(void) void cFrameDetector::Reset(void)
{ {
newFrame = independentFrame = false; newFrame = independentFrame = false;
payloadUnitOfFrame = 0;
scanning = false; scanning = false;
scanner = EMPTY_SCANNER; scanner = EMPTY_SCANNER;
} }
@ -831,8 +829,8 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
return Processed; return Processed;
if (Length < MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE) 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 return Processed; // need more data, in case the frame type is not stored in the first TS packet
if (!frameDuration) { if (!framesPerSecond) {
// frame duration unknown, so collect a sequence of PTS values: // frame rate unknown, so collect a sequence of PTS values:
if (numPtsValues < MaxPtsValues && numIFrames < 2) { // collect a sequence containing at least two I-frames if (numPtsValues < MaxPtsValues && numIFrames < 2) { // collect a sequence containing at least two I-frames
const uchar *Pes = Data + TsPayloadOffset(Data); const uchar *Pes = Data + TsPayloadOffset(Data);
if (PesHasPts(Pes)) { if (PesHasPts(Pes)) {
@ -857,28 +855,22 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
uint32_t Delta = ptsValues[0]; uint32_t Delta = ptsValues[0];
// determine frame info: // determine frame info:
if (isVideo) { if (isVideo) {
if (Delta % 3600 == 0) if (abs(Delta - 3600) <= 1)
frameDuration = 3600; // PAL, 25 fps, exact timing framesPerSecond = 25.0;
else if (abs(Delta % 3600) == 3599 || abs(Delta % 3600) == 1)
frameDuration = 3600; // PAL, 25 fps, timing with jitter
else if (Delta % 3003 == 0) else if (Delta % 3003 == 0)
frameDuration = 3003; // NTSC, 29.97 fps framesPerSecond = 30.0 / 1.001;
else if (abs(Delta - 1800) <= 1) { else if (abs(Delta - 1800) <= 1)
frameDuration = 3600; // PAL, 25 fps framesPerSecond = 50.0;
framesPerPayloadUnit = -2; else if (Delta == 1501)
} framesPerSecond = 60.0 / 1.001;
else if (Delta == 1501) {
frameDuration = 3003; // NTSC, 29.97 fps
framesPerPayloadUnit = -2;
}
else { else {
frameDuration = 3600; // unknown, assuming 25 fps framesPerSecond = 25.0;
dsyslog("unknown frame duration (%d), assuming 25 fps", Delta); dsyslog("unknown frame delta (%d), assuming 25 fps", Delta);
} }
} }
else // audio else // audio
frameDuration = Delta; // PTS of audio frames is always increasing framesPerSecond = 90000.0 / Delta; // PTS of audio frames is always increasing
dbgframes("\nframe duration = %d FPS = %5.2f FPPU = %d\n", frameDuration, 90000.0 / frameDuration, framesPerPayloadUnit); dbgframes("\nDelta = %d FPS = %5.2f FPPU = %d\n", Delta, framesPerSecond, framesPerPayloadUnit);
} }
} }
scanner = EMPTY_SCANNER; scanner = EMPTY_SCANNER;
@ -927,13 +919,6 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
newFrame = true; newFrame = true;
independentFrame = Data[i + 1] == 0x10; independentFrame = Data[i + 1] == 0x10;
if (synced) { if (synced) {
if (framesPerPayloadUnit < 0) {
payloadUnitOfFrame = (payloadUnitOfFrame + 1) % -framesPerPayloadUnit;
if (payloadUnitOfFrame != 0 && independentFrame)
payloadUnitOfFrame = 0;
if (payloadUnitOfFrame)
newFrame = false;
}
if (framesPerPayloadUnit <= 1) if (framesPerPayloadUnit <= 1)
scanning = false; scanning = false;
} }
@ -964,7 +949,7 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
pid = 0; // let's just ignore any further data pid = 0; // let's just ignore any further data
} }
} }
if (!synced && frameDuration && independentFrame) { if (!synced && framesPerSecond && independentFrame) {
synced = true; synced = true;
dbgframes("*"); dbgframes("*");
Reset(); Reset();

10
remux.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __REMUX_H
@ -347,12 +347,10 @@ private:
int numPtsValues; int numPtsValues;
int numIFrames; int numIFrames;
bool isVideo; bool isVideo;
int frameDuration; double framesPerSecond;
int framesInPayloadUnit; int framesInPayloadUnit;
int framesPerPayloadUnit; // Some broadcasters send one frame per payload unit (== 1), int framesPerPayloadUnit; // Some broadcasters send one frame per payload unit (== 1),
// some put an entire GOP into one payload unit (> 1), and // while others put an entire GOP into one payload unit (> 1).
// some spread a single frame over several payload units (< 0).
int payloadUnitOfFrame;
bool scanning; bool scanning;
uint32_t scanner; uint32_t scanner;
public: public:
@ -380,7 +378,7 @@ public:
///< Returns true if a new frame was detected and this is an independent frame ///< 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 ///< (i.e. one that can be displayed by itself, without using data from any
///< other frames). ///< 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 ///< Returns the number of frames per second, or 0 if this information is not
///< available. ///< available.
}; };