diff options
author | Paul Adenot <[email protected]> | 2022-12-13 19:35:19 +0100 |
---|---|---|
committer | Paul Adenot <[email protected]> | 2022-12-14 18:33:27 +0100 |
commit | 36ac2a31d884319ee17ebf7411961a2a3046383e (patch) | |
tree | b4ca2cf2fd218a2ba26f1bb8e449d1336027933c | |
parent | ab242f6935e56660fe0ce06cbae2b90bbeb2cc06 (diff) | |
download | cubeb-36ac2a31d884319ee17ebf7411961a2a3046383e.tar.gz cubeb-36ac2a31d884319ee17ebf7411961a2a3046383e.zip |
Rewrite aaudio_stream_get_position with the accurate timing info provided by AAudio
A/V sync is now perfect regardless of the output device (bluetooth,
wired, speaker), and client side interpolation provides high accuracy
regardless of the buffer-size that the users decides on.
-rw-r--r-- | src/cubeb_aaudio.cpp | 34 |
1 files changed, 14 insertions, 20 deletions
diff --git a/src/cubeb_aaudio.cpp b/src/cubeb_aaudio.cpp index cea48d5..5c63735 100644 --- a/src/cubeb_aaudio.cpp +++ b/src/cubeb_aaudio.cpp @@ -1342,33 +1342,27 @@ aaudio_stream_get_position(cubeb_stream * stm, uint64_t * position) break; } - int64_t pos; - int64_t ns; - aaudio_result_t res; - res = WRAP(AAudioStream_getTimestamp)(stream, CLOCK_MONOTONIC, &pos, &ns); - if (res != AAUDIO_OK) { - // When the audio stream is not running, invalid_state is returned and we - // simply fall back to the method we use for non-playing streams. - if (res == AAUDIO_ERROR_INVALID_STATE) { - *position = WRAP(AAudioStream_getFramesRead)(stream); - if (*position < stm->previous_clock) { - *position = stm->previous_clock; - } else { - stm->previous_clock = *position; - } - return CUBEB_OK; - } - - LOG("AAudioStream_getTimestamp: %s", WRAP(AAudio_convertResultToText)(res)); - return CUBEB_ERROR; + // No callback yet, the stream hasn't really started. + if (stm->previous_clock == 0 && !stm->timing_info.updated()) { + LOG("Not timing info yet"); + *position = 0; + return CUBEB_OK; } - *position = pos; + AAudioTimingInfo info = stm->timing_info.read(); + LOGV("AAudioTimingInfo idx:%lu tstamp:%lu latency:%u", info.frame_index, + info.tstamp, info.latency); + // Interpolate client side since the last callback. + int64_t interpolation = stm->sample_rate * (now_ns() - info.tstamp) / 1e9; + *position = info.frame_index + interpolation - info.latency; if (*position < stm->previous_clock) { *position = stm->previous_clock; } else { stm->previous_clock = *position; } + + LOG("aaudio_stream_get_position: %ld", *position); + return CUBEB_OK; } |