Fixed audio thread may set the state to playing even in certain conditions even if the player has been user-paused or stopped (race condition)

This commit is contained in:
Thong Nguyen 2014-02-05 18:05:47 +00:00
parent 63bb19747f
commit ce6f2b9512
1 changed files with 45 additions and 19 deletions

View File

@ -175,6 +175,7 @@ STKAudioPlayerInternalState;
NSMutableArray* bufferingQueue;
OSSpinLock pcmBufferSpinLock;
OSSpinLock internalStateLock;
volatile UInt32 pcmBufferTotalFrameCount;
volatile UInt32 pcmBufferFrameStartIndex;
volatile UInt32 pcmBufferUsedFrameCount;
@ -250,16 +251,14 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn
-(void) setInternalState:(STKAudioPlayerInternalState)value
{
if (value == internalState)
{
return;
}
internalState = value;
[self setInternalState:value ifInState:NULL];
}
-(void) setInternalState:(STKAudioPlayerInternalState)value ifInState:(BOOL(^)(STKAudioPlayerInternalState))ifInState
{
STKAudioPlayerState newState;
switch (internalState)
switch (value)
{
case STKAudioPlayerInternalStateInitialised:
newState = STKAudioPlayerStateReady;
@ -295,17 +294,44 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn
break;
}
OSSpinLockLock(&internalStateLock);
if (value == internalState)
{
OSSpinLockUnlock(&internalStateLock);
return;
}
if (ifInState != NULL)
{
if (!ifInState(self->internalState))
{
OSSpinLockUnlock(&internalStateLock);
return;
}
}
internalState = value;
STKAudioPlayerState previousState = self.state;
if (newState != previousState)
{
self.state = newState;
OSSpinLockUnlock(&internalStateLock);
dispatch_async(dispatch_get_main_queue(), ^
{
[self.delegate audioPlayer:self stateChanged:self.state previousState:previousState];
});
}
else
{
OSSpinLockUnlock(&internalStateLock);
}
}
-(STKAudioPlayerStopReason) stopReason
@ -971,6 +997,7 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn
}
[self processFinishPlayingIfAnyAndPlayingNext:currentlyPlayingEntry withNext:entry];
[self startAudioGraph];
}
else
@ -1472,7 +1499,7 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn
if (audioGraph)
{
error = AUGraphStop(audioGraph);
if (error)
{
[self unexpectedError:STKAudioPlayerErrorAudioSystemError];
@ -2204,19 +2231,11 @@ static OSStatus OutputRenderCallback(void* inRefCon, AudioUnitRenderActionFlags*
UInt32 frameSizeInBytes = audioPlayer->pcmBufferFrameSizeInBytes;
UInt32 used = audioPlayer->pcmBufferUsedFrameCount;
UInt32 start = audioPlayer->pcmBufferFrameStartIndex;
STKAudioPlayerInternalState state = audioPlayer->internalState;
UInt32 end = (audioPlayer->pcmBufferFrameStartIndex + audioPlayer->pcmBufferUsedFrameCount) % audioPlayer->pcmBufferTotalFrameCount;
BOOL signal = audioPlayer->waiting && used < audioPlayer->pcmBufferTotalFrameCount / 2;
NSArray* frameFilters = audioPlayer->frameFilters;
STKAudioPlayerInternalState state = audioPlayer.internalState;
if (state == STKAudioPlayerInternalStatePendingNext)
{
OSSpinLockUnlock(&audioPlayer->pcmBufferSpinLock);
return 0;
}
if (entry)
{
if (state == STKAudioPlayerInternalStateWaitingForData)
@ -2268,7 +2287,7 @@ static OSStatus OutputRenderCallback(void* inRefCon, AudioUnitRenderActionFlags*
UInt32 totalFramesCopied = 0;
if (used > 0 && !waitForBuffer && entry != nil)
if (used > 0 && !waitForBuffer && entry != nil && ((state & STKAudioPlayerInternalStateRunning) && state != STKAudioPlayerInternalStatePaused))
{
if (state == STKAudioPlayerInternalStateWaitingForData)
{
@ -2346,6 +2365,11 @@ static OSStatus OutputRenderCallback(void* inRefCon, AudioUnitRenderActionFlags*
OSSpinLockUnlock(&audioPlayer->pcmBufferSpinLock);
}
[audioPlayer setInternalState:STKAudioPlayerInternalStatePlaying ifInState:^BOOL(STKAudioPlayerInternalState state)
{
return (state & STKAudioPlayerInternalStateRunning) && state != STKAudioPlayerInternalStatePaused;
}];
audioPlayer.internalState = STKAudioPlayerInternalStatePlaying;
}
@ -2359,7 +2383,9 @@ static OSStatus OutputRenderCallback(void* inRefCon, AudioUnitRenderActionFlags*
{
// Buffering
pthread_mutex_lock(&audioPlayer->playerMutex);
audioPlayer.internalState = STKAudioPlayerInternalStateRebuffering;
pthread_mutex_unlock(&audioPlayer->playerMutex);
}
}