GetPosition() -> GetHardwareFrame; handle timing retry in the driver,

so the logic is available to the driver
This commit is contained in:
Glenn Maynard
2006-12-22 22:22:01 +00:00
parent 4dd1f97875
commit bafea3b7ab
7 changed files with 49 additions and 40 deletions
+3 -35
View File
@@ -477,7 +477,7 @@ float RageSound::GetLengthSeconds()
} }
/* Get the position in frames. */ /* Get the position in frames. */
int64_t RageSound::GetPositionSecondsInternal( bool *bApproximate ) const int64_t RageSound::GetPositionSecondsInternal( bool *bApproximate, RageTimer *pTimer ) const
{ {
LockMut( m_Mutex ); LockMut( m_Mutex );
@@ -499,7 +499,7 @@ int64_t RageSound::GetPositionSecondsInternal( bool *bApproximate ) const
} }
/* Get our current hardware position. */ /* Get our current hardware position. */
int64_t iCurrentHardwareFrame = SOUNDMAN->GetPosition(); int64_t iCurrentHardwareFrame = SOUNDMAN->GetPosition( pTimer );
/* It's sometimes possible for the hardware position to move backwards, usually /* It's sometimes possible for the hardware position to move backwards, usually
* on underrun. We can try to prevent this in each driver, but it's an obscure * on underrun. We can try to prevent this in each driver, but it's an obscure
@@ -543,39 +543,7 @@ float RageSound::GetPositionSeconds( bool *bApproximate, RageTimer *pTimestamp )
{ {
LockMut( m_Mutex ); LockMut( m_Mutex );
if( pTimestamp == NULL ) const int64_t iPositionFrames = GetPositionSecondsInternal( bApproximate, pTimestamp );
{
const int64_t iPositionFrames = GetPositionSecondsInternal( bApproximate );
return iPositionFrames / float(samplerate());
}
/*
* We may have unpredictable scheduling delays between updating the timestamp
* and reading the sound position. If we're preempted while doing this and
* it may have caused the timestamp to not match the returned time, retry.
*
* As a failsafe, only allow a few attempts. If this has to try more than
* a few times, then probably we have thread contention that's causing more
* severe performance problems, anyway.
*/
int iTries = 3;
int64_t iPositionFrames;
do
{
pTimestamp->Touch();
iPositionFrames = GetPositionSecondsInternal( bApproximate );
} while( --iTries && pTimestamp->Ago() > 0.002f );
if( iTries == 0 )
{
static bool bLogged = false;
if( !bLogged )
{
bLogged = true;
LOG->Warn( "RageSound::GetPositionSeconds: too many tries" );
}
}
return iPositionFrames / float(samplerate()); return iPositionFrames / float(samplerate());
} }
+2 -1
View File
@@ -186,7 +186,8 @@ private:
RString m_sError; RString m_sError;
int64_t GetPositionSecondsInternal( bool *bApproximate=NULL ) const; int64_t GetPositionSecondsInternal( bool *bApproximate = NULL, RageTimer *pTimer = NULL ) const;
bool SetPositionFrames( int frames = -1 ); bool SetPositionFrames( int frames = -1 );
int GetData( char *pBuffer, int iSize ); int GetData( char *pBuffer, int iSize );
void Fail( RString sReason ); void Fail( RString sReason );
+2 -2
View File
@@ -103,11 +103,11 @@ bool RageSoundManager::Pause( RageSoundBase *pSound, bool bPause )
return m_pDriver->PauseMixing( pSound, bPause ); return m_pDriver->PauseMixing( pSound, bPause );
} }
int64_t RageSoundManager::GetPosition() const int64_t RageSoundManager::GetPosition( RageTimer *pTimer ) const
{ {
if( m_pDriver == NULL ) if( m_pDriver == NULL )
return 0; return 0;
return m_pDriver->GetPosition(); return m_pDriver->GetHardwareFrame( pTimer );
} }
void RageSoundManager::Update() void RageSoundManager::Update()
+2 -1
View File
@@ -13,6 +13,7 @@ class RageSoundDriver;
struct RageSoundParams; struct RageSoundParams;
class RageSoundReader; class RageSoundReader;
class RageSoundReader_Preload; class RageSoundReader_Preload;
class RageTimer;
class RageSoundManager class RageSoundManager
{ {
@@ -37,7 +38,7 @@ public:
void StartMixing( RageSoundBase *snd ); /* used by RageSound */ void StartMixing( RageSoundBase *snd ); /* used by RageSound */
void StopMixing( RageSoundBase *snd ); /* used by RageSound */ void StopMixing( RageSoundBase *snd ); /* used by RageSound */
bool Pause( RageSoundBase *snd, bool bPause ); /* used by RageSound */ bool Pause( RageSoundBase *snd, bool bPause ); /* used by RageSound */
int64_t GetPosition() const; /* used by RageSound */ int64_t GetPosition( RageTimer *pTimer ) const; /* used by RageSound */
void RegisterSound( RageSound *p ); /* used by RageSound */ void RegisterSound( RageSound *p ); /* used by RageSound */
void UnregisterSound( RageSound *p ); /* used by RageSound */ void UnregisterSound( RageSound *p ); /* used by RageSound */
int GetUniqueID(); /* used by RageSound */ int GetUniqueID(); /* used by RageSound */
+2 -1
View File
@@ -5,6 +5,7 @@
#include "arch/RageDriver.h" #include "arch/RageDriver.h"
class RageSoundBase; class RageSoundBase;
class RageTimer;
class RageSoundDriver: public RageDriver class RageSoundDriver: public RageDriver
{ {
public: public:
@@ -36,7 +37,7 @@ public:
/* Get the current hardware frame position, in the same time base as passed to /* Get the current hardware frame position, in the same time base as passed to
* RageSound::CommitPlayingPosition. */ * RageSound::CommitPlayingPosition. */
virtual int64_t GetPosition() const = 0; virtual int64_t GetHardwareFrame( RageTimer *pTimer ) const = 0;
/* When a sound is finished playing (GetDataToPlay returns 0) and the sound has /* When a sound is finished playing (GetDataToPlay returns 0) and the sound has
* been completely flushed (so GetPosition is no longer meaningful), call * been completely flushed (so GetPosition is no longer meaningful), call
@@ -445,6 +445,41 @@ RageSound_Generic_Software::~RageSound_Generic_Software()
} }
} }
int64_t RageSound_Generic_Software::GetHardwareFrame( RageTimer *pTimestamp ) const
{
if( pTimestamp == NULL )
return GetPosition();
/*
* We may have unpredictable scheduling delays between updating the timestamp
* and reading the sound position. If we're preempted while doing this and
* it may have caused the timestamp to not match the returned time, retry.
*
* As a failsafe, only allow a few attempts. If this has to try more than
* a few times, then probably we have thread contention that's causing more
* severe performance problems, anyway.
*/
int iTries = 3;
int64_t iPositionFrames;
do
{
pTimestamp->Touch();
iPositionFrames = GetPosition();
} while( --iTries && pTimestamp->Ago() > 0.002f );
if( iTries == 0 )
{
static bool bLogged = false;
if( !bLogged )
{
bLogged = true;
LOG->Warn( "RageSound_Generic_Software::GetHardwareFrame: too many tries" );
}
}
return iPositionFrames;
}
/* /*
* (c) 2002-2004 Glenn Maynard * (c) 2002-2004 Glenn Maynard
* All rights reserved. * All rights reserved.
@@ -20,6 +20,9 @@ public:
RageSound_Generic_Software(); RageSound_Generic_Software();
virtual ~RageSound_Generic_Software(); virtual ~RageSound_Generic_Software();
virtual int64_t GetHardwareFrame( RageTimer *pTimer ) const;
virtual int64_t GetPosition() const = 0;
protected: protected:
/* Start the decoding. This should be called once the hardware is set up and /* Start the decoding. This should be called once the hardware is set up and
* GetSampleRate will return the correct value. */ * GetSampleRate will return the correct value. */