diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-10-03 00:05:47 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-10-03 00:05:47 +0000 |
commit | f3c7f9aa97c759ff56dc65c887b87be09da877c7 (patch) | |
tree | 917584c5dcf0c78a7c41f32d9a02b558f5f7e91f /src/conversation/gnunet-helper-audio-playback.c | |
parent | 17ee77576112312de11efa52eda7fa960fb908e2 (diff) | |
download | gnunet-f3c7f9aa97c759ff56dc65c887b87be09da877c7.tar.gz gnunet-f3c7f9aa97c759ff56dc65c887b87be09da877c7.zip |
-much better latency
Diffstat (limited to 'src/conversation/gnunet-helper-audio-playback.c')
-rw-r--r-- | src/conversation/gnunet-helper-audio-playback.c | 95 |
1 files changed, 29 insertions, 66 deletions
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; | |||
74 | static pa_stream *stream_out; | 74 | static pa_stream *stream_out; |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * Pulseaudio io events | ||
78 | */ | ||
79 | static pa_io_event *stdio_event; | ||
80 | |||
81 | /** | ||
82 | * OPUS decoder | 77 | * OPUS decoder |
83 | */ | 78 | */ |
84 | static OpusDecoder *dec; | 79 | static OpusDecoder *dec; |
@@ -99,20 +94,9 @@ static int pcm_length; | |||
99 | static int frame_size; | 94 | static 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 | */ | ||
104 | static void *buffer; | ||
105 | |||
106 | /** | ||
107 | * Length of audio buffer | ||
108 | */ | 98 | */ |
109 | static size_t buffer_length; | 99 | static int ready_pipe[2]; |
110 | |||
111 | /** | ||
112 | * Read index for transmit buffer | ||
113 | */ | ||
114 | static 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 | */ | ||
178 | static void | ||
179 | do_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 | */ |
216 | static void | 163 | static 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", |