This could trigger an assertion when using ao_alsa or ao_coreaudio. The
code was simply assuming the number of channel maps was bounded
statically (which was true at first in both AOs).
Fix by using dynamic memory allocation. It needs to be explicitly
enabled by the AOs by setting a temp context, because otherwise the
memory couldn't be freed. (Or at least this seems to be the most elegant
solution.)
Fixes#1306.
This seems safer: otherwise, opening the AO could randomly fail if the
audio formats happens to be not float.
Unfortunately, this only works if the user does not select a device.
Since ALSA devices are arbitrary strings, including plugins with complex
parameters, it's not trivial or maybe even impossible to edit the string
in a way the "plug" plugin is added.
With --audio-device, it would be safe for users to select either
"default" or one of the "plughw" devices. Everything else seems
questionable.
Use the ALSA channel map API for querying and selecting supported
channel maps.
Since we (probably?) want to be compatible with ALSA versions before the
change, we still try to select the device name by channel map, and open
that device. There's no way to negotiate a channel map before opening,
so we're stuck with this approach. Fortunately, it seems these devices
allow selecting and setting any other supported channel layout, so maybe
this is not an issue at all. In particular, this avoids selecting the
default (dmix) device, which can only do stereo.
Most code is based on Martin Herkt <lachs0r@srsfckn.biz>'s alsa_ng
branch, with heavy modifications.
Don't crash if no fallback channel layout could be found (caller can't
handle NULL return from select_chmap()). Apparently this could never
actually happen, though.
Don't treat snd_pcm_hw_params_set_periods_near() failure as fatal error.
Same deal as with snd_pcm_hw_params_set_buffer_time_near().
Actually free channel maps returned by snd_pcm_get_chmap().
Adjust some messages.
No functional changes.
ALSA_PCM_NEW_HW_PARAMS_API was a pre-ALSA 1.0.0 thing and does nothing
with modern ALSA. It stopped being necessary about 10 years ago.
3 functions are moved to avoid forward references.
If ALSA reports a channel map, and it looks like it makes sense (i.e.
could be converted to mpv channel map, and the channel count matches),
then use that instead of the channel map we are assuming.
This is based on code written by lachs0r (alsa_ng branch).
The caller set up the "start" pointer array using the number of planes,
the encode() function used the number of channels. This copied
uninitialized values for packed formats, which makes Coverity warn.
From what I understand the division is to align the dimension of the
value from seconds to milliseconds. Hard to tell whether the "rounding"
was intentional or not; I'm tipping on "not".
Found by Coverity.
When the audio thread fails to properly init, it signals failure
to the main thread, AND THEN starts to clean up. For this to work,
ao_init callback must not return until the thread's cleanup is finished.
This is correctly handled in the ao_uninit callback by waiting for
the thread to exit, so just call that to clean up the main thread.
I have no idea why I didn't do this in the first place.
dsound was set as default, because there were some hard to fix problems
with wasapi. These problems were probably fixed now, so let's try with
wasapi as default again.
Even with change notifications, there are still (rare) cases when the
feed thread gets AUDCLIENT_DEVICE_INVALIDATED. So handle failures in
thread_feed by requesting ao_reload.
on changes to PKEY_AudioEngine_DeviceFormat, device status, and default device.
call ao_reload directly in the change_notify "methods".
this requires keeping a device enumerator around for the duration of
execution, rather than just for initially querying devices
Implement skeleton IMMNotificationClient to watch for changes in the
sound device. This will make recovery possible from changes shared
mode sample rate, bit depth, "enhancements"/effects and even graceful
device removal.
http://msdn.microsoft.com/en-us/library/windows/desktop/dd371417%28v=vs.85%29.aspx
Signed-off-by: Kevin Mitchell <kevmitch@gmail.com>
Before, failures, particularly in the thread loop init, could lead to a
bad state for the duration of mpvs execution. Make sure that
everything that was initialized gets properly and safely
uninitialized.
When initialization failed, vo_lavc may cause an irrecoverable state in
the ffmpeg-related structs. Therefore, we reject additional
initialization attempts at least until we know a better way to clean up
the mess.
ao_lavc currently cannot be initialized more than once, yet it's good to
do consistent changes there as well.
Also, clean up uninit-after-failure handling to be less spammy.
The mp_audio_from_avframe() function requires the AVFrame to be
refcounted, and merely increases its refcount while referencing the same
data. For non-refcounted frames, it simply did nothing and potentially
would make the caller pass around a frame with dangling pointers.
(libavcodec should always return refcounted frames, but it's not clear
what other code does; and also the function should simply work, instead
of having weird requirements on its arguments.)