diff --git a/modules/audio_device/audio_device_buffer.cc b/modules/audio_device/audio_device_buffer.cc index b1be445e0d..91964d1edd 100644 --- a/modules/audio_device/audio_device_buffer.cc +++ b/modules/audio_device/audio_device_buffer.cc @@ -248,11 +248,28 @@ int32_t AudioDeviceBuffer::SetRecordedBuffer( } if (capture_timestamp_ns) { - capture_timestamp_ns_ = - rtc::kNumNanosecsPerMicrosec * - timestamp_aligner_.TranslateTimestamp( - *capture_timestamp_ns / rtc::kNumNanosecsPerMicrosec, - rtc::TimeMicros()); + int64_t align_offsync_estimation_time = rtc::TimeMicros(); + if (align_offsync_estimation_time - + rtc::TimestampAligner::kMinFrameIntervalUs > + align_offsync_estimation_time_) { + align_offsync_estimation_time_ = align_offsync_estimation_time; + capture_timestamp_ns_ = + rtc::kNumNanosecsPerMicrosec * + timestamp_aligner_.TranslateTimestamp( + *capture_timestamp_ns / rtc::kNumNanosecsPerMicrosec, + align_offsync_estimation_time); + } else { + // The Timestamp aligner is designed to prevent timestamps that are too + // similar, and produces warnings if it is called to often. We do not care + // about that here, so we do this workaround. If we where to call the + // aligner within a millisecond, we instead call this, that do not update + // the clock offset estimation. This get us timestamps without generating + // warnings, but could generate two timestamps within a millisecond. + capture_timestamp_ns_ = + rtc::kNumNanosecsPerMicrosec * + timestamp_aligner_.TranslateTimestamp(*capture_timestamp_ns / + rtc::kNumNanosecsPerMicrosec); + } } // Derive a new level value twice per second and check if it is non-zero. int16_t max_abs = 0; diff --git a/modules/audio_device/audio_device_buffer.h b/modules/audio_device/audio_device_buffer.h index eb681a7a68..f7c4ecdcff 100644 --- a/modules/audio_device/audio_device_buffer.h +++ b/modules/audio_device/audio_device_buffer.h @@ -196,6 +196,10 @@ class AudioDeviceBuffer { // Capture timestamp. absl::optional capture_timestamp_ns_; + // The last time the Timestamp Aligner was used to estimate clock offset + // between system clock and capture time from audio. + // This is used to prevent estimating the clock offset too often. + absl::optional align_offsync_estimation_time_; // Counts number of times LogStats() has been called. size_t num_stat_reports_ RTC_GUARDED_BY(task_queue_); diff --git a/rtc_base/timestamp_aligner.cc b/rtc_base/timestamp_aligner.cc index 34b68bf39e..6c7ac1f839 100644 --- a/rtc_base/timestamp_aligner.cc +++ b/rtc_base/timestamp_aligner.cc @@ -112,7 +112,6 @@ int64_t TimestampAligner::UpdateOffset(int64_t capturer_time_us, int64_t TimestampAligner::ClipTimestamp(int64_t filtered_time_us, int64_t system_time_us) { - const int64_t kMinFrameIntervalUs = rtc::kNumMicrosecsPerMillisec; // Clip to make sure we don't produce timestamps in the future. int64_t time_us = filtered_time_us - clip_bias_us_; if (time_us > system_time_us) { diff --git a/rtc_base/timestamp_aligner.h b/rtc_base/timestamp_aligner.h index 138e936af2..636afcd659 100644 --- a/rtc_base/timestamp_aligner.h +++ b/rtc_base/timestamp_aligner.h @@ -14,6 +14,7 @@ #include #include "rtc_base/system/rtc_export.h" +#include "rtc_base/time_utils.h" namespace rtc { @@ -38,6 +39,12 @@ class RTC_EXPORT TimestampAligner { TimestampAligner& operator=(const TimestampAligner&) = delete; public: + // Minimum difference of two timestamps generated by + // "TranslateTimestamp(int64_t capturer_time_us, int64_t system_time_us)" + // This avoids the caller from getting two timestamps with the same + // millisecond. + static constexpr int64_t kMinFrameIntervalUs = rtc::kNumMicrosecsPerMillisec; + // Translates timestamps of a capture system to the same timescale as is used // by rtc::TimeMicros(). `capturer_time_us` is assumed to be accurate, but // with an unknown epoch and clock drift. `system_time_us` is