summaryrefslogtreecommitdiffstats
path: root/libao2/ao_pulse.c
Commit message (Collapse)AuthorAgeFilesLines
* Merge remote-tracking branch 'origin/master'wm42012-07-301-29/+55
|\
| * ao_pulse: work around PulseAudio timing bugsUoti Urpala2012-07-291-29/+55
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Work around PulseAudio bugs more effectively. In particular, this should avoid two issues: playback never finishing at end of file / segment due to PulseAudio always claiming there's still time before audio playback reaches the end, and jerky playback especially after seeking due to bogus output from PulseAudio's timing interpolation code. This time, I looked into the PulseAudio code itself and analyzed the bugs causing problems. Fortunately, two of the serious ones can be worked around in client code. Write a new get_delay() implementation doing that, and remove some of the previous workarounds which are now unnecessary. Also add a pa_stream_trigger() call to ensure playback of files shorter than prebuf value starts (btw doing that by setting a low prebuf hits yet another PulseAudio bug, even if you then write the whole file in one call). There are still a couple of known PulseAudio bugs that can not be worked around in client code. Especially, bug 4 below can cause issues when pausing. Below is a copy of a message I sent to the pulseaudio-discuss mailing list, describing some of the PulseAudio bugs: ================================================== A lot of mplayer2 users with PulseAudio have experienced problems. I investigated some of those and confirmed that they are caused by PulseAudio. There are quite a few distinct PulseAudio bugs; some are analyzed below. Overall, however, I wonder why there are so many fairly obvious bugs in a widely used piece of software. Is there no maintenance? Or do people not test it? Some of the bugs are probably less obvious if you request low latency (though they're not specific to higher-latency case); do people test the low-latency case only? 1. The timing interpolation functionality can return completely bogus values for playback position and latency, especially after seeking (mplayer2 does cork / flush / uncork, as flushing alone does not seem to remove data already in sink). I've seen quickly repeated seeks report over 10 second latency, when there aren't any buffers anywhere that big. I have not investigated the exact cause. Instead I disabled interpolation and added code to always call pa_stream_update_timing_info(). (I assume that always waiting for this to complete, instead of doing custom interpolation, may give bad performance if it queries a remote server. But at least it works better locally.) 2. Position/latency reporting is wrong at the end of a stream (after the lack of more data triggers underflow status). As a result mplayer2 never ends the playback of a file, as it's waiting forever for audio to finish playing. The reason for this is that the calculations in PulseAudio add the whole length of data in the sink to the current latency (subtract from position), even if the sink does not contain that much data *from this stream* in underflow conditions. I was able to work around this bug by calculating latency from pa_timing_info data myself as follows (ti=pa_timing_info): int64_t latency = pa_bytes_to_usec(ti->write_index - ti->read_index, ss); latency -= ti->transport_usec; int64_t sink_latency = ti->sink_usec; if (!ti->playing) // this part is missing from PulseAudio itself sink_latency -= pa_bytes_to_usec(ti->since_underrun, ss); if (sink_latency > 0) latency += sink_latency; if (latency < 0) latency = 0; However, this still doesn't always work due to the next bug. 3. The since_underrun field in pa_timing_info is wrong if PulseAudio is resampling the stream. As a result, the above code indicated that the playback of a 0.1 second 8-bit mono file would take about 0.5 seconds. This bug is in pa_sink_input_peek(). The problematic parts are: ilength = pa_resampler_request(i->thread_info.resampler, slength); ... if (ilength > block_size_max_sink_input) ilength = block_size_max_sink_input; ... pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE, TRUE); ... i->thread_info.underrun_for += ilength; This is measuring audio in two different units, bytes for resampled-to-sink (slength) and original stream (ilength). However, the block_size_max_sink_input test only adjusts ilength; after that the values may be out of sync. Thus underrun_for is incremented by less than it should be to match the slength value used in pa_memblockq_seek. 4. Stream rewind functionality breaks if the sink is suspended (while the stream is corked). Thus, if you pause for more than 5 seconds without other audio playing, things are broken after that. The most obvious symptom is that playback can continue for a significant time after corking. This is caused by sink_input and sink getting out of sync. First, after uncorking a stream on a suspended sink, pa_sink_input_request_rewind() is called while the sink is still in suspended state. This sets sink_input->thread_info.rewrite_nbytes to -1 and calls pa_sink_request_rewind(). However, the sink ignores rewind requests while suspended. Thus this particular rewind does nothing. The problem is that rewrite_nbytes is left at -1. Further calls to pa_sink_input_request_rewind() do nothing because "nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);" sets nbytes to -1, and the call to pa_sink_request_rewind() is under "if (nbytes != (size_t) -1) {". Usually, after a sink responds to a rewind request, rewrite_bytes is reset in pa_sink_input_process_rewind(), but this doesn't happen if the sink ever ignores one request. This broken state can be resolved if pa_sink_input_process_rewind() is called due to a rewind triggered by _another_ stream. There were more bugs, but I'll leave those for later.
* | ao_pulse: don't always print error message if PulseAudio unavailablewm42012-07-301-2/+5
|/ | | | | | | | | | | | | | PulseAudio is rather high on the auto proving order (to avoid using an emulated sound API), but it prints an annoying error message if the PA client library can't connect to a server. On the other hand, we do want this error message printed if the user explicitly selects the pulse audio output driver. Add a flag to indicate that an AO is opened due to auto probing. ao_pulse checks that flag, and if it's set, do not print if the initialization error is PA_ERR_CONNECTIONREFUSED, whcih I assume is the error signalling PulseAudio unavailability. (This error happens if no PulseAudio server is installed.)
* ao_pulse: fix specifying host/sink after 4fed8ad197Uoti Urpala2012-05-031-1/+1
| | | | | | | Commit 4fed8ad197 ("ao_pulse: convert to new AO API") failed to change the variable name used on one line in suboption handling. This caused a crash due to NULL dereference if you tried to specify any suboptions for the AO (as in "--ao=pulse:foo"). Fix.
* ao_pulse: support native mute controlwm42012-04-111-29/+55
|
* libao2: change control() types to enum, remove unused onesUoti Urpala2012-04-081-1/+1
| | | | | | | | | Change the audio driver control() command argument from "int" to "enum aocontrol". Remove unused control types (SET_DEVICE, GET_DEVICE, QUERY_FORMAT, SET_PLUGIN_DRIVER, SET_PLUGIN_LIST). The QUERY_FORMAT one looks like there's a possibility such functionality could be useful in the future, but as ao_oss was the only driver to have an actual implementation of it, the current code wasn't worth keeping.
* ao_pulse: add hacks to work around seek problemsUoti Urpala2012-03-261-1/+19
| | | | | | | | pa_stream_flush() seems to work pretty badly in general. The visible symptoms included at least old audio continuing for a significant time after the call, and bogus latency reporting causing temporary video freezes after a seek. Add some hacks to work around these problems. The result seems to work most of the time on my machine at least...
* ao_pulse, core: make pulse thread wake up core for more dataUoti Urpala2012-03-261-2/+10
| | | | | | | | | | | | | | | For ao_pulse, the current latency is not a good indicator of how soon the AO requires new data to avoid underflow. Add an internal pipe that can be used to wake up the input loop from select(), and make the pulseaudio main loop (which runs in a separate thread) use this mechanism when pulse requests more data. The wakeup signal currently contains no information about the reason for the wakup, but audio buffers are always filled when the event loop wakes up. Also, request a latency of 1 second from the Pulseaudio server. The default is normally significantly higher. We don't need low latency, while higher latency helps prevent underflows reduces need for wakeups.
* ao_pulse: convert to new AO APIUoti Urpala2012-03-261-222/+282
|
* Add a missing const, fixes a compiler warning.reimar2009-12-181-1/+1
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@30062 b3059339-0415-0410-9bf9-f77b7e298cf2
* Allow pulseaudio to restore the previous volume on init instead of forcing toreimar2009-12-181-4/+1
| | | | | | | | full volume. The old behaviour can be restored by using -volume 100. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@30061 b3059339-0415-0410-9bf9-f77b7e298cf2
* Get rid of global volume variable, it is only used for temporary values.reimar2009-12-181-5/+7
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@30060 b3059339-0415-0410-9bf9-f77b7e298cf2
* Disable pause-hack from PulseAudio 0.9.15 on, it should be fixed.reimar2009-04-091-3/+3
| | | | | | | | Patch Lennart Poettering [lennart poettering net] with documentation update by me. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@29160 b3059339-0415-0410-9bf9-f77b7e298cf2
* Split oversized of "argument" onto a separate line.reimar2009-04-091-1/+2
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@29159 b3059339-0415-0410-9bf9-f77b7e298cf2
* Also lock the mainloop when doing adjusting the volume for PulseAudio.reimar2009-04-091-0/+3
| | | | | | | Patch by Lennart Poettering [lennart poettering net] git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@29158 b3059339-0415-0410-9bf9-f77b7e298cf2
* Make sure waitop always unlocks the mainloop even if the operation could notreimar2009-04-091-1/+4
| | | | | | | | be created. Patch by Lennart Poettering [lennart poettering net] git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@29157 b3059339-0415-0410-9bf9-f77b7e298cf2
* Make ao_info_t structs const.reimar2009-03-061-1/+1
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28858 b3059339-0415-0410-9bf9-f77b7e298cf2
* Work around a PulseAudio bug that causes MPlayer to hang after unpausing.reimar2009-02-191-0/+18
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28668 b3059339-0415-0410-9bf9-f77b7e298cf2
* Use standard license headers with standard formatting.diego2008-05-141-3/+4
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@26775 b3059339-0415-0410-9bf9-f77b7e298cf2
* Avoid dependency on newer pulseaudio version.reimar2008-05-071-0/+4
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@26681 b3059339-0415-0410-9bf9-f77b7e298cf2
* Add support for 32 bit format to ao_pulse.reimar2008-05-011-0/+2
| | | | | | | Based on patch by James Warden [warjamy yahoo com] git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@26635 b3059339-0415-0410-9bf9-f77b7e298cf2
* Make ao_pulse fall back to s16le format instead of just failing.reimar2008-05-011-4/+5
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@26634 b3059339-0415-0410-9bf9-f77b7e298cf2
* pa_stream_write reportedly needs locking of the main loopreimar2007-12-151-1/+3
| | | | | | | (could not find official documentation on this subject...) git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@25414 b3059339-0415-0410-9bf9-f77b7e298cf2
* Fix indentationreimar2007-12-151-4/+4
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@25413 b3059339-0415-0410-9bf9-f77b7e298cf2
* Remove pointless pa_stream_trigger callreimar2007-12-151-10/+0
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@25412 b3059339-0415-0410-9bf9-f77b7e298cf2
* Documentation for waitop functionreimar2007-12-151-0/+6
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@25411 b3059339-0415-0410-9bf9-f77b7e298cf2
* Remove idiotic check that would always be falsereimar2007-11-031-1/+1
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@24951 b3059339-0415-0410-9bf9-f77b7e298cf2
* Change parsing to allow host == NULL and sink != NULLreimar2007-11-031-4/+6
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@24949 b3059339-0415-0410-9bf9-f77b7e298cf2
* Simplify argument "parsing"reimar2007-11-031-4/+2
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@24948 b3059339-0415-0410-9bf9-f77b7e298cf2
* Make sink variable local, it is only used in one placereimar2007-11-031-3/+1
| | | | git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@24947 b3059339-0415-0410-9bf9-f77b7e298cf2
* Add missing ao_pulse.creimar2007-10-181-0/+382
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@24810 b3059339-0415-0410-9bf9-f77b7e298cf2