summaryrefslogtreecommitdiffstats
path: root/audio/out/internal.h
Commit message (Collapse)AuthorAgeFilesLines
* ao: simplify hack for float atomicswm42017-11-301-2/+2
| | | | | | | 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.
* audio: add audio softvol processing to AOwm42017-11-291-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* command: drop "audio-out-detected-device" propertywm42017-10-091-3/+0
| | | | | | Coreaudio stopped setting it a few releases ago (66a958bb4fa). There is not much of a user- or API-visible change, so remove it without deprecation.
* audio/out: add helper code to do 24 bit conversion in AOwm42017-07-071-0/+15
| | | | | | | | | | | | | | | | | | | | | | | | | 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: require AO drivers to report period size and correct bufferwm42017-06-251-0/+8
| | | | | | | | | | | | | | | | 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.
* audio/out: change license of some core files to LGPLwm42017-05-201-7/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 7a2eec4b59f4 (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.) 242aa6ebd40: anders mostly disagreed with the LGPL relicensing, but we got permission for this particular commit. 0ef8e555735: nick could not be reached, but the include statement was removed again anyway. 879e05a7c17: iive agreed to LGPL v3+ only, but this line of code was removed anyway, so ao_null.c can be LGPL v2.1+. 9dd8f241ac2: patch author could not be reached, but the corresponding code (old slave mode interface) was completely removed later.
* options: remove remaining deprecated audio device selection optionswm42017-04-231-3/+0
|
* options: remove deprecated sub-option handling for --vo and --aowm42016-11-251-1/+1
| | | | | | | | Long planned. Leads to some sanity. There still are some rather gross things. Especially g_groups is ugly, and a hack that can hopefully be removed. (There is a plan for it, but whether it's implemented depends on how much energy is left.)
* player, ao, vo: don't call mp_input_wakeup() directlywm42016-09-161-1/+2
| | | | | | | | | | | | | 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.
* audio/out: deprecate device sub-optionswm42016-09-051-0/+3
| | | | | We have --audio-device, which can force the device. Also add something describing to this extent to the manpage.
* options: add automagic hack for handling sub-option deprecationswm42016-09-051-0/+1
| | | | | | | | | | | | | | | | | I decided that it's too much work to convert all the VO/AOs to the new option system manually at once. So here's a shitty hack instead, which achieves almost the same thing. (The only user-visible difference is that e.g. --vo=name:help will list the sub-options normally, instead of showing them as deprecation placeholders. Also, the sub-option parser will verify each option normally, instead of deferring to the global option parser.) Another advantage is that once we drop the deprecated options, converting the remaining things will be easier, because we obviously don't need to add the compatibility hacks. Using this mechanism is separate in the next commit to keep the diff noise down.
* options: add a mechanism to make sub-option replacement slightly easierwm42016-09-051-0/+1
| | | | | | | | Instead of requiring each VO or AO to manually add members to MPOpts and the global option table, make it possible to register them automatically via vo_driver/ao_driver.global_opts members. This avoids modifying options.c/options.h every time, including having to duplicate the exact ifdeffery used to enable a driver.
* ao_alsa: change sub-options to global optionswm42016-09-021-0/+1
| | | | | | Same deal as with vo_opengl. Also edit the outdated information about multichannel output a little.
* player: add --audio-stream-silencewm42016-08-091-0/+1
| | | | | Completely insane that this has to be done. Crap for compensating HDMI crap.
* audio: use --audio-channels=auto behavior, except on ALSAwm42016-08-041-0/+3
| | | | | | | | | | | | | | | | | | | | | | | This commit adds an --audio-channel=auto-safe mode, and makes it the default. This mode behaves like "auto" with most AOs, except with ao_alsa. The intention is to allow multichannel output by default on sane APIs. ALSA is not sane as in it's so low level that it will e.g. configure any layout over HDMI, even if the connected A/V receiver does not support it. The HDMI fuckup is of course not ALSA's fault, but other audio APIs normally isolate applications from dealing with this and require the user to globally configure the correct output layout. This will help with other AOs too. ao_lavc (encoding) is changed to the new semantics as well, because it used to force stereo (perhaps because encoding mode is supposed to produce safe files for crap devices?). Exclusive mode output on Windows might need to be adjusted accordingly, as it grants the same kind of low level access as ALSA (requires more research). In addition to the things mentioned above, the --audio-channels option is extended to accept a set of channel layouts. This is supposed to be the correct way to configure mpv ALSA multichannel output. You need to put a list of channel layouts that your A/V receiver supports.
* ao: make better use of atomicswm42015-05-111-1/+1
| | | | | The main reason for this was compatibility; but some associated problems have been solved in the previous commit.
* Update license headersMarcin Kurczewski2015-04-131-5/+4
| | | | Signed-off-by: wm4 <wm4@nowhere>
* audio: add device change notification for hotpluggingwm42015-02-121-10/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | Not very important for the command line player; but GUI applications will want to know about this. This only adds the internal API; support for specific audio outputs comes later. This reuses the ao struct as context for the hotplug event listener, similar to how the "old" device listing API did. This is probably a bit unclean and confusing. One argument got reusing it is that otherwise rewriting parts of ao_pulse would be required (because the PulseAudio API requires so damn much boilerplate). Another is that --ao-defaults is applied to the hotplug dummy ao struct, which automatically applies such defaults even to the hotplug context. Notification works through the property observation mechanism in the client API. The notification chain is a bit complicated: the AO notifies the player, which in turn notifies the clients, which in turn will actually retrieve the device list. (It still has the advantage that it's slightly cleaner, since the AO stuff doesn't need to know about client API issues.) The weird handling of atomic flags in ao.c is because we still don't require real atomics from the compiler. Otherwise we'd just use atomic bitwise operations.
* command: add property returning detected audio deviceStefano Pigozzi2015-02-031-0/+3
| | | | | This can be useful to adjust some other audio related properties at runtime depending on the audio device being used.
* 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 ao_request_reload() idempotentwm42014-11-091-2/+3
| | | | | | | | | | This is what you would expect. Before this commit, each ao_request_reload() call would just queue a reload command, and then recreate the AO for the number of times the function was called. Instead of sending a command, introduce some sort of event retrieval mechanism. At least for the reload case, use atomics, because we're too lazy to setup an extra mutex.
* audio: add --audio-client-name optionwm42014-11-071-0/+3
| | | | | | The main need I see for this is with libmpv - it would be confusing if some application showed up as "mpv" on whateverthehell PulseAudio uses it for (generally it does show up on various PA GUI tools).
* audio: add command/function to reload audio outputwm42014-10-271-0/+2
| | | | | Anticipated use: simple solution for dealing with audio APIs which request configuration changes via events.
* audio/out: add redirection-on-init mechanismwm42014-10-221-0/+3
| | | | | Looks like this will help us with making --audio-device and spdif work as expected on OSX. To be used ina following commit.
* audio: change internal device listing APIwm42014-10-101-2/+12
| | | | | Now we run ao_driver->list_devs on a dummy AO instance, which will probably confuse everyone. This is done for the sake of PulseAudio.
* audio/out/push: fix EOF heuristicwm42014-10-101-5/+0
| | | | | | | | | | | | | Since the internal AO driver API has no proper way to determine EOF, we need to guess by querying get_delay. But some AOs (e.g. ao_pulse with no-latency-hacks set) may never reach 0, maybe because they naively add the latency to the buffer level. In this case our heuristic can break. Fix by always using the delay to estimate the EOF time. It's not even that important - it's mostly used to avoid blocking draining. So this should be ok. CC: @mpv-player/stable (maybe)
* fix -Wvisibility warnings with clangStefano Pigozzi2014-10-091-2/+1
| | | | Now everything compiles with no warnings! yay!
* audio: add device selection & listing with --audio-devicewm42014-10-091-0/+14
| | | | | | | Not sure how good of an idea this is. This commit doesn't add support for this to any AO yet; the AO implementations will follow later.
* audio/out: remove old thingswm42014-09-061-2/+0
| | | | | | | | Remove the unnecessary indirection through ao fields. Also fix the inverted result of AOCONTROL_HAS_TEMP_VOLUME. Hopefully the change is equivalent. But actually, it looks like the old code did it wrong.
* audio/out: make EOF handling properly event-basedwm42014-09-051-0/+2
| | | | | | | | | | | | | | | | | 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)
* audio: make buffer size configurablewm42014-09-051-3/+1
| | | | Really only for testing.
* audio: don't wait for draining if pausedwm42014-07-131-1/+0
| | | | | | | | | | | | | 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/push: add a way to wait for the audio device with poll()wm42014-05-301-0/+4
| | | | Will be used for ALSA.
* audio/out/push: add mechanism for event-based waitingwm42014-05-301-1/+17
| | | | | | | | | | | | | | | | 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).
* audio/out: adjust documentation commentswm42014-05-301-11/+19
|
* audio/out/pull: remove race conditionswm42014-05-291-0/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* player: unrangle one aspect of audio EOF handlingwm42014-04-171-0/+5
| | | | | | | | | | | | | | | | | | 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.)
* audio: wake up the core when audio buffer is running lowwm42014-04-151-0/+1
| | | | | | | | | | | | | | | | | 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.
* audio/out: reduce amount of audio bufferingwm42014-03-101-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | 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.
* audio/out: make draining a separate operationwm42014-03-091-1/+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-3/+56
| | | | | | | | | | | | | | | | | | 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.
* ao: remove opts fieldwm42014-03-091-1/+0
| | | | Apparently unused.
* audio/out: make ao struct opaquewm42014-03-091-0/+76
We want to move the AO to its own thread. There's no technical reason for making the ao struct opaque to do this. But it helps us sleep at night, because we can control access to shared state better.