Esempio n. 1
0
void Audio_Queue::enqueueCachedData()
{
    AQ_ASSERT(!m_waitingOnBuffer);
    AQ_ASSERT(!m_bufferInUse[m_fillBufferIndex]);
    
    /* Queue up as many packets as possible into the buffers */
    queued_packet_t *cur = m_queuedHead;
    while (cur) {
        int ret = handlePacket(cur->data, &cur->desc);
        if (ret == 0) {
           break; 
        }
        queued_packet_t *next = cur->next;
        free(cur);
        cur = next;
    }
    m_queuedHead = cur;
    
    /* If we finished queueing all our saved packets, we can re-schedule the
     * stream to run */
    if (cur == NULL) {
        m_queuedTail = NULL;
        if (m_delegate) {
            m_delegate->audioQueueUnderflow();
        }
    }
}
Esempio n. 2
0
void Audio_Queue::enqueueBuffer()
{
    AQ_ASSERT(!m_bufferInUse[m_fillBufferIndex]);
    
    Stream_Configuration *config = Stream_Configuration::configuration();
    
    AQ_TRACE("%s: enter\n", __PRETTY_FUNCTION__);
    
    pthread_mutex_lock(&m_bufferInUseMutex);
    
    m_bufferInUse[m_fillBufferIndex] = true;
    m_buffersUsed++;
    
    // enqueue buffer
    AudioQueueBufferRef fillBuf = m_audioQueueBuffer[m_fillBufferIndex];
    fillBuf->mAudioDataByteSize = m_bytesFilled;
    
    pthread_mutex_unlock(&m_bufferInUseMutex);
    
    AQ_ASSERT(m_packetsFilled > 0);
    OSStatus err = AudioQueueEnqueueBuffer(m_outAQ, fillBuf, m_packetsFilled, m_packetDescs);
    
    if (!err) {
        m_lastError = noErr;
        start();
    } else {
        /* If we get an error here, it very likely means that the audio queue is no longer
           running */
        AQ_TRACE("%s: error in AudioQueueEnqueueBuffer\n", __PRETTY_FUNCTION__);
        m_lastError = err;
        return;
    }
    
    pthread_mutex_lock(&m_bufferInUseMutex);
    // go to next buffer
    if (++m_fillBufferIndex >= config->bufferCount) {
        m_fillBufferIndex = 0; 
    }
    // reset bytes filled
    m_bytesFilled = 0;
    // reset packets filled
    m_packetsFilled = 0;
    
    // wait until next buffer is not in use
    
    while (m_bufferInUse[m_fillBufferIndex]) {
        AQ_TRACE("waiting for buffer %u\n", (unsigned int)m_fillBufferIndex);
        
        pthread_cond_wait(&m_bufferFreeCondition, &m_bufferInUseMutex);
    }
    pthread_mutex_unlock(&m_bufferInUseMutex);
}
Esempio n. 3
0
// this is called by the audio queue when it has finished decoding our data. 
// The buffer is now free to be reused.
void Audio_Queue::audioQueueOutputCallback(void *inClientData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
{
    Audio_Queue *audioQueue = static_cast<Audio_Queue*>(inClientData);
    
    Stream_Configuration *config = Stream_Configuration::configuration();
    
    int bufIndex = -1;
    
    for (unsigned int i = 0; i < config->bufferCount; ++i) {
        if (inBuffer == audioQueue->m_audioQueueBuffer[i]) {
            AQ_TRACE("findQueueBuffer %i\n", i);
            bufIndex = i;
            break;
        }
    }
    
    if (bufIndex == -1) {
        return;
    }
    
    pthread_mutex_lock(&audioQueue->m_bufferInUseMutex);
    
    AQ_ASSERT(audioQueue->m_bufferInUse[bufIndex]);
    
    audioQueue->m_bufferInUse[bufIndex] = false;
    audioQueue->m_buffersUsed--;
    
    AQ_TRACE("signaling buffer free for inuse %i....\n", bufIndex);
    pthread_cond_signal(&audioQueue->m_bufferFreeCondition);
    AQ_TRACE("signal sent!\n");
    
    if (audioQueue->m_buffersUsed == 0 && audioQueue->m_delegate) {
        AQ_LOCK_TRACE("audioQueueOutputCallback: unlock 2\n");
        pthread_mutex_unlock(&audioQueue->m_bufferInUseMutex);
        
        if (audioQueue->m_delegate) {
            audioQueue->m_delegate->audioQueueBuffersEmpty();
        }
    } else {
        pthread_mutex_unlock(&audioQueue->m_bufferInUseMutex);
        
        if (audioQueue->m_delegate) {
            audioQueue->m_delegate->audioQueueFinishedPlayingPacket();
        }
    }
    
    AQ_LOCK_TRACE("audioQueueOutputCallback: unlock\n");
}
Esempio n. 4
0
// this is called by the audio queue when it has finished decoding our data. 
// The buffer is now free to be reused.
void Audio_Queue::audioQueueOutputCallback(void *inClientData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
{
    Audio_Queue *audioQueue = static_cast<Audio_Queue*>(inClientData);    
    unsigned int bufIndex = audioQueue->findQueueBuffer(inBuffer);
    
    AQ_ASSERT(audioQueue->m_bufferInUse[bufIndex]);
    
    audioQueue->m_bufferInUse[bufIndex] = false;
    audioQueue->m_buffersUsed--;
    
    if (audioQueue->m_buffersUsed == 0 && !audioQueue->m_queuedHead && audioQueue->m_delegate) {
        audioQueue->m_delegate->audioQueueBuffersEmpty();
    } else if (audioQueue->m_waitingOnBuffer) {
        audioQueue->m_waitingOnBuffer = false;
        audioQueue->enqueueCachedData();
    }
}