summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_wasapi.c
Commit message (Collapse)AuthorAgeFilesLines
* ao_wasapi: fix player core lockup when avoiding premature buffer fillsnanahi6 days1-9/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 6863eefc3d1d683a08f56aeaca0b4706672f2447 handled this situation by using an atomic variable to express the state for which the wakeup is caused by AO control, and the dispatch queue is only processed at this state. However, this can cause permanent lockup of the player core when the following happens: - AO control sets the thread state to WASAPI_THREAD_DISPATCH, and sets the wakeup handle. - WASAPI thread reads the WASAPI_THREAD_DISPATCH state and processes the dispatch queue. - Another AO control happens. A dispatch item is enqueued, and the state stays at WASAPI_THREAD_DISPATCH. - WASAPI thread resets the thread state to WASAPI_THREAD_FEED since the state has not changed. - WaitForSingleObject() returns in the WASAPI thread, sees this state, and does not process the dispatch queue. - The player core locks permanently because it is waiting for the dispatch to be processed. This has been experimentally verified on a system under high contention: The easiest way to trigger this lockup is to continuously hold down "i", which rapidly issues AO get volume/mute controls. To properly handle this, use separate handles for system and user wakeup requests. Only feed audio when woke up by system and only process the dispatch queue when woke up by user. Fixes: 6863eefc3d1d683a08f56aeaca0b4706672f2447
* Revert "ao_wasapi: address premature buffer fills in exclusive mode"nanahi6 days1-12/+13
| | | | This reverts commit 6863eefc3d1d683a08f56aeaca0b4706672f2447.
* ao_wasapi: add `--wasapi-exclusive-buffer` optionsunpenghao2024-04-191-0/+6
| | | | | | | | | | | This allows users to set buffer duration in exclusive mode. We have been using the default device period as the buffer size and it is robust enough in most cases. However, on some devices there are horrible glitches after a stream reset. Unfortunately, the issue is not consistently reproducible, but using a smaller buffer size (e.g., the minimum device period) seems to resolve the problem. Fixes #13715.
* ao_wasapi: support set_pauseMisaki Kasumi2024-04-031-9/+35
|
* ao_wasapi: scale queried AO volume to (0, 100)sunpenghao2024-02-241-2/+2
| | | | This was done for `AOCONTROL_SET_VOLUME` but not `AOCONTROL_GET_VOLUME`.
* ao_wasapi: address premature buffer fills in exclusive modesunpenghao2024-02-241-13/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Currently, running AO control wakes up the WASAPI renderer thread in the `WASAPI_THREAD_FEED` state, where `thread_feed` will be called. However, it seems that in recent Windows versions (tested on Windows 10 build 19044.3930 and Windows 11 build 22631.3007) we can't know if it is safe to feed more audio data in event-driven exclusive mode: - `IAudioClient_GetCurrentPadding` always returns `bufferFrameCount`, even if *NO* data has ever been written. This means we don't know how much free space we have that is available for writing. This is not the case in shared mode, where the return value correctly reflects the size of data waiting to be processed. As a sidenote, MS did not document the precise definition of the return value for an event-driven, exclusive stream [1]. - `IAudioRenderClient_GetBuffer` never fails. We can call it for 10 times in a roll, each time requesting an entire buffer (the unit at which data is exchanged in exclusive mode using event-driven buffering; there are 2 such buffers) and get a successful return code everytime. In shared mode, we get `AUDCLNT_E_BUFFER_TOO_LARGE` if we request a buffer larger than that currently available. As a result, `thread_feed` will always write `bufferFrameCount` frames of audio in exclusive mode. There will therefore be glitches each time `thread_control` is called due to the subsequent `thread_feed` overwriting frames yet to be processed. Also, an irreversible error is accumulated to `sample_count` as long as there is no AO reset, leading to eventual, unbounded A/V desync. As a fix to the issue, add a dedicated state for dispatch queue processing so that `thread_feed` is only called when signaled by the OS. The buffer checks in `thread_feed` that use `GetCurrentPadding` in exclusive mode are kept in case there are older versions where the two APIs behave differently. Closes #12615. [1] https://learn.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getcurrentpadding
* ALL: use new mp_thread abstractionKacper Michajłow2023-11-051-1/+1
|
* mp_threads: rename threads for consistent naming across all of themKacper Michajłow2023-10-271-1/+1
| | | | | | | | I'd like some names to be more descriptive, but to work with 15 chars limit we have to make some sacrifice. Also because of the limit, remove the `mpv/` prefix and prioritize actuall thread name.
* ao: convert all timing code to nanosecondsDudemanguy2023-10-161-10/+11
| | | | | | | Pull AOs work off of a callback that relies on mpv's internal timer. So like with the related video changes, convert all of these to nanoseconds instead. In many cases, the underlying audio API does actually provide nanosecond resolution as well.
* ao_wasapi: remove infinite loop hack in AOCONTROL_UPDATE_STREAM_TITLEKacper Michajłow2023-06-211-13/+21
| | | | | | | | | | | | | | | | Instead of brute forcing the name until it is set, without any error checking and expecting it would start to work, fallback to client name if initial request fails. Fixes player going into infinite loop with very long title names. The API rejects unreasonably long names, which make sense. As for alleged "weird race condition in the IAudioSessionControl itself" I cannot comment. It works on my end and even if it fails, it is not a critical error or even something that we should care about... and obviously not hang the whole player for that. Fixes: #11803
* audio: simplify implementation of property ao-volumeThomas Weißschuh2023-01-251-10/+4
| | | | | | | | | | | | | | ao-volume is represented in the code with a `struct ao_control_vol_t` which contains volumes for two channels, left and right. However the code implementing this property in command.c never treats these values individually. They are always averaged together. On the other hand the code in the AOs handling these values also has to handle the case where *not* exactly two channels are handled. So let's remove the `struct ao_control_vol_t` and replace it with a simple float. This makes the semantics clear to AO authors and allows us to drop some code from the AOs and command.c.
* audio: redo internal AO APIwm42020-06-011-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | This affects "pull" AOs only: ao_alsa, ao_pulse, ao_openal, ao_pcm, ao_lavc. There are changes to the other AOs too, but that's only about renaming ao_driver.resume to ao_driver.start. ao_openal is broken because I didn't manage to fix it, so it exits with an error message. If you want it, why don't _you_ put effort into it? I see no reason to waste my own precious lifetime over this (I realize the irony). ao_alsa loses the poll() mechanism, but it was mostly broken and didn't really do what it was supposed to. There doesn't seem to be anything in the ALSA API to watch the playback status without polling (unless you want to use raw UNIX signals). No idea if ao_pulse is correct, or whether it's subtly broken now. There is no documentation, so I can't tell what is correct, without reverse engineering the whole project. I recommend using ALSA. This was supposed to be just a simple fix, but somehow it expanded scope like a train wreck. Very high chance of regressions, but probably only for the AOs listed above. The rest you can figure out from reading the diff.
* audio/out: rip out old unused app/softvolume reportingwm42019-10-111-4/+0
| | | | | | | | | | | This was all dead code. Commit 995c47da9a (over 3 years ago) removed all uses of the controls. It would be nice if AOs could apply a linear gain volume, that only affects the AO's audio stream for low-latency volume adjust and muting. AOCONTROL_HAS_SOFT_VOLUME was supposed to signal this, but to use it, we'd have to thoroughly check whether it really uses the expected semantics, so there's really nothing useful left in this old code.
* ao_wasapi: return bool instead of HRESULT from thread_initKevin Mitchell2017-08-071-4/+4
| | | | | | | | 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.
* ao_wasapi: drop use of AF_FORMAT_S24wm42017-07-071-2/+3
| | | | | | | | | | | 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.
* ao_wasapi: UWP wrapper hack supportwm42017-06-291-1/+4
| | | | | | | | | | | 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.
* ao_wasapi: do not use deprecated wchar functionsPedro Pombeiro2017-06-291-1/+1
| | | | These break on UWP. Based on a patch by Pedro Pombeiro.
* ao_wasapi: set name of event threadJames Ross-Gowan2017-05-181-0/+2
|
* win32: add COM-specific SAFE_RELEASE to windows_utils.hJames Ross-Gowan2017-01-301-6/+6
| | | | | | | | | | | | | | | See: https://msdn.microsoft.com/en-us/library/windows/desktop/dd743946.aspx Microsoft example code often uses a SAFE_RELEASE macro like the one in the above link. This makes it easier to avoid errors when releasing COM interfaces. It also reduces noise in COM-heavy code. ao_wasapi.h also had a macro called SAFE_RELEASE, though unlike the version above, its SAFE_RELEASE macro accepted a second parameter which allowed it to destroy arbitrary objects other than just COM interfaces. This renames ao_wasapi's SAFE_RELEASE to SAFE_DESTROY, which should more accurately reflect what it does and prevent confusion with the Microsoft version.
* options: remove deprecated sub-option handling for --vo and --aowm42016-11-251-7/+0
| | | | | | | | 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.)
* audio/out: deprecate "exclusive" sub-optionswm42016-09-051-1/+4
| | | | | | | And introduce a global option which does this. Or more precisely, this deprecates the global wasapi and coreaudio options, and adds a new one that merges their functionality. (Due to the way the sub-option deprecation mechanism works, this is simpler.)
* audio/out: deprecate device sub-optionswm42016-09-051-1/+1
| | | | | We have --audio-device, which can force the device. Also add something describing to this extent to the manpage.
* options: deprecate suboptions for the remaining AO/VOswm42016-09-051-0/+1
|
* Fix misspellingsstepshal2016-06-261-1/+1
|
* ao_wasapi: initialize COM in main thread with MTAKevin Mitchell2016-06-051-2/+2
| | | | | | Since the main thread is shared by other things in the player, using STA (single threaded aparement) may have caused problems. Instead initialize in MTA (multithreaded apartment).
* ao_wasapi: make wait for audio thread termination infiniteKevin Mitchell2016-02-261-4/+3
| | | | | The time-out was a terrible hack for marginally better behaviour when encountering #1773, which appears to have been resolved by a previous commit.
* ao_wasapi: further flatten/simplify volume controlKevin Mitchell2016-02-261-39/+34
|
* ao_wasapi: use MP_FATAL for stuff that leads to init failureKevin Mitchell2016-02-261-4/+4
|
* ao_wasapi: move pre-resume reset into resume functionKevin Mitchell2016-02-261-16/+14
|
* ao_wasapi: move resetting the thread state into main loopKevin Mitchell2016-02-261-11/+3
| | | | | This was previously duplicated between the reset/resume functions, and not properly handled in the "impossible" invalid thread state case.
* ao_wasapi: replace laggy COM messaging with mp_dispatch_queueKevin Mitchell2016-02-261-68/+78
| | | | | | | | | | A COM message loop is apparently totally inappropriate for a low latency thread. It leads to audio glitches because the thread doesn't wake up fast enough when it should. It also causes mysterious correlations between the vo and ao thread (i.e., toggling fullscreen delays audio feed events). Instead use an mp_dispatch_queue to set/get volume/mute/session display name from the audio thread. This has the added benefit of obviating the need to marshal the associated interfaces from the audio thread.
* ao_wasapi: avoid under-run cascade in exclusive mode.Kevin Mitchell2016-02-261-24/+36
| | | | | | | | | | | | | | | | Don't wait for WASAPI to send another feed event if we detect an underfull buffer. It seems that WASAPI doesn't always send extra feed events if something causes rendering to fall behind. This causes every subsequent playback buffer to under-run until playback is reset. The fix is simply to do a one-shot double feed when this happens, which allows rendering to catch up with playback. This was observed to happen when using MsgWaitForMultipleObjects to wait for the feed event and toggling fullscreen with vo=opengl:backend=win. This commit improves the behaviour in that specific case and more generally makes exclusive mode significantly more robust. This commit also moves the logic to avoid *over*filling the exclusive mode buffer into thread_feed right next to the above described underfil logic.
* ao_wasapi: fix typo in commentKevin Mitchell2016-02-261-1/+1
|
* ao_wasapi: use SUCCEEDED/FAILED macrosKevin Mitchell2016-02-261-12/+8
|
* ao_wasapi: add "wasapi" prefix to non-static find_deviceID functionKevin Mitchell2016-01-281-1/+1
|
* 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.
* ao_wasapi: use share_mode value instead of raw option opt_exclusiveKevin Mitchell2016-01-181-1/+1
| | | | | | | Previously used opt_exclusive option to decide which volume control code to run. The might not always reflect the actual state, for example if passthrough is used. Admittedly, none of the volume controls will work anyway with passthrough, but this is the right thing to do.
* ao_wasapi: remove unnecessary header fileKevin Mitchell2016-01-051-11/+2
| | | | | All the wasapi files were including both ao_wasapi.h and ao_wasapi_utils.h. Just merge them into a single file.
* ao_wasapi: initialize change notify in main threadKevin Mitchell2016-01-051-0/+6
| | | | This is something else that has nothing to do with audio rendering.
* ao_wasapi: make find_deviceID read only wrt struct aoKevin Mitchell2016-01-051-1/+2
| | | | This makes it clearer that state->device is being allocated.
* ao_wasapi: move device selection to main threadKevin Mitchell2016-01-051-1/+6
| | | | In attempt to simplify the audio event thread, this can now be moved out.
* ao_wasapi: make persistent enumerator local to change_notifyKevin Mitchell2016-01-041-8/+1
| | | | This is no longer required by anything else
* ao_wasapi: fix delay calculation againKevin Mitchell2016-01-021-6/+12
| | | | | | | | Apparently it's only wine where the qpc_position returned by IAudioClock_GetPosition can be overflowed. So actually do the rescaling correctly, but throw away the result if it looks unreasonable. this fixes a regression in 5afa68835ade9f21f9c709f791319bf9d2e35265
* ao_wasapi: fix delay calculationKevin Mitchell2015-12-211-21/+36
| | | | | | | | | | | | | | | | | | | Make sure that subtraction of performance counters is done correctly. Follow the *exact* instructions for converting performance counter to something comparable to the QPCposition returned by IAudioClient::GetPosition https://msdn.microsoft.com/en-us/library/windows/desktop/dd370889%28v=vs.85%29.aspx Also make sure that subtraction of unsigned integers is stored into a signed integer to avoid nastiness. Also be more careful about overflow in the conversion of the device position into number of samples. Avoid casting mp_time_us() to a double, and use llrint to convert the double precision delay_us back to integer for ao_read_data. Finally, actually check the return value of ao_read_data and add a verbose message if it is not the expected value. Unfortunately, there is no way to tell WASAPI when this happens since the frame_count in ReleaseBuffer must match GetBuffer.
* ao_wasapi: non-fatal error handling for COM marshallingKevin Mitchell2015-12-211-1/+1
| | | | | Also make sure that CoReleaseMarshalData is called if errors occur before unmarshalling.
* ao_wasapi: wrap long lines and use only c99 comment styleKevin Mitchell2015-12-211-32/+43
| | | | | also remove a log message in AOCONTROL_UPDATE_STREAM_TITLE since none of the other controls have one.
* ao_wasapi: move exclusive and shared-specific controls to functionsKevin Mitchell2015-12-211-75/+87
|
* ao_wasapi: check for proxy availability in controlKevin Mitchell2015-12-201-22/+37
| | | | | Make sure that the proxy has been created before using it. This will be used when a future commit makes proxy setup optional.
* ao_wasapi: actually use hw volume support information for exclusive modeKevin Mitchell2015-12-201-17/+29
| | | | | | | | | Do not try and set/get master volume in exclusive if there is no hardware support. This would just uselessly change the master slider, but have no effect on the actual volume. Furthermore if getting hardware volume support information fails, then assume it has none.
* ao_wasapi: don't cast control arg to something it isn'tKevin Mitchell2015-12-201-9/+14
| | | | | the ao_control_vol_t cast was happening outside AOCONTROL_GET/SET_VOLUME which is the only place that would be valid
* ao_wasapi: remove volume "restore" on exitKevin Mitchell2015-12-201-28/+9
| | | | | | It was complicated and not even very intuitive to the user. If you are controlling the master volume, you just have to be prepared to deal with the consequences.
* ao_wasapi: split exclusive/shared specific ao controlsKevin Mitchell2015-12-201-37/+60
| | | | | this avoids having to check if we're exclusive or shared for every control
* ao_wasapi: get rid of Vistablob hackKevin Mitchell2015-11-241-4/+0
| | | | | This was required to work around XP linking issues and is no longer required.
* ao_wasapi: only report per-app volume in shared modeKevin Mitchell2015-11-191-1/+2
| | | | | otherwise we were incorrectly adjusting the hardware master volume in exclusive mode with softvol=auto
* win32: revert wchar_t changeswm42015-08-011-3/+2
| | | | | | | | | | | Revert "win32: more wchar_t -> WCHAR replacements" Revert "win32: replace wchar_t with WCHAR" Doing a "partial" port of this makes no sense anymore from my perspective. Revert the changes, as they're confusing without context, maintenance, and progress. These changes were a bit premature anyway, and might actually cause other issues (locale neutrality etc. as it was pointed out).
* win32: replace wchar_t with WCHARwm42015-07-291-2/+3
| | | | | | | | | | | | | WCHAR is more portable. While at least MinGW, Cygwin, and MSVC actually use 16 bit wchar_t, Midipix will have 32 bit wchar_t. In that context, using WCHAR instead is more portable. This affects only non-MinGW parts, so not all uses of wchar_t need to be changed. For example, terminal-win.c won't be used on Midipix at all. (Most of io.c won't either, so the search & replace here is more than necessary, but also not harmful.) (Midipix is not useable yet, so this is just preparation.)
* ao_wasapi: fix crash on hotplug init errorwm42015-06-171-0/+1
| | | | | On init error, the mp_msg macros are actually called. They could cause a crash because state->log was NULL.
* ao/wasapi: use atomic state variable instead of different eventsKevin Mitchell2015-04-041-54/+61