summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorDiogo Franco (Kovensky) <diogomfranco@gmail.com>2014-03-06 16:28:11 -0300
committerDiogo Franco (Kovensky) <diogomfranco@gmail.com>2014-03-06 17:21:34 -0300
commitfe03981bbc20694fd6a4a61461727e02bf9192a8 (patch)
tree05d1ea8bba4dd3f50153a397ca9321b96db18d05 /audio
parent1d096f9f1bbe2d8da8860003457d1161deb873f6 (diff)
downloadmpv-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.c15
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;