Commit Graph

70 Commits

Author SHA1 Message Date
Kevin Mitchell c52833bf16 ao/wasapi: move resume to audio thread
This echanges the two events hForceFeed/hFeedDone for hResume. This
like the last commit makes things more deterministic.

Importantly, the forcefeed is only done if there is not already a full
buffer yet to be played by the device. This should fix some of the
problems with exclusive mode.

This commit also removes the necessity to have a proxy to the
AudioClient object in the main thread.

fixes #1529
2015-02-23 14:02:08 -08:00
Kevin Mitchell 446fd5a43a ao_wasapi: move reset into audio thread
This makes things a bit more deterministic. It ensures that the audio
thread isn't doing anything between IAudioClient_Stop(),
IAudioClient_Reset() and setting the sample_count to 0.

Buffer overfilling on resume is still a problem in exclusive mode (see
next commit).
2015-02-23 14:01:05 -08:00
wm4 f61b8b312d win32: request UTF-16 API variants, Vista+ APIs, and COM C macros
Put the Vista+ (_WIN32_WINNT) and the COM C (COBJMACROS) defines into
the build system, instead of defining them over and over in the code.
2015-01-07 21:42:44 +01:00
Kevin Mitchell 6a6620a554 ao/wasapi: style/code formatting tweaks 2015-01-02 14:50:59 -08:00
Kevin Mitchell b83e447e2b ao/wasapi: remove unnecessary check of audio thread input
it would have caused a deadlock if it fired anyway.
2014-11-28 10:52:48 -08:00
Kevin Mitchell 8908b80b77 ao/wasapi: more missed cleanup on failure 2014-11-28 10:52:43 -08:00
Kevin Mitchell 7b5baf3b53 ao/wasapi: check return values
Only issue a warning for failure of wasapi_enumerate_devices and
wasapi_fill_VistaBlob.
2014-11-28 10:52:12 -08:00
Kevin Mitchell 3b0b89c0af ao/wasapi: just return 0 unconditionally from the thread
We weren't actually checking this value anyway. We only really
cared about init failure, which was checked another way.
2014-11-28 10:48:36 -08:00
Kevin Mitchell d40c0d4f90 ao/wasapi: fix unmatched CoUninitialize() on init failure 2014-11-28 10:48:36 -08:00
Kevin Mitchell d0c37f0731 ao/wasapi: more debugging messages 2014-11-28 10:48:07 -08:00
Kevin Mitchell e4aaaf69df ao/wasapi: make get_device_delay return an error code 2014-11-28 08:02:16 -08:00
Kevin Mitchell c545c406fa ao/wasapi: increase buffer size to 50 ms
Before it was the default device period, which was too small
causing glitches on on entering/exiting fullscreen.
2014-11-18 05:03:33 -08:00
Kevin Mitchell 22bf0a78df ao/wasapi: Don't free stuff the thread may still be using on timeout
In the unlikely event of a timeout waiting for the audio thread to return,
don't free stuff that it may still be using.
2014-11-17 23:46:38 -08:00
Kevin Mitchell 20d42b3475 ao/wasapi: also free the threadLoop handle on uninit
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx
2014-11-17 23:43:51 -08:00
Kevin Mitchell 23f52fd41b ao/wasapi: fix leaked event handles 2014-11-17 23:32:28 -08:00
Kevin Mitchell ebd161b256 ao/wasapi: fix race condition in uninit on failure.
When the audio thread fails to properly init, it signals failure
to the main thread, AND THEN starts to clean up. For this to work,
ao_init callback must not return until the thread's cleanup is finished.
This is correctly handled in the ao_uninit callback by waiting for
the thread to exit, so just call that to clean up the main thread.
I have no idea why I didn't do this in the first place.
2014-11-17 23:32:13 -08:00
Kevin Mitchell 4c8b841fc4 ao/wasapi: request ao reload on thread_feed failures
Even with change notifications, there are still (rare) cases when the
feed thread gets AUDCLIENT_DEVICE_INVALIDATED. So handle failures in
thread_feed by requesting ao_reload.
2014-11-17 04:31:22 -08:00
Kevin Mitchell 6c512892d4 ao/wasapi: request reset on appropriate events
on changes to PKEY_AudioEngine_DeviceFormat, device status, and default device.
call ao_reload directly in the change_notify "methods".

this requires keeping a device enumerator around for the duration of
execution, rather than just for initially querying devices
2014-11-17 04:31:20 -08:00
Kevin Mitchell 3da6f723c6 ao/wasapi: tidy up better on failure
Before, failures, particularly in the thread loop init, could lead to a
bad state for the duration of mpvs execution. Make sure that
everything that was initialized gets properly and safely
uninitialized.
2014-11-17 04:13:52 -08:00
Kevin Mitchell e28102f1a8 ao/wasapi: improve error messages and add more debug statements
also enforce more consistency in the exit codes and error handling

thanks to Jonathan Yong <10walls@gmail.com>
2014-11-17 04:13:49 -08:00
Kevin Mitchell d4393be0f9 ao/wasapi: make calling of thread_init consistent with thread_uninit 2014-11-17 03:37:07 -08:00
Kevin Mitchell 6eb5c6d186 ao/wasapi: reenable the reset function
the race condition that necessitated disabling
this was fixed in
e440352313
2014-11-17 03:37:07 -08:00
wm4 e9b0a61444 ao_wasapi: implement device listing 2014-10-13 18:21:45 +02:00
wm4 439a05d8c3 audio/out: remove old things
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.
2014-09-06 02:30:57 +02:00
wm4 c36faf8c49 audio/out/pull: remove race conditions
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.
2014-05-29 02:24:17 +02:00
wm4 8e7cf4bc99 atomics: switch to C11 stdatomic.h
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.
2014-05-21 02:21:18 +02:00
Diogo Franco (Kovensky) a0347e0651 ao_wasapi: Use the character set conversion functions from io.h
...rather than rolling out our own. The only possible advantage is that
the "custom" ones didn't use talloc.
2014-03-11 16:37:22 -03:00
Diogo Franco (Kovensky) c5012946ee ao_wasapi: Implement AOCONTROL_UPDATE_STREAM_TITLE 2014-03-11 16:37:22 -03:00
Diogo Franco (Kovensky) f8bdada77f ao_wasapi: Implement per-application mixing
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.
2014-03-11 16:37:21 -03:00
Diogo Franco (Kovensky) f3e9b94622 ao_wasapi: Move non-critical code outside of the event thread
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.
2014-03-11 16:37:02 -03:00
Diogo Franco (Kovensky) 58011810e5 ao_wasapi: Split into 2 files
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.
2014-03-11 16:37:02 -03:00
Diogo Franco (Kovensky) f3514fb4bd ao_wasapi: Initial conversion to the new pull model
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.
2014-03-11 16:37:01 -03:00
Diogo Franco (Kovensky) 5c9c81efcc ao_wasapi: Use double math for QueryPerformanceCounter correction
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.
2014-03-09 17:56:29 -03:00
wm4 e16c91d07a audio/out: make draining a separate operation
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.
2014-03-09 01:27:41 +01:00
wm4 41f2b26d11 audio/out: make ao struct opaque
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.
2014-03-09 00:19:31 +01:00
Diogo Franco (Kovensky) fe03981bbc ao_wasapi: Slightly improve timer accuracy
Use QueryPerformanceCounter to improve the accuracy of
IAudioClock::GetPosition.

While this is mainly for "realtime correctness" (usually the delay is a
single sample or less), there are cases where IAudioClock::GetPosition
takes a long time to return from its call (though the documentation doesn't
define what a "long time" is), so correcting its value might be important in
case the documented possible delay happens.
2014-03-06 17:21:34 -03:00
Diogo Franco (Kovensky) 1d096f9f1b ao_wasapi: Add device latency to get_delay
The lack of device latency made get_delay report latencies shorter than
they should; on systems with fast enough drivers, the delay is not
perceptible, but high enough invisible delays would cause desyncs.

I'm not yet completely sure whether this is 100% accurate, there are
some issues involved when repeatedly pausing+unpausing (the delay might
jump around by several dozen miliseconds), but seeking seems to be
working correctly now.
2014-03-06 17:21:33 -03:00
James Ross-Gowan d26ee98fa6 w32: use safe DLL search paths everywhere
Windows applications that use LoadLibrary are vulnerable to DLL
preloading attacks if a malicious DLL with the same name as a system DLL
is placed in the current directory. mpv had some code to avoid this in
ao_wasapi.c. This commit just moves it to main.c, since there's no
reason it can't be used process-wide.

This change can affect how plugins are loaded in AviSynth, but it
shouldn't be a problem since MPC-HC also does this and it's a very
popular AviSynth client.
2014-01-27 10:04:29 +01:00
wm4 9242c34fa2 m_option: add mp_log callback to OPT_STRING_VALIDATE options
And also convert a bunch of other code, especially ao_wasapi and
ao_portaudio.
2013-12-21 21:43:16 +01:00
wm4 7cc3c3aeec ao_wasapi: mp_msg conversions
Remove the nonsensical print_lock too.

Things that are called from the option validator are not converted yet,
because the option parser doesn't provide a log context yet.
2013-12-21 20:50:12 +01:00
wm4 03e53ab430 ao_wasapi: fix includes
Broken due to recent header renaming. Untested.
2013-12-18 17:14:31 +01:00
wm4 0112143fda Split mpvcore/ into common/, misc/, bstr/ 2013-12-17 02:39:45 +01:00
wm4 eb15151705 Move options/config related files from mpvcore/ to options/
Since m_option.h and options.h are extremely often included, a lot of
files have to be changed.

Moving path.c/h to options/ is a bit questionable, but since this is
mainly about access to config files (which are also handled in
options/), it's probably ok.
2013-12-17 02:07:57 +01:00
Diogo Franco (Kovensky) 04faf9a1cb ao_wasapi: Fix mistaken behavior on uninit
The parameter, when true, tells whether uninit should block for flushing
the buffers, not whether it should quit immediately without flushing.
2013-12-08 19:36:44 -03:00
Diogo Franco (Kovensky) c7064ce5e5 ao_wasapi: handle AOPLAY_FINAL_CHUNK
Used for writing down all samples to the audio driver, even if it's not
a full chunk; needed at EOF on weird files.
2013-12-08 19:36:43 -03:00
Diogo Franco (Kovensky) 8f4380d6d5 ao_wasapi: Reduce the buffer size to a sane value
The previous RING_BUFFER_COUNT value, 64, would have ao_wasapi buffer 64
frames of audio in the ring buffer; a delay of 1280ms, which is clearly
overkill for everything. A value of 8 buffers 8 frames for a total of
160ms.
2013-12-08 19:14:56 -03:00
Diogo Franco (Kovensky) 2329e46229 ao_wasapi: fix audio buffering delay calculation
When get_space was converted to returning samples instead of bytes, a
unit type mismatch in get_delay's calculation returned bogus values. Fix
by converting get_space's value back to bytes.

Fixes playback with ao_wasapi when reaching EOF, or seeking past it.
2013-12-08 19:03:26 -03:00
wm4 380fc765e4 audio/out: prepare for non-interleaved audio
This comes with two internal AO API changes:

1. ao_driver.play now can take non-interleaved audio. For this purpose,
the data pointer is changed to void **data, where data[0] corresponds to
the pointer in the old API. Also, the len argument as well as the return
value are now in samples, not bytes. "Sample" in this context means the
unit of the smallest possible audio frame, i.e. sample_size * channels.

2. ao_driver.get_space now returns samples instead of bytes. (Similar to
the play function.)

Change all AOs to use the new API.

The AO API as exposed to the rest of the player still uses the old API.
It's emulated in ao.c. This is purely to split the commits changing all
AOs and the commits adding actual support for outputting N-I audio.
2013-11-12 23:27:51 +01:00
wm4 bf60281ffb audio/out: reject non-interleaved formats
No AO can handle these, so it would be a problem if they get added
later, and non-interleaved formats get accepted erroneously. Let them
gracefully fall back to other formats.

Most AOs actually would fall back, but to an unrelated formats. This is
covered by this commit too, and if possible they should pick the
interleaved variant if a non-interleaved format is requested.
2013-11-12 23:16:31 +01:00
wm4 91626b1c06 audio: replace af_fmt2str_short -> af_fmt_to_str
Also, remove all af_fmt2str usages.
2013-11-07 22:12:36 +01:00