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 68562243ec
commit 55a95afef0
6 changed files with 54 additions and 33 deletions

View file

@ -85,7 +85,7 @@ public:
// TODO: getTime
private:
void prepareDecoder();
bool prepareDecoder();
inline bool bufferMore(uint bytes);
private:

View file

@ -5,7 +5,7 @@
<ATOM Name="MinDistance" Value="100000"/>
<ATOM Name="MaxDistance" Value="200000"/>
<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>
<ATOM Name="AbsolutePosition" Value="false"/>
<ATOM Name="Priority" Value="Highest"/>

View file

@ -46,7 +46,8 @@
#define 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 NLMISC;
@ -94,6 +95,8 @@ static void initSample()
s_AudioMixer->getListener()->setPos(initpos);
s_AudioMixer->getListener()->setOrientation(frontvec, upvec);
CPath::addSearchPath(RYZOM_DATA, true, false);
//NLMISC::CHTimer::startBench();
s_Source = s_AudioMixer->createSource(CStringMapper::map("stream_file"));

View file

@ -1651,6 +1651,7 @@ void CAudioMixerUser::update()
_MusicChannelFaders[i].update();
// Check all playing track and stop any terminated buffer.
std::list<CSourceCommon *>::size_type nbWaitingSources = _Sources.size();
for (i=0; i<_Tracks.size(); ++i)
{
if (!_Tracks[i]->isPlaying())
@ -1662,13 +1663,14 @@ void CAudioMixerUser::update()
}
// try to play any waiting source.
if (!_SourceWaitingForPlay.empty())
if (!_SourceWaitingForPlay.empty() && nbWaitingSources)
{
// check if the source still exist before trying to play it
if (_Sources.find(_SourceWaitingForPlay.front()) != _Sources.end())
_SourceWaitingForPlay.front()->play();
// nldebug("Before POP Sources waiting : %u", _SourceWaitingForPlay.size());
_SourceWaitingForPlay.pop_front();
--nbWaitingSources;
// 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!
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());
CStreamSource::play();
if (!_Playing && !m_WaitingForPlay)
if (m_NextBuffer || !m_FreeBuffers)
{
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
{
nldebug("play waiting, hop onto waiting list %s", getStreamFileSound()->getFilePath().c_str());
m_WaitingForPlay = true;
CAudioMixerUser *mixer = CAudioMixerUser::instance();
mixer->addSourceWaitingForPlay(this);
// thread went kaboom while not started playing yet, probably the audiodecoder cannot be started
// don't play
m_WaitingForPlay = false;
}
}
else if (!_Playing)
{
nldebug("play go %s", getStreamFileSound()->getFilePath().c_str());
if (!m_WaitingForPlay)
{
//if (!m_WaitingForPlay)
//{
// thread may be stopping from stop call
m_Thread->wait();
}
else
{
nlwarning("Already waiting for play");
}
//}
//else
//{
// nlwarning("Already waiting for play");
//}
if (!getStreamFileSound()->getAsync())
prepareDecoder();
{
if (!prepareDecoder())
{
return;
}
}
// else load audiodecoder in thread
m_WaitingForPlay = true;
m_Thread->start();
@ -221,7 +235,7 @@ bool CStreamFileSource::isLoadingAsync()
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
@ -243,13 +257,15 @@ void CStreamFileSource::prepareDecoder()
if (!m_AudioDecoder)
{
nlwarning("Failed to create IAudioDecoder, likely invalid format");
return;
return false;
}
this->setFormat(m_AudioDecoder->getChannels(), m_AudioDecoder->getBitsPerSample(), (uint32)m_AudioDecoder->getSamplesPerSec());
}
uint samples, bytes;
this->getRecommendedBufferSize(samples, bytes);
this->preAllocate(bytes * 2);
return true;
}
inline bool CStreamFileSource::bufferMore(uint bytes) // buffer from bytes (minimum) to bytes * 2 (maximum)
@ -271,7 +287,10 @@ void CStreamFileSource::run()
bool looping = _Looping;
if (getStreamFileSound()->getAsync())
prepareDecoder();
{
if (!prepareDecoder())
return;
}
uint samples, bytes;
this->getRecommendedBufferSize(samples, bytes);
uint32 recSleep = 40;

View file

@ -161,7 +161,7 @@ void CStreamSource::play()
delete 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;
}
@ -182,12 +182,9 @@ void CStreamSource::play()
// pSource->setPos( _Position, 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->setVelocity(_Velocity);
}
pSource->setMinMaxDistances(m_StreamSound->getMinDistance(), m_StreamSound->getMaxDistance(), false);
setDirection(_Direction); // because there is a workaround inside
pSource->setVelocity(_Velocity);
pSource->setGain(getFinalGain());
pSource->setSourceRelativeMode(_RelativeMode);
// pSource->setLooping(_Looping);
@ -435,7 +432,7 @@ uint32 CStreamSource::getRecommendedSleepTime() const
{
if (m_FreeBuffers > 0) return 0;
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;
}