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.)
mplayer had three ways of enabling CPU specific assembler routines:
a) Enable them at compile time; crash if the CPU can't handle it.
b) Enable them at compile time, but let the configure script detect
your CPU. Your binary will only crash if you try to run it on a
different system that has less features than yours.
This was the default, I think.
c) Runtime detection.
The implementation of b) and c) suck. a) is not really feasible (it
sucks for users). Remove all code related to this, and use libav's CPU
detection instead. Now the configure script will always enable CPU
specific features, and disable them at runtime if libav reports them
not as available.
One implication is that now the compiler is always expected to handle
SSE (etc.) inline assembly at runtime, unless it's explicitly disabled.
Only checks for x86 CPU specific features are kept, the rest is either
unused or barely used.
Get rid of all the dump -mpcu, -march etc. flags. Trust the compiler
to select decent settings.
Get rid of support for the following operating systems:
- BSD/OS (some ancient BSD fork)
- QNX (don't care)
- BeOS (dead, Haiku support is still welcome)
- AIX (don't care)
- HP-UX (don't care)
- OS/2 (dead, actual support has been removed a while ago)
Remove the configure code for detecting the endianness. Instead, use
the standard header <endian.h>, which can be used if _GNU_SOURCE or
_BSD_SOURCE is defined. (Maybe these changes should have been in a
separate commit.)
Since this is a quite violent code removal orgy, and I'm testing only
on x86 32 bit Linux, expect regressions.
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.
Some of these have only limited use, and some of these have no use at
all. Remove them. They make maintainance harder and nobody needs them.
It's possible that many of the removed drivers were very useful a dozen
of years ago, but now it's 2012.
Note that some of these could be added back, in case they were more
useful than I thought. But right now, they are just a burden.
Reason for removal for each module:
vo_3dfx, vo_dfbmga, vo_dxr3, vo_ivtv, vo_mga, vo_s3fb,
vo_tdfxfb, vo_xmga, vo_tdfx_vid:
All of these are for very specific and outdated hardware. Some
of them require non-standard kernel drivers or do direct HW
access.
vo_dga: the most crappy and ancient way to get fast output on X.
vo_aa: there's vo_caca for the same purpose.
vo_ggi: this never lived, and is entirely useless.
vo_mpegpes: for DVB cards, I can't test this and it's crappy.
vo_fbdev, vo_fbdev2: there's vo_directfb2
vo_bl: what is this even? But it's neither important, nor alive.
vo_svga, vo_vesa: you want to use this? You can't be serious.
vo_wii: I can't test this, and who the hell uses this?
vo_xvr100: some Sun thing.
vo_xover: only useful in connection with xvr100.
ao_nas: still alive, but I doubt it has any meaning today.
ao_sun: Sun.
ao_win32: use ao_dsound or ao_portaudio instead.
ao_ivtv: removed along vo_ivtv.
Also get rid of anything SDL related. SDL 1.x is total crap for video
output, and will be replaced with SDL 2.x soon (perhaps), so if you
want to use SDL, write output drivers for SDL 2.x.
Additionally, I accidentally damaged Sun support, which made me
completely remove Sun/Solaris support. Nobody cares about this anyway.
Some left overs from previous commits removing modules were cleaned up.
This AO has potential to be useful on platforms other than Linux. On
Windows in particular, PortAudio can make use of newer/better audio
APIs like WASAPI, instead of DirectSound.
As an implementation choice, the PortAudio callback API was used. The
blocking API might be a better match for mplayer's requirements, but
caused severe problems on Linux/ALSA (possibly PortAudio bugs).
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.
Conflicts:
command.c
libao2/ao_alsa.c
libao2/ao_dsound.c
libao2/ao_pulse.c
libao2/audio_out.h
mixer.c
mixer.h
mplayer.c
Replace my mixer changes with uau's implementation, which is based on
my code.
If digital pass-through is used, this supported setting the volume
(just mute, actually), but not getting the volume. This will probably
lead to a stuck mute state in the mplayer frontend. Make the code
respond to volume queries even if digital pass-through is used.
Make mixer support setting the mute attribute at audio driver level,
if one exists separately from volume. As of this commit, no libao2
driver exposes such an attribute yet; that will be added in later
commits.
Since the mute status can now be set externally, it's no longer
completely obvious when the player should automatically disable mute
when uninitializing an audio output. The implemented behavior is to
turn mute off at uninitialization if we turned it on and haven't
noticed it turn off (by external means) since.
MPlayer volume control was originally implemented with the assumption
that it controls a system-wide volume setting which keeps its value
even if a process closes and reopens the audio device. However, this
is not actually true for --softvol mode or some audio output APIs that
only consider volume as a per-client setting for software mixing. This
could have annoying results, as the volume would be reset to a default
value if the AO was closed and reopened, for example whem moving to a
new file or crossing ordered chapter boundaries. Add code to set the
previous volume again after audio reinitialization if the current
audio chain is known to behave this way (softvol active or the AO
driver is known to not keep persistent volume externally).
This also avoids an inconsistency with the mute flag. The frontend
assumed the mute status is persistent across file changes, but it
could be similarly lost.
The audio drivers that are assumed to not keep persistent volume are:
coreaudio, dsound, esd, nas, openal, sdl. None of these changes have
been tested. I'm guessing that ESD and NAS do per-connection
non-persistent volume settings.
Partially based on code by wm4.
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.
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...
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.
Now "-ao openal:device=<subdevice>" will pass <subdevice> as device to
OpenAL. This allows selecting both the OpenAL backend (OS-level audio
API) and the physical output device.
The available devices can be listed with "-ao openal:device=help".
The recent changes in mixer.c require the AO to return a volume of
exactly 0 when audio has been muted. Rather than adding just another
special case to mixer.c, fix ao_dsound.c to return previously set
volumes exactly. Because DirectSound volume control is not connected
with the system mixer, which could change the volume without mplayer
knowing, reading the volume back from DirectSound is pointless.
Also, the code tried to calculate log10(0). Clip the volume to 1,
which results in -10000, DirectSound's definition of silence.
When layback of a file ends, the audio output doesn't receive new audio
data, but the rest of the data must be played properly. ao_dsound.c
doesn't handle this properly: DirectSound will continue to play the
ringbuffer, even if mplayer doesn't write any data. There's no explicit
way to prevent such a buffer underrun. Try to detect it and stop
playback.
Some of the code, especially the dshow and windows codec loader parts,
are extremely hacky and likely full of bugs. The goal is merely getting
rid of warnings that could obscure more important warnings and actual
bugs, instead of fixing actual problems. This reduces the number of
warnings from over 500 to almost the same as when compiling on Linux.
Note that many problems stem from using the ancient wine-derived
windows headers. There are some differences to the "proper" windows
header. Changing the code to compile with the proper headers would be
too much trouble, and it still has to work on Unix.
Some of the changes might actually break compilation on legacy MinGW,
but we don't support that anymore. Always use MinGW-w64, even when
compiling to 32 bit.
Fixes some warnings in the win32 loader code on Linux too.
If digital pass-through is used, this supported setting the volume (just
mute, actually), but not getting the volume. This will probably lead to a
stuck mute state in the mplayer frontend. Make the code respond to volume
queries even if digital pass-through is used.
Ideally, ao_coreaudio should implement full mute control, but I can't
even test on OSX.
The mixer frontend code can now make use of a proper system mixer mute
toggle, if the audio output driver supports it.
The consequence is that, if support is available, mplayer will no longer
temporarily set the system volume to 0 if mute is enabled.
Generally, the code now deals with the following combinations of available
AO features:
- software volume control forced by user (--softvol / soft_vol flag)
=> if enabled, never touch the "hardware" controls
- "hardware"/driver volume control available (whether
AOCONTROL_GET/SET_VOLUME works)
=> if not available, enable volume controls by enabling softvol
- "hardware"/driver mute control (AOCONTROL_GET/SET_MUTE)
=> if not available, emulate by setting volume to 0
- whether the volume+mute controls are kept or not when the AO is closed
(indicated by ao->no_persistent_volume)
=> if not persistent, restore the volume/mute next time the AO is opened
The mplayer frontend (specifically, mixer.c) needs to know this. If the
audio output doesn't remember the volume across reinitialization, the
frontend will restore the volume settings. There is also the assumption
that the volume setting isn't global in this case (i.e. changing it
won't change the volume of other applications or annoy the user
otherwise).
None of these changes have been tested. I'm guessing that ESD and NAS do
per-connection non-persistent volume settings.
Some audio outputs don't provide access to a system-wide mixer control, and
do per-application audio mixing. Further, some of these forget the volume
as soon as the audio device is closed. This can be annoying, because
mplayer will "forget" the volume when playing a new file or when crossing
ordered chapter boundaries. Support restoring the volume on audio
reinitialization if an audio output driver knowingly behaves this way.
(This doesn't change that mplayer never writes any settings into the config
file, including volume settings.)
This commit doesn't yet change any actual output driver to use this code.
Hopefully make some logic in the volume restore code a bit more robust.
Now PulseAudio is preferred over ALSA, which in turn is preferred over
OSS. This should give best results on all systems. On systems with
PulseAudio, we will always use it natively, rather than through the
suboptimal ALSA emulation (which the default ALSA output is normally
redirected to when PulseAudio is active; ALSA hardware devices will
not be, but to use those the user must set AO explicitly in any case,
so changing the defaults makes no difference). The fallback from
ao_pulse to ao_alsa causes no noticeable delay on systems without
PulseAudio. On systems with ALSA, we won't attempt to use OSS anymore.
Also, move OpenAL above SDL. OpenAL should generally work better than
SDL.
RenderCallbackSPDIF might call read_buffer with NULL data. The purpose
is to drain data from the buffer when the output is muted. Add a check
to call av_fifo_drain() in this case.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@34241 b3059339-0415-0410-9bf9-f77b7e298cf2
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@34242 b3059339-0415-0410-9bf9-f77b7e298cf2
The variable corresponding to the "fast" suboption of ao_pcm was
uninitialized. Fix. The only effect was possibly printing a warning
about the suboption being deprecated even if it wasn't used.
Move the buffer storing audio data ready to be fed to the audio output
driver from the audio decoder object to the AO object. This will help
encoding code deal with end of input, and may also be useful to
improve other general gapless audio behavior (as AOs which do not
accept chunks smaller than a certain size may keep them in the buffer
while the decoder changes).
Less data may be dropped now when changing audio filters or switching
timeline parts.
On MinGW64 io.h is needed for _get_osfhandle().
patch by Stephen Sheldon, sfsheldo gmail com
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@33341 b3059339-0415-0410-9bf9-f77b7e298cf2