The previous RING_BUFFER_COUNT value, 64, would have ao_wasapi buffer 64
frames of audio in the ring buffer; a delay of 1280ms, which is clearly
overkill for everything. A value of 8 buffers 8 frames for a total of
160ms.
When get_space was converted to returning samples instead of bytes, a
unit type mismatch in get_delay's calculation returned bogus values. Fix
by converting get_space's value back to bytes.
Fixes playback with ao_wasapi when reaching EOF, or seeking past it.
There are some use cases for this. For example, you can use it to set
defaults of automatically inserted filters (like af_lavrresample). It's
also useful if you have a non-trivial VO configuration, and want to use
--vo to quickly change between the drivers without repeating the whole
configuration in the --vo argument.
This partially reverts commit 7d152965. It turns out that at least some
ALSA drivers (at least snd-hda-intel) report incorrect audio delay with
non-native sample rates, even if the sample rate is only very slightly
different from the native one.
For example, 48000Hz is fine on my hda-intel system, while both 8000Hz
and 47999Hz lead to a delay off by 40ms (according to mpv's A/V
difference display), which suggests that something in ALSA is
calculating the delay using the wrong sample rate.
As an additional problem, with ALSA resampling enabled, using
48001Hz/float/2ch fails, while 49000Hz/float/2ch or 48001Hz/s16/2ch
work. With resampling disabled, all these cases work obviously, because
our own resampler doesn't just refuse any of these formats.
Since some people want to use the ALSA resampler (because it's highly
configurable, supports multiple backends, etc.), we still allow enabling
ALSA resampling with an ao_alsa suboption.
Previous code was using the values of the AudioChannelLabel enum directly to
create the channel bitmap. While this was quite smart it was pretty unreadable
and fragile (what if Apple changes the values of those enums?).
Change it to use a 'dumb' conversion table.
The code stopped at kAudioChannelLabel_TopBackRight and missed mapping for
5 more channel labels. These are in a completely different order that the mpv
ones so they must be mapped manually.
Resampling with non-ancient ALSA setups works fine, so there is no
need to keep this around. Furthermore, as of writing, the default
builtin resampler used by many ALSA setups (taken from libspeex)
actually has higher quality than the default resampling modes of
avresample and swresample.
Simulate proper handling of AOPLAY_FINAL_CHUNK. Print when underruns
occur (i.e. running out of data). Add some options that control
simulated buffer and outburst sizes.
All this is useful for debugging and self-documentation. (Note that
ao_null always was supposed to simulate an ideal AO, which is the reason
why it fools people who try to use it for benchmarking video.)
This should allow it to select better fallback formats, instead of
picking the first encoder sample format if ao->format is not equal to
any of the encoder sample formats.
Not sure what is supposed to happen if the encoder provides no
compatible sample format (or no sample format list at all), but in this
case ao_lavc.c still fails gracefully.
These must be written even if there was no "final frame", e.g. due to
the player being exited with "q".
Although the issue is mostly of theoretical nature, as most audio codecs
don't need the final encoding calls with NULL data. Maybe will be more
relevant in the future.
ao_null should simulate a "perfect" AO, but framestepping behaved quite
badly with it. Framstepping usually exposes problems with AOs dropping
their buffers on pause, and that's what happened here.
Since ao_openal simulates multi-channel audio by placing a bunch of
mono-sources in 3D space, non-interleaved audio is a perfect match for
it. We just have to remove the interleaving code.
ALSA supports non-interleaved audio natively using a separate API
function for writing audio. (Though you have to tell it about this on
initialization.) ALSA doesn't have separate sample formats for this,
so just pretend to negotiate the interleaved format, and assume that
all non-interleaved formats have an interleaved companion format.
Replace the code that used a single buffer with mp_audio_buffer. This
also enables non-interleaved output operation, although it's still
disabled, and no AO supports it yet.
This comes with two internal AO API changes:
1. ao_driver.play now can take non-interleaved audio. For this purpose,
the data pointer is changed to void **data, where data[0] corresponds to
the pointer in the old API. Also, the len argument as well as the return
value are now in samples, not bytes. "Sample" in this context means the
unit of the smallest possible audio frame, i.e. sample_size * channels.
2. ao_driver.get_space now returns samples instead of bytes. (Similar to
the play function.)
Change all AOs to use the new API.
The AO API as exposed to the rest of the player still uses the old API.
It's emulated in ao.c. This is purely to split the commits changing all
AOs and the commits adding actual support for outputting N-I audio.
No AO can handle these, so it would be a problem if they get added
later, and non-interleaved formats get accepted erroneously. Let them
gracefully fall back to other formats.
Most AOs actually would fall back, but to an unrelated formats. This is
covered by this commit too, and if possible they should pick the
interleaved variant if a non-interleaved format is requested.
Now to shift audio pts when outputting to e.g. avi, you need an explicit
facility to insert/remove initial samples, to avoid initial regions of
the video to be sped up/slowed down.
One such facility is the delay filter in libavfilter.
Set the PulseAudio stream title, just like the VO window title is set.
Refactor update_vo_window_title() so that we can use it for AOs too.
The ao_pulse.c bit is stolen from MPlayer.
I have no idea what these do, but apparently they are needed to inform
ALSA about spdif configuration. First, replace the literal constant "6"
for the AES0 parameter with the symbolic constants from the ALSA
headers (the final value is the same). Second, copy paste some funky
looking parameter setup from VLC's alsa output for setting the AES1,
AES2, AES3 parameters. (The code is actually not literally copy-pasted,
but does exactly the same.)
My small but non-zero hope is that this could make DTS-HD work, or at
least work into that direction. I can't test spdif stuff though, and
for DTS-HD not even opening the ALSA device succeeds on my system.
Using spdif with alsa requires adding magic parameters to the device
name, and the existing code tried to deal with the situation when the
user wanted to add parameters too.
Rewrite this code, in particular remove the duplicated parameter string
as preparation for the next commit. The new code is a bit stricter, e.g.
it doesn't skip spaces before and after '{' and '}'. (Just don't add
spaces.)
ao_lavc.c accesses ao->buffer, which I consider internal. The access was
done in ao_lavc.c/uninit(), which tried to get the left-over audio in
order to write the last (possibly partial) audio frame. The play()
function didn't accept partial frames, because the AOPLAY_FINAL_CHUNK
flag was not correctly set, and handling it otherwise would require an
internal FIFO.
Fix this by making sure that with gapless audio (used with encoding),
the AOPLAY_FINAL_CHUNK is set only once, instead when each file ends.
Basically, move the hack in ao_lavc's uninit to uninit_player.
One thing can not be entirely correctly handled: if gapless audio is
active, we don't know really whether the AO is closed because the file
ended playing (i.e. we want to send the buffered remainder of the audio
to the AO), or whether the user is quitting the player. (The stop_play
flag is overwritten, fixing that is perhaps not worth it.) Handle this
by adding additional code to drain the AO and the buffers when playback
is quit (see play_current_file() change).
Test case: mpv avdevice://lavfi:sine=441 avdevice://lavfi:sine=441 -length 0.2267 -gapless-audio
The configure followed 5 different convetions of defines because the next guy
always wanted to introduce a new better way to uniform it[1]. For an
hypothetic feature 'hurr' you could have had:
* #define HAVE_HURR 1 / #undef HAVE_DURR
* #define HAVE_HURR / #undef HAVE_DURR
* #define CONFIG_HURR 1 / #undef CONFIG_DURR
* #define HAVE_HURR 1 / #define HAVE_DURR 0
* #define CONFIG_HURR 1 / #define CONFIG_DURR 0
All is now uniform and uses:
* #define HAVE_HURR 1
* #define HAVE_DURR 0
We like definining to 0 as opposed to `undef` bcause it can help spot typos
and is very helpful when doing big reorganizations in the code.
[1]: http://xkcd.com/927/ related
The code was selecting PA_CHANNEL_POSITION_MONO for MP_SPEAKER_ID_FC,
which is correct only with the "mono" channel layout, but not anything
else. Remove the mono entry, and handle mono separately.
See github issue #326.
It's true that ALSA uses alloca() in some of its API functions, but
since this is hidden behind macros in the ALSA headers, we have no
reason to include alloca.h ourselves.
Might help with portability (FreeBSD).
At least not with ffmpeg.
Honestly, I have no idea how little endian AC3 works at all, since
ao_pcm doesn't do anything special about it, and treats it like s16le.
Maybe it's broken and ffmpeg has special logic to detect it.
Was disabled by default, was never used, internal support was
inconsistent and poor, and there has been virtually no interest in
creating translations.
And I don't even think that a terminal program should be translated.
This is something for (hypothetical) GUIs.
Output silence to the output buffer during underruns. This removes small
occasional glitches that happen before the AUHAL is actually paused from the
`audio_pause` call.
Fixes#269
Trying to connect multiple mpv clients to JACK with the
JackUseExactName option would fail unless the user manually
specifies a unique client name. This changes the behavior
to automatically generate a unique name if the requested
one is already in use.
Use the new MP_ macros for some AOs instead of mp_msg.
Not all AOs are converted, and some only partially. In some cases, some
additional cosmetic changes are made.
Using the default output audio unit should provide a much better user
exeperience since it changes automatically the output device based on which
becomes the default one.
This was removed in d427b4fd. I now found a sample that causes underruns when
moving to a chapter and apparently this is also a problem when taking
screenshots.
Reverts one of the changes from 18777ecf. `kAudioObjectPropertyScopeOutput`
was introduced in the 10.8 SDK while `kAudioDevicePropertyScopeOutput` was
moved to `AudioHardwareDeprecated.h`. Since the deprecation is silent for now
(no warnings), just use the old constant.
Either way, they both evaluate to 'outp', and in the 10.8 SDK the deprecated
constant is defined in terms of the non-deprecated one.
Fixes#155
This is not done automatically by CoreAudio. I am told that it would a PITA
to have to switch back the format manually on the device (especially if the
same device is used for lpcm output).
b2f9e0610 introduced this functionality with code that was quite 'monolithic'.
Split the functionality over several functions and ose the new macros to get
array properties.
Introduce some macros to deal with properties. These allow to work around the
limitation of CoreAudio's API being `void **` based. The macros allow to keep
their client's code DRY, by not asking size and other details which can be
derived by the macro itself. I have no idea why Apple didn't design their API
like this in the first place.
* ao_coreaudio_utils: contains several utility function
* ao_coreaudio_properties: contains functions to set and get audio object
properties.
Conflicts:
audio/out/ao_coreaudio.c
The condition was checked wrongly on asbd which is the input format
description. This lead to the condition always being true, thus selecting lpcm
streams for digital input.
The initialization is split more clearly between compressed and lpcm case.
For the compressed case, format selection is simplified a lot and negotiation
removed. The way it was written it just passed back to the core the original
requested format, not what was found available on hardware.
Since this is most likely useless for the compressed case, I didn't bother
with this. In the future I'd like to split this AO in two one that only uses
the AUHAL and the other with direct access to the hardware so that even
passthrough of lcpm can be possible. This would decrease the latency,
audiophiles would like that.
Split out some utility functions that use the CoreAudio API but are not related
the main task of the AOs (which is to move data correctly to the ringbuffer).
These are mainly need for the verbosity of the CoreAudio API and are just
obscuring the 'real' code.
Read only the requested amount by the AUHAL (instead of all the buffered data).
No idea what the deal is with pausing the audio units if there is no audio to
play, maybe to avoid underruns of some sort. Anyway from my tests this
condition never occurred so I'm removing it all.
MSDN tells me to multiply the samplerates by 4 (for setting up the S/PDIF
signal frequency), but doesn't mention that I'm only supposed to do it
on the new, NT6.1+ IEC 61937 structs. Works on my Realtek Digital Output,
but as I can't connect any hardware to it I can't hear the result.
Also, always ask for little-endian AC3. I'm not sure if this is supposed
to be LE or NE, but Windows is LE on all platforms, so we go with LE.
Entirely untested as this troper has no S/PDIF hardware.
Refuses trying any other format if we can't use passthrough, or we would
end up sending white noise at the user.
Do an strstr match against the device description and, if we have only
a single match, take it. This works as long as the devices in the system
don't change, but it's not supposed to be reliable; if one wants
reliability, one uses the device ID string.
Formatting.
This could turn valid parameters into syntax errors by the mere presence
or abscence of a device (e.g. USB audio devices), so don't do that.
We do validate that, if the parameter is an integer, it is not negative.
We also respond to the "help" parameter, which does the same as the "list"
suboption but exits after listing.
Demote the validation logging to MSGL_DBG2.
Validates by trying to pick the device using the device enumerator and
aborting with out of range on failure.
Refactors find_and_load_device to not use the wasapi_state; it might be
called during validation. Adds missing CoInitialize/CoUninitialize calls.
Remove unused variables (the SAFE_RELEASE macros keep them referenced so
compiler warnings don't help finding them...).
Remove the IMMDeviceEnumerator from the wasapi_state, it's only needed
during initialization and initialization is now well factored enough to
get rid of it.
Try and connect to unplugged devices as well when using the device ID
string.
Omit "{0.0.0.00000000}." on devices that start with that substring,
re-add when searching for devices by ID.
Log the device ID of the default device.
Log the friendly name of the used device.
Consistently refer to endpoints/devices as devices, as this is more
consistent with mpv terminology.
Uses WASAPI in shared mode by default, add :exclusive flag to choose
exclusive mode (duh). WASAPI works somewhat different in shared mode:
the OS suggests the sample format to use, and the GetBuffer call is
done slightly differently.
The shared mode driver does not consume audio as fast as it notifies
the thread; we need to check how much we're allowed to write. Not doing
this correctly results in spamming the console with
AUDCLNT_E_BUFFER_TOO_LARGE errors.
When guessing formats for exclusive mode, try several sample size and
sample rate combinations instead of just falling back to s16le@44100hz.
If none of the rates are accepted, tries remixing >6 channels to 5.1
channels. Failing that, tries remixing to stereo. Failing everything,
including the CD Red Book format, what else is left to test?
Calculate buffer_block_size based on the configured channels and bytes
per sample; MSDN docs say nBlockAlign is not guaranteed to be set for
anything but integer PCM formats.
Adds the :list suboption to ao_wasapi0, which enumerates the audio endpoints
in the system.
Adds the :device=<n> suboption, which either takes an ID string (as output by
list) or a device number and uses the requested device instead of the system
default.
These two options were supported by ALSA and OSS only. Further, their
values were specific to the respective audio systems, so it doesn't make
sense to keep them as top-level options.