mirror of https://github.com/axmolengine/axmol.git
Fixes crash while invoking pause&resume right after play2d. (#16406)
This commit is contained in:
parent
0fbc404cd9
commit
727c501285
|
@ -96,49 +96,7 @@ static void removeItemFromVector(std::vector<T>& v, T item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioMixerController::mixOneFrame()
|
void AudioMixerController::initTrack(Track* track, std::vector<Track*>& tracksToRemove)
|
||||||
{
|
|
||||||
_isMixingFrame = true;
|
|
||||||
_activeTracksMutex.lock();
|
|
||||||
|
|
||||||
auto mixStart = clockNow();
|
|
||||||
|
|
||||||
std::vector<Track*> tracksToRemove;
|
|
||||||
tracksToRemove.reserve(_activeTracks.size());
|
|
||||||
|
|
||||||
// FOR TESTING BEGIN
|
|
||||||
// Track* track = _activeTracks[0];
|
|
||||||
//
|
|
||||||
// AudioBufferProvider::Buffer buffer;
|
|
||||||
// buffer.frameCount = _bufferSizeInFrames;
|
|
||||||
// status_t r = track->getNextBuffer(&buffer);
|
|
||||||
//// ALOG_ASSERT(buffer.frameCount == _mixing->size / 2, "buffer.frameCount:%d, _mixing->size/2:%d", buffer.frameCount, _mixing->size/2);
|
|
||||||
// if (r == NO_ERROR)
|
|
||||||
// {
|
|
||||||
// ALOGV("getNextBuffer succeed ...");
|
|
||||||
// memcpy(_mixing->buf, buffer.raw, _mixing->size);
|
|
||||||
// }
|
|
||||||
// if (buffer.raw == nullptr)
|
|
||||||
// {
|
|
||||||
// ALOGV("Play over ...");
|
|
||||||
// tracksToRemove.push_back(track);
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// track->releaseBuffer(&buffer);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// _mixing->state = BufferState::FULL;
|
|
||||||
// _activeTracksMutex.unlock();
|
|
||||||
// FOR TESTING END
|
|
||||||
|
|
||||||
Track::State state;
|
|
||||||
// set up the tracks.
|
|
||||||
for (auto&& track : _activeTracks)
|
|
||||||
{
|
|
||||||
state = track->getState();
|
|
||||||
|
|
||||||
if (state == Track::State::IDLE)
|
|
||||||
{
|
{
|
||||||
uint32_t channelMask = audio_channel_out_mask_from_count(2);
|
uint32_t channelMask = audio_channel_out_mask_from_count(2);
|
||||||
int32_t name = _mixer->getTrackName(channelMask, AUDIO_FORMAT_PCM_16_BIT,
|
int32_t name = _mixer->getTrackName(channelMask, AUDIO_FORMAT_PCM_16_BIT,
|
||||||
|
@ -188,12 +146,65 @@ void AudioMixerController::mixOneFrame()
|
||||||
_mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &rVolume);
|
_mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &rVolume);
|
||||||
|
|
||||||
track->setVolumeDirty(false);
|
track->setVolumeDirty(false);
|
||||||
|
track->setInitialized(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioMixerController::mixOneFrame()
|
||||||
|
{
|
||||||
|
_isMixingFrame = true;
|
||||||
|
_activeTracksMutex.lock();
|
||||||
|
|
||||||
|
auto mixStart = clockNow();
|
||||||
|
|
||||||
|
std::vector<Track*> tracksToRemove;
|
||||||
|
tracksToRemove.reserve(_activeTracks.size());
|
||||||
|
|
||||||
|
// FOR TESTING BEGIN
|
||||||
|
// Track* track = _activeTracks[0];
|
||||||
|
//
|
||||||
|
// AudioBufferProvider::Buffer buffer;
|
||||||
|
// buffer.frameCount = _bufferSizeInFrames;
|
||||||
|
// status_t r = track->getNextBuffer(&buffer);
|
||||||
|
//// ALOG_ASSERT(buffer.frameCount == _mixing->size / 2, "buffer.frameCount:%d, _mixing->size/2:%d", buffer.frameCount, _mixing->size/2);
|
||||||
|
// if (r == NO_ERROR)
|
||||||
|
// {
|
||||||
|
// ALOGV("getNextBuffer succeed ...");
|
||||||
|
// memcpy(_mixing->buf, buffer.raw, _mixing->size);
|
||||||
|
// }
|
||||||
|
// if (buffer.raw == nullptr)
|
||||||
|
// {
|
||||||
|
// ALOGV("Play over ...");
|
||||||
|
// tracksToRemove.push_back(track);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// track->releaseBuffer(&buffer);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// _mixing->state = BufferState::FULL;
|
||||||
|
// _activeTracksMutex.unlock();
|
||||||
|
// FOR TESTING END
|
||||||
|
|
||||||
|
Track::State state;
|
||||||
|
// set up the tracks.
|
||||||
|
for (auto&& track : _activeTracks)
|
||||||
|
{
|
||||||
|
state = track->getState();
|
||||||
|
|
||||||
|
if (state == Track::State::IDLE)
|
||||||
|
{
|
||||||
|
initTrack(track, tracksToRemove);
|
||||||
|
}
|
||||||
else if (state == Track::State::PLAYING)
|
else if (state == Track::State::PLAYING)
|
||||||
{
|
{
|
||||||
ALOG_ASSERT(track->getName() >= 0);
|
if (!track->isInitialized())
|
||||||
|
{
|
||||||
|
initTrack(track, tracksToRemove);
|
||||||
|
}
|
||||||
|
|
||||||
int name = track->getName();
|
int name = track->getName();
|
||||||
|
ALOG_ASSERT(name >= 0);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lk(track->_volumeDirtyMutex);
|
std::lock_guard<std::mutex> lk(track->_volumeDirtyMutex);
|
||||||
|
|
||||||
|
@ -213,6 +224,11 @@ void AudioMixerController::mixOneFrame()
|
||||||
}
|
}
|
||||||
else if (state == Track::State::RESUMED)
|
else if (state == Track::State::RESUMED)
|
||||||
{
|
{
|
||||||
|
if (!track->isInitialized())
|
||||||
|
{
|
||||||
|
initTrack(track, tracksToRemove);
|
||||||
|
}
|
||||||
|
|
||||||
if (track->getPrevState() == Track::State::PAUSED)
|
if (track->getPrevState() == Track::State::PAUSED)
|
||||||
{
|
{
|
||||||
_mixer->enable(track->getName());
|
_mixer->enable(track->getName());
|
||||||
|
@ -220,21 +236,28 @@ void AudioMixerController::mixOneFrame()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ALOGW("Previous state (%d) isn't PAUSED, couldn't resume!", track->getPrevState());
|
ALOGW("Previous state (%d) isn't PAUSED, couldn't resume!", static_cast<int>(track->getPrevState()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (state == Track::State::PAUSED)
|
else if (state == Track::State::PAUSED)
|
||||||
{
|
{
|
||||||
|
if (!track->isInitialized())
|
||||||
|
{
|
||||||
|
initTrack(track, tracksToRemove);
|
||||||
|
}
|
||||||
|
|
||||||
if (track->getPrevState() == Track::State::PLAYING || track->getPrevState() == Track::State::RESUMED)
|
if (track->getPrevState() == Track::State::PLAYING || track->getPrevState() == Track::State::RESUMED)
|
||||||
{
|
{
|
||||||
_mixer->disable(track->getName());
|
_mixer->disable(track->getName());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ALOGW("Previous state (%d) isn't PLAYING, couldn't pause!", track->getPrevState());
|
ALOGW("Previous state (%d) isn't PLAYING, couldn't pause!", static_cast<int>(track->getPrevState()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (state == Track::State::STOPPED)
|
else if (state == Track::State::STOPPED)
|
||||||
|
{
|
||||||
|
if (track->isInitialized())
|
||||||
{
|
{
|
||||||
if (track->getPrevState() != Track::State::IDLE)
|
if (track->getPrevState() != Track::State::IDLE)
|
||||||
{
|
{
|
||||||
|
@ -244,6 +267,11 @@ void AudioMixerController::mixOneFrame()
|
||||||
{
|
{
|
||||||
ALOGV("Stop track (%p) while it's in IDLE state!", track);
|
ALOGV("Stop track (%p) while it's in IDLE state!", track);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ALOGV("Track (%p) hasn't been initialized yet!", track);
|
||||||
|
}
|
||||||
tracksToRemove.push_back(track);
|
tracksToRemove.push_back(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,6 @@ public:
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
bool addTrack(Track* track);
|
bool addTrack(Track* track);
|
||||||
|
|
||||||
bool hasPlayingTacks();
|
bool hasPlayingTacks();
|
||||||
|
|
||||||
void pause();
|
void pause();
|
||||||
|
@ -67,6 +66,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void destroy();
|
void destroy();
|
||||||
|
void initTrack(Track* track, std::vector<Track*>& tracksToRemove);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _bufferSizeInFrames;
|
int _bufferSizeInFrames;
|
||||||
|
|
|
@ -40,6 +40,7 @@ Track::Track(const PcmData &pcmData)
|
||||||
, _volume(1.0f)
|
, _volume(1.0f)
|
||||||
, _isVolumeDirty(true)
|
, _isVolumeDirty(true)
|
||||||
, _isLoop(false)
|
, _isLoop(false)
|
||||||
|
, _isInitialized(false)
|
||||||
{
|
{
|
||||||
init(_pcmData.pcmBuffer->data(), _pcmData.numFrames, _pcmData.bitsPerSample / 8 * _pcmData.numChannels);
|
init(_pcmData.pcmBuffer->data(), _pcmData.numFrames, _pcmData.bitsPerSample / 8 * _pcmData.numChannels);
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,12 @@ private:
|
||||||
inline void setVolumeDirty(bool isDirty)
|
inline void setVolumeDirty(bool isDirty)
|
||||||
{ _isVolumeDirty = isDirty; };
|
{ _isVolumeDirty = isDirty; };
|
||||||
|
|
||||||
|
inline bool isInitialized() const
|
||||||
|
{ return _isInitialized; };
|
||||||
|
|
||||||
|
inline void setInitialized(bool isInitialized)
|
||||||
|
{ _isInitialized = isInitialized; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PcmData _pcmData;
|
PcmData _pcmData;
|
||||||
State _prevState;
|
State _prevState;
|
||||||
|
@ -89,6 +95,7 @@ private:
|
||||||
bool _isVolumeDirty;
|
bool _isVolumeDirty;
|
||||||
std::mutex _volumeDirtyMutex;
|
std::mutex _volumeDirtyMutex;
|
||||||
bool _isLoop;
|
bool _isLoop;
|
||||||
|
bool _isInitialized;
|
||||||
|
|
||||||
friend class AudioMixerController;
|
friend class AudioMixerController;
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,6 +42,7 @@ AudioEngineTests::AudioEngineTests()
|
||||||
ADD_TEST_CASE(AudioPerformanceTest);
|
ADD_TEST_CASE(AudioPerformanceTest);
|
||||||
ADD_TEST_CASE(AudioSwitchStateTest);
|
ADD_TEST_CASE(AudioSwitchStateTest);
|
||||||
ADD_TEST_CASE(AudioSmallFileTest);
|
ADD_TEST_CASE(AudioSmallFileTest);
|
||||||
|
ADD_TEST_CASE(AudioPauseResumeAfterPlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -803,3 +804,27 @@ std::string AudioSmallFileTest::subtitle() const
|
||||||
{
|
{
|
||||||
return "Should not crash";
|
return "Should not crash";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
bool AudioPauseResumeAfterPlay::init()
|
||||||
|
{
|
||||||
|
if (AudioEngineTestDemo::init())
|
||||||
|
{
|
||||||
|
int audioId = AudioEngine::play2d("audio/SoundEffectsFX009/FX082.mp3");
|
||||||
|
AudioEngine::pause(audioId);
|
||||||
|
AudioEngine::resume(audioId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AudioPauseResumeAfterPlay::title() const
|
||||||
|
{
|
||||||
|
return "pause & resume right after play2d";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AudioPauseResumeAfterPlay::subtitle() const
|
||||||
|
{
|
||||||
|
return "Should not crash";
|
||||||
|
}
|
||||||
|
|
|
@ -199,4 +199,15 @@ public:
|
||||||
virtual std::string subtitle() const override;
|
virtual std::string subtitle() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AudioPauseResumeAfterPlay : public AudioEngineTestDemo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CREATE_FUNC(AudioPauseResumeAfterPlay);
|
||||||
|
|
||||||
|
virtual bool init() override;
|
||||||
|
|
||||||
|
virtual std::string title() const override;
|
||||||
|
virtual std::string subtitle() const override;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* defined(__NEWAUDIOENGINE_TEST_H_) */
|
#endif /* defined(__NEWAUDIOENGINE_TEST_H_) */
|
||||||
|
|
Loading…
Reference in New Issue