Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
latency_tuner.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Roc Streaming authors
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8 
9 //! @file roc_audio/latency_tuner.h
10 //! @brief Latency tuner.
11 
12 #ifndef ROC_AUDIO_LATENCY_TUNER_H_
13 #define ROC_AUDIO_LATENCY_TUNER_H_
14 
16 #include "roc_audio/sample_spec.h"
17 #include "roc_core/noncopyable.h"
18 #include "roc_core/optional.h"
19 #include "roc_core/time.h"
20 #include "roc_packet/ilink_meter.h"
21 #include "roc_packet/units.h"
22 #include "roc_status/status_code.h"
23 
24 namespace roc {
25 namespace audio {
26 
27 //! Latency tuner backend.
28 //! Defines which latency we monitor and tune to achieve target.
30  //! Deduce best default for given settings.
32 
33  //! Latency is Network Incoming Queue length.
34  //! Calculated on receiver without use of any signaling protocol.
35  //! Reported back to sender via RTCP XR.
37 
38  //! Latency is End-to-end delay.
39  //! Can on receiver if RTCP XR is supported by both sides.
40  //! Reported back to sender via RTCP XR.
42 };
43 
44 //! Latency tuner profile.
45 //! Defines whether and how we tune latency on fly to compensate clock
46 //! drift and jitter.
48  //! Deduce best default for given settings.
50 
51  //! Do not tune latency.
53 
54  //! Fast and responsive tuning.
55  //! Good for lower network latency and jitter.
57 
58  //! Slow and smooth tuning.
59  //! Good for higher network latency and jitter.
61 };
62 
63 //! Latency settings.
64 struct LatencyConfig {
65  //! Latency tuner backend to use.
66  //! @remarks
67  //! Defines which latency to monitor & tune.
69 
70  //! Latency tuner profile to use.
71  //! @remarks
72  //! Defines how smooth is the tuning.
74 
75  //! Target latency.
76  //! @remarks
77  //! Latency tuner will try to keep latency close to this value.
78  //! @note
79  //! If zero, default value is used if possible.
80  //! Negative value is an error.
82 
83  //! Maximum allowed deviation from target latency.
84  //! @remarks
85  //! If the latency goes out of bounds, the session is terminated.
86  //! @note
87  //! If zero, default value is used if possible.
88  //! Negative value is an error.
90 
91  //! Maximum delay since last packet before queue is considered stalling.
92  //! @remarks
93  //! If niq_stalling becomes larger than stalling_tolerance, latency
94  //! tolerance checks are temporary disabled.
95  //! @note
96  //! If zero, default value is used if possible.
97  //! Negative value is an error.
99 
100  //! Scaling update interval.
101  //! @remarks
102  //! How often to run FreqEstimator and update Resampler scaling.
103  //! @note
104  //! If zero, default value is used.
105  //! Negative value is an error.
107 
108  //! Maximum allowed deviation of freq_coeff from 1.0.
109  //! @remarks
110  //! If the scaling goes out of bounds, it is trimmed.
111  //! For example, 0.01 allows freq_coeff values in range [0.99; 1.01].
112  //! @note
113  //! If zero, default value is used.
114  //! Negative value is an error.
116 
117  //! Initialize.
121  , target_latency(0)
122  , latency_tolerance(0)
123  , stale_tolerance(0)
124  , scaling_interval(0)
125  , scaling_tolerance(0) {
126  }
127 
128  //! Automatically fill missing settings.
129  void deduce_defaults(core::nanoseconds_t default_target_latency, bool is_receiver);
130 };
131 
132 //! Latency-related metrics.
134  //! Estimated network incoming queue latency.
135  //! An estimate of how much media is buffered in receiver packet queue.
137 
138  //! Delay since last received packet.
139  //! In other words, how long there were no new packets in network incoming queue.
141 
142  //! Estimated end-to-end latency.
143  //! An estimate of the time from recording a frame on sender to playing it
144  //! on receiver.
146 
148  : niq_latency(0)
149  , niq_stalling(0)
150  , e2e_latency(0) {
151  }
152 };
153 
154 //! Latency tuner.
155 //!
156 //! On receiver, LatencyMonitor computes local metrics and passes them to LatencyTuner.
157 //! On sender, FeedbackMonitor obtains remote metrics and passes them to LatencyTuner.
158 //! In both cases, LatencyTuner processes metrics and computes scaling factor that
159 //! should be passed to resampler.
160 //!
161 //! Features:
162 //! - monitors how close actual latency and target latency are
163 //! - monitors whether latency goes out of bounds
164 //! - assuming that the difference between actual latency and target latency is
165 //! caused by the clock drift between sender and receiver, calculates scaling
166 //! factor for resampler to compensate it
167 class LatencyTuner : public core::NonCopyable<> {
168 public:
169  //! Initialize.
170  LatencyTuner(const LatencyConfig& config, const SampleSpec& sample_spec);
171 
172  //! Check if the object was initialized successfully.
173  bool is_valid() const;
174 
175  //! Pass updated metrics to tuner.
176  //! Tuner will use new values next time when update_stream() is called.
177  void write_metrics(const LatencyMetrics& latency_metrics,
178  const packet::LinkMetrics& link_metrics);
179 
180  //! Update stream latency and scaling.
181  //! This method performs all actual work:
182  //! - depending on configured backend, selects which latency from
183  //! metrics to use
184  //! - check if latency goes out of bounds and session should be
185  //! terminated; if so, returns false
186  //! - computes updated scaling based on latency history and configured
187  //! profile
189 
190  //! Advance stream by given number of samples.
191  //! Should be called after updating stream.
193 
194  //! If scaling has changed, returns updated value.
195  //! Otherwise, returns zero.
196  //! @remarks
197  //! Latency tuner expects that this scaling will applied to the stream
198  //! resampler, so that the latency will slowly achieve target value.
199  //! Returned value is close to 1.0.
200  float fetch_scaling();
201 
202 private:
203  bool check_bounds_(packet::stream_timestamp_diff_t latency);
204  void compute_scaling_(packet::stream_timestamp_diff_t latency);
205  void report_();
206 
208 
209  packet::stream_timestamp_t stream_pos_;
210 
211  packet::stream_timestamp_diff_t scale_interval_;
212  packet::stream_timestamp_t scale_pos_;
213 
214  packet::stream_timestamp_diff_t report_interval_;
215  packet::stream_timestamp_t report_pos_;
216 
217  bool has_new_freq_coeff_;
218  float freq_coeff_;
219  const float freq_coeff_max_delta_;
220 
221  const LatencyTunerBackend backend_;
222  const LatencyTunerProfile profile_;
223 
224  const bool enable_tuning_;
225  const bool enable_bounds_;
226 
227  bool has_niq_latency_;
228  packet::stream_timestamp_diff_t niq_latency_;
229  packet::stream_timestamp_diff_t niq_stalling_;
230 
231  bool has_e2e_latency_;
232  packet::stream_timestamp_diff_t e2e_latency_;
233 
234  bool has_jitter_;
236 
237  packet::stream_timestamp_diff_t target_latency_;
238  packet::stream_timestamp_diff_t min_latency_;
239  packet::stream_timestamp_diff_t max_latency_;
240  packet::stream_timestamp_diff_t max_stalling_;
241 
242  const SampleSpec sample_spec_;
243 
244  bool valid_;
245 };
246 
247 //! Get string name of latency backend.
249 
250 //! Get string name of latency tuner.
252 
253 } // namespace audio
254 } // namespace roc
255 
256 #endif // ROC_AUDIO_LATENCY_TUNER_H_
float fetch_scaling()
If scaling has changed, returns updated value. Otherwise, returns zero.
void advance_stream(packet::stream_timestamp_t duration)
Advance stream by given number of samples. Should be called after updating stream.
bool is_valid() const
Check if the object was initialized successfully.
bool update_stream()
Update stream latency and scaling. This method performs all actual work:
void write_metrics(const LatencyMetrics &latency_metrics, const packet::LinkMetrics &link_metrics)
Pass updated metrics to tuner. Tuner will use new values next time when update_stream() is called.
LatencyTuner(const LatencyConfig &config, const SampleSpec &sample_spec)
Initialize.
Sample specification. Describes sample rate and channels.
Definition: sample_spec.h:30
Base class for non-copyable objects.
Definition: noncopyable.h:23
Optionally constructed object.
Definition: optional.h:25
Frequency estimator.
LatencyTunerBackend
Latency tuner backend. Defines which latency we monitor and tune to achieve target.
Definition: latency_tuner.h:29
@ LatencyTunerBackend_Niq
Latency is Network Incoming Queue length. Calculated on receiver without use of any signaling protoco...
Definition: latency_tuner.h:36
@ LatencyTunerBackend_E2e
Latency is End-to-end delay. Can on receiver if RTCP XR is supported by both sides....
Definition: latency_tuner.h:41
@ LatencyTunerBackend_Default
Deduce best default for given settings.
Definition: latency_tuner.h:31
const char * latency_tuner_profile_to_str(LatencyTunerProfile tuner)
Get string name of latency tuner.
LatencyTunerProfile
Latency tuner profile. Defines whether and how we tune latency on fly to compensate clock drift and j...
Definition: latency_tuner.h:47
@ LatencyTunerProfile_Responsive
Fast and responsive tuning. Good for lower network latency and jitter.
Definition: latency_tuner.h:56
@ LatencyTunerProfile_Default
Deduce best default for given settings.
Definition: latency_tuner.h:49
@ LatencyTunerProfile_Gradual
Slow and smooth tuning. Good for higher network latency and jitter.
Definition: latency_tuner.h:60
@ LatencyTunerProfile_Intact
Do not tune latency.
Definition: latency_tuner.h:52
const char * latency_tuner_backend_to_str(LatencyTunerBackend backend)
Get string name of latency backend.
int64_t nanoseconds_t
Nanoseconds.
Definition: time.h:58
uint32_t stream_timestamp_t
Packet stream timestamp.
Definition: units.h:36
int32_t stream_timestamp_diff_t
Packet stream timestamp delta.
Definition: units.h:41
Root namespace.
Non-copyable object.
Optionally constructed object.
Sample specifications.
Status codes.
Latency settings.
Definition: latency_tuner.h:64
core::nanoseconds_t target_latency
Target latency.
Definition: latency_tuner.h:81
LatencyTunerProfile tuner_profile
Latency tuner profile to use.
Definition: latency_tuner.h:73
core::nanoseconds_t latency_tolerance
Maximum allowed deviation from target latency.
Definition: latency_tuner.h:89
void deduce_defaults(core::nanoseconds_t default_target_latency, bool is_receiver)
Automatically fill missing settings.
core::nanoseconds_t scaling_interval
Scaling update interval.
float scaling_tolerance
Maximum allowed deviation of freq_coeff from 1.0.
core::nanoseconds_t stale_tolerance
Maximum delay since last packet before queue is considered stalling.
Definition: latency_tuner.h:98
LatencyTunerBackend tuner_backend
Latency tuner backend to use.
Definition: latency_tuner.h:68
Latency-related metrics.
core::nanoseconds_t niq_latency
Estimated network incoming queue latency. An estimate of how much media is buffered in receiver packe...
core::nanoseconds_t e2e_latency
Estimated end-to-end latency. An estimate of the time from recording a frame on sender to playing it ...
core::nanoseconds_t niq_stalling
Delay since last received packet. In other words, how long there were no new packets in network incom...
Time definitions.
Various units used in packets.