This eliminates some intermittent pops heard in a HRT MicroStreamer DAC
uncorrelated with user interaction. As a bonus, this resolves#1773 which I can
o longer reproduce as of this commit. Leave the 50ms buffer for shared mode
since that seems to be working quite well.
This is also the way exclusive mode is done in the MSDN example code:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd370844%28v=vs.85%29.aspx
This was originally increased in c545c40 to mitigate glitches that subsequent
refactorings have eliminated.
A COM message loop is apparently totally inappropriate for a low latency
thread. It leads to audio glitches because the thread doesn't wake up fast
enough when it should. It also causes mysterious correlations between the vo
and ao thread (i.e., toggling fullscreen delays audio feed events). Instead use
an mp_dispatch_queue to set/get volume/mute/session display name from the audio
thread. This has the added benefit of obviating the need to marshal the
associated interfaces from the audio thread.
Don't wait for WASAPI to send another feed event if we detect an underfull
buffer. It seems that WASAPI doesn't always send extra feed events if
something causes rendering to fall behind. This causes every subsequent playback
buffer to under-run until playback is reset. The fix is simply to do a one-shot
double feed when this happens, which allows rendering to catch up with playback.
This was observed to happen when using MsgWaitForMultipleObjects to wait for the
feed event and toggling fullscreen with vo=opengl:backend=win. This commit
improves the behaviour in that specific case and more generally makes exclusive
mode significantly more robust.
This commit also moves the logic to avoid *over*filling the exclusive mode
buffer into thread_feed right next to the above described underfil logic.
OpenSL ES is used on Android. At the moment only stereo output is
supported. Two options are supported: 'frames-per-buffer' and
'sample-rate'. To get better latency the user of libmpv should pass
values obtained from AudioManager.getProperty(PROPERTY_OUTPUT_FRAMES_PER_BUFFER)
and AudioManager.getProperty(PROPERTY_OUTPUT_SAMPLE_RATE).
I can't explain this, but it seems to be a similar case to the ALSA HDMI
one. I find it hard to tell because of the slightly different names and
conventions in use in libavcodec, WAVEEXT channel masks, decoders, codec
specifications, HDMI, and platform audio APIs.
The fix is the same as the one for ao_alsa (see commit be49da72). This
should fix at least playing 7.1 sources on OSX with 7.1(rear) selected
in Audio MIDI Setup. The ao_alsa commit mentions XBMC, but I couldn't
find out where it does that or if it also does that for CoreAudio. It's
woth noting that PHT (essentially an old XBMC fork) also exhibited the
incorrect behavior (i.e. side and back speakers were swapped).
Correctly avoid a reload if the current device was specified by the user through
--audio-device. Previously, we only recognized if the user had specified
--ao=wasapi:device=.
Notably, the address of the enumerator->count member is passed to
IMMDeviceCollection::GetCount(), which expects a UINT variable, not an int. How
did this ever work?
Previously, if the enumerator found no devices, attempting to get the default
device with IMMDeviceEnumerator::GetDefaultAudioEndpoint would result in the
cryptic (and undocumented) E_PROP_ID_UNSUPPORTED. This way, the user is given a
better indication of what exactly is wrong and isolates any other possible
triggers for this error.
While the situation is not really clear for the other rewritten
coreaudio code, it's very clear for the channel mapping code. It was all
written by us. (MPlayer doesn't even have any channel map handling.)
This covers source files which were added in mplayer2 and mpv times
only, and where all code is covered by LGPL relicensing agreements.
There are probably more files to which this applies, but I'm being
conservative here.
A file named ao_sdl.c exists in MPlayer too, but the mpv one is a
complete rewrite, and was added some time after the original ao_sdl.c
was removed. The same applies to vo_sdl.c, for which the SDL2 API is
radically different in addition (MPlayer supports SDL 1.2 only).
common.c contains only code written by me. But common.h is a strange
case: although it originally was named mp_common.h and exists in MPlayer
too, by now it contains only definitions written by uau and me. The
exceptions are the CONTROL_ defines - thus not changing the license of
common.h yet.
codec_tags.c contained once large tables generated from MPlayer's
codecs.conf, but all of these tables were removed.
From demux_playlist.c I'm removing a code fragment from someone who was
not asked; this probably could be done later (see commit 15dccc37).
misc.c is a bit complicated to reason about (it was split off mplayer.c
and thus contains random functions out of this file), but actually all
functions have been added post-MPlayer. Except get_relative_time(),
which was written by uau, but looks similar to 3 different versions of
something similar in each of the Unix/win32/OSX timer source files. I'm
not sure what that means in regards to copyright, so I've just moved it
into another still-GPL source file for now.
screenshot.c once had some minor parts of MPlayer's vf_screenshot.c, but
they're all gone.
Previously used opt_exclusive option to decide which volume control code to run.
The might not always reflect the actual state, for example if passthrough
is used. Admittedly, none of the volume controls will work anyway with
passthrough, but this is the right thing to do.
Note that hresult_to_str() (coming from wasapi_explain_err()) is mostly
wasapi-specific, but since HRESULT error codes are unique, it can be
extended for any other use.
It existed for XP-compatibility only. There was also a time where
ao_wasapi caused issues, but we're relatively confident that ao_wasapi
works better or at least as good as ao_dsound on Windows Vista and
later.
Normally, PulseAudio accepts any combination of sample format, sample
rate, channel count/map. Sometimes it does not. For example, the channel
rate or channel count have fixed maximum values. We should not fail
fatally in such cases, but attempt to fall back to a working format.
We could just send pass an "unset" format to Pulse, but this is not too
attractive. Pulse could use a format which we do not support, and also
doing so much for an obscure corner case is not reasonable. So just pick
a format that is very likely supported.
This still could fail at runtime (the stream could fail instead of going
to the ready state), but this sounds also too complicated. In
particular, it doesn't look like pulse will tell us the cause of the
stream failure. (Or maybe it does - but I didn't find anything.)
Last but not least, our fallback could be less dumb, and e.g. try to fix
only one of samplerate or channel count first to reduce the loss, but
this is also not particularly worthy the effort.
Fixes#2654.
Unify and clean up listing and selection. Use common enumerator code for both
operations to avoid duplication or inconsistencies.
Maintain, but significatnly simplify manual device selection by id, name or
number. This actually fixes loading by name which didn't really work before
since the "name" displayed by --audio-device=help differed from that used to
match the selection, which used the device "description" instead.
Save the selected deviceID in the private structure for later loading. This will
permit moving the device selection into the main thread in a future commit.
Apparently it's only wine where the qpc_position returned by
IAudioClock_GetPosition can be overflowed. So actually do the rescaling
correctly, but throw away the result if it looks unreasonable.
this fixes a regression in 5afa68835a
Make sure that subtraction of performance counters is done correctly.
Follow the *exact* instructions for converting performance counter to something
comparable to the QPCposition returned by IAudioClient::GetPosition
https://msdn.microsoft.com/en-us/library/windows/desktop/dd370889%28v=vs.85%29.aspx
Also make sure that subtraction of unsigned integers is stored into a signed
integer to avoid nastiness. Also be more careful about overflow in the
conversion of the device position into number of samples.
Avoid casting mp_time_us() to a double, and use llrint to convert the
double precision delay_us back to integer for ao_read_data.
Finally, actually check the return value of ao_read_data and add a verbose
message if it is not the expected value. Unfortunately,
there is no way to tell WASAPI when this happens since the frame_count in
ReleaseBuffer must match GetBuffer.