aboutsummaryrefslogtreecommitdiff
path: root/src/conversation
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-10-03 00:05:47 +0000
committerChristian Grothoff <christian@grothoff.org>2013-10-03 00:05:47 +0000
commitf3c7f9aa97c759ff56dc65c887b87be09da877c7 (patch)
tree917584c5dcf0c78a7c41f32d9a02b558f5f7e91f /src/conversation
parent17ee77576112312de11efa52eda7fa960fb908e2 (diff)
downloadgnunet-f3c7f9aa97c759ff56dc65c887b87be09da877c7.tar.gz
gnunet-f3c7f9aa97c759ff56dc65c887b87be09da877c7.zip
-much better latency
Diffstat (limited to 'src/conversation')
-rw-r--r--src/conversation/gnunet-conversation-test.c8
-rw-r--r--src/conversation/gnunet-helper-audio-playback.c95
-rw-r--r--src/conversation/gnunet-helper-audio-record.c29
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,
147 fprintf (stderr, "\nPlaying..."); 147 fprintf (stderr, "\nPlaying...");
148 for (rec=rec_head; NULL != rec; rec = rec->next) 148 for (rec=rec_head; NULL != rec; rec = rec->next)
149 { 149 {
150 fprintf (stderr, "<-%u\n", (unsigned int) rec->size); 150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
151 "Replaying %u bytes\n",
152 (unsigned int) rec->size);
151 speaker->play (speaker->cls, 153 speaker->play (speaker->cls,
152 rec->size, 154 rec->size,
153 &rec[1]); 155 &rec[1]);
@@ -173,7 +175,9 @@ record (void *cls,
173{ 175{
174 struct Recording *rec; 176 struct Recording *rec;
175 177
176 fprintf (stderr, "->%u\n", (unsigned int) data_size); 178 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
179 "Recorded %u bytes\n",
180 (unsigned int) data_size);
177 rec = GNUNET_malloc (sizeof (struct Recording) + data_size); 181 rec = GNUNET_malloc (sizeof (struct Recording) + data_size);
178 rec->size = data_size; 182 rec->size = data_size;
179 memcpy (&rec[1], data, data_size); 183 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
@@ -74,11 +74,6 @@ static pa_context *context;
74static pa_stream *stream_out; 74static pa_stream *stream_out;
75 75
76/** 76/**
77 * Pulseaudio io events
78 */
79static pa_io_event *stdio_event;
80
81/**
82 * OPUS decoder 77 * OPUS decoder
83 */ 78 */
84static OpusDecoder *dec; 79static OpusDecoder *dec;
@@ -99,20 +94,9 @@ static int pcm_length;
99static int frame_size; 94static int frame_size;
100 95
101/** 96/**
102 * Audio buffer 97 * Pipe we use to signal the main loop that we are ready to receive.
103 */
104static void *buffer;
105
106/**
107 * Length of audio buffer
108 */ 98 */
109static size_t buffer_length; 99static int ready_pipe[2];
110
111/**
112 * Read index for transmit buffer
113 */
114static size_t buffer_index;
115
116 100
117/** 101/**
118 * Message callback 102 * Message callback
@@ -143,9 +127,10 @@ stdin_receiver (void *cls,
143 return GNUNET_OK; 127 return GNUNET_OK;
144 } 128 }
145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
146 "Decoded frame\n"); 130 "Decoded frame with %u bytes\n",
131 ntohs (audio->header.size));
147 if (pa_stream_write 132 if (pa_stream_write
148 (stream_out, (uint8_t *) pcm_buffer, pcm_length, NULL, 0, 133 (stream_out, pcm_buffer, pcm_length, NULL, 0,
149 PA_SEEK_RELATIVE) < 0) 134 PA_SEEK_RELATIVE) < 0)
150 { 135 {
151 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 136 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -173,44 +158,6 @@ quit (int ret)
173 158
174 159
175/** 160/**
176 * Write some data to the stream
177 */
178static void
179do_stream_write (size_t length)
180{
181 size_t l;
182
183 GNUNET_assert (0 != length);
184 if ( (! buffer) || (! buffer_length) )
185 return;
186
187 l = length;
188 if (l > buffer_length)
189 l = buffer_length;
190 if (0 > pa_stream_write (stream_out,
191 (uint8_t *) buffer + buffer_index,
192 l,
193 NULL, 0,
194 PA_SEEK_RELATIVE))
195 {
196 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
197 _("pa_stream_write() failed: %s\n"),
198 pa_strerror (pa_context_errno (context)));
199 quit (1);
200 return;
201 }
202 buffer_length -= l;
203 buffer_index += l;
204 if (! buffer_length)
205 {
206 pa_xfree (buffer);
207 buffer = NULL;
208 buffer_index = buffer_length = 0;
209 }
210}
211
212
213/**
214 * Callback when data is there for playback 161 * Callback when data is there for playback
215 */ 162 */
216static void 163static void
@@ -218,11 +165,13 @@ stream_write_callback (pa_stream * s,
218 size_t length, 165 size_t length,
219 void *userdata) 166 void *userdata)
220{ 167{
221 if (stdio_event) 168 /* unblock 'main' */
222 mainloop_api->io_enable (stdio_event, PA_IO_EVENT_INPUT); 169 if (-1 != ready_pipe[1])
223 if (!buffer) 170 {
224 return; 171 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
225 do_stream_write (length); 172 "Unblocking main loop!\n");
173 write (ready_pipe[1], "r", 1);
174 }
226} 175}
227 176
228 177
@@ -269,7 +218,7 @@ context_state_callback (pa_context * c,
269 goto fail; 218 goto fail;
270 } 219 }
271 pa_stream_set_write_callback (stream_out, 220 pa_stream_set_write_callback (stream_out,
272 stream_write_callback, 221 &stream_write_callback,
273 NULL); 222 NULL);
274 if ((p = 223 if ((p =
275 pa_stream_connect_playback (stream_out, NULL, NULL, 0, NULL, 224 pa_stream_connect_playback (stream_out, NULL, NULL, 0, NULL,
@@ -279,7 +228,7 @@ context_state_callback (pa_context * c,
279 _("pa_stream_connect_playback() failed: %s\n"), 228 _("pa_stream_connect_playback() failed: %s\n"),
280 pa_strerror (pa_context_errno (c))); 229 pa_strerror (pa_context_errno (c)));
281 goto fail; 230 goto fail;
282 } 231 }
283 break; 232 break;
284 } 233 }
285 case PA_CONTEXT_TERMINATED: 234 case PA_CONTEXT_TERMINATED:
@@ -379,17 +328,31 @@ main (int argc, char *argv[])
379 328
380 char readbuf[MAXLINE]; 329 char readbuf[MAXLINE];
381 struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst; 330 struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst;
331 char c;
332 ssize_t ret;
382 333
383 GNUNET_assert (GNUNET_OK == 334 GNUNET_assert (GNUNET_OK ==
384 GNUNET_log_setup ("gnunet-helper-audio-playback", 335 GNUNET_log_setup ("gnunet-helper-audio-playback",
385 "DEBUG", 336 "DEBUG",
386 "/tmp/helper-audio-playback")); 337 "/tmp/helper-audio-playback"));
338 if (0 != pipe (ready_pipe))
339 {
340 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "pipe");
341 return 1;
342 }
387 stdin_mst = GNUNET_SERVER_mst_create (&stdin_receiver, NULL); 343 stdin_mst = GNUNET_SERVER_mst_create (&stdin_receiver, NULL);
388 opus_init (); 344 opus_init ();
389 pa_init (); 345 pa_init ();
346 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
347 "Waiting for PulseAudio to be ready.\n");
348 GNUNET_assert (1 == read (ready_pipe[0], &c, 1));
349 close (ready_pipe[0]);
350 close (ready_pipe[1]);
351 ready_pipe[0] = -1;
352 ready_pipe[1] = -1;
390 while (1) 353 while (1)
391 { 354 {
392 ssize_t ret = read (0, readbuf, sizeof (readbuf)); 355 ret = read (0, readbuf, sizeof (readbuf));
393 toff += ret; 356 toff += ret;
394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 357 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
395 "Received %d bytes of audio data (total: %llu)\n", 358 "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,
221{ 221{
222 const void *data; 222 const void *data;
223 223
224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
225 "Got %u/%u bytes of PCM data\n",
226 length,
227 pcm_length);
228
224 GNUNET_assert (NULL != s); 229 GNUNET_assert (NULL != s);
225 GNUNET_assert (length > 0); 230 GNUNET_assert (length > 0);
226 if (stdio_event) 231 if (stdio_event)
@@ -288,6 +293,7 @@ stream_state_callback (pa_stream * s, void *userdata)
288 case PA_STREAM_READY: 293 case PA_STREAM_READY:
289 { 294 {
290 const pa_buffer_attr *a; 295 const pa_buffer_attr *a;
296
291 char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], 297 char cmt[PA_CHANNEL_MAP_SNPRINT_MAX],
292 sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; 298 sst[PA_SAMPLE_SPEC_SNPRINT_MAX];
293 299
@@ -307,7 +313,7 @@ stream_state_callback (pa_stream * s, void *userdata)
307 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 313 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
308 _("Buffer metrics: maxlength=%u, fragsize=%u\n"), 314 _("Buffer metrics: maxlength=%u, fragsize=%u\n"),
309 a->maxlength, a->fragsize); 315 a->maxlength, a->fragsize);
310 } 316 }
311 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 317 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
312 _("Using sample spec '%s', channel map '%s'.\n"), 318 _("Using sample spec '%s', channel map '%s'.\n"),
313 pa_sample_spec_snprint (sst, sizeof (sst), 319 pa_sample_spec_snprint (sst, sizeof (sst),
@@ -321,7 +327,7 @@ stream_state_callback (pa_stream * s, void *userdata)
321 pa_stream_get_device_index (s), 327 pa_stream_get_device_index (s),
322 pa_stream_is_suspended (s) ? "" : "not "); 328 pa_stream_is_suspended (s) ? "" : "not ");
323 } 329 }
324 break; 330 break;
325 case PA_STREAM_FAILED: 331 case PA_STREAM_FAILED:
326 default: 332 default:
327 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 333 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -350,6 +356,7 @@ context_state_callback (pa_context * c,
350 case PA_CONTEXT_READY: 356 case PA_CONTEXT_READY:
351 { 357 {
352 int r; 358 int r;
359 pa_buffer_attr na;
353 360
354 GNUNET_assert (!stream_in); 361 GNUNET_assert (!stream_in);
355 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 362 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -362,9 +369,13 @@ context_state_callback (pa_context * c,
362 pa_strerror (pa_context_errno (c))); 369 pa_strerror (pa_context_errno (c)));
363 goto fail; 370 goto fail;
364 } 371 }
365 pa_stream_set_state_callback (stream_in, stream_state_callback, NULL); 372 pa_stream_set_state_callback (stream_in, &stream_state_callback, NULL);
366 pa_stream_set_read_callback (stream_in, stream_read_callback, NULL); 373 pa_stream_set_read_callback (stream_in, &stream_read_callback, NULL);
367 if ((r = pa_stream_connect_record (stream_in, NULL, NULL, 0)) < 0) 374 memset (&na, 0, sizeof (na));
375 na.maxlength = UINT32_MAX;
376 na.fragsize = pcm_length;
377 if ((r = pa_stream_connect_record (stream_in, NULL, &na,
378 PA_STREAM_EARLY_REQUESTS)) < 0)
368 { 379 {
369 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 380 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
370 _("pa_stream_connect_record() failed: %s\n"), 381 _("pa_stream_connect_record() failed: %s\n"),
@@ -416,8 +427,8 @@ pa_init ()
416 /* listen to signals */ 427 /* listen to signals */
417 r = pa_signal_init (mainloop_api); 428 r = pa_signal_init (mainloop_api);
418 GNUNET_assert (r == 0); 429 GNUNET_assert (r == 0);
419 pa_signal_new (SIGINT, exit_signal_callback, NULL); 430 pa_signal_new (SIGINT, &exit_signal_callback, NULL);
420 pa_signal_new (SIGTERM, exit_signal_callback, NULL); 431 pa_signal_new (SIGTERM, &exit_signal_callback, NULL);
421 432
422 /* connect to the main pulseaudio context */ 433 /* connect to the main pulseaudio context */
423 434
@@ -426,7 +437,7 @@ pa_init ()
426 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 437 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
427 _("pa_context_new() failed.\n")); 438 _("pa_context_new() failed.\n"));
428 } 439 }
429 pa_context_set_state_callback (context, context_state_callback, NULL); 440 pa_context_set_state_callback (context, &context_state_callback, NULL);
430 if (pa_context_connect (context, NULL, 0, NULL) < 0) 441 if (pa_context_connect (context, NULL, 0, NULL) < 0)
431 { 442 {
432 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 443 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -475,6 +486,8 @@ main (int argc, char *argv[])
475 GNUNET_log_setup ("gnunet-helper-audio-record", 486 GNUNET_log_setup ("gnunet-helper-audio-record",
476 "DEBUG", 487 "DEBUG",
477 "/tmp/helper-audio-record")); 488 "/tmp/helper-audio-record"));
489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
490 "Audio source starts\n");
478 audio_message = GNUNET_malloc (UINT16_MAX); 491 audio_message = GNUNET_malloc (UINT16_MAX);
479 audio_message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO); 492 audio_message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
480 opus_init (); 493 opus_init ();