diff --git a/src/mod/endpoints/mod_portaudio/mod_portaudio.c b/src/mod/endpoints/mod_portaudio/mod_portaudio.c index 230f72eee2..b3dc44defd 100644 --- a/src/mod/endpoints/mod_portaudio/mod_portaudio.c +++ b/src/mod/endpoints/mod_portaudio/mod_portaudio.c @@ -85,7 +85,6 @@ struct private_object { switch_frame_t hold_frame; unsigned char holdbuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; switch_codec_t write_codec; - switch_timer_t timer; struct private_object *next; }; @@ -267,7 +266,7 @@ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan) if (olen == 0) { break; } - WriteAudioStream(globals.ring_stream, abuf, (long) olen, globals.read_codec.implementation->microseconds_per_frame / 1000); + WriteAudioStream(globals.ring_stream, abuf, (long) olen, &globals.timer); } } } @@ -281,8 +280,6 @@ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan) if (ring_file) { deactivate_ring_device(); switch_core_file_close(&fh); - switch_core_codec_destroy(&tech_pvt->write_codec); - switch_core_timer_destroy(&tech_pvt->timer); } if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) { @@ -565,30 +562,13 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch if (!is_master(tech_pvt)) { if (tech_pvt->hold_file) { if (!tech_pvt->hfh) { - int codec_ms = tech_pvt->codec_ms ? tech_pvt->codec_ms : globals.codec_ms; int sample_rate = tech_pvt->sample_rate ? tech_pvt->sample_rate : globals.sample_rate; - - if (switch_core_codec_init(&tech_pvt->write_codec, - "L16", - NULL, - sample_rate, - codec_ms, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); - switch_core_codec_destroy(&globals.read_codec); - tech_pvt->hold_file = NULL; - goto cng; - } - if (switch_core_file_open(&tech_pvt->fh, tech_pvt->hold_file, globals.read_codec.implementation->number_of_channels, globals.read_codec.implementation->samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { - switch_core_codec_destroy(&tech_pvt->write_codec); tech_pvt->hold_file = NULL; goto cng; } @@ -597,7 +577,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch tech_pvt->hold_frame.data = tech_pvt->holdbuf; tech_pvt->hold_frame.buflen = sizeof(tech_pvt->holdbuf); tech_pvt->hold_frame.rate = sample_rate; - tech_pvt->hold_frame.codec = &tech_pvt->write_codec; + tech_pvt->hold_frame.codec = &globals.write_codec; } goto hold; @@ -611,9 +591,8 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch { switch_size_t olen = globals.read_codec.implementation->samples_per_frame; - if (switch_core_timer_next(&tech_pvt->timer) != SWITCH_STATUS_SUCCESS) { + if (switch_core_timer_next(&globals.timer) != SWITCH_STATUS_SUCCESS) { switch_core_file_close(&tech_pvt->fh); - switch_core_codec_destroy(&tech_pvt->write_codec); goto cng; } switch_core_file_read(tech_pvt->hfh, tech_pvt->hold_frame.data, &olen); @@ -627,7 +606,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch tech_pvt->hold_frame.datalen = (uint32_t) (olen * sizeof(int16_t)); tech_pvt->hold_frame.samples = (uint32_t) olen; - tech_pvt->hold_frame.timestamp = tech_pvt->timer.samplecount; + tech_pvt->hold_frame.timestamp = globals.timer.samplecount; *frame = &tech_pvt->hold_frame; } @@ -639,7 +618,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch if ((samples = ReadAudioStream(globals.audio_stream, globals.read_frame.data, globals.read_codec.implementation->samples_per_frame, - globals.read_codec.implementation->microseconds_per_frame / 1000)) == 0) { + &globals.timer)) == 0) { goto cng; } else { @@ -687,7 +666,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc if (globals.audio_stream) { if (switch_test_flag((&globals), GFLAG_EAR)) { WriteAudioStream(globals.audio_stream, (short *) frame->data, (int) (frame->datalen / sizeof(SAMPLE)), - globals.read_codec.implementation->microseconds_per_frame / 1000); + &globals.timer); } status = SWITCH_STATUS_SUCCESS; } @@ -991,6 +970,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_portaudio_shutdown) switch_core_codec_destroy(&globals.write_codec); } + switch_core_timer_destroy(&globals.timer); Pa_Terminate(); return SWITCH_STATUS_SUCCESS; @@ -1253,8 +1233,6 @@ static switch_status_t engage_device(int sample_rate, int codec_ms) - - globals.read_frame.rate = sample_rate; globals.read_frame.codec = &globals.read_codec; @@ -1273,7 +1251,8 @@ static switch_status_t engage_device(int sample_rate, int codec_ms) outputParameters.sampleFormat = SAMPLE_TYPE; outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; - err = OpenAudioStream(&globals.audio_stream, &inputParameters, &outputParameters, sample_rate, paClipOff); + err = OpenAudioStream(&globals.audio_stream, &inputParameters, &outputParameters, sample_rate, paClipOff, + globals.read_codec.implementation->samples_per_frame); /* UNLOCKED ************************************************************************************************* */ switch_mutex_unlock(globals.device_lock); @@ -1297,7 +1276,6 @@ static switch_status_t engage_device(int sample_rate, int codec_ms) static switch_status_t engage_ring_device(int sample_rate, int channels) { - //int codec_ms = 20; PaStreamParameters outputParameters; PaError err; @@ -1313,7 +1291,8 @@ static switch_status_t engage_ring_device(int sample_rate, int channels) outputParameters.sampleFormat = SAMPLE_TYPE; outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; - err = OpenAudioStream(&globals.ring_stream, NULL, &outputParameters, sample_rate, paClipOff); + err = OpenAudioStream(&globals.ring_stream, NULL, &outputParameters, sample_rate, paClipOff, + globals.read_codec.implementation->samples_per_frame); /* UNLOCKED ************************************************************************************************* */ switch_mutex_unlock(globals.device_lock); @@ -1410,7 +1389,6 @@ static switch_status_t hangup_call(char **argv, int argc, switch_stream_handle_t if (tech_pvt) { switch_channel_hangup(switch_core_session_get_channel(tech_pvt->session), SWITCH_CAUSE_NORMAL_CLEARING); - //switch_set_flag_locked(tech_pvt, TFLAG_HUP); stream->write_function(stream, "OK\n"); } else { stream->write_function(stream, "NO SUCH CALL\n"); diff --git a/src/mod/endpoints/mod_portaudio/pablio.c b/src/mod/endpoints/mod_portaudio/pablio.c index 6ba32ed300..b62c71cbfd 100644 --- a/src/mod/endpoints/mod_portaudio/pablio.c +++ b/src/mod/endpoints/mod_portaudio/pablio.c @@ -40,6 +40,7 @@ * license above. */ +#include #include #include #include @@ -50,12 +51,6 @@ #include -/************************************************************************/ -/******** Constants *****************************************************/ -/************************************************************************/ - -#define FRAMES_PER_BUFFER (2048) - /************************************************************************/ /******** Prototypes ****************************************************/ /************************************************************************/ @@ -70,17 +65,20 @@ static PaError PABLIO_TermFIFO(PaUtilRingBuffer * rbuf); /************************************************************************/ /* Called from PortAudio. - * Read and write data only if there is room in FIFOs. + * Read and write data */ static int blockingIOCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo * timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { PABLIO_Stream *data = (PABLIO_Stream *) userData; long numBytes = data->bytesPerFrame * framesPerBuffer; - + /* This may get called with NULL inputBuffer during initial setup. */ if (inputBuffer != NULL) { - PaUtil_WriteRingBuffer(&data->inFIFO, inputBuffer, numBytes); + if (PaUtil_WriteRingBuffer(&data->inFIFO, inputBuffer, numBytes) != numBytes) { + PaUtil_FlushRingBuffer(&data->inFIFO); + PaUtil_WriteRingBuffer(&data->inFIFO, inputBuffer, numBytes); + } } if (outputBuffer != NULL) { int i; @@ -118,23 +116,23 @@ static PaError PABLIO_TermFIFO(PaUtilRingBuffer * rbuf) * Write data to ring buffer. * Will not return until all the data has been written. */ -long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int timeout) +long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch_timer_t *timer) { long bytesWritten; char *p = (char *) data; long numBytes = aStream->bytesPerFrame * numFrames; - int time = 0; while (numBytes > 0) { bytesWritten = PaUtil_WriteRingBuffer(&aStream->outFIFO, p, numBytes); numBytes -= bytesWritten; p += bytesWritten; if (numBytes > 0) { - Pa_Sleep(1); - if (++time >= timeout * 2) { + if (switch_core_timer_check(timer) == SWITCH_STATUS_SUCCESS) { PaUtil_FlushRingBuffer(&aStream->outFIFO); + printf("ASS\n"); return 0; } + switch_yield(1000); } } return numFrames; @@ -144,27 +142,23 @@ long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int t * Read data from ring buffer. * Will not return until all the data has been read. */ -long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int timeout) +long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch_timer_t *timer) { long bytesRead; char *p = (char *) data; long numBytes = aStream->bytesPerFrame * numFrames; - int time = 0; while (numBytes > 0) { bytesRead = PaUtil_ReadRingBuffer(&aStream->inFIFO, p, numBytes); numBytes -= bytesRead; - p += bytesRead; if (numBytes > 0) { - Pa_Sleep(1); - time++; - if (time > timeout * 2) { + if (switch_core_timer_check(timer) == SWITCH_STATUS_SUCCESS) { PaUtil_FlushRingBuffer(&aStream->inFIFO); return 0; } + switch_yield(1000); } } - //printf("%d\n", time); return numFrames; } @@ -188,7 +182,7 @@ long GetAudioStreamReadable(PABLIO_Stream * aStream) return bytesFull / aStream->bytesPerFrame; } -/*********************************************************** +/***********************************************************/ static unsigned long RoundUpToNextPowerOf2(unsigned long n) { long numBits = 0; @@ -200,7 +194,7 @@ static unsigned long RoundUpToNextPowerOf2(unsigned long n) } return (1 << numBits); } -*/ + /************************************************************ @@ -209,8 +203,11 @@ static unsigned long RoundUpToNextPowerOf2(unsigned long n) * */ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr, - const PaStreamParameters * inputParameters, const PaStreamParameters * outputParameters, double sampleRate, - PaStreamFlags streamFlags) + const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate, + PaStreamFlags streamFlags, + long samples_per_frame) { long bytesPerSample = 2; PaError err; @@ -236,7 +233,7 @@ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr, channels = outputParameters->channelCount; } - numFrames = FRAMES_PER_BUFFER; + numFrames = RoundUpToNextPowerOf2(samples_per_frame * 5); aStream->bytesPerFrame = bytesPerSample; /* Initialize Ring Buffers */ @@ -260,7 +257,8 @@ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr, /* Open a PortAudio stream that we will use to communicate with the underlying * audio drivers. */ - err = Pa_OpenStream(&aStream->stream, inputParameters, outputParameters, sampleRate, FRAMES_PER_BUFFER, streamFlags, blockingIOCallback, aStream); + err = Pa_OpenStream(&aStream->stream, inputParameters, outputParameters, sampleRate, samples_per_frame, streamFlags, blockingIOCallback, aStream); + if (err != paNoError) goto error; diff --git a/src/mod/endpoints/mod_portaudio/pablio.h b/src/mod/endpoints/mod_portaudio/pablio.h index f56f754d26..a50f90dd3d 100644 --- a/src/mod/endpoints/mod_portaudio/pablio.h +++ b/src/mod/endpoints/mod_portaudio/pablio.h @@ -74,13 +74,13 @@ extern "C" { * Write data to ring buffer. * Will not return until all the data has been written. */ - long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int timeout); + long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch_timer_t *timer); /************************************************************ * Read data from ring buffer. * Will not return until all the data has been read. */ - long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int timeout); + long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch_timer_t *timer); /************************************************************ * Return the number of frames that could be written to the stream without @@ -104,7 +104,7 @@ extern "C" { */ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr, const PaStreamParameters * inputParameters, - const PaStreamParameters * outputParameters, double sampleRate, PaStreamCallbackFlags statusFlags); + const PaStreamParameters * outputParameters, double sampleRate, PaStreamCallbackFlags statusFlags, long samples_per_frame); PaError CloseAudioStream(PABLIO_Stream * aStream);