From f3c7f9aa97c759ff56dc65c887b87be09da877c7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 3 Oct 2013 00:05:47 +0000 Subject: [PATCH] -much better latency --- src/conversation/gnunet-conversation-test.c | 8 +- .../gnunet-helper-audio-playback.c | 95 ++++++------------- src/conversation/gnunet-helper-audio-record.c | 29 ++++-- 3 files changed, 56 insertions(+), 76 deletions(-) diff --git a/src/conversation/gnunet-conversation-test.c b/src/conversation/gnunet-conversation-test.c index 7f8c52228..c55f9f951 100644 --- a/src/conversation/gnunet-conversation-test.c +++ b/src/conversation/gnunet-conversation-test.c @@ -147,7 +147,9 @@ switch_to_speaker (void *cls, fprintf (stderr, "\nPlaying..."); for (rec=rec_head; NULL != rec; rec = rec->next) { - fprintf (stderr, "<-%u\n", (unsigned int) rec->size); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Replaying %u bytes\n", + (unsigned int) rec->size); speaker->play (speaker->cls, rec->size, &rec[1]); @@ -173,7 +175,9 @@ record (void *cls, { struct Recording *rec; - fprintf (stderr, "->%u\n", (unsigned int) data_size); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Recorded %u bytes\n", + (unsigned int) data_size); rec = GNUNET_malloc (sizeof (struct Recording) + data_size); rec->size = data_size; memcpy (&rec[1], data, data_size); diff --git a/src/conversation/gnunet-helper-audio-playback.c b/src/conversation/gnunet-helper-audio-playback.c index 74571e538..6b2a3df6d 100644 --- a/src/conversation/gnunet-helper-audio-playback.c +++ b/src/conversation/gnunet-helper-audio-playback.c @@ -73,11 +73,6 @@ static pa_context *context; */ static pa_stream *stream_out; -/** - * Pulseaudio io events - */ -static pa_io_event *stdio_event; - /** * OPUS decoder */ @@ -99,20 +94,9 @@ static int pcm_length; static int frame_size; /** - * Audio buffer - */ -static void *buffer; - -/** - * Length of audio buffer + * Pipe we use to signal the main loop that we are ready to receive. */ -static size_t buffer_length; - -/** - * Read index for transmit buffer - */ -static size_t buffer_index; - +static int ready_pipe[2]; /** * Message callback @@ -143,9 +127,10 @@ stdin_receiver (void *cls, return GNUNET_OK; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Decoded frame\n"); + "Decoded frame with %u bytes\n", + ntohs (audio->header.size)); if (pa_stream_write - (stream_out, (uint8_t *) pcm_buffer, pcm_length, NULL, 0, + (stream_out, pcm_buffer, pcm_length, NULL, 0, PA_SEEK_RELATIVE) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -172,44 +157,6 @@ quit (int ret) } -/** - * Write some data to the stream - */ -static void -do_stream_write (size_t length) -{ - size_t l; - - GNUNET_assert (0 != length); - if ( (! buffer) || (! buffer_length) ) - return; - - l = length; - if (l > buffer_length) - l = buffer_length; - if (0 > pa_stream_write (stream_out, - (uint8_t *) buffer + buffer_index, - l, - NULL, 0, - PA_SEEK_RELATIVE)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("pa_stream_write() failed: %s\n"), - pa_strerror (pa_context_errno (context))); - quit (1); - return; - } - buffer_length -= l; - buffer_index += l; - if (! buffer_length) - { - pa_xfree (buffer); - buffer = NULL; - buffer_index = buffer_length = 0; - } -} - - /** * Callback when data is there for playback */ @@ -218,11 +165,13 @@ stream_write_callback (pa_stream * s, size_t length, void *userdata) { - if (stdio_event) - mainloop_api->io_enable (stdio_event, PA_IO_EVENT_INPUT); - if (!buffer) - return; - do_stream_write (length); + /* unblock 'main' */ + if (-1 != ready_pipe[1]) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unblocking main loop!\n"); + write (ready_pipe[1], "r", 1); + } } @@ -269,7 +218,7 @@ context_state_callback (pa_context * c, goto fail; } pa_stream_set_write_callback (stream_out, - stream_write_callback, + &stream_write_callback, NULL); if ((p = pa_stream_connect_playback (stream_out, NULL, NULL, 0, NULL, @@ -279,7 +228,7 @@ context_state_callback (pa_context * c, _("pa_stream_connect_playback() failed: %s\n"), pa_strerror (pa_context_errno (c))); goto fail; - } + } break; } case PA_CONTEXT_TERMINATED: @@ -379,17 +328,31 @@ main (int argc, char *argv[]) char readbuf[MAXLINE]; struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst; + char c; + ssize_t ret; GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("gnunet-helper-audio-playback", "DEBUG", "/tmp/helper-audio-playback")); + if (0 != pipe (ready_pipe)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "pipe"); + return 1; + } stdin_mst = GNUNET_SERVER_mst_create (&stdin_receiver, NULL); opus_init (); pa_init (); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Waiting for PulseAudio to be ready.\n"); + GNUNET_assert (1 == read (ready_pipe[0], &c, 1)); + close (ready_pipe[0]); + close (ready_pipe[1]); + ready_pipe[0] = -1; + ready_pipe[1] = -1; while (1) { - ssize_t ret = read (0, readbuf, sizeof (readbuf)); + ret = read (0, readbuf, sizeof (readbuf)); toff += ret; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d bytes of audio data (total: %llu)\n", diff --git a/src/conversation/gnunet-helper-audio-record.c b/src/conversation/gnunet-helper-audio-record.c index c14b35fe6..b3828498f 100644 --- a/src/conversation/gnunet-helper-audio-record.c +++ b/src/conversation/gnunet-helper-audio-record.c @@ -221,6 +221,11 @@ stream_read_callback (pa_stream * s, { const void *data; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got %u/%u bytes of PCM data\n", + length, + pcm_length); + GNUNET_assert (NULL != s); GNUNET_assert (length > 0); if (stdio_event) @@ -288,6 +293,7 @@ stream_state_callback (pa_stream * s, void *userdata) case PA_STREAM_READY: { const pa_buffer_attr *a; + char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; @@ -307,7 +313,7 @@ stream_state_callback (pa_stream * s, void *userdata) GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Buffer metrics: maxlength=%u, fragsize=%u\n"), a->maxlength, a->fragsize); - } + } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Using sample spec '%s', channel map '%s'.\n"), pa_sample_spec_snprint (sst, sizeof (sst), @@ -321,7 +327,7 @@ stream_state_callback (pa_stream * s, void *userdata) pa_stream_get_device_index (s), pa_stream_is_suspended (s) ? "" : "not "); } - break; + break; case PA_STREAM_FAILED: default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -350,6 +356,7 @@ context_state_callback (pa_context * c, case PA_CONTEXT_READY: { int r; + pa_buffer_attr na; GNUNET_assert (!stream_in); GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -362,9 +369,13 @@ context_state_callback (pa_context * c, pa_strerror (pa_context_errno (c))); goto fail; } - pa_stream_set_state_callback (stream_in, stream_state_callback, NULL); - pa_stream_set_read_callback (stream_in, stream_read_callback, NULL); - if ((r = pa_stream_connect_record (stream_in, NULL, NULL, 0)) < 0) + pa_stream_set_state_callback (stream_in, &stream_state_callback, NULL); + pa_stream_set_read_callback (stream_in, &stream_read_callback, NULL); + memset (&na, 0, sizeof (na)); + na.maxlength = UINT32_MAX; + na.fragsize = pcm_length; + if ((r = pa_stream_connect_record (stream_in, NULL, &na, + PA_STREAM_EARLY_REQUESTS)) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_stream_connect_record() failed: %s\n"), @@ -416,8 +427,8 @@ pa_init () /* listen to signals */ r = pa_signal_init (mainloop_api); GNUNET_assert (r == 0); - pa_signal_new (SIGINT, exit_signal_callback, NULL); - pa_signal_new (SIGTERM, exit_signal_callback, NULL); + pa_signal_new (SIGINT, &exit_signal_callback, NULL); + pa_signal_new (SIGTERM, &exit_signal_callback, NULL); /* connect to the main pulseaudio context */ @@ -426,7 +437,7 @@ pa_init () GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_context_new() failed.\n")); } - pa_context_set_state_callback (context, context_state_callback, NULL); + pa_context_set_state_callback (context, &context_state_callback, NULL); if (pa_context_connect (context, NULL, 0, NULL) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -475,6 +486,8 @@ main (int argc, char *argv[]) GNUNET_log_setup ("gnunet-helper-audio-record", "DEBUG", "/tmp/helper-audio-record")); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Audio source starts\n"); audio_message = GNUNET_malloc (UINT16_MAX); audio_message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO); opus_init (); -- 2.25.1