~zanneth/StreamPlayer

a938d25a1f2e99241895c3edf7c74aed3177feaa — Charles Magahern 8 years ago 35fe6e6
Correctly handle case for when there are no available buffers
1 files changed, 38 insertions(+), 3 deletions(-)

M StreamPlayer/Source/ZANStreamPlayer.m
M StreamPlayer/Source/ZANStreamPlayer.m => StreamPlayer/Source/ZANStreamPlayer.m +38 -3
@@ 8,6 8,7 @@

#import "ZANStreamPlayer.h"
#import <AudioToolbox/AudioToolbox.h>
#import <pthread.h>

#if !__has_feature(objc_arc)
#error ARC is required for this file


@@ 45,7 46,9 @@ static void _ZANAudioQueueOutputCallback(void *clientData,
    AudioStreamPacketDescription _packetDescriptions[MAX_PACKET_DESCRIPTIONS];
    
    NSOperationQueue            *_inputQueue;
    NSUInteger                   _buffersEnqueued;
    BOOL                         _queueBuffersUsageStates[AUDIO_QUEUE_BUFFERS_COUNT];
    pthread_mutex_t              _queueBuffersMutex;
    pthread_cond_t               _queueBufferReadyCondition;
    
    NSUInteger                   _dataOffset;
    NSUInteger                   _packetBufferSize;


@@ 65,6 68,9 @@ static void _ZANAudioQueueOutputCallback(void *clientData,
        _inputQueue = [[NSOperationQueue alloc] init];
        _inputQueue.maxConcurrentOperationCount = 1;
        
        pthread_mutex_init(&_queueBuffersMutex, NULL);
        pthread_cond_init(&_queueBufferReadyCondition, NULL);
        
        NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
        _urlSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:_inputQueue];
    }


@@ 76,6 82,11 @@ static void _ZANAudioQueueOutputCallback(void *clientData,
    [self _closeReadStream];
    [self _closeAudioStream];
    [self _destroyAudioOutputQueue];
    
    pthread_mutex_destroy(&_queueBuffersMutex);
    pthread_cond_destroy(&_queueBufferReadyCondition);
    
    [_urlSession invalidateAndCancel];
}

#pragma mark - API


@@ 277,6 288,11 @@ static void _ZANAudioQueueOutputCallback(void *clientData,
    OSStatus status = noErr;
    
    do {
        // mark that this buffer is in use
        pthread_mutex_lock(&_queueBuffersMutex);
        _queueBuffersUsageStates[_currentBufferIndex] = YES;
        pthread_mutex_unlock(&_queueBuffersMutex);
        
        // fill in bytes used
        AudioQueueBufferRef buffer = _audioQueueBuffers[_currentBufferIndex];
        buffer->mAudioDataByteSize = (UInt32)_bytesFilled;


@@ 299,7 315,6 @@ static void _ZANAudioQueueOutputCallback(void *clientData,
        _currentBufferIndex = (_currentBufferIndex + 1) % AUDIO_QUEUE_BUFFERS_COUNT;
        _bytesFilled = 0;
        _packetsFilled = 0;
        ++_buffersEnqueued;
    } while (0);
}



@@ 406,6 421,13 @@ static void _ZANAudioQueueOutputCallback(void *clientData,
                [self _enqueueAudioBuffer];
            }
            
            // wait until the current buffer is available
            pthread_mutex_lock(&_queueBuffersMutex);
            while (_queueBuffersUsageStates[_currentBufferIndex]) {
                pthread_cond_wait(&_queueBufferReadyCondition, &_queueBuffersMutex);
            }
            pthread_mutex_unlock(&_queueBuffersMutex);
            
            // copy audio data into buffer
            AudioQueueBufferRef buffer = _audioQueueBuffers[_currentBufferIndex];
            memcpy(buffer->mAudioData + _bytesFilled, audioData.bytes + packetOffset, packetSize);


@@ 433,7 455,20 @@ static void _ZANAudioQueueOutputCallback(void *clientData,

- (void)_handleBufferCompleteFromQueue:(AudioQueueRef)queue buffer:(AudioQueueBufferRef)buffer
{
    --_buffersEnqueued;
    NSInteger bufferIdx = NSNotFound;
    for (unsigned i = 0; i < AUDIO_QUEUE_BUFFERS_COUNT; ++i) {
        if (buffer == _audioQueueBuffers[i]) {
            bufferIdx = i;
            break;
        }
    }
    
    NSAssert(bufferIdx != NSNotFound, @"An unknown audio buffer was completed");
    
    pthread_mutex_lock(&_queueBuffersMutex);
    _queueBuffersUsageStates[bufferIdx] = NO;
    pthread_cond_signal(&_queueBufferReadyCondition);
    pthread_mutex_unlock(&_queueBuffersMutex);
}

- (NSError *)_errorFromOSStatus:(OSStatus)status