From d1dd7df17ab9c24867491c7cbaa148ad83ec216f Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 20 Mar 2011 10:22:22 +0100 Subject: Fixed detecting frames on channels that broadcast with separate "fields" instead of complete frames --- HISTORY | 4 +++- remux.c | 40 ++++++++++++++++++++++++++++++++++------ remux.h | 7 +++++-- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/HISTORY b/HISTORY index 9451433c..ea57a04e 100644 --- a/HISTORY +++ b/HISTORY @@ -6557,8 +6557,10 @@ Video Disk Recorder Revision History - The original display size of subtitles is now used to scale them properly when displaying them on an HD OSD. -2011-03-13: Version 1.7.18 +2011-03-20: Version 1.7.18 - Changed -O2 to -O3 in Make.config.template (reported by Matti Lehtimäki). - Added a missing 'default' case in cPixmapMemory::DrawEllipse(). - Fixed some direct comparisons of double values. +- Fixed detecting frames on channels that broadcast with separate "fields" instead + of complete frames. diff --git a/remux.c b/remux.c index afe9180e..f7ef87a9 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.52 2011/03/13 13:57:09 kls Exp $ + * $Id: remux.c 2.53 2011/03/20 10:21:14 kls Exp $ */ #include "remux.h" @@ -783,9 +783,11 @@ cFrameDetector::cFrameDetector(int Pid, int Type) synced = false; newFrame = independentFrame = false; numPtsValues = 0; + numFrames = 0; numIFrames = 0; framesPerSecond = 0; framesInPayloadUnit = framesPerPayloadUnit = 0; + payloadUnitOfFrame = 0; scanning = false; scanner = EMPTY_SCANNER; } @@ -807,6 +809,7 @@ void cFrameDetector::SetPid(int Pid, int Type) void cFrameDetector::Reset(void) { newFrame = independentFrame = false; + payloadUnitOfFrame = 0; scanning = false; scanner = EMPTY_SCANNER; } @@ -844,6 +847,7 @@ int cFrameDetector::Analyze(const uchar *Data, int Length) dbgframes("#"); numPtsValues = 0; numIFrames = 0; + numFrames = 0; } else numPtsValues++; @@ -863,10 +867,23 @@ int cFrameDetector::Analyze(const uchar *Data, int Length) framesPerSecond = 25.0; else if (Delta % 3003 == 0) framesPerSecond = 30.0 / 1.001; - else if (abs(Delta - 1800) <= 1) - framesPerSecond = 50.0; + else if (abs(Delta - 1800) <= 1) { + if (numFrames > 50) { + // this is a "best guess": if there are more than 50 frames between two I-frames, we assume each "frame" actually contains a "field", so two "fields" make one "frame" + framesPerSecond = 25.0; + framesPerPayloadUnit = -2; + } + else + framesPerSecond = 50.0; + } else if (Delta == 1501) - framesPerSecond = 60.0 / 1.001; + if (numFrames > 50) { + // this is a "best guess": if there are more than 50 frames between two I-frames, we assume each "frame" actually contains a "field", so two "fields" make one "frame" + framesPerSecond = 30.0 / 1.001; + framesPerPayloadUnit = -2; + } + else + framesPerSecond = 60.0 / 1.001; else { framesPerSecond = 25.0; dsyslog("unknown frame delta (%d), assuming 25 fps", Delta); @@ -874,7 +891,7 @@ int cFrameDetector::Analyze(const uchar *Data, int Length) } else // audio framesPerSecond = 90000.0 / Delta; // PTS of audio frames is always increasing - dbgframes("\nDelta = %d FPS = %5.2f FPPU = %d\n", Delta, framesPerSecond, framesPerPayloadUnit); + dbgframes("\nDelta = %d FPS = %5.2f FPPU = %d NF = %d\n", Delta, framesPerSecond, framesPerPayloadUnit, numFrames); } } scanner = EMPTY_SCANNER; @@ -909,6 +926,8 @@ int cFrameDetector::Analyze(const uchar *Data, int Length) framesInPayloadUnit++; if (independentFrame) numIFrames++; + if (numIFrames == 1) + numFrames++; dbgframes("%d ", (Data[i + 2] >> 3) & 0x07); } if (synced) @@ -923,6 +942,13 @@ 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; } @@ -930,6 +956,8 @@ int cFrameDetector::Analyze(const uchar *Data, int Length) framesInPayloadUnit++; if (independentFrame) numIFrames++; + if (numIFrames == 1) + numFrames++; dbgframes("%02X ", Data[i + 1]); } if (synced) @@ -955,7 +983,7 @@ int cFrameDetector::Analyze(const uchar *Data, int Length) } if (!synced && framesPerSecond > 0.0 && independentFrame) { synced = true; - dbgframes("*"); + dbgframes("*\n"); Reset(); return Processed + TS_SIZE; } diff --git a/remux.h b/remux.h index 7140aaf0..60a9a578 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.27 2010/11/01 11:24:20 kls Exp $ + * $Id: remux.h 2.28 2011/03/19 16:52:46 kls Exp $ */ #ifndef __REMUX_H @@ -345,12 +345,15 @@ private: bool independentFrame; uint32_t ptsValues[MaxPtsValues]; // 32 bit is enough - we only need the delta int numPtsValues; + int numFrames; int numIFrames; bool isVideo; double framesPerSecond; int framesInPayloadUnit; int framesPerPayloadUnit; // Some broadcasters send one frame per payload unit (== 1), - // while others put an entire GOP into one 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; bool scanning; uint32_t scanner; public: -- cgit v1.2.3