From 837b8a68f88b44fcb7d424da911a04c6465dd23c Mon Sep 17 00:00:00 2001 From: Alexandre Savard <alexandre.savard@savoirfairelinux.net> Date: Mon, 19 Oct 2009 11:50:37 -0400 Subject: [PATCH] [#2308] Implement two different callbacks for capture/playback in pulseaudio So that we can now initialize capture/playback audiostream using different pa_buffer_attr values which have great effect on latency, and callback frequency --- .../src/audio/pulseaudio/audiostream.cpp | 22 ++++++------ .../src/audio/pulseaudio/pulselayer.cpp | 36 ++++++++++++++----- .../src/audio/pulseaudio/pulselayer.h | 4 ++- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/sflphone-common/src/audio/pulseaudio/audiostream.cpp b/sflphone-common/src/audio/pulseaudio/audiostream.cpp index bd13814025..e30f40f78b 100644 --- a/sflphone-common/src/audio/pulseaudio/audiostream.cpp +++ b/sflphone-common/src/audio/pulseaudio/audiostream.cpp @@ -182,12 +182,14 @@ AudioStream::createStream (pa_context* c) assert (s); + // parameters are defined as number of bytes + // 2048 bytes (1024 int16) is 20 ms at 44100 Hz if (_streamType == PLAYBACK_STREAM) { - attributes->maxlength = 60000; - attributes->tlength = 4096; - attributes->prebuf = 4096; - attributes->minreq = 940; - attributes->fragsize = 4096; + attributes->maxlength = 16000; + attributes->tlength = 2048; + attributes->prebuf = 1024; + attributes->minreq = 1024; + attributes->fragsize = 1024; pa_stream_connect_playback( s , NULL , attributes, PA_STREAM_INTERPOLATE_TIMING, &_volume, NULL); // pa_stream_connect_playback (s , NULL , attributes, PA_STREAM_START_CORKED, &_volume, NULL); } else if (_streamType == CAPTURE_STREAM) { @@ -195,11 +197,11 @@ AudioStream::createStream (pa_context* c) // attributes->maxlength = 66500; // attributes->fragsize = (uint32_t)-1; - attributes->maxlength = 60000; - attributes->tlength = 4096; - attributes->prebuf = 4096; - attributes->minreq = 940; - attributes->fragsize = 4096; + attributes->maxlength = 16000; + attributes->tlength = 1024; + attributes->prebuf = 1024; + attributes->minreq = 512; + attributes->fragsize = 1024; // pa_stream_connect_record (s , NULL , attributes , PA_STREAM_START_CORKED); pa_stream_connect_record( s , NULL , attributes , PA_STREAM_INTERPOLATE_TIMING ); diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp index 43656b34d5..cea5e4eecc 100644 --- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp +++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp @@ -23,11 +23,22 @@ int framesPerBuffer = 2048; -static void audioCallback (pa_stream* s, size_t bytes, void* userdata) +static void playback_callback (pa_stream* s, size_t bytes, void* userdata) { + _debug("playback_callback\n"); + assert (s && bytes); assert (bytes > 0); - static_cast<PulseLayer*> (userdata)->processData(); + static_cast<PulseLayer*> (userdata)->processPlaybackData(); +} + +static void capture_callback (pa_stream* s, size_t bytes, void* userdata) +{ + // _debug("capture_callback\n"); + + assert(s && bytes); + assert(bytes > 0); + static_cast<PulseLayer*> (userdata)->processCaptureData(); } @@ -138,7 +149,7 @@ PulseLayer::connectPulseAudioServer (void) if (pa_context_get_state (context) != PA_CONTEXT_READY) { _debug ("Error connecting to pulse audio server\n"); - pa_threaded_mainloop_unlock (m); + // pa_threaded_mainloop_unlock (m); } pa_threaded_mainloop_unlock (m); @@ -212,9 +223,9 @@ bool PulseLayer::createStreams (pa_context* c) playback = new AudioStream (playbackParam); playback->connectStream(); - pa_stream_set_write_callback(playback->pulseStream(), audioCallback, this); + pa_stream_set_write_callback(playback->pulseStream(), playback_callback, this); pa_stream_set_overflow_callback(playback->pulseStream(), playback_overflow_callback, this); - // pa_stream_set_underflow_callback(playback->pulseStream(), playback_underflow_callback, this); + pa_stream_set_underflow_callback(playback->pulseStream(), playback_underflow_callback, this); // pa_stream_set_suspended_callback(playback->pulseStream(), stream_suspended_callback, this); // pa_stream_set_moved_callback(playback->pulseStream(), stream_moved_callback, this); delete playbackParam; @@ -228,7 +239,7 @@ bool PulseLayer::createStreams (pa_context* c) record = new AudioStream (recordParam); record->connectStream(); - pa_stream_set_read_callback (record->pulseStream() , audioCallback, this); + pa_stream_set_read_callback (record->pulseStream() , capture_callback, this); // pa_stream_set_suspended_callback(record->pulseStream(), stream_suspended_callback, this); // pa_stream_set_moved_callback(record->pulseStream(), stream_moved_callback, this); delete recordParam; @@ -412,7 +423,7 @@ void PulseLayer::overflow (pa_stream* s, void* userdata UNUSED) } -void PulseLayer::processData (void) +void PulseLayer::processPlaybackData (void) { // Handle the data for the speakers if ( playback &&(playback->pulseStream()) && (pa_stream_get_state (playback->pulseStream()) == PA_STREAM_READY)) { @@ -424,13 +435,17 @@ void PulseLayer::processData (void) writeToSpeaker(); } +} + + +void PulseLayer::processCaptureData(void) +{ // Handle the mic // We check if the stream is ready if ( record &&(record->pulseStream()) && (pa_stream_get_state (record->pulseStream()) == PA_STREAM_READY)) readFromMic(); - - + } void PulseLayer::writeToSpeaker (void) @@ -534,7 +549,10 @@ void PulseLayer::writeToSpeaker (void) } else { + _debug("send zeros......................\n"); + bzero (out, maxNbBytesToGet); + pa_stream_write (playback->pulseStream(), out, maxNbBytesToGet, NULL, 0, PA_SEEK_RELATIVE); } _urgentRingBuffer.Discard(toGet); diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.h b/sflphone-common/src/audio/pulseaudio/pulselayer.h index 5056b8231e..151fdec005 100644 --- a/sflphone-common/src/audio/pulseaudio/pulselayer.h +++ b/sflphone-common/src/audio/pulseaudio/pulselayer.h @@ -130,7 +130,9 @@ class PulseLayer : public AudioLayer { int getMicVolume( void ) { return micVolume; } void setMicVolume( int value ) { micVolume = value; } - void processData( void ); + void processPlaybackData( void ); + + void processCaptureData( void ); private: // Copy Constructor -- GitLab