mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Fixed detecting frames on channels that broadcast with 50 or 60 fps
This commit is contained in:
parent
55d0d8f9ba
commit
4f50c34824
7
HISTORY
7
HISTORY
@ -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
47
remux.c
@ -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
10
remux.h
@ -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.
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user