Improve TV mode detection logic:

* Skip the first view frames
    * Change the algorithm to be more eager to accept mode changes until the
      mode has settled for at least five frames
    * If in doubt, assign odd frames to NTSC
This commit is contained in:
Christian Speckner 2016-12-12 22:25:47 +01:00
parent b9e2fc9022
commit a35f378d87
2 changed files with 60 additions and 21 deletions

View File

@ -17,6 +17,8 @@
// $Id$ // $Id$
//============================================================================ //============================================================================
// #define TIA_FRAMEMANAGER_DEBUG_LOG
#include "FrameManager.hxx" #include "FrameManager.hxx"
enum Metrics: uInt32 { enum Metrics: uInt32 {
@ -30,7 +32,9 @@ enum Metrics: uInt32 {
visibleOverscan = 20, visibleOverscan = 20,
maxUnderscan = 10, maxUnderscan = 10,
maxFramesWithoutVsync = 50, maxFramesWithoutVsync = 50,
tvModeDetectionTolerance = 20 tvModeDetectionTolerance = 20,
modeDetectionInitialFrameskip = 5,
framesForModeConfirmation = 5
}; };
static constexpr uInt32 static constexpr uInt32
@ -65,6 +69,9 @@ void FrameManager::reset()
myWaitForVsync = true; myWaitForVsync = true;
myVsync = false; myVsync = false;
myVblank = false; myVblank = false;
myTotalFrames = 0;
myFramesInMode = 0;
myModeConfirmed = false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -146,7 +153,10 @@ void FrameManager::setVsync(bool vsync)
break; break;
case State::frame: case State::frame:
if (myVsync) finalizeFrame(State::waitForVsyncEnd); if (myVsync) {
myCurrentFrameTotalLines++;
finalizeFrame(State::waitForVsyncEnd);
}
break; break;
default: default:
@ -237,25 +247,50 @@ void FrameManager::setState(FrameManager::State state)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameManager::finalizeFrame(FrameManager::State state) void FrameManager::finalizeFrame(FrameManager::State state)
{ {
const uInt32
deltaNTSC = abs(Int32(myCurrentFrameTotalLines) - Int32(frameLinesNTSC)),
deltaPAL = abs(Int32(myCurrentFrameTotalLines) - Int32(frameLinesPAL));
if (std::min(deltaNTSC, deltaPAL) <= Metrics::tvModeDetectionTolerance) {
setTvMode(deltaNTSC <= deltaPAL ? TvMode::ntsc : TvMode::pal);
}
if (myOnFrameComplete) { if (myOnFrameComplete) {
myOnFrameComplete(); myOnFrameComplete();
} }
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG #ifdef TIA_FRAMEMANAGER_DEBUG_LOG
(cout << "frame complete @ " << myLineInState << " (" << myCurrentFrameFinalLines << " total)" << "\n").flush(); (cout << "frame complete @ " << myLineInState << " (" << myCurrentFrameTotalLines << " total)" << "\n").flush();
#endif // TIA_FRAMEMANAGER_DEBUG_LOG #endif // TIA_FRAMEMANAGER_DEBUG_LOG
myCurrentFrameFinalLines = myCurrentFrameTotalLines; myCurrentFrameFinalLines = myCurrentFrameTotalLines;
myCurrentFrameTotalLines = 0; myCurrentFrameTotalLines = 0;
setState(state); setState(state);
myTotalFrames++;
if (myTotalFrames <= Metrics::modeDetectionInitialFrameskip) {
return;
}
const TvMode oldMode = myMode;
const uInt32
deltaNTSC = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesNTSC)),
deltaPAL = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesPAL));
if (std::min(deltaNTSC, deltaPAL) <= Metrics::tvModeDetectionTolerance)
setTvMode(deltaNTSC <= deltaPAL ? TvMode::ntsc : TvMode::pal);
else if (!myModeConfirmed) {
if (
(myCurrentFrameFinalLines < frameLinesPAL) &&
(myCurrentFrameFinalLines > frameLinesNTSC) &&
(myCurrentFrameFinalLines % 2)
)
setTvMode(TvMode::ntsc);
else
setTvMode(deltaNTSC <= deltaPAL ? TvMode::ntsc : TvMode::pal);
}
if (oldMode == myMode)
myFramesInMode++;
else
myFramesInMode = 0;
if (myFramesInMode > Metrics::framesForModeConfirmation)
myModeConfirmed = true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -97,6 +97,10 @@ class FrameManager : public Serializable
uInt32 myCurrentFrameTotalLines; uInt32 myCurrentFrameTotalLines;
uInt32 myCurrentFrameFinalLines; uInt32 myCurrentFrameFinalLines;
uInt32 myTotalFrames;
uInt32 myFramesInMode;
bool myModeConfirmed;
bool myVsync; bool myVsync;
bool myVblank; bool myVblank;