Changed: #795 Handle safely when audio decoder fails to be created
This commit is contained in:
parent
4ac6c26dfd
commit
49ad587f0d
6 changed files with 54 additions and 33 deletions
|
@ -85,7 +85,7 @@ public:
|
||||||
// TODO: getTime
|
// TODO: getTime
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void prepareDecoder();
|
bool prepareDecoder();
|
||||||
inline bool bufferMore(uint bytes);
|
inline bool bufferMore(uint bytes);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<ATOM Name="MinDistance" Value="100000"/>
|
<ATOM Name="MinDistance" Value="100000"/>
|
||||||
<ATOM Name="MaxDistance" Value="200000"/>
|
<ATOM Name="MaxDistance" Value="200000"/>
|
||||||
<ATOM Name="Async" Value ="true"/>
|
<ATOM Name="Async" Value ="true"/>
|
||||||
<ATOM Name="FilePath" Value="D:/source/kaetemi/toverhex/src/samples/music_stream/data/aeon_1_10_mystic_river.ogg"/>
|
<ATOM Name="FilePath" Value="Pyr Entrance.ogg"/>
|
||||||
</VSTRUCT>
|
</VSTRUCT>
|
||||||
<ATOM Name="AbsolutePosition" Value="false"/>
|
<ATOM Name="AbsolutePosition" Value="false"/>
|
||||||
<ATOM Name="Priority" Value="Highest"/>
|
<ATOM Name="Priority" Value="Highest"/>
|
||||||
|
|
|
@ -46,7 +46,8 @@
|
||||||
#define NL_SOUND_DATA "."
|
#define NL_SOUND_DATA "."
|
||||||
#endif // NL_SOUND_DATA
|
#endif // NL_SOUND_DATA
|
||||||
|
|
||||||
#define SAMPLE_OGG "D:/source/kaetemi/toverhex/src/samples/music_stream/data/aeon_1_10_mystic_river.ogg"
|
#define RYZOM_DATA "P:/data"
|
||||||
|
#define SAMPLE_OGG "Pyr Entrance.ogg"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace NLMISC;
|
using namespace NLMISC;
|
||||||
|
@ -94,6 +95,8 @@ static void initSample()
|
||||||
s_AudioMixer->getListener()->setPos(initpos);
|
s_AudioMixer->getListener()->setPos(initpos);
|
||||||
s_AudioMixer->getListener()->setOrientation(frontvec, upvec);
|
s_AudioMixer->getListener()->setOrientation(frontvec, upvec);
|
||||||
|
|
||||||
|
CPath::addSearchPath(RYZOM_DATA, true, false);
|
||||||
|
|
||||||
//NLMISC::CHTimer::startBench();
|
//NLMISC::CHTimer::startBench();
|
||||||
|
|
||||||
s_Source = s_AudioMixer->createSource(CStringMapper::map("stream_file"));
|
s_Source = s_AudioMixer->createSource(CStringMapper::map("stream_file"));
|
||||||
|
|
|
@ -1651,6 +1651,7 @@ void CAudioMixerUser::update()
|
||||||
_MusicChannelFaders[i].update();
|
_MusicChannelFaders[i].update();
|
||||||
|
|
||||||
// Check all playing track and stop any terminated buffer.
|
// Check all playing track and stop any terminated buffer.
|
||||||
|
std::list<CSourceCommon *>::size_type nbWaitingSources = _Sources.size();
|
||||||
for (i=0; i<_Tracks.size(); ++i)
|
for (i=0; i<_Tracks.size(); ++i)
|
||||||
{
|
{
|
||||||
if (!_Tracks[i]->isPlaying())
|
if (!_Tracks[i]->isPlaying())
|
||||||
|
@ -1662,13 +1663,14 @@ void CAudioMixerUser::update()
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to play any waiting source.
|
// try to play any waiting source.
|
||||||
if (!_SourceWaitingForPlay.empty())
|
if (!_SourceWaitingForPlay.empty() && nbWaitingSources)
|
||||||
{
|
{
|
||||||
// check if the source still exist before trying to play it
|
// check if the source still exist before trying to play it
|
||||||
if (_Sources.find(_SourceWaitingForPlay.front()) != _Sources.end())
|
if (_Sources.find(_SourceWaitingForPlay.front()) != _Sources.end())
|
||||||
_SourceWaitingForPlay.front()->play();
|
_SourceWaitingForPlay.front()->play();
|
||||||
// nldebug("Before POP Sources waiting : %u", _SourceWaitingForPlay.size());
|
// nldebug("Before POP Sources waiting : %u", _SourceWaitingForPlay.size());
|
||||||
_SourceWaitingForPlay.pop_front();
|
_SourceWaitingForPlay.pop_front();
|
||||||
|
--nbWaitingSources;
|
||||||
// nldebug("After POP Sources waiting : %u", _SourceWaitingForPlay.size());
|
// nldebug("After POP Sources waiting : %u", _SourceWaitingForPlay.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,39 +63,53 @@ void CStreamFileSource::play()
|
||||||
// note: CStreamSource will assert crash if already physically playing!
|
// note: CStreamSource will assert crash if already physically playing!
|
||||||
|
|
||||||
|
|
||||||
if (m_Thread->isRunning() && m_WaitingForPlay)
|
if (m_WaitingForPlay)
|
||||||
{
|
{
|
||||||
if (m_NextBuffer || !m_FreeBuffers)
|
if (m_Thread->isRunning())
|
||||||
{
|
{
|
||||||
nldebug("play waiting, play stream %s", getStreamFileSound()->getFilePath().c_str());
|
if (m_NextBuffer || !m_FreeBuffers)
|
||||||
CStreamSource::play();
|
|
||||||
if (!_Playing && !m_WaitingForPlay)
|
|
||||||
{
|
{
|
||||||
nldebug("playing not possible or necessary for some reason");
|
nldebug("play waiting, play stream %s", getStreamFileSound()->getFilePath().c_str());
|
||||||
|
CStreamSource::play();
|
||||||
|
if (!_Playing && !m_WaitingForPlay)
|
||||||
|
{
|
||||||
|
nldebug("playing not possible or necessary for some reason");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nldebug("play waiting, hop onto waiting list %s", getStreamFileSound()->getFilePath().c_str());
|
||||||
|
m_WaitingForPlay = true;
|
||||||
|
CAudioMixerUser *mixer = CAudioMixerUser::instance();
|
||||||
|
mixer->addSourceWaitingForPlay(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nldebug("play waiting, hop onto waiting list %s", getStreamFileSound()->getFilePath().c_str());
|
// thread went kaboom while not started playing yet, probably the audiodecoder cannot be started
|
||||||
m_WaitingForPlay = true;
|
// don't play
|
||||||
CAudioMixerUser *mixer = CAudioMixerUser::instance();
|
m_WaitingForPlay = false;
|
||||||
mixer->addSourceWaitingForPlay(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!_Playing)
|
else if (!_Playing)
|
||||||
{
|
{
|
||||||
nldebug("play go %s", getStreamFileSound()->getFilePath().c_str());
|
nldebug("play go %s", getStreamFileSound()->getFilePath().c_str());
|
||||||
if (!m_WaitingForPlay)
|
//if (!m_WaitingForPlay)
|
||||||
{
|
//{
|
||||||
// thread may be stopping from stop call
|
// thread may be stopping from stop call
|
||||||
m_Thread->wait();
|
m_Thread->wait();
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
nlwarning("Already waiting for play");
|
// nlwarning("Already waiting for play");
|
||||||
}
|
//}
|
||||||
if (!getStreamFileSound()->getAsync())
|
if (!getStreamFileSound()->getAsync())
|
||||||
prepareDecoder();
|
{
|
||||||
|
if (!prepareDecoder())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
// else load audiodecoder in thread
|
// else load audiodecoder in thread
|
||||||
m_WaitingForPlay = true;
|
m_WaitingForPlay = true;
|
||||||
m_Thread->start();
|
m_Thread->start();
|
||||||
|
@ -221,7 +235,7 @@ bool CStreamFileSource::isLoadingAsync()
|
||||||
return m_WaitingForPlay;
|
return m_WaitingForPlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStreamFileSource::prepareDecoder()
|
bool CStreamFileSource::prepareDecoder()
|
||||||
{
|
{
|
||||||
// creates a new decoder or keeps going with the current decoder if the stream was paused
|
// creates a new decoder or keeps going with the current decoder if the stream was paused
|
||||||
|
|
||||||
|
@ -243,13 +257,15 @@ void CStreamFileSource::prepareDecoder()
|
||||||
if (!m_AudioDecoder)
|
if (!m_AudioDecoder)
|
||||||
{
|
{
|
||||||
nlwarning("Failed to create IAudioDecoder, likely invalid format");
|
nlwarning("Failed to create IAudioDecoder, likely invalid format");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
this->setFormat(m_AudioDecoder->getChannels(), m_AudioDecoder->getBitsPerSample(), (uint32)m_AudioDecoder->getSamplesPerSec());
|
this->setFormat(m_AudioDecoder->getChannels(), m_AudioDecoder->getBitsPerSample(), (uint32)m_AudioDecoder->getSamplesPerSec());
|
||||||
}
|
}
|
||||||
uint samples, bytes;
|
uint samples, bytes;
|
||||||
this->getRecommendedBufferSize(samples, bytes);
|
this->getRecommendedBufferSize(samples, bytes);
|
||||||
this->preAllocate(bytes * 2);
|
this->preAllocate(bytes * 2);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool CStreamFileSource::bufferMore(uint bytes) // buffer from bytes (minimum) to bytes * 2 (maximum)
|
inline bool CStreamFileSource::bufferMore(uint bytes) // buffer from bytes (minimum) to bytes * 2 (maximum)
|
||||||
|
@ -271,7 +287,10 @@ void CStreamFileSource::run()
|
||||||
|
|
||||||
bool looping = _Looping;
|
bool looping = _Looping;
|
||||||
if (getStreamFileSound()->getAsync())
|
if (getStreamFileSound()->getAsync())
|
||||||
prepareDecoder();
|
{
|
||||||
|
if (!prepareDecoder())
|
||||||
|
return;
|
||||||
|
}
|
||||||
uint samples, bytes;
|
uint samples, bytes;
|
||||||
this->getRecommendedBufferSize(samples, bytes);
|
this->getRecommendedBufferSize(samples, bytes);
|
||||||
uint32 recSleep = 40;
|
uint32 recSleep = 40;
|
||||||
|
|
|
@ -161,7 +161,7 @@ void CStreamSource::play()
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
nldebug("CStreamSource %p : play FAILED, source is too far away !", (CAudioMixerUser::IMixerEvent*)this);
|
nldebug("CStreamSource %p : play FAILED, source is too far away !", (CAudioMixerUser::IMixerEvent*)this);
|
||||||
m_WaitingForPlay = false;
|
// m_WaitingForPlay = false; // not necessary, delete ensures waiting for thread stop
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,12 +182,9 @@ void CStreamSource::play()
|
||||||
|
|
||||||
// pSource->setPos( _Position, false);
|
// pSource->setPos( _Position, false);
|
||||||
pSource->setPos(getVirtualPos(), false);
|
pSource->setPos(getVirtualPos(), false);
|
||||||
if (!m_Buffers[0]->isStereo())
|
pSource->setMinMaxDistances(m_StreamSound->getMinDistance(), m_StreamSound->getMaxDistance(), false);
|
||||||
{
|
setDirection(_Direction); // because there is a workaround inside
|
||||||
pSource->setMinMaxDistances(m_StreamSound->getMinDistance(), m_StreamSound->getMaxDistance(), false);
|
pSource->setVelocity(_Velocity);
|
||||||
setDirection(_Direction); // because there is a workaround inside
|
|
||||||
pSource->setVelocity(_Velocity);
|
|
||||||
}
|
|
||||||
pSource->setGain(getFinalGain());
|
pSource->setGain(getFinalGain());
|
||||||
pSource->setSourceRelativeMode(_RelativeMode);
|
pSource->setSourceRelativeMode(_RelativeMode);
|
||||||
// pSource->setLooping(_Looping);
|
// pSource->setLooping(_Looping);
|
||||||
|
@ -435,7 +432,7 @@ uint32 CStreamSource::getRecommendedSleepTime() const
|
||||||
{
|
{
|
||||||
if (m_FreeBuffers > 0) return 0;
|
if (m_FreeBuffers > 0) return 0;
|
||||||
uint32 sleepTime = (uint32)((1000.0f * ((float)m_LastSize) / (float)m_BytesPerSecond) * m_PitchInv);
|
uint32 sleepTime = (uint32)((1000.0f * ((float)m_LastSize) / (float)m_BytesPerSecond) * m_PitchInv);
|
||||||
clamp(sleepTime, (uint32)0, (uint32)1000);
|
clamp(sleepTime, (uint32)0, (uint32)80);
|
||||||
return sleepTime;
|
return sleepTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue