Re: [pulseaudio-discuss] My attempt to reduce latency with pacat and tvtime
On Mon, 2012-05-21 at 21:09 +0600, Alexander E. Patrakov wrote: 2012/5/21 Pierre-Louis Bossart pierre-louis.boss...@linux.intel.com: I am not sure if there's really a problem. Increasing the audio latency doesn't necessarily result in A/V sync issues. As long as the A/V sync is done by querying how many samples are queued instead of using the number of samples pushed into PulseAudio, you should be able to use pretty much whatever buffer size you want. It's the same issue with ALSA, if you use large buffers and base the A/V on the number of samples written to the ring buffer, A/V sync will be off. Use snd_pcm_delay() and you'll be fine. Dear Pierre-Louis, this thread is based on a misunderstanding. The original poster, instead of asking someone to fix the original problem (see below), asks you about workarounds, and you don't see the big picture. Thanks for that explanation. Yes, the issue is that tvtime does not handle A/V sync and yes, admittedly I'm trying to fix the problem somewhere other than where it should be fixed ideally. But I thought this might be a case where it would be easiest to fix the problem in PulseAudio. -- | Steven Elliott | http://selliott.org | sellio...@austin.rr.com | ___ pulseaudio-discuss mailing list pulseaudio-discuss@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] My attempt to reduce latency with pacat and tvtime
On Mon, 2012-05-21 at 18:15 -0500, Pierre-Louis Bossart wrote: 1) TVtime (that's what the original poster uses): doesn't handle audio at all (but I was told that there is a fork that does), assumes that there is a zero-latency analog wire coming from the TV tuner audio output to the sound card's TV input. That's why the OP asks about module-loopback and/or parec|pacat solution, as a replacement of the said wire. Due to the now-invalid assumption about the wire, zero latency is needed. Because the audio chain is external to tvtime, there is no possibility for any A/V sync queries. Isn't the simplest solution to add a fixed delay for the video in TVtime, and apply the same fixed delay in module-loopback? That's an interesting idea. I suppose the audio frames would have to be queued up and then rendered after the appropriate delay. I'm not sure if that would be simpler than my patch or not. I'd have to know more about how tvtime handles audio. One concern is that tvtime has not had a release since 2005. Also, are there other programs that don't maintain A/V sync? Perhaps it would benefit them as well. Any attempts to emulate the behavior of an zero-latency analog wire with PulseAudio aren't very likely to succeed :-) Fair enough. My hope was just to keep it low enough. -- | Steven Elliott | http://selliott.org | sellio...@austin.rr.com | ___ pulseaudio-discuss mailing list pulseaudio-discuss@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] My attempt to reduce latency with pacat and tvtime
On Mon, 2012-03-26 at 23:54 -0500, Steven Elliott wrote: I use tvtime (an open source TV application) to watch TV on my Fedora 16 system. As some of you may know forwarding audio from the sound card built into the TV tuner card to the primary sound card is not done by tvtime. There are various ways of forwarding the audio including SoX, module-loopback, etc. but I've had the best luck (least latency) using pacat in a manner similar to what this webpage describes: http://thelinuxexperiment.com/guinea-pigs/tyler-b/fix-pulseaudio-loopback-delay/ But with a change that I've made to pacat that I'd like to share in case it's helpful. Since I've posted the above I've refined my patch a bit, which I've attached, but I've also explored an additional cause of latency in the PulseAudio server. I've found that, if for some reason, there is an underrun the watermark or latency is increased via increase_watermark() in alsa-source.c and alsa-sink.c. That probably makes sense in a lot of cases, but in the case of watching TV via tvtime I'd rather suffer a fleeting glitch due to underrun than a longer lasting A/V sync issue. I don't think the attached pulseaudio-limited-watermark-experimental.diff patch is ideal which why I marked it experimental. Consequently I'm curious if there is potential for it to evolve into a submitable patch. Should the 50 msec limit that I've imposed in fix_tsched_watermark() be configurable? Would it be preferable to decrease the watermark more aggressively in decrease_watermark()? -- | Steven Elliott | http://selliott.org | sellio...@austin.rr.com | This experimental patch adds a --drain option to pacat that causes pacat to drain extra data from stdin. This is helpful when pacat is used to forward audio from one audio card to another with minimal latency. --- man/pacat.1.xml.in.orig 2011-03-20 08:28:04.299902459 -0500 +++ man/pacat.1.xml.in 2012-04-06 15:12:55.642080385 -0500 @@ -212,6 +212,14 @@ /option option + popt--drain/opt/p + optdescpContinually drain stdin. This is used for forwarding + audio from one device to another where latency is to be minimized + by discarding extra audio from stdin when this program is invoked + as cmdpacat/cmd./p/optdesc +/option + +option popt--property/optarg=PROPERTY=VALUE/arg/p optdescpAttach a property to the client and stream. May be used multiple times/p/optdesc --- src/utils/pacat.c.orig 2011-06-23 15:18:54.497124797 -0500 +++ src/utils/pacat.c 2012-04-06 15:25:53.478846580 -0500 @@ -51,6 +51,12 @@ #define CLEAR_LINE \x1B[K +/* It's not obvious what to set this to. Setting it has high as 100 causes + bit of a delay before draining, but makes the adjustments less frequent. */ +#define DRAIN_THRESHOLD 5 + +#define DRAIN_BYTES 65536 + static enum { RECORD, PLAYBACK } mode = PLAYBACK; static pa_context *context = NULL; @@ -70,6 +76,7 @@ static pa_bool_t verbose = FALSE; static pa_volume_t volume = PA_VOLUME_NORM; static pa_bool_t volume_is_set = FALSE; +static pa_bool_t drain = FALSE; static pa_sample_spec sample_spec = { .format = PA_SAMPLE_S16LE, @@ -501,8 +508,9 @@ /* New data on STDIN **/ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { -size_t l, w = 0; +size_t l, l_extra, w = 0; ssize_t r; +static int full_reads; /* Consecutive full reads (all bytes read). */ pa_assert(a == mainloop_api); pa_assert(e); @@ -516,9 +524,14 @@ if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream))) l = 4096; -buffer = pa_xmalloc(l); +if (drain) { +l_extra = (full_reads DRAIN_THRESHOLD) ? (l + DRAIN_BYTES) : l; +} else { +l_extra = l; +} +buffer = pa_xmalloc(l_extra); -if ((r = read(fd, buffer, l)) = 0) { +if ((r = read(fd, buffer, l_extra)) = 0) { if (r == 0) { if (verbose) pa_log(_(Got EOF.)); @@ -535,8 +548,31 @@ return; } -buffer_length = (uint32_t) r; -buffer_index = 0; +if (drain) { +if ((size_t) r == l_extra) { +full_reads++; +} +else { +full_reads = 0; +} +} + +if ((size_t) r l) { +/* The read exceeds the writeable size. Find the end of the buffer + that is aligned on a 4 byte boundary. + TODO: This probably fails if frame_size is not a power of 2. */ +const pa_sample_spec *spec = pa_stream_get_sample_spec(stream); +size_t frame_size = pa_frame_size(spec); +buffer_index = (~frame_size) (r - l); +buffer_length = (size_t) r - buffer_index; +if (buffer_length l) +{ +buffer_length
Re: [pulseaudio-discuss] My attempt to reduce latency with pacat and tvtime
On 3/26/2012 11:54 PM, Steven Elliott wrote: I use tvtime (an open source TV application) to watch TV on my Fedora 16 system. As some of you may know forwarding audio from the sound card built into the TV tuner card to the primary sound card is not done by tvtime. There are various ways of forwarding the audio including SoX, module-loopback, etc. but I've had the best luck (least latency) using pacat in a manner similar to what this webpage describes: http://thelinuxexperiment.com/guinea-pigs/tyler-b/fix-pulseaudio-loopback-delay/ But with a change that I've made to pacat that I'd like to share in case it's helpful. Why not use module-loopback with latency set to a low value? Worked well when I last used it. -Pierre ___ pulseaudio-discuss mailing list pulseaudio-discuss@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] My attempt to reduce latency with pacat and tvtime
On Tue, 2012-03-27 at 12:16 -0500, Pierre-Louis Bossart wrote: On 3/26/2012 11:54 PM, Steven Elliott wrote: I use tvtime (an open source TV application) to watch TV on my Fedora 16 system. As some of you may know forwarding audio from the sound card built into the TV tuner card to the primary sound card is not done by tvtime. There are various ways of forwarding the audio including SoX, module-loopback, etc. but I've had the best luck (least latency) using pacat in a manner similar to what this webpage describes: http://thelinuxexperiment.com/guinea-pigs/tyler-b/fix-pulseaudio-loopback-delay/ But with a change that I've made to pacat that I'd like to share in case it's helpful. Why not use module-loopback with latency set to a low value? Worked well when I last used it. I have tried it, but I've had better luck with the pacat solution I outlined. I've tried various latency times for each. I just noticed that pa_stream_writable_size() typically returns values that make sense for 23 msec instead of the 1 msec that I have latency set to (I know it's not realistic to have latency be that low, but I thought I'd try to get as close as possible). Anyway, maybe that's something I should investigate further since that 23 msec is only part of the total latency. -- | Steven Elliott | http://selliott.org | sellio...@austin.rr.com | ___ pulseaudio-discuss mailing list pulseaudio-discuss@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] My attempt to reduce latency with pacat and tvtime
I use tvtime (an open source TV application) to watch TV on my Fedora 16 system. As some of you may know forwarding audio from the sound card built into the TV tuner card to the primary sound card is not done by tvtime. There are various ways of forwarding the audio including SoX, module-loopback, etc. but I've had the best luck (least latency) using pacat in a manner similar to what this webpage describes: http://thelinuxexperiment.com/guinea-pigs/tyler-b/fix-pulseaudio-loopback-delay/ But with a change that I've made to pacat that I'd like to share in case it's helpful. The web page above describes using two instances of pacat with a pipe: pacat -r ... | pacat -p ... to forward the audio. I've found that this works quite well for a while, but gradually the latency increases. If for some reason the pacat processes are temporarily suspended and then resumed (ctrl-Z followed by bg, for example) the latency increases drastically. I've found that the increased latency is due to audio queuing up on the input to the play instance of pacat (the pacat on the right side of the | shown above). The extra queued up audio never gets consumed because audio is being produced by the record instance of pacat (the pacat on the left side of the | shown above) at the same rate it is consumed by the play instance of pacat. So I experimented with ways of discarding the queued up audio that did not interfere with the sound quality too much. Each time stdin_callback() is called by the play instance of pacat to get audio from the input pa_stream_writable_size() is called to see how many bytes the sink can take. This limits the amount of data that can be read from stdin. Each read of stdin is either full (precisely the number of bytes requested is returned) or partial (less than the number of bytes requested is returned). I've found the if a large number of full reads occur in a row that it's likely there latency due to extra audio queued up in the input. When this happens I've modified pacat to read as much as 64 KiB more than what pa_stream_writable_size() requested, but then discard the extra data read. I suspect that there may be a more elegant solution at a different layer in the code. At the very least the change should be made optional so that it does not break pacat when playing a file instead of reading from a pipe: pacapt -p ... audio.raw But if there is interest I can add a command line option so that the change is not always in effect. -- | Steven Elliott | http://selliott.org | sellio...@austin.rr.com | --- src/utils/pacat.c.orig 2012-03-24 10:13:10.382540053 -0500 +++ src/utils/pacat.c 2012-03-24 22:51:41.350164538 -0500 @@ -51,6 +51,10 @@ #define CLEAR_LINE \x1B[K +#define DRAIN_THRESHOLD 100 + +#define DRAIN_BYTES 65536 + static enum { RECORD, PLAYBACK } mode = PLAYBACK; static pa_context *context = NULL; @@ -501,8 +505,9 @@ /* New data on STDIN **/ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { -size_t l, w = 0; +size_t l, l_extra, w = 0; ssize_t r; +static int full_reads; // Consecutive full reads (all bytes read). pa_assert(a == mainloop_api); pa_assert(e); @@ -516,9 +521,10 @@ if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream))) l = 4096; -buffer = pa_xmalloc(l); +l_extra = (full_reads DRAIN_THRESHOLD) ? (l + DRAIN_BYTES) : l; +buffer = pa_xmalloc(l_extra); -if ((r = read(fd, buffer, l)) = 0) { +if ((r = read(fd, buffer, l_extra)) = 0) { if (r == 0) { if (verbose) pa_log(_(Got EOF.)); @@ -535,8 +541,27 @@ return; } -buffer_length = (uint32_t) r; -buffer_index = 0; +if ((size_t) r == l_extra) { +full_reads++; +} +else { +full_reads = 0; +} + +if ((size_t) r l) { +// The read exceeds the writeable size. Find the end of the buffer +// that is aligned on a 4 byte boundary. +// TODO: Determine the alignment bytes rather than assuming 4. +buffer_index = (~3) (r - l); +buffer_length = (size_t) r - buffer_index; +if (buffer_length l) +{ +buffer_length = l; +} +} else { +buffer_length = (uint32_t) r; +buffer_index = 0; +} if (w) do_stream_write(w); ___ pulseaudio-discuss mailing list pulseaudio-discuss@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss