summaryrefslogtreecommitdiffstats
path: root/audio/out/pull.c
Commit message (Collapse)AuthorAgeFilesLines
* audio: merge pull/push ring buffer glue codewm42020-05-251-340/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is preparation to further cleanups (and eventually actual improvements) of the audio output code. AOs are split into two classes: pull and push. Pull AOs let an audio callback of the native audio API read from a ring buffer. Push AOs expose a function that works similar to write(), and for which we start a "feeder" thread. It seems making this split was beneficial, because of the different data flow, and emulating the one or other in the AOs directly would have created code duplication (all the "pull" AOs had their own ring buffer implementation before it was cleaned up). Unfortunately, both types had completely separate implementations (in pull.c and push.c). The idea was that little can be shared anyway. But that's very annoying now, because I want to change the API between AO and player. This commit attempts to merge them. I've moved everything from push.c to pull.c, the trivial entrypoints from ao.c to pull.c, and attempted to reconcile the differences. It's a mess, but at least there's only one ring buffer within the AO code now. Everything should work mostly the same. Pull AOs now always copy the audio data under a lock; before this commit, all ring buffer access was lock-free (except for the decoder wakeup callback, which acquired a mutex). In theory, this is "bad", and people obsessed with lock-free stuff will hate me, but in practice probably won't matter. The planned change will probably remove this copying-under-lock again, but who knows when this will happen. One change for the push AOs now makes it drop audio, where before only a warning was logged. This is only in case of AOs or drivers which exhibit unexpected (and now unsupported) behavior. This is a risky change. Although it's completely trivial conceptually, there are too many special cases. In addition, I barely tested it, and I've messed with it in a half-motivated state over a longer time, barely making any progress, and finishing it under a rush when I already should have been asleep. Most things seem to work, and I made superficial tests with alsa, sdl, and encode mode. This should cover most things, but there are a lot of tricky things that received no coverage. All this text means you should be prepared to roll back to an older commit and report your problem.
* audio: slightly simplify pull underrun message printingwm42020-02-131-15/+6
| | | | | | | | | | | | | | | A previous commit moved the underrun reporting to report_underruns(), and called it from get_space(). One reason was that I worried about printing a log message from a "realtime" callback, so I tried to move it out of the way. (Though there's little justification other than a bad feeling. While an older version of the pull code tried to avoid any mutexes at all in the callback to accommodate "requirements" from APIs like jackaudio, we gave up on that. Nobody has complained yet.) Simplify this and move underrun reporting back to the callback. But instead of printing the message from there, move the message into the playloop. Change the message slightly, because ao->log is inaccessible, and without the log prefix (e.g. "[ao/alsa]"), some context is missing.
* player: consider audio buffer if AO driver does not report underrunswm42020-02-131-10/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | AOs can report audio underruns, but only ao_alsa and ao_sdl (???) currently do so. If the AO was marked as not reporting it, the cache state was used to determine whether playback was interrupted due to slow input. This caused problems in some cases, such as video with very low video frame rate: when a new frame is displayed, a new frame has to be decoded, and since there it's so much further into the file (long frame durations), the cache gets into an underrun state for a short moment, even though both audio and video are playing fine. Enlarging the audio buffer didn't help. Fix this by making all AOs report underruns. If the AO driver does not report underruns, fall back to using the buffer state. pull.c behavior is slightly changed. Pull AOs are normally intended to be used by pseudo-realtime audio APIs that fetch an audio buffer from the API user via callback. I think it makes no sense to consider a buffer underflow not an underrun in any situation, since we return silence to the reader. (OK, maybe the reader could check the return value? But let's not go there as long as there's no implementation.) Remove the flag from ao_sdl.c, since it just worked via the generic mechanism. Make the redundant underrun message verbose only. push.c seems to log a redundant underflow message when resuming (because somehow ao_play_data() is called when there's still no new data in the buffer). But since ao_alsa does its own underrun reporting, and I only use ao_alsa, I don't really care. Also in all my tests, there seemed to be a rather high delay until the underflow was logged (with audio only). I have no idea why this happened and didn't try to debug this, but there's probably something wrong somewhere. This commit may cause random regressions. See: #7440
* audio/out/pull, ao_sdl: implement new underrun reportingwm42019-10-111-2/+7
| | | | | | | | | | | | | | | | See previous commits. ao_sdl is worthless, but it might be a good test for pull-based AOs. This stops using the old underrun reporting if the new one is enabled. Also, since the AO's behavior can in theory not be according to expectations, this needs to be enabled for every single pull AO separately. For some reason, in certain cases I get multiple underrun warnings while cache-pausing is active. It fills the cache, restarts the AO, immediately underruns again, and then fills the cache again. I'm not sure why this happens; maybe ao_sdl tries to catch up when it shouldn't. Who knows.
* audio/out/pull: fix underflow reportingwm42019-10-111-2/+2
| | | | | | | | I think this was _always_ wrong. Due to the line above the first changed line, buffered_bytes==bytes always. I can only hope I broke this in a less under-tested edit when I originally wrote this. Fixes: c5a82f729bd097
* audio: add audio softvol processing to AOwm42017-11-291-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* audio/out: initialize an array to avoid confusing static analyzerwm42017-10-271-1/+1
| | | | | | | 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.)
* audio/out: correct copy length in ao_read_data_convertedKevin Mitchell2017-07-091-6/+7
| | | | | | | | | | | | | 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
* audio/out: add helper code to do 24 bit conversion in AOwm42017-07-071-0/+45
| | | | | | | | | | | | | | | | | | | | | | | | | 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.)
* audio/out/pull: detect and log underflowswm42017-06-281-0/+20
| | | | Mostly for debugging, I guess.
* audio: fix --audio-stream-silence with ao_wasapiwm42016-11-211-2/+4
| | | | | Seems like wasapi will restart the HDMI stream if resume is called during playback.
* player, ao, vo: don't call mp_input_wakeup() directlywm42016-09-161-1/+1
| | | | | | | | | | | | | Currently, calling mp_input_wakeup() will wake up the core thread (also called the playloop). This seems odd, but currently the core indeed calls mp_input_wait() when it has nothing more to do. It's done this way because MPlayer used input_ctx as central "mainloop". This is probably going to change. Remove direct calls to this function, and replace it with mp_wakeup_core() calls. ao and vo are changed to use opaque callbacks and not use input_ctx for this purpose. Other code already uses opaque callbacks, or has legitimate reasons to use input_ctx directly (such as sending actual user input).
* osdep: rename atomics.h to atomic.hwm42016-09-071-1/+1
| | | | | The standard header is stdatomic.h, so the extra "s" freaks me out every time I look at it.
* player: add --audio-stream-silencewm42016-08-091-2/+6
| | | | | Completely insane that this has to be done. Crap for compensating HDMI crap.
* Relicense some non-MPlayer source files to LGPL 2.1 or laterwm42016-01-191-7/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This covers source files which were added in mplayer2 and mpv times only, and where all code is covered by LGPL relicensing agreements. There are probably more files to which this applies, but I'm being conservative here. A file named ao_sdl.c exists in MPlayer too, but the mpv one is a complete rewrite, and was added some time after the original ao_sdl.c was removed. The same applies to vo_sdl.c, for which the SDL2 API is radically different in addition (MPlayer supports SDL 1.2 only). common.c contains only code written by me. But common.h is a strange case: although it originally was named mp_common.h and exists in MPlayer too, by now it contains only definitions written by uau and me. The exceptions are the CONTROL_ defines - thus not changing the license of common.h yet. codec_tags.c contained once large tables generated from MPlayer's codecs.conf, but all of these tables were removed. From demux_playlist.c I'm removing a code fragment from someone who was not asked; this probably could be done later (see commit 15dccc37). misc.c is a bit complicated to reason about (it was split off mplayer.c and thus contains random functions out of this file), but actually all functions have been added post-MPlayer. Except get_relative_time(), which was written by uau, but looks similar to 3 different versions of something similar in each of the Unix/win32/OSX timer source files. I'm not sure what that means in regards to copyright, so I've just moved it into another still-GPL source file for now. screenshot.c once had some minor parts of MPlayer's vf_screenshot.c, but they're all gone.
* Fix some typos in code commentsAman Gupta2015-12-211-1/+1
| | | | Signed-off-by: wm4 <wm4@nowhere>
* audio/out/pull: avoid dropping some audio when drainingwm42015-06-091-9/+18
| | | | | | | | | | | | If the audio API takes a while for starting the audio callback, the current heuristic can be off. In particular, with very short files, it can happen that the audio callback is not called before playback is stopped, so no audio is output at all. Change draining so that it essentially waits for the ringbuffer to empty. The assumption is that once the audio API has read the data via the callback, it will always output it, even if the audio API is stopped right after the callback has returned.
* audio/out/pull: correctly pad partial frames with silencewm42015-06-091-1/+1
| | | | | | | | If a frame could only be partially filled with real audio data, the silence wasn't written at the correct offset. It could have happened that the remainder of the frame contained garbage. (This didn't happen in the more common case of playing dummy silence.)
* audio/out/pull: avoid deadlock if audio callback stopswm42014-11-091-26/+40
| | | | | | | | | | | | | | | | | | | | | | | | If the audio callback suddenly stops, and the AO provides no "reset" callback, then reset() could deadlock by waiting on the audio callback forever. The waiting was needed to enter a consistent state, where the audio callback guarantees it won't access the ringbuffer. This in turn is needed because mp_ring_reset() is not concurrency-safe. This active waiting is unavoidable. But the way it was implemented, the audio callback had to call ao_read_data() at least once when reset() is called. Fix this by making ao_read_data() set a flag upon entering and leaving, which basically turns p->state into some sort of spinlock. The audio callback actually never needs to spin, because there are only 2 states: playing audio, or playing silence. This might be a bit surprising, because usually atomic_compare_exchange_strong() requires a retry-loop idiom for correct operation. This commit is needed because ao_wasapi can (or will in the future) randomly stop the audio callback in certain corner cases. Then the player would hang forever in reset().
* audio/out: consistently use double return type for get_delaywm42014-11-091-1/+1
| | | | | ao_get_delay() returns double, but the get_delay callback still returned float.
* audio/out: make EOF handling properly event-basedwm42014-09-051-0/+9
| | | | | | | | | | | | | | | | | With --gapless-audio=no, changing from one file to the next apparently made it hang, until the player was woken up by unrelated events like input. The reason was that the AO doesn't notify the player of EOF properly. the played was querying ao_eof_reached(), and then just went to sleep, without anything waking it up. Make it event-based: the AO wakes up the playloop if the EOF state changes. We could have fixed this in a simpler way by synchronously draining the AO in these cases. But I think proper event handling is preferable. Fixes: #1069 CC: @mpv-player/stable (perhaps)
* Move compat/ and bstr/ directory contents somewhere elsewm42014-08-291-1/+1
| | | | | | | | | bstr.c doesn't really deserve its own directory, and compat had just a few files, most of which may as well be in osdep. There isn't really any justification for these extra directories, so get rid of them. The compat/libav.h was empty - just delete it. We changed our approach to API compatibility, and will likely not need it anymore.
* audio: don't wait for draining if pausedwm42014-07-131-0/+9
| | | | | | | | | | | | | 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
* audio/out/pull: remove race conditionswm42014-05-291-34/+40
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* atomics: switch to C11 stdatomic.hwm42014-05-211-27/+17
| | | | | | | | | | | | | | | | | | | | | | | | | 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.
* audio: wake up the core when audio buffer is running low (2)wm42014-04-151-2/+9
| | | | | | | | | | | | | | 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.
* audio/out: make draining a separate operationwm42014-03-091-2/+2
| | | | | | | | | | | | 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.
* audio/out: feed AOs from a separate threadwm42014-03-091-0/+219
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.