diff options
author | Diogo Franco (Kovensky) <diogomfranco@gmail.com> | 2014-03-06 16:28:11 -0300 |
---|---|---|
committer | Diogo Franco (Kovensky) <diogomfranco@gmail.com> | 2014-03-06 17:21:34 -0300 |
commit | fe03981bbc20694fd6a4a61461727e02bf9192a8 (patch) | |
tree | 05d1ea8bba4dd3f50153a397ca9321b96db18d05 /audio | |
parent | 1d096f9f1bbe2d8da8860003457d1161deb873f6 (diff) | |
download | mpv-fe03981bbc20694fd6a4a61461727e02bf9192a8.tar.bz2 mpv-fe03981bbc20694fd6a4a61461727e02bf9192a8.tar.xz |
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.
Diffstat (limited to 'audio')
-rw-r--r-- | audio/out/ao_wasapi.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c index fdca69c20c..39199159b3 100644 --- a/audio/out/ao_wasapi.c +++ b/audio/out/ao_wasapi.c @@ -121,6 +121,7 @@ typedef struct wasapi_state { IAudioClock *pAudioClock; UINT64 clock_frequency; /* scale for the "samples" returned by the clock */ UINT64 sample_count; /* the amount of samples per channel written to a GetBuffer buffer */ + LARGE_INTEGER qpc_frequency; /* frequency of windows' high resolution timer */ int opt_exclusive; int opt_list; @@ -528,6 +529,8 @@ static int init_clock(struct wasapi_state *state) { hr = IAudioClock_GetFrequency(state->pAudioClock, &state->clock_frequency); EXIT_ON_ERROR(hr); + QueryPerformanceFrequency(&state->qpc_frequency); + state->sample_count = 0; MP_VERBOSE(state, "IAudioClock::GetFrequency gave a frequency of %"PRIu64".\n", (uint64_t) state->clock_frequency); @@ -1362,19 +1365,25 @@ static int play(struct ao *ao, void **data, int samples, int flags) } static float get_device_delay(struct wasapi_state *state) { - /* where we pray that this hasn't desynced */ + /* where we pray that sample_count hasn't desynced */ mp_memory_barrier(); UINT64 sample_count = state->sample_count; - UINT64 position; + UINT64 position, qpc_position; HRESULT hr; - switch (hr = IAudioClock_GetPosition(state->pAudioClock, &position, NULL)) { + switch (hr = IAudioClock_GetPosition(state->pAudioClock, &position, &qpc_position)) { case S_OK: case S_FALSE: break; default: MP_ERR(state, "IAudioClock::GetPosition returned %s\n", explain_err(hr)); } + LARGE_INTEGER qpc_count; + QueryPerformanceCounter(&qpc_count); + UINT64 qpc_diff = (qpc_count.QuadPart * 10000000 / state->qpc_frequency.QuadPart) - qpc_position; + + position += state->clock_frequency * qpc_diff / 10000000; + /* convert position to the same base as sample_count */ position = position * state->format.Format.nSamplesPerSec / state->clock_frequency; |