blob: 993287a28fe4700ca877e5c4a75fdf1274318426 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_MEDIA_AUDIO_RATE_ADJUSTER_H_
#define CHROMECAST_MEDIA_AUDIO_RATE_ADJUSTER_H_
#include <cstdint>
#include <memory>
#include "base/callback.h"
#include "base/time/time.h"
namespace chromecast {
class WeightedMovingLinearRegression;
namespace media {
// RateAdjuster handles adjusting a clock rate to minimize errors over time.
// This can be used for A/V sync, for example. The RateAdjuster smooths the
// error samples over time using a moving linear regression. It attempts to
// adjust the clock rate to correct the current absolute error, and the slope
// of the change in error, with the goal of maintaining as close as possible to
// 0 errors over time.
class RateAdjuster {
public:
struct Config {
// The minimum interval between clock rate changes.
base::TimeDelta rate_change_interval = base::TimeDelta::FromSeconds(1);
// How long to make the linear regression window for smoothing errors.
base::TimeDelta linear_regression_window = base::TimeDelta::FromSeconds(10);
// The maximum current error to ignore, in microseconds.
int64_t max_ignored_current_error = 0;
// The maximum current absolute error that should be adjusted for in a
// single clock rate adjustment.
double max_current_error_correction = 2.5e-4;
// The minimum difference between the optimal clock rate and the current
// clock rate required to actually change the rate.
double min_rate_change = 0;
};
// Called to change the clock rate. Returns the actual new clock rate. The
// |error_slope| and |current_error| are provided for debugging/logging
// purposes.
using RateChangeCallback =
base::RepeatingCallback<double(double desired_clock_rate,
double error_slope,
double current_error)>;
RateAdjuster(const Config& config,
RateChangeCallback change_clock_rate,
double current_clock_rate);
~RateAdjuster();
// Adds an error sample at the given |timestamp|. Both the |error| and the
// |timestamp| are in microseconds. The error of some event should be
// calculated as <actual time of event> - <desired time of event>. Timestamps
// should increase monotonically. The clock rate will be adjusted
// synchronously within this method via the callback, if necessary.
void AddError(int64_t error, int64_t timestamp);
private:
const Config config_;
RateChangeCallback change_clock_rate_;
std::unique_ptr<WeightedMovingLinearRegression> linear_error_;
int64_t clock_rate_start_timestamp_ = 0;
int64_t initial_timestamp_ = 0;
double clock_rate_error_base_ = 0.0;
double current_clock_rate_;
};
} // namespace media
} // namespace chromecast
#endif // CHROMECAST_MEDIA_AUDIO_RATE_ADJUSTER_H_