Changed: #795 Handle safely when audio decoder fails to be created

This commit is contained in:
kaetemi 2012-04-12 12:06:03 +02:00
parent 4ac6c26dfd
commit 49ad587f0d
6 changed files with 54 additions and 33 deletions

View file

@ -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:

View file

@ -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"/>

View file

@ -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;
@ -93,6 +94,8 @@ static void initSample()
CVector upvec(0.0f, 0.0f, 1.0f); CVector upvec(0.0f, 0.0f, 1.0f);
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();

View 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());
} }
} }

View file

@ -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;

View file

@ -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;
} }