// Audio encoding main process int CAudioEncoder::ThreadMain(void) { CMsg* pMsg; bool stop = false; debug_message("audio encoder thread %s %s %s start", Profile()->GetName(), Profile()->GetStringValue(CFG_AUDIO_ENCODER), Profile()->GetStringValue(CFG_AUDIO_ENCODING)); while (stop == false && SDL_SemWait(m_myMsgQueueSemaphore) == 0) { pMsg = m_myMsgQueue.get_message(); if (pMsg != NULL) { switch (pMsg->get_value()) { case MSG_NODE_STOP_THREAD: DoStopAudio(); stop = true; break; case MSG_NODE_START: // DoStartTransmit(); Anything ? break; case MSG_NODE_STOP: DoStopAudio(); break; case MSG_SINK_FRAME: { uint32_t dontcare; CMediaFrame *mf = (CMediaFrame*)pMsg->get_message(dontcare); if (m_stop_thread == false) ProcessAudioFrame(mf); if (mf->RemoveReference()) { delete mf; } break; } } delete pMsg; } } while ((pMsg = m_myMsgQueue.get_message()) != NULL) { if (pMsg->get_value() == MSG_SINK_FRAME) { uint32_t dontcare; CMediaFrame *mf = (CMediaFrame*)pMsg->get_message(dontcare); if (mf->RemoveReference()) { delete mf; } } delete pMsg; } if (m_audioResample != NULL) { for (uint ix = 0; ix < m_audioDstChannels; ix++) { st_resample_stop(m_audioResample[ix]); m_audioResample[ix] = NULL; } free(m_audioResample); } CHECK_AND_FREE(m_audioPreEncodingBuffer); debug_message("audio encoder thread %s exit", Profile()->GetName()); return 0; }
void COSSAudioSource::ProcessAudio(void) { #ifdef SNDCTL_DSP_GETERROR audio_errinfo errinfo; if (m_audioSrcFrameNumber == 0) { ioctl(m_audioDevice, SNDCTL_DSP_GETERROR, &errinfo); } else { ioctl(m_audioDevice, SNDCTL_DSP_GETERROR, &errinfo); if (errinfo.rec_overruns > 0) { debug_message("overrun error found in audio - adding "U64" samples", SrcBytesToSamples(errinfo.rec_ptradjust)); close(m_audioDevice); InitDevice(); m_audioSrcSampleNumber = 0; } } #endif if (m_audioSrcFrameNumber == 0) { // Pull the trigger and start the audio input int enablebits; ioctl(m_audioDevice, SNDCTL_DSP_GETTRIGGER, &enablebits); enablebits |= PCM_ENABLE_INPUT; ioctl(m_audioDevice, SNDCTL_DSP_SETTRIGGER, &enablebits); } // for efficiency, process 1 second before returning to check for commands for (int pass = 0; pass < m_maxPasses; pass++) { audio_buf_info info; int rc = ioctl(m_audioDevice, SNDCTL_DSP_GETISPACE, &info); Timestamp currentTime = GetTimestamp(); if (rc<0) { error_message("Failed to query OSS GETISPACE"); info.bytes = 0; } uint32_t bytesRead = read(m_audioDevice, m_pcmFrameBuffer, m_pcmFrameSize); if (bytesRead < m_pcmFrameSize) { debug_message("bad audio read"); continue; } Timestamp timestamp; if (info.bytes == m_audioOssMaxBufferSize) { // means the audio buffer is full, and not capturing // we want to make the timestamp based on the previous one // When we hit this case, we start using the m_timestampOverflowArray // This will give us a timestamp for when the array is full. // // In other words, if we have a full audio buffer (ie: it's not loading // any more), we start storing the current timestamp into the array. // This will let us "catch up", and have a somewhat accurate timestamp // when we loop around // // wmay - I'm not convinced that this actually works - if the buffer // cleans up, we'll ignore m_timestampOverflowArray if (m_timestampOverflowArray != NULL && m_timestampOverflowArray[m_timestampOverflowArrayIndex] != 0) { timestamp = m_timestampOverflowArray[m_timestampOverflowArrayIndex]; } else { timestamp = m_prevTimestamp + SrcSamplesToTicks(m_audioSrcSamplesPerFrame); } if (m_timestampOverflowArray != NULL) m_timestampOverflowArray[m_timestampOverflowArrayIndex] = currentTime; debug_message("audio buffer full !"); } else { // buffer is not full - so, we make the timestamp based on the number // of bytes in the buffer that we read. timestamp = currentTime - SrcSamplesToTicks(SrcBytesToSamples(info.bytes)); if (m_timestampOverflowArray != NULL) m_timestampOverflowArray[m_timestampOverflowArrayIndex] = 0; } #ifdef DEBUG_TIMESTAMPS debug_message("info.bytes=%d t="U64" timestamp="U64" delta="U64, info.bytes, currentTime, timestamp, timestamp - m_prevTimestamp); #endif m_prevTimestamp = timestamp; if (m_timestampOverflowArray != NULL) { m_timestampOverflowArrayIndex = (m_timestampOverflowArrayIndex + 1) % m_audioOssMaxBufferFrames; } ProcessAudioFrame(m_pcmFrameBuffer, m_pcmFrameSize, timestamp); } }