stdatomic.h defines no atomic_float typedef. We can't just use _Atomic
unconditionally, because we support compilers without C11 atomics. So
just create a custom atomic_float typedef in the wrapper, which uses
_Atomic in the C11 code path.
This does what af_volume used to do. Since we couldn't relicense it,
just rewrite it. Since we don't have a new filter mechanism yet, and the
libavfilter is too inconvenient, do applying the volume gain in ao.c
directly. This is done before handling the audio data to the driver.
Since push.c runs a separate thread, and pull.c is called asynchronously
from the audio driver's thread, the volume value needs to be
synchronized. There's no existing central mutex, so do some shit with
atomics. Since there's no atomic_float type predefined (which is at
least needed when using the legacy wrapper), do some nonsense about
reinterpret casting the float value to an int for the purpose of atomic
access. Not sure if using memcpy() is undefined behavior, but for now I
don't care.
The advantage of not using a filter is lower complexity (no filter auto
insertion), and lower latency (gain processing is done after our
internal audio buffer of at least 200ms).
Disavdantages include inability to use native volume control _before_
other filters with custom filter chains, and the need to add new
processing for each new sample type.
Since this doesn't reuse any of the old GPL code, nor does indirectly
rely on it, volume and replaygain handling now works in LGPL mode.
How to process the gain is inspired by libavfilter's af_volume (LGPL).
In particular, we use exactly the same rounding, and we quantize
processing for integer sample types by 256 steps. Some of libavfilter's
copyright may or may not apply, but I think not, and it's the same
license anyway.
Looks like this is covered by LGPL relicensing agreements now.
Notes about contributors who could not be reached or who didn't agree:
Commit 7fccb6486e has tons of mp_msg changes look like they are not
copyrightable (even if they were, all mp_msg calls were rewritten in
mpv times again). The additional play() change looks suspicious, but
the function was rewritten several times anyway (first time after that
commit in 4f40ec312).
Commit 89ed1748ae was rewritten in commit 325311af3 and then again
several times after that. Basically all this code is unnecessary in
modern mpv and has been removed.
No code survived from the following commits: 4d31c3c53, 61ecf838f2,
d38968bd, 4deb67c3f. At least two cosmetic typo fixes are not
considered as well.
Commit 22bb046ad is reverted (this wasn't a valid warning anyway, just
a C++-ism icc applied to C). Using the constants is nicer, but at least
I don't have to decide whether that change was copyrightable.
I _think_ this confuses Coverity and it thinks there is uninitialized
data to be read. Initialize the array to change/remove the warning, or
if there's a real problem, to make it easier to detect. (Basically apply
defensive coding.)
This should actually cover all of them, if you take into account that
some unchanged GPL source files include header files with such checks.
Also this was done already for the libaf derived code.
This is only for "safety" and to avoid misunderstandings.
Just reimplement it in some way, as mp_audio is GPL-only.
Actually I wanted to get rid of audio_buffer.c completely (and instead
have a list of mp_aframes), but to do so would require rewriting some
more player core audio code. So to get this LGPL relicensing over
quickly, just do some extra work.
Completely untested (rsound dev libs unavailable on my system). Trivial
enough that it's very likely that it'll just work. No port selection,
but could be added by parsing it as part of the device name.
Should fix#4714.
This is pretty pointless, but I believe it allows us to claim that the
new code is not affected by the copyright of the old code. This is
needed, because the original mp_audio struct was written by someone who
has disagreed with LGPL relicensing (it was called af_data at the time,
and was defined in af.h).
The "GPL'ed" struct contents that surive are pretty trivial: just the
data pointer, and some metadata like the format, samplerate, etc. - but
at least in this case, any new code would be extremely similar anyway,
and I'm not really sure whether it's OK to claim different copyright. So
what we do is we just use AVFrame (which of course is LGPL with 100%
certainty), and add some accessors around it to adapt it to mpv
conventions.
Also, this gets rid of some annoying conventions of mp_audio, like the
struct fields that require using an accessor to write to them anyway.
For the most part, this change is only dumb replacements of mp_audio
related functions and fields. One minor actual change is that you can't
allocate the new type on the stack anymore.
Some code still uses mp_audio. All audio filter code will be deleted, so
it makes no sense to convert this code. (Audio filters which are LGPL
and which we keep will have to be ported to a new filter infrastructure
anyway.) player/audio.c uses it because it interacts with the old filter
code. push.c has some complex use of mp_audio and mp_audio_buffer, but
this and pull.c will most likely be rewritten to do something else.
Any bad HRESULTs should have been printed already and lots of failure modes
don't have an HRESULT leading to awkward hr = E_FAIL business.
This also checks the exit status of GetBufferSize in the align hack. A final
fatal message is added if either of the retry hacks fail.
Previously, the entire convert_buffer was being copied to the desination without
regard to the fact that it may be packed and therefore smaller.
The allocated conversion buffer was also way to big
bytes * (channels * samples) ** 2
instead of
bytes * channels * samples
This shouldn't affect which are chosen, but it should speed up the search by
putting more common configurations earlier so that a working sample format and
sample rates can be found sooner obviating the need to search them for each
iteration of the outer loops.
The loop to select the native wasapi_format for the incoming audio was
not breaking correctly when it found the most desirable format. It
therefore executed completely leaving the least desirable format (u8) as
the choice.
fixes#4582
I'd actually be somewhat interested in supporting this, as it could help
testing the S24 conversion code. But then again it's only a pain,
there's no immediate need, and it would require new options to make
ao_pcm.c select this output format at all.
Do conversion directly, using the infrastructure that was added before.
This also rewrites part of format negotation, I guess.
I couldn't test the format that was used for S24 - my hardware does not
report support for it. So I commented it, as it could be buggy. Testing
this with the wasapi_formats[] entry for 24/24 uncommented would be
appreciated.
Instead of the infrastructure added in the previous commit to do the
conversion within the AO.
If this is used, and snd_pcm_status_get_avail() returns more frames than
snd_pcm_write*() actually accepts, you will get some nice audio
corruption.
Also, this mutates the data passed via play(), which is rather fishy,
but sort of doesn't matter for now. Surely this will cause unintended
bugs and WTFs.
I plan to remove the S24 sample formats in mpv. It seems like we should
still support this _somehow_ in AOs though. So the idea is to convert
the data to more obscure representations (that would not be useful for
filtering etc. anyway) within the AO.
This commit adds helper to enable this. ao_convert_fmt is meant to
provide mechanisms for this, rather than a generic audio format
description (as the latter leads only to overly generic misery). The
conversion also supports only cases which we think will be needed at
all.
The main advantage of this approach is that we get S24 out of sight,
and that we could support other crazy formats (like S20). The main
disadvantage is that usually S32 will be selected (if both S32 and S24
are available), and there's no user control to force S24. That doesn't
really matter though, and at worst makes testing harder or will lead
to unpleasant arguments with audiophiles (they'd be wrong anyway).
ao_convert_fmt.pad_lsb is ignored, although if we ever find a case in
which playing S32 with data in the LSBs breaks when playing it as padded
24 bit format. (For example, WAVEFORMATEXTENSIBLE recommends setting the
unused bits to 0 if wValidBitsPerSample implies LSB padding.)
UWP does not support the whole IMMDevice API. Instead, you need to use a
new API (available starting from Windows 8), which is in addition not in
MinGW, and extremely unpleasant to use.
The wasapiuwp2.dll wrapper is a small custom MSVC DLL, which does this
instead, and returns a normal IAudioClient.
Before this, ao_wasapi did not initialize on UWP.
While this is perfectly OK on Unix, it causes annoying valgrind
warnings, and might be otherwise confusing to others.
On Windows, the runtime can actually abort the process if this is
called.
push.c part taken from a patch by Pedro Pombeiro.
The code accounting for the terrible AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED
semantics (which MSDN claims can happen "starting with Windows 7" - so
probably on Windows 10 too) duplicated the call for creating the
IAudioClient. That's not great, so get rid of it.
Let wasapi_thread_init() handle this. It has a retry loop anyway. This
redoes device lookup and format negotiation, but potential failures due
to race conditions (what if the driver decides to change behavior)
shouldn't be worse than before.
Before this change, AOs could have internal alignment, and play() would
not consume the trailing data if the size passed to it is not aligned.
Change this to require AOs to report their alignment (via period_size),
and make sure to always send aligned data.
The buffer reported by get_space() now always has to be correct and
reliable. If play() does not consume all data provided (which is bounded
by get_space()), an error is printed.
This is preparation for potential further AO changes.
I casually checked alsa/lavc/null/pcm, the other AOs might or might not
work.
Right now, the current order pretty much means that pulse defaults to
S16 for arbitrary unsupported formats, but fallback to float would make
more sense since it's the easiest to convert everything to without
requiring dithering, and PA will probably just internally convert things
to float anyway.
Also move S32 above S16, which essentially means format_maps is sorted
by preference. (Although ao_pulse currently ignores this and always
picks the first as a fallback)
The user bugmen0t was apparently a shared github account with publicly
available login. Thus, we can't get LGPL relicensing permission from the
people who used this account. To relicense successfully, we have to
remove all their changes.
This commit should remove 20d1fc13, f26fb009, defbe48d. It also should
remove whatever test fragments were copied from the ancient configure,
as well as some configure logic (potentially that device path stuff).
I think this change still preserves the most important use-cases of OSS:
BSDs, and the Linux OSS emulation (the latter for testing only).
According to an OSS user, the 4front checks were probably broken anyway.
The SunAudio stuff was probably for (Open)Solaris, which is dead.
ao_oss.c itself will remain GPL, and still contains bugmen0t changes.
All relevant authors have agreed to the relicensing.
Problem cases:
eca47b1a5e: someone else gets credited for the "idea" of this change,
but it doesn't seem like it was a patch (otherwise reimar would have
said "patch"). Also, the associated code got essentially removed again
anyway. (The option parsing was rewritten fully.)
ffb529e4eb: anonymous/unknown author, but the code was fully removed
anyway. The struct was removed, and the modern code does explicit
read/write calls.
40789473d2: author was not contacted, but this code was removed
anyway. The magic number (0x7ffff000) is still in the new code, but I
don't think that is copyright relevant.
c750b8ab2d: the message was entirely removed.
All contributors of the current code have agreed. ao.c requires a
"driver" entry for each audio output - we assume that if someone who
didn't agree to LGPL added a line, it's fine for ao.c to be LGPL
anyway. If the affected audio output is not disabled at compilation
time, the resulting binary will be GPL anyway, and ootherwise the
code is not included.
The audio output code itself was inspired or partially copied from
libao in 7a2eec4b59 (thus why MPlayer's audio code is named libao2).
Just to be sure we got permission from Aaron Holtzman, Jack Moffitt, and
Stan Seibert, who according to libao's SVN history and README are the
initial author. (Something similar was done for libvo, although the
commit relicensing it forgot to mention it.)
242aa6ebd4: anders mostly disagreed with the LGPL relicensing, but we
got permission for this particular commit.
0ef8e55573: nick could not be reached, but the include statement was
removed again anyway.
879e05a7c1: iive agreed to LGPL v3+ only, but this line of code was
removed anyway, so ao_null.c can be LGPL v2.1+.
9dd8f241ac: patch author could not be reached, but the corresponding
code (old slave mode interface) was completely removed later.