1 /*
2 * ALSA streaming support
3 *
4 * Originally written by:
5 * Copyright (c) by Devin Heitmueller <dheitmueller@kernellabs.com>
6 * for usage at tvtime
7 * Derived from the alsa-driver test tool latency.c:
8 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
9 *
10 * Copyright (c) 2011 - Mauro Carvalho Chehab
11 * Ported to xawtv, with bug fixes and improvements
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 */
28
29 #ifdef HAVE_ALSA
30 #include "alsa_stream.h"
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sched.h>
36 #include <errno.h>
37 #include <getopt.h>
38 #include <pthread.h>
39 #include <alsa/asoundlib.h>
40 #include <sys/time.h>
41 #include <math.h>
42
43 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
44
45 /* Private vars to control alsa thread status */
46 static int stop_alsa = 0;
47 static snd_htimestamp_t timestamp;
48
49 /* Error handlers */
50 snd_output_t *output = NULL;
51 FILE *error_fp;
52 int verbose = 0;
53
54 struct final_params {
55 int bufsize;
56 int rate;
57 int latency;
58 int channels;
59 };
60
setparams_stream(snd_pcm_t * handle,snd_pcm_hw_params_t * params,snd_pcm_format_t format,int * channels,const char * id)61 static int setparams_stream(snd_pcm_t *handle,
62 snd_pcm_hw_params_t *params,
63 snd_pcm_format_t format,
64 int *channels,
65 const char *id)
66 {
67 int err;
68
69 err = snd_pcm_hw_params_any(handle, params);
70 if (err < 0) {
71 fprintf(error_fp,
72 "alsa: Broken configuration for %s PCM: no configurations available: %s\n",
73 snd_strerror(err), id);
74 return err;
75 }
76
77 err = snd_pcm_hw_params_set_access(handle, params,
78 SND_PCM_ACCESS_RW_INTERLEAVED);
79 if (err < 0) {
80 fprintf(error_fp, "alsa: Access type not available for %s: %s\n", id,
81 snd_strerror(err));
82 return err;
83 }
84
85 err = snd_pcm_hw_params_set_format(handle, params, format);
86 if (err < 0) {
87 fprintf(error_fp, "alsa: Sample format not available for %s: %s\n", id,
88 snd_strerror(err));
89 return err;
90 }
91
92 retry:
93 err = snd_pcm_hw_params_set_channels(handle, params, *channels);
94 if (err < 0) {
95 if (strcmp(id, "capture") == 0 && *channels == 2) {
96 *channels = 1;
97 goto retry; /* Retry with mono capture */
98 }
99 fprintf(error_fp, "alsa: Channels count (%i) not available for %s: %s\n",
100 *channels, id, snd_strerror(err));
101 return err;
102 }
103
104 return 0;
105 }
106
getparams_periods(snd_pcm_t * handle,snd_pcm_hw_params_t * params,unsigned int * usecs,unsigned int * count,const char * id)107 static void getparams_periods(snd_pcm_t *handle,
108 snd_pcm_hw_params_t *params,
109 unsigned int *usecs,
110 unsigned int *count,
111 const char *id)
112 {
113 unsigned min = 0, max = 0;
114
115 snd_pcm_hw_params_get_periods_min(params, &min, 0);
116 snd_pcm_hw_params_get_periods_max(params, &max, 0);
117 if (min && max) {
118 if (verbose)
119 fprintf(error_fp, "alsa: %s periods range between %u and %u. Want: %u\n",
120 id, min, max, *count);
121 if (*count < min)
122 *count = min;
123 if (*count > max)
124 *count = max;
125 }
126
127 min = max = 0;
128 snd_pcm_hw_params_get_period_time_min(params, &min, 0);
129 snd_pcm_hw_params_get_period_time_max(params, &max, 0);
130 if (min && max) {
131 if (verbose)
132 fprintf(error_fp, "alsa: %s period time range between %u and %u. Want: %u\n",
133 id, min, max, *usecs);
134 if (*usecs < min)
135 *usecs = min;
136 if (*usecs > max)
137 *usecs = max;
138 }
139 }
140
setparams_periods(snd_pcm_t * handle,snd_pcm_hw_params_t * params,unsigned int * usecs,unsigned int * count,const char * id)141 static int setparams_periods(snd_pcm_t *handle,
142 snd_pcm_hw_params_t *params,
143 unsigned int *usecs,
144 unsigned int *count,
145 const char *id)
146 {
147 int err;
148
149 err = snd_pcm_hw_params_set_period_time_near(handle, params, usecs, 0);
150 if (err < 0) {
151 fprintf(error_fp, "alsa: Unable to set period time %u for %s: %s\n",
152 *usecs, id, snd_strerror(err));
153 return err;
154 }
155
156 err = snd_pcm_hw_params_set_periods_near(handle, params, count, 0);
157 if (err < 0) {
158 fprintf(error_fp, "alsa: Unable to set %u periods for %s: %s\n",
159 *count, id, snd_strerror(err));
160 return err;
161 }
162
163 if (verbose)
164 fprintf(error_fp, "alsa: %s period set to %u periods of %u time\n",
165 id, *count, *usecs);
166
167 return 0;
168 }
169
setparams_set(snd_pcm_t * handle,snd_pcm_hw_params_t * params,snd_pcm_sw_params_t * swparams,snd_pcm_uframes_t start_treshold,const char * id)170 static int setparams_set(snd_pcm_t *handle,
171 snd_pcm_hw_params_t *params,
172 snd_pcm_sw_params_t *swparams,
173 snd_pcm_uframes_t start_treshold,
174 const char *id)
175 {
176 int err;
177
178 err = snd_pcm_hw_params(handle, params);
179 if (err < 0) {
180 fprintf(error_fp, "alsa: Unable to set hw params for %s: %s\n",
181 id, snd_strerror(err));
182 return err;
183 }
184 err = snd_pcm_sw_params_current(handle, swparams);
185 if (err < 0) {
186 fprintf(error_fp, "alsa: Unable to determine current swparams for %s: %s\n",
187 id, snd_strerror(err));
188 return err;
189 }
190 err = snd_pcm_sw_params_set_start_threshold(handle, swparams,
191 start_treshold);
192 if (err < 0) {
193 fprintf(error_fp, "alsa: Unable to set start threshold mode for %s: %s\n",
194 id, snd_strerror(err));
195 return err;
196 }
197
198 err = snd_pcm_sw_params_set_avail_min(handle, swparams, 4);
199 if (err < 0) {
200 fprintf(error_fp, "alsa: Unable to set avail min for %s: %s\n",
201 id, snd_strerror(err));
202 return err;
203 }
204
205 err = snd_pcm_sw_params_set_tstamp_mode(handle, swparams, SND_PCM_TSTAMP_ENABLE);
206 if (err < 0) {
207 fprintf(error_fp, "alsa: Unable to enable timestamps for %s: %s\n",
208 id, snd_strerror(err));
209 }
210
211 err = snd_pcm_sw_params(handle, swparams);
212 if (err < 0) {
213 fprintf(error_fp, "alsa: Unable to set sw params for %s: %s\n",
214 id, snd_strerror(err));
215 return err;
216 }
217 return 0;
218 }
219
alsa_try_rate(snd_pcm_t * phandle,snd_pcm_t * chandle,snd_pcm_hw_params_t * p_hwparams,snd_pcm_hw_params_t * c_hwparams,int allow_resample,unsigned * ratep,unsigned * ratec)220 static int alsa_try_rate(snd_pcm_t *phandle, snd_pcm_t *chandle,
221 snd_pcm_hw_params_t *p_hwparams,
222 snd_pcm_hw_params_t *c_hwparams,
223 int allow_resample, unsigned *ratep, unsigned *ratec)
224 {
225 int err;
226
227 err = snd_pcm_hw_params_set_rate_near(chandle, c_hwparams, ratec, 0);
228 if (err)
229 return err;
230
231 *ratep = *ratec;
232 err = snd_pcm_hw_params_set_rate_near(phandle, p_hwparams, ratep, 0);
233 if (err)
234 return err;
235
236 if (*ratep == *ratec)
237 return 0;
238
239 if (verbose)
240 fprintf(error_fp,
241 "alsa_try_rate: capture wanted %u, playback wanted %u%s\n",
242 *ratec, *ratep, allow_resample ? " with resample enabled": "");
243
244 return 1; /* No error, but also no match */
245 }
246
setparams(snd_pcm_t * phandle,snd_pcm_t * chandle,snd_pcm_format_t format,int latency,int allow_resample,struct final_params * negotiated)247 static int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle,
248 snd_pcm_format_t format,
249 int latency, int allow_resample,
250 struct final_params *negotiated)
251 {
252 int i;
253 unsigned ratep, ratec = 0;
254 unsigned ratemin = 32000, ratemax = 96000, val;
255 int err, channels = 2;
256 snd_pcm_hw_params_t *p_hwparams, *c_hwparams;
257 snd_pcm_sw_params_t *p_swparams, *c_swparams;
258 snd_pcm_uframes_t c_size, p_psize, c_psize;
259 /* Our latency is 2 periods (in usecs) */
260 unsigned int c_periods = 2, p_periods;
261 unsigned int c_periodtime, p_periodtime;
262 const unsigned int prefered_rates[] = { 44100, 48000, 32000 };
263
264 snd_pcm_hw_params_alloca(&p_hwparams);
265 snd_pcm_hw_params_alloca(&c_hwparams);
266 snd_pcm_sw_params_alloca(&p_swparams);
267 snd_pcm_sw_params_alloca(&c_swparams);
268
269 if (setparams_stream(chandle, c_hwparams, format, &channels, "capture"))
270 return 1;
271
272 if (setparams_stream(phandle, p_hwparams, format, &channels, "playback"))
273 return 1;
274
275 if (allow_resample) {
276 err = snd_pcm_hw_params_set_rate_resample(chandle, c_hwparams, 1);
277 if (err < 0) {
278 fprintf(error_fp, "alsa: Resample setup failed: %s\n", snd_strerror(err));
279 return 1;
280 } else if (verbose)
281 fprintf(error_fp, "alsa: Resample enabled.\n");
282 }
283
284 err = snd_pcm_hw_params_get_rate_min(c_hwparams, &ratemin, 0);
285 if (err >= 0 && verbose)
286 fprintf(error_fp, "alsa: Capture min rate is %d\n", ratemin);
287 err = snd_pcm_hw_params_get_rate_max(c_hwparams, &ratemax, 0);
288 if (err >= 0 && verbose)
289 fprintf(error_fp, "alsa: Capture max rate is %u\n", ratemax);
290
291 err = snd_pcm_hw_params_get_rate_min(p_hwparams, &val, 0);
292 if (err >= 0) {
293 if (verbose)
294 fprintf(error_fp, "alsa: Playback min rate is %u\n", val);
295 if (val > ratemin)
296 ratemin = val;
297 }
298 err = snd_pcm_hw_params_get_rate_max(p_hwparams, &val, 0);
299 if (err >= 0) {
300 if (verbose)
301 fprintf(error_fp, "alsa: Playback max rate is %u\n", val);
302 if (val < ratemax)
303 ratemax = val;
304 }
305
306 if (verbose)
307 fprintf(error_fp,
308 "alsa: Will search a common rate between %u and %u\n",
309 ratemin, ratemax);
310
311 /* First try a set of common rates */
312 err = -1;
313 for (i = 0; i < ARRAY_SIZE(prefered_rates); i++) {
314 if (prefered_rates[i] < ratemin || prefered_rates[i] > ratemax)
315 continue;
316 ratep = ratec = prefered_rates[i];
317 err = alsa_try_rate(phandle, chandle, p_hwparams, c_hwparams,
318 allow_resample, &ratep, &ratec);
319 if (err == 0)
320 break;
321 }
322
323 if (err != 0) {
324 if (ratemin >= 44100) {
325 for (i = ratemin; i <= ratemax; i += 100) {
326 ratep = ratec = i;
327 err = alsa_try_rate(phandle, chandle, p_hwparams, c_hwparams,
328 allow_resample, &ratep, &ratec);
329 if (err == 0)
330 break;
331 }
332 } else {
333 for (i = ratemax; i >= ratemin; i -= 100) {
334 ratep = ratec = i;
335 err = alsa_try_rate(phandle, chandle, p_hwparams, c_hwparams,
336 allow_resample, &ratep, &ratec);
337 if (err == 0)
338 break;
339 }
340 }
341 }
342
343 if (err < 0) {
344 fprintf(error_fp, "alsa: Failed to set a supported rate: %s\n",
345 snd_strerror(err));
346 return 1;
347 }
348 if (ratep != ratec) {
349 if (verbose || allow_resample)
350 fprintf(error_fp,
351 "alsa: Couldn't find a rate that it is supported by both playback and capture\n");
352 return 2;
353 }
354 if (verbose)
355 fprintf(error_fp, "alsa: Using Rate %d\n", ratec);
356
357 /* Negotiate period parameters */
358
359 c_periodtime = latency * 1000 / c_periods;
360 getparams_periods(chandle, c_hwparams, &c_periodtime, &c_periods, "capture");
361 p_periods = c_periods * 2;
362 p_periodtime = c_periodtime;
363 getparams_periods(phandle, p_hwparams, &p_periodtime, &p_periods, "playback");
364 c_periods = p_periods / 2;
365
366 /*
367 * Some playback devices support a very limited periodtime range. If the user needs to
368 * use a higher latency to avoid overrun/underrun, use an alternate algorithm of incresing
369 * the number of periods, to archive the needed latency
370 */
371 if (p_periodtime < c_periodtime) {
372 c_periodtime = p_periodtime;
373 c_periods = round (latency * 1000.0 / c_periodtime + 0.5);
374 getparams_periods(chandle, c_hwparams, &c_periodtime, &c_periods, "capture");
375 p_periods = c_periods * 2;
376 p_periodtime = c_periodtime;
377 getparams_periods(phandle, p_hwparams, &p_periodtime, &p_periods, "playback");
378 c_periods = p_periods / 2;
379 }
380
381 if (setparams_periods(chandle, c_hwparams, &c_periodtime, &c_periods, "capture"))
382 return 1;
383
384 /* Note we use twice as much periods for the playback buffer, since we
385 will get a period size near the requested time and we don't want it to
386 end up smaller than the capture buffer as then we could end up blocking
387 on writing to it. Note we will configure the playback dev to start
388 playing as soon as it has 2 capture periods worth of data, so this
389 won't influence latency */
390 if (setparams_periods(phandle, p_hwparams, &p_periodtime, &p_periods, "playback"))
391 return 1;
392
393 snd_pcm_hw_params_get_period_size(p_hwparams, &p_psize, NULL);
394 snd_pcm_hw_params_get_period_size(c_hwparams, &c_psize, NULL);
395 snd_pcm_hw_params_get_buffer_size(c_hwparams, &c_size);
396
397 latency = c_periods * c_psize;
398 if (setparams_set(phandle, p_hwparams, p_swparams, latency, "playback"))
399 return 1;
400
401 if (setparams_set(chandle, c_hwparams, c_swparams, c_psize, "capture"))
402 return 1;
403
404 if ((err = snd_pcm_prepare(phandle)) < 0) {
405 fprintf(error_fp, "alsa: Prepare error: %s\n", snd_strerror(err));
406 return 1;
407 }
408
409 if (verbose) {
410 fprintf(error_fp, "alsa: Negotiated configuration:\n");
411 snd_pcm_dump_setup(phandle, output);
412 snd_pcm_dump_setup(chandle, output);
413 fprintf(error_fp, "alsa: Parameters are %iHz, %s, %i channels\n",
414 ratep, snd_pcm_format_name(format), channels);
415 fprintf(error_fp, "alsa: Set bitrate to %u%s, buffer size is %u\n", ratec,
416 allow_resample ? " with resample enabled at playback": "",
417 (unsigned int)c_size);
418 }
419
420 negotiated->bufsize = c_size;
421 negotiated->rate = ratep;
422 negotiated->channels = channels;
423 negotiated->latency = latency;
424 return 0;
425 }
426
427 /* Read up to len frames */
readbuf(snd_pcm_t * handle,char * buf,long len)428 static snd_pcm_sframes_t readbuf(snd_pcm_t *handle, char *buf, long len)
429 {
430 snd_pcm_sframes_t r;
431 snd_pcm_uframes_t frames;
432 snd_pcm_htimestamp(handle, &frames, ×tamp);
433 r = snd_pcm_readi(handle, buf, len);
434 if (r < 0 && !(r == -EAGAIN || r == -ENODEV)) {
435 r = snd_pcm_recover(handle, r, 0);
436 if (r < 0)
437 fprintf(error_fp, "alsa: overrun recover error: %s\n", snd_strerror(r));
438 }
439 return r;
440 }
441
442 /* Write len frames (note not up to len, but all of len!) */
writebuf(snd_pcm_t * handle,char * buf,long len)443 static snd_pcm_sframes_t writebuf(snd_pcm_t *handle, char *buf, long len)
444 {
445 snd_pcm_sframes_t r;
446
447 while (!stop_alsa) {
448 r = snd_pcm_writei(handle, buf, len);
449 if (r == len)
450 return 0;
451 if (r < 0) {
452 r = snd_pcm_recover(handle, r, 0);
453 if (r < 0) {
454 fprintf(error_fp, "alsa: underrun recover error: %s\n",
455 snd_strerror(r));
456 return r;
457 }
458 }
459 buf += r * 4;
460 len -= r;
461 snd_pcm_wait(handle, 100);
462 }
463 return -1;
464 }
465
alsa_stream(const char * pdevice,const char * cdevice,int latency)466 static int alsa_stream(const char *pdevice, const char *cdevice, int latency)
467 {
468 snd_pcm_t *phandle, *chandle;
469 char *buffer;
470 int err;
471 ssize_t r;
472 struct final_params negotiated;
473 snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
474 char pdevice_new[32];
475
476 err = snd_output_stdio_attach(&output, error_fp, 0);
477 if (err < 0) {
478 fprintf(error_fp, "alsa: Output failed: %s\n", snd_strerror(err));
479 return 0;
480 }
481
482 /* Open the devices */
483 if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK,
484 0)) < 0) {
485 fprintf(error_fp, "alsa: Cannot open playback device %s: %s\n",
486 pdevice, snd_strerror(err));
487 return 0;
488 }
489 if ((err = snd_pcm_open(&chandle, cdevice, SND_PCM_STREAM_CAPTURE,
490 SND_PCM_NONBLOCK)) < 0) {
491 fprintf(error_fp, "alsa: Cannot open capture device %s: %s\n",
492 cdevice, snd_strerror(err));
493 snd_pcm_close(phandle);
494 return 0;
495 }
496
497 err = setparams(phandle, chandle, format, latency, 0, &negotiated);
498
499 /* Try to use plughw instead, as it allows emulating speed */
500 if (err == 2 && strncmp(pdevice, "hw", 2) == 0) {
501
502 snd_pcm_close(phandle);
503
504 sprintf(pdevice_new, "plug%s", pdevice);
505 pdevice = pdevice_new;
506 if (verbose)
507 fprintf(error_fp, "alsa: Trying %s for playback\n", pdevice);
508 if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK,
509 0)) < 0) {
510 fprintf(error_fp, "alsa: Cannot open playback device %s: %s\n",
511 pdevice, snd_strerror(err));
512 snd_pcm_close(chandle);
513 return 0;
514 }
515
516 err = setparams(phandle, chandle, format, latency, 1, &negotiated);
517 }
518
519 if (err != 0) {
520 fprintf(error_fp, "alsa: setparams failed\n");
521 snd_pcm_close(phandle);
522 snd_pcm_close(chandle);
523 return 1;
524 }
525
526 buffer = malloc((negotiated.bufsize * snd_pcm_format_width(format) / 8)
527 * negotiated.channels);
528 if (buffer == NULL) {
529 fprintf(error_fp, "alsa: Failed allocating buffer for audio\n");
530 snd_pcm_close(phandle);
531 snd_pcm_close(chandle);
532 return 0;
533 }
534
535 if (verbose)
536 fprintf(error_fp,
537 "alsa: stream started from %s to %s (%i Hz, buffer delay = %.2f ms)\n",
538 cdevice, pdevice, negotiated.rate,
539 negotiated.latency * 1000.0 / negotiated.rate);
540
541 while (!stop_alsa) {
542 /* We start with a read and not a wait to auto(re)start the capture */
543 r = readbuf(chandle, buffer, negotiated.bufsize);
544 if (r == 0) /* Succesfully recovered from an overrun? */
545 continue; /* Force restart of capture stream */
546 if (r > 0)
547 writebuf(phandle, buffer, r);
548 /* use poll to wait for next event */
549 while (!stop_alsa && !snd_pcm_wait(chandle, 50))
550 ;
551 }
552
553 snd_pcm_drop(chandle);
554 snd_pcm_drop(phandle);
555
556 snd_pcm_unlink(chandle);
557 snd_pcm_hw_free(phandle);
558 snd_pcm_hw_free(chandle);
559
560 snd_pcm_close(phandle);
561 snd_pcm_close(chandle);
562
563 return 0;
564 }
565
566 struct input_params {
567 char *pdevice;
568 char *cdevice;
569 int latency;
570 };
571
alsa_thread_entry(void * whatever)572 static void *alsa_thread_entry(void *whatever)
573 {
574 struct input_params *inputs = (struct input_params *) whatever;
575
576 if (verbose)
577 fprintf(error_fp, "alsa: starting copying alsa stream from %s to %s\n",
578 inputs->cdevice, inputs->pdevice);
579 alsa_stream(inputs->pdevice, inputs->cdevice, inputs->latency);
580 if (verbose)
581 fprintf(error_fp, "alsa: stream stopped\n");
582
583 free(inputs->pdevice);
584 free(inputs->cdevice);
585 free(inputs);
586
587 return NULL;
588 }
589
590 /*************************************************************************
591 Public functions
592 *************************************************************************/
593
594 static int alsa_is_running = 0;
595 static pthread_t alsa_thread;
596
alsa_thread_startup(const char * pdevice,const char * cdevice,int latency,FILE * __error_fp,int __verbose)597 int alsa_thread_startup(const char *pdevice, const char *cdevice, int latency,
598 FILE *__error_fp, int __verbose)
599 {
600 int ret;
601 struct input_params *inputs;
602
603 if ((strcasecmp(pdevice, "disabled") == 0) ||
604 (strcasecmp(cdevice, "disabled") == 0))
605 return 0;
606
607 if (__error_fp)
608 error_fp = __error_fp;
609 else
610 error_fp = stderr;
611
612 verbose = __verbose;
613
614 if (alsa_is_running) {
615 fprintf(error_fp, "alsa: Already running\n");
616 return EBUSY;
617 }
618
619 inputs = malloc(sizeof(struct input_params));
620 if (inputs == NULL) {
621 fprintf(error_fp, "alsa: failed allocating memory for inputs\n");
622 return ENOMEM;
623 }
624
625 inputs->pdevice = strdup(pdevice);
626 inputs->cdevice = strdup(cdevice);
627 inputs->latency = latency;
628
629 stop_alsa = 0;
630 ret = pthread_create(&alsa_thread, NULL,
631 &alsa_thread_entry, (void *) inputs);
632 if (ret == 0)
633 alsa_is_running = 1;
634
635 return ret;
636 }
637
alsa_thread_stop(void)638 void alsa_thread_stop(void)
639 {
640 if (!alsa_is_running)
641 return;
642
643 stop_alsa = 1;
644 pthread_join(alsa_thread, NULL);
645 alsa_is_running = 0;
646 }
647
alsa_thread_is_running(void)648 int alsa_thread_is_running(void)
649 {
650 return alsa_is_running;
651 }
652
alsa_thread_timestamp(struct timeval * tv)653 void alsa_thread_timestamp(struct timeval *tv)
654 {
655 if (alsa_thread_is_running()) {
656 tv->tv_sec = timestamp.tv_sec;
657 tv->tv_usec = timestamp.tv_nsec / 1000;
658 } else {
659 tv->tv_sec = 0;
660 tv->tv_usec = 0;
661 }
662 }
663 #endif
664