Reduce from 1000ms to 100ms. Since there is an audio thread updating AOs
quickly enough now, requesting such a large buffer size makes no sense
anymore.
Use OPT_KEYVALUELIST() for all places where AVOptions are directly set
from mpv command line options. This allows escaping values, better
diagnostics (also no more "pal"), and somehow reduces code size.
Remove the old crappy option parser (av_opts.c).
Some ALSA plugins take non-interleaved audio, but treat it as
interleaved, which results in various funny bugs. Users keep hitting
this issue, and it just doesn't seem worth the trouble.
CC: @mpv-player/stable
It probably happens relatively often that the first packet (or even the
first N packets) of a stream will fail to decode, but decoding will
eventually succeed at a later point. Before commit 261506e3, this was
handled by an explicit retry loop (although this was also for other
purposes), but with then was changed to abort on the first error. This
makes it impossible to decode some audio streams.
Change this so that errors are ignored for the first 50 packets, which
should make it equivalent to the old code.
This commit makes audio decoding non-blocking. If e.g. the network is
too slow the playloop will just go to sleep, instead of blocking until
enough data is available.
For video, this was already done with commit 7083f88c. For audio, it's
unfortunately much more complicated, because the audio decoder was used
in a blocking manner. Large changes are required to get around this.
The whole playback restart mechanism must be turned into a statemachine,
especially since it has close interactions with video restart. Lots of
video code is thus also changed.
(For the record, I don't think switching this code to threads would
make this conceptually easier: the code would still have to deal with
external input while blocked, so these in-between states do get visible
[and thus need to be handled] anyway. On the other hand, it certainly
should be possible to modularize this code a bit better.)
This will probably cause a bunch of regressions.
Add an option that enables using native PulseAudio auto-updated timing
information, instead of the manual calculations added in mplayer2 times.
You can use --ao=pulse:no-latency-hacks to enable the new code. The code
is almost the same as the code that was removed with commit de435ed5,
but I didn't readd some bits I didn't understand. Likewise, the option
will disable the code added with that commit.
In my tests this seemed to work well, though the A/V sync display looks
funny when seeking.
The default is still the old behavior.
See issue #959.
This was needed by very old (0.9) versions only. Get rid of it.
Unfortunately, I can't cross-check with the original bug report, since
the bug URL leads to this:
Internal Server Error
TracError: IOError: [Errno 2] No such file or directory: '/home/lennart/svn/trac/pulseaudio/VERSION'
ao_null is used to stop autoprobing (if all AOs before fail to init).
After it come things like ao_pcm, which should never be automatically
selected.
Remove a certain theoretically possible failure case, and force "some"
fallback.
mp_make_wakeup_pipe() always fails on win32. If this call fails on Linux
(and e.g. ao_alsa is used), this will probably burn CPU since poll()
won't work on the invalid file descriptor, but whatever, the failure
case is obscure enough.
Accidentally broken in b6af44d3. For ad_lavc (and in general), the PTS
was not updated correctly when filtering only parts of audio frames,
and for ad_mpg123 and ad_spdif the PTS was additionally offset by the
frame size.
This could lead to incorrect time display, and possibly broken A/V sync.
Execute the format change based on whether we logically detected EOF
(after filters), instead of when the decode buffer was drained. It's
slightly cleaner. (The requirement of len>0 existed before.)
Don't return an EOF code if there's still buffered data.
Also, don't call demux_stream_eof() in the playloop. There's probably
nothing wrong with it, but it's cleaner not to use it.
Also give AD_EOF its own value, so that a decoding error doesn't drain
audio by causing an EOF condition.
Move a function call, which does not change semantics.
Write the extra buffer sample count in a more straight-forward way; the
old code was not meaningful in any way (anymore).
It's true that the decoder can successfully decode, but return no data
(for various reasons). We don't need to handle this specially, though.
We just let the decoder decode some more data. This doesn't increase the
danger of an endless loop either, because audio_decode() already calls
this function until enough is decoded.
This commit mainly moves the initial decoding of data (done to probe the
audio format) to generic code. This will make it easier to make audio
decoding non-blocking in a later commit.
This commit also changes how decoders return data: instead of having
them write the data into a prepared buffer, they return a reference to
an internal buffer (by setting dec_audio.decoded). This makes it
significantly easier to handle audio format changes, since the decoders
don't really need to care anymore.
If the decoder didn't set a samplerate, it was initialized from the
container samplerate.
This probably didn't make much sense, because it's passed to the
decoder on initialization (so it could definitely use it). It's an
artifact from commit 66a9eb57 (which removed some Matroska-specific non-
sense), and I've never seen it actually happen since it was made into a
warning. Just get rid of it.
There was confusion about what should go into audio pts calculation and
what not (mainly due to the audio push thread). This has been fixed by
using the playing - not written - audio pts (which properly takes into
account the ao's buffer), and incrementing the samples count only by the
amount of samples actually taken from the buffer (unfortunately this
now forces us to keep the lock too long for my taste).
The final goal is all mp_msg calls produce complete lines. We want this
because otherwise, race conditions could corrupt the terminal output,
and it's inconvenient for the client API too. This commit works towards
this goal. There's still code that has this not fixed yet, though.
Logic for this was missing from pull.c. For push.c it was missing if the
driver didn't support it. But even if the driver supported it (such as
with ao_alsa), strange behavior was observed by users. See issue #933.
Always check explicitly whether the AO is in paused mode, and if so,
don't drain.
Possibly fixes#933.
CC: @mpv-player/stable
There is no standard mechanism for detecting endianess. Doing it at
compile time in a portable way is probably hard. Doing it properly
with a configure check is probably hard too. Using the endian
definitions in <sys/types.h> (usually includes <endian.h>, which is
not available everywhere) works under circumstances, but the previous
commit broke it on OSX.
Ideally all code should be endian dependent, but that is not possible
due to the dependencies (such as FFmpeg, some video output APIs, some
audio output APIs).
Create a header osdep/endian.h, which contains various fallbacks.
Note that the last fallback uses libavutil; however, it's not clear
whether AV_HAVE_BIGENDIAN is a public symbol, or whether including
<libavutil/bswap.h> really makes it visible. And in fact we don't want
to pollute the namespace with libavutil definitions either. Thus it's
only the last fallback.
Doesn't work quite right, and will pause for the latency duration after
seeking. Some users use --ao=null to disable audio (even though they
should probably use --no-audio), and this use-case is broken by this
issue too.
CC: @mpv-player/stable
Previous code was completly wrong. This still doesn't report the device
latency, but we report the buffer latency (as before the AO refactoring) and
the AudioUnit's latency (this is a new 'feature').
Apparently we can also report the device actual latency and we should also
calculate the actual sample rate of the audio device instead of using the
nominal sample rate, but I'll leave this for a later commit.
The mplayer1/2/mpv CoreAudio audio output historically contained both usage
of AUHAL APIs (these go through the CoreAudio audio server) and the Device
based APIs (used only for output of compressed formats in exclusive mode).
The latter is a very unwieldy and low level API and pretty much forces us to
write a lot of code for little workr. Also with the widespread of HDMI, the
actual need for outputting compressed audio directly to the device is getting
lower (it was very useful with S/PDIF for bandwidth constraints not allowing
a number if channels transmitted in LPCM).
Considering how invasive it is (uses hog/exclusive mode), the new AO
(`ao_coreaudio_device`) is not going to be autoprobed but the user will have
to select it.
Something like "char *s = ...; isdigit(s[0]);" triggers undefined
behavior, because char can be signed, and thus s[0] can be a negative
value. The is*() functions require unsigned char _or_ EOF. EOF is a
special value outside of unsigned char range, thus the argument to the
is*() functions can't be a char.
This undefined behavior can actually trigger crashes if the
implementation of these functions e.g. uses lookup tables, which are
then indexed with out-of-range values.
Replace all <ctype.h> uses with our own custom mp_is*() functions added
with misc/ctype.h. As a bonus, these functions are locale-independent.
(Although currently, we _require_ C locale for other reasons.)
rgain is not an additive value. It's a multiplier/gain.
Previous behaviour produced negative level values in some cases
(when rgain < 1.0) which caused volume to be louder when its value
was lowered.
CC: @mpv-player/stable
Signed-off-by: Mohammad Alsaleh <CE.Mohammad.AlSaleh@gmail.com>
Signed-off-by: wm4 <wm4@nowhere>
While I'm not very fond of "const", it's important for declarations
(it decides whether a symbol is emitted in a read-only or read/write
section). Fix all these cases, so we have writeable global data only
when we really need.
So the device buffer can be refilled quickly. Fixes dropouts in certain
cases: if all data is moved from the soft buffer to the audio device
buffer, the waiting code thinks it has to enter the mode in which it
waits for new data from the decoder. This doesn't work, because the
get_space() logic tries to keep the total buffer size down. get_space()
will return 0 (or a very low value) because the device buffer is full,
and the decoder can't refill the soft buffer. But this means if the AO
buffer runs out, the device buffer can't be refilled from the soft
buffer. I guess this mess happened because the code is trying to deal
with both AOs with proper event handling, and AOs with arbitrary
behavior.
Unfortunately this increases latency, as the total buffered audio
becomes larger. There are other ways to fix this again, but not today.
Fixes#818.
Apparently this can happen. So actually only return from waiting if ALSA
excplicitly signals that new output is available, or if we are woken up
externally.
This did not flush remaining audio in the buffer correctly (in case an
AO has an internal block size). So we have to make the audio feed thread
to write the remaining audio, and wait until it's done.
Checking the avoid_ao_wait variable should be enough to be sure that all
data that can be written was written to the AO driver.
This code handles buggy AOs (even if all AOs are bug-free, it's good for
robustness). Move handling of it to the AO feed thread. Now this check
doesn't require magic numbers and does exactly what's it supposed to do.
Until now, we've always calculated a timeout based on a heuristic when
to refill the audio buffers. Allow AOs to do it completely event-based
by providing wait and wakeup callbacks.
This also shuffles around the heuristic used for other AOs, and there is
a minor possibility that behavior slightly changes in real-world cases.
But in general it should be much more robust now.
ao_pulse.c now makes use of event-based waiting. It already did before,
but the code for time-based waiting was also involved. This commit also
removes one awkward artifact of the PulseAudio API out of the generic
code: the callback asking for more data can be reentrant, and thus
requires a separate lock for waiting (or a recursive mutex).
There were subtle and minor race conditions in the pull.c code, and AOs
using it (jack, portaudio, sdl, wasapi). Attempt to remove these.
There was at least a race condition in the ao_reset() implementation:
mp_ring_reset() was called concurrently to the audio callback. While the
ringbuffer uses atomics to allow concurrent access, the reset function
wasn't concurrency-safe (and can't easily be made to).
Fix this by stopping the audio callback before doing a reset. After
that, we can do anything without needing synchronization. The callback
is resumed when resuming playback at a later point.
Don't call driver->pause, and make driver->resume and driver->reset
start/stop the audio callback. In the initial state, the audio callback
must be disabled.
JackAudio of course is different. Maybe there is no way to suspend the
audio callback without "disconnecting" it (what jack_deactivate() would
do), so I'm not trying my luck, and implemented a really bad hack doing
active waiting until we get the audio callback into a state where it
won't interfere. Once the callback goes from AO_STATE_WAIT to NONE, we
can be sure that the callback doesn't access the ringbuffer or anything
else anymore. Since both sched_yield() and pthread_yield() apparently
are not always available, use mp_sleep_us(1) to avoid burning CPU during
active waiting.
The ao_jack.c change also removes a race condition: apparently we didn't
initialize _all_ ao fields before starting the audio callback.
In ao_wasapi.c, I'm not sure whether reset really waits for the audio
callback to return. Kovensky says it's not guaranteed, so disable the
reset callback - for now the behavior of ao_wasapi.c is like with
ao_jack.c, and active waiting is used to deal with the audio callback.
In most places where af_fmt2bits is called to get the bits/sample, the
result is immediately converted to bytes/sample. Avoid this by getting
bytes/sample directly by introducing af_fmt2bps.
The i_bps members of the sh_audio and dev_video structs are mostly used
for displaying the average audio and video bitrates. Keeping them in
bits-per-second avoids truncating them to bytes-per-second and changing
them back lateron.
In my opinion, we shouldn't use atomics at all, but ok.
This switches the mpv code to use C11 stdatomic.h, and for compilers
that don't support stdatomic.h yet, we emulate the subset used by mpv
using the builtins commonly provided by gcc and clang.
This supersedes an earlier similar attempt by Kovensky. That attempt
unfortunately relied on a big copypasted freebsd header (which also
depended on much more highly compiler-specific functionality, defined
reserved symbols, etc.), so it had to be NIH'ed.
Some issues:
- C11 says default initialization of atomics "produces a valid state",
but it's not sure whether the stored value is really 0. But we rely on
this.
- I'm pretty sure our use of the __atomic... builtins is/was incorrect.
We don't use atomic load/store intrinsics, and access stuff directly.
- Our wrapper actually does stricter typechecking than the stdatomic.h
implementation by gcc 4.9. We make the atomic types incompatible with
normal types by wrapping them into structs. (The FreeBSD wrapper does
the same.)
- I couldn't test on MinGW.
Use the time as returned by mp_time_us() for mpthread_cond_timedwait(),
instead of calculating the struct timespec value based on a timeout.
This (probably) makes it easier to wait for a specific deadline.
This didn't quite work. The main issue was that get_space tries to be
clever to reduce overall buffering, so it will cause the playloop to
decode and queue only as much audio as is needed to refill the AO in
reasonable time. Also, even if ignoring the problem, the logic of the
previous commit was slightly broken. (This required a few retries,
because I couldn't reproduce the issue on my own machine.)
When the audio buffer went low, but could not be refilled yet, it could
happen that the AO playback thread and the decode thread could enter a
wakeup feedback loop, causing up to 100% CPU usage doing nothing. This
happened because the decoder thread would wake up the AO thread when
writing 0 bytes of newly decoded data, and the AO thread in reaction
wakes up the decoder thread after writing 0 bytes to the AO buffer.
Fix this by waking up the decoder thread only if data was actually
played or queued. (This will still cause some redundant wakeups, but
will eventually settle down, reducing CPU usage close to ideal.)
I don't think this is really a very good idea because it is conceptually
incorrect but other prominent multimedia programs use this approach
(VLC and xbmc), and it seems to make the conversion more robust in certain
cases.
For example it has been reported, that configuring a receiver that can output
7.1 to output 5.1, will make CoreAudio report 8 channel descriptions, and the
last 2 descriptions will be tagged kAudioChannelLabel_Unknown.
Fixes#737
The code was falling back to the full waveext chmap_sel when less than 2
channels were detected. This new code is slightly more correct since it only
fills the chmap_sel with the stereo or mono chmap in the fallback case.
CoreAudio supports 3 kinds of layouts: bitmap based, tag based, and speaker
description based (using either channel labels or positional data).
Previously we tried to convert everything to bitmap based channel layouts,
but it turns out description based ones are the most generic and there are
built-in CoreAudio APIs to perform the conversion in this direction.
Moreover description based layouts support waveext extensions (like SDL and
SDR), and are easier to map to mp_chmaps.
Changing --softvol-max and then resuming would change the volume level
on resume to something different than the original volume. This is
because the user volume setting is always between 0-100, and 100
corresponds to --softvol-max gain.
Avoid that changing -softvol-max and resuming an older file could lead
to a too loud volume level by refusing to restore if --softvol-max
changed.
The comment says that it wakes up the main thread if 50% has been
played, but in reality the value was 0.74/2 => 37.5%. Correct this. This
probably changes little, because it's a very fuzzy heuristic in the
first place.
Also move down the min_wait calculation to where it's actually used.
Also remove MSGL_SMODE and friends.
Note: The indent in options.rst was added to work around a bug in
ReportLab that causes the PDF manual build to fail.
This avoids too many realloc() calls if the caller is appending to an
audo buffer. This case is actually quite noticeable when using something
that buffers a large amount of audio.
For some reason, the buffered_audio variable was used to "cache" the
ao_get_delay() result. But I can't really see any reason why this should
be done, and it just seems to complicate everything.
One reason might be that the value should be checked only if the AO
buffers have been recently filled (as otherwise the delay could go low
and trigger an accidental EOF condition), but this didn't work anyway,
since buffered_audio is set from ao_get_delay() anyway at a later point
if it was unset. And in both cases, the value is used _after_ filling
the audio buffers anyway.
Simplify it. Also, move the audio EOF condition to a separate function.
(Note that ao_eof_reached() probably could/should whether the last
ao_play() call had AOPLAY_FINAL_CHUNK set to avoid accidental EOF on
underflows, but for now let's keep the code equivalent.)
This was reported with PulseAudio 2.1. Apparently it still has problems
with reporting the correct delay. Since ao_pulse.c still has our custom
get_delay implementation, there's a possibility that this is our fault,
but this seems unlikely, because it's full of workarounds for issues
like this. It's also possible that this problem doesn't exist on
PulseAudio 5.0 anymore (I didn't explicitly retest it).
The check is general and works for all push based AOs. For pull based
AOs, this can't happen as pull.c implements all the logic correctly.
This should probably be an AO function, but since the playloop still has
some strange stuff (using the buffered_audio variable instead of calling
ao_get_delay() directly), just leave it and make it more explicit.
This collects statistics and other things. The option dumps raw data
into a file. A script to visualize this data is included too.
Litter some of the player code with calls that generate these
statistics.
In general, this will be helpful to debug timing dependent issues, such
as A/V sync problems. Normally, one could argue that this is the task of
a real profiler, but then we'd have a hard time to include extra
information like audio/video PTS differences. We could also just
hardcode all statistics collection and processing in the player code,
but then we'd end up with something like mplayer's status line, which
was cluttered and required a centralized approach (i.e. getting the data
to the status line; so it was all in mplayer.c). Some players can
visualize such statistics on OSD, but that sounds even more complicated.
So the approach added with this commit sounds sensible.
The stats-conv.py script is rather primitive at the moment and its
output is semi-ugly. It uses matplotlib, so it could probably be
extended to do a lot, so it's not a dead-end.
Same change as in e2184fcb, but this time for pull based AOs. This is
slightly controversial, because it will make a fast syscall from e.g.
ao_jack. And according to JackAudio developers, syscalls are evil and
will destroy realtime operation. But I don't think this is an issue at
all.
Still avoid locking a mutex. I'm not sure what jackaudio does in the
worst case - but if they set the jackaudio thread (and only this thread)
to realtime, we might run into deadlock situations due to priority
inversion and such. I'm not quite sure whether this can happen, but I'll
readily follow the cargo cult if it makes hack happy.
I'm not quite sure why ao_pulse needs this. It was broken when a thread
to fill audio buffers was added to AO - the pulseaudio callback was
waking up the playback thread, not the audio thread. But nobody noticed,
so it can't be very important. In any case, this change makes it wake up
the audio thread instead (which in turn wakes up the playback thread if
needed).
And also add a function ao_need_data(), which AO drivers can call if
their audio buffer runs low.
This change intends to make it easier for the playback thread: instead
of making the playback thread calculate a timeout at which the audio
buffer should be refilled, make the push.c audio thread wakeup the core
instead.
ao_need_data() is going to be used by ao_pulse, and we need to
workaround a stupid situation with pulseaudio causing a deadlock because
its callback still holds the internal pulseaudio lock.
For AOs that don't call ao_need_data(), the deadline is calculated by
the buffer fill status and latency, as before.
I hate tabs.
This replaces all tabs in all source files with spaces. The only
exception is old-makefile. The replacement was made by running the
GNU coreutils "expand" command on every file. Since the replacement was
automatic, it's possible that some formatting was destroyed (but perhaps
only if it was assuming that the end of a tab does not correspond to
aligning the end to multiples of 8 spaces).
Also fix a format string mistake in a log call using it.
I wonder if this code shouldn't use FormatMessage, but it looks kind
of involved [1], so: no, thanks.
[1] http://support.microsoft.com/kb/256348/en-us
This was accidentally broken in commit b72ba3f7. I somehow made the
wild assumption that replaygain adjusted the volume relative to 0%
instead of 100%.
The detach suboption was similarly broken.
Set refcounted_frames, because in some versions of libavcodec mixing the
new AVFrame API and non-refcounted decoding could cause memory
corruption. Likewise, it's probably still required to unref a frame
before calling the decoder.
Maybe this should be default. On the other hand, this filter does
something even if the volume is neutral: it clips samples against the
allowed range, should the decoder or a previous filter output garbage.
Currently, both replaygain adjustment and user volume control (if
softvol is enabled) share the same variable. Sharing the variable would
cause especially if --volume is used; then the replaygain volume would
always be overwritten.
Now both gain values are simple added right before doing filtering.
This adds the options replaygain-track and replaygain-album. If either is set,
the replaygain track or album gain will be automatically read from the track
metadata and the volume adjusted accordingly.
This only supports reading REPLAYGAIN_(TRACK|ALBUM)_GAIN tags. Other formats
like LAME's info header would probably require support from libav.
The main incompatibility was that Libav didn't have av_opt_set_int_list.
But since that function is excessively ugly and idiotic (look how it
handles types), I'm not missing it much. Use an aformat filter instead
to handle the functionality that was indirectly provided by it. This is
similar to how vf_lavfi works.
The other incompatibility was channel handling. Libav consistently uses
channel layouts only, why ffmpeg still requires messing with channel
counts to some degree. Get rid of most channel count uses (and hope
channel layouts are "exact" enough). Only in one case FFmpeg fails with
a runtime check if we feed it AVFrames with channel count unset.
Another issue were AVFrame accessor functions. FFmpeg introduced these
for ABI compatibility with Libav. I refuse to use them, and it's not my
problem if FFmpeg doesn't manage to provide a stable ABI for fields
provided both by FFmpeg and Libav.
The volume controls in mpv now affect the session's volume (the
application's volume in the mixer). Since we do not request a
non-persistent session, the volume and mute status persist across mpv
invocations and system reboots.
In exclusive mode, WASAPI doesn't have access to a mixer so the endpoint
(sound card)'s master volume is modified instead. Since by definition
mpv is the only thing outputting audio in exclusive mode, this causes no
conflict, and ao_wasapi restores the last user-set volume when it's
uninitialized.
Due to the COM Single-Threaded Apartment model, the thread owning the
objects will still do all the actual method calls (in the form of
message dispatches), but at least this will be COM's problem rather than
having to set up several handles and adding extra code to the event
thread.
Since the event thread still needs to own the WASAPI handles to avoid
waiting on another thread to dispatch the messages, the init and uninit
code still has to run in the thread.
This also removes a broken drain implementation and removes unused
headers from each of the files split from the original ao_wasapi.c.
ao_wasapi.c was almost entirely init code mixed with option code and
occasionally actual audio handling code. Split most things to
ao_wasapi_utils.c and keep the audio handling code in ao_wasapi.c.
Gets rid of the internal ring buffer and get_buffer. Corrects an
implementation error in thread_reset.
There is still a possible race condition on reset, and a few refactors
left to do. If feasible, the thread that handles everything
WASAPI-related will be made to only handle feed events.
Assume obtained.samples contains the number of samples the SDL audio
callback will request at once. Then make sure ao.c will set the buffer
size at least to 3 times that value (or more).
Might help with bad SDL audio backends like ESD, which supposedly uses a
500ms buffer.
In general, we don't need to have a large hw audio buffer size anymore,
because we can quickly fill it from the soft buffer.
Note that this probably doesn't change much anyway. On my system (dmix
enabled), the buffer size is only 170ms, and ALSA won't give more. Even
when using a hardware device the buffer size seems to be limited to
341ms.
This AO pretended to support volume operations when in spdif passthrough
mode, but actually did nothing. This is wrong: at least the GET
operations must write their argument. Signal that volume is unsupported
instead.
This was probably a hack to prevent insertion of volume filters or so,
but it didn't work anyway, while recovering after failed volume filter
insertion does work, so this is not needed at all.
Since the addition of the AO feed thread, 200ms of latency (MIN_BUFFER)
was added to all push-based AOs. This is not so nice, because even AOs
with relatively small buffering (e.g. ao_alsa on my system with ~170ms
of buffer size), the additional latency becomes noticable when e.g.
toggling mute with softvol.
Fix this by trying to keep not only 200ms minimum buffer, but also 200ms
maximum buffer. In other words, never buffer beyond 200ms in total. Do
this by estimating the AO's buffer fill status using get_space and the
initially known AO buffer size (the get_space return value on
initialization, before any audio was played). We limit the maximum
amount of data written to the soft buffer so that soft buffer size and
audio buffer size equal to 200ms (MIN_BUFFER).
To avoid weird problems with weird AOs, we buffer beyond MIN_BUFFER if
the AO's get_space requests more data than that, and as long as the soft
buffer is large enough.
Note that this is just a hack to improve the latency. When the audio
chain gains the ability to refilter data, this won't be needed anymore,
and instead we can introduce some sort of buffer replacement function in
order to update data in the soft buffer.
It is possible to have ao->reset() called between ao->pause() and
ao->resume() when seeking during the pause. If the underlying PCM
supports pausing, resuming an already reset PCM will produce an error.
Avoid that by explicitly checking PCM state before calling
snd_pcm_pause().
Signed-off-by: wm4 <wm4@nowhere>
The uint64_t math would cause overflow at long enough system uptimes
(...such as 3 days), and any precision error given by the double math will
be under one milisecond.
One strange issue is that we apparently can't stop the audio API on
audio reset (ao_driver.reset). We could use SDL_PauseAudio, but that
doesn't specify whether remaining audio is dropped. We also could use
SDL_LockAudio, but holding that over a long time will probably be bad,
and it probably doesn't drop audio. This means we simply play silence
after a reset, instead of stopping the callback completely. (The
existing code ran into an underrun in this situation.)
The delay estimation works about the same. We simply assume that the
callback is locked to audio timing (like ao_jack), and that 1 callback
corresponds to 1 period. It seems this (removed) code fragment assumes
there 1 one period size delay:
// delay subcomponent: remaining audio from the next played buffer, as
// provided by the callback
buffer_interval += callback_interval;
so we explicitly do that too.
Until now, this was always conflated with uninit. This was ugly, and
also many AOs emulated this manually (or just ignored it). Make draining
an explicit operation, so AOs which support it can provide it, and for
all others generic code will emulate it.
For ao_wasapi, we keep it simple and basically disable the internal
draining implementation (maybe it should be restored later).
Tested on Linux only.
Same deal as with the previous commit. We don't lose any functionality,
except for waiting "properly" on audio end, instead of waiting using the
delay estimate.
This removes the ringbuffer management from the code, and uses the
generic code added with the previous commit. The result should be
pretty much the same.
The "estimate" sub-option goes away. This estimation is now always
active. The new code for delay estimation is slightly different, and
follows the claim of the jack framework that callbacks are timed
exactly.
This has 2 goals:
- Ensure that AOs have always enough data, even if the device buffers
are very small.
- Reduce complexity in some AOs, which do their own buffering.
One disadvantage is that performance is slightly reduced due to more
copying.
Implementation-wise, we don't change ao.c much, and instead "redirect"
the driver's callback to an API wrapper in push.c.
Additionally, we add code for dealing with AOs that have a pull API.
These AOs usually do their own buffering (jack, coreaudio, portaudio),
and adding a thread is basically a waste. The code in pull.c manages
a ringbuffer, and allows callback-based AOs to read data directly.
Since the AO will run in a thread, and there's lots of shared state with
encoding, we have to add locking.
One case this doesn't handle correctly are the encode_lavc_available()
calls in ao_lavc.c and vo_lavc.c. They don't do much (and usually only
to protect against doing --ao=lavc with normal playback), and changing
it would be a bit messy. So just leave them.