GetPosition() -> GetHardwareFrame; handle timing retry in the driver,
so the logic is available to the driver
This commit is contained in:
@@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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. */
|
||||||
|
|||||||
Reference in New Issue
Block a user