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.