mediasoup 3.27.0 → 3.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/package.json +1 -1
  3. package/worker/fbs/FBS/meson.build +25 -0
  4. package/worker/fbs/meson.build +15 -18
  5. package/worker/include/RTC/BWE/BweTypes.hpp +1 -1
  6. package/worker/include/RTC/BWE/LossBasedController.hpp +520 -0
  7. package/worker/include/RTC/BWE/TargetRateController.hpp +306 -0
  8. package/worker/include/RTC/BWE/TrendlineEstimator.hpp +58 -16
  9. package/worker/include/RTC/BWE/Utils.hpp +39 -0
  10. package/worker/include/RTC/SCTP/association/StreamResetHandler.hpp +36 -0
  11. package/worker/include/RTC/SCTP/public/SctpTypes.hpp +5 -5
  12. package/worker/include/RTC/SCTP/rx/ReassemblyQueue.hpp +10 -0
  13. package/worker/meson.build +6 -0
  14. package/worker/src/RTC/BWE/LossBasedController.cpp +1046 -0
  15. package/worker/src/RTC/BWE/TargetRateController.cpp +435 -0
  16. package/worker/src/RTC/BWE/TrendlineEstimator.cpp +83 -5
  17. package/worker/src/RTC/BWE/Utils.cpp +54 -0
  18. package/worker/src/RTC/SCTP/association/Association.cpp +15 -1
  19. package/worker/src/RTC/SCTP/association/StreamResetHandler.cpp +106 -1
  20. package/worker/src/RTC/SCTP/public/AssociationMetrics.cpp +1 -1
  21. package/worker/src/RTC/Transport.cpp +37 -18
  22. package/worker/tasks.py +43 -18
  23. package/worker/test/src/RTC/BWE/TestLossBasedController.cpp +1199 -0
  24. package/worker/test/src/RTC/BWE/TestTargetRateController.cpp +337 -0
  25. package/worker/test/src/RTC/BWE/TestTrendlineEstimator.cpp +45 -0
  26. package/worker/test/src/RTC/BWE/TestUtils.cpp +61 -0
  27. package/worker/test/src/RTC/SCTP/association/TestStreamResetHandler.cpp +111 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ### NEXT
4
4
 
5
+ ### 3.27.1
6
+
7
+ - Worker: Fix endless regeneration of FlatBuffers generated headers ([PR #1926](https://github.com/versatica/mediasoup/pull/1926)).
8
+ - SCTP: Fix unbounded SCTP reassembly queue growth during deferred reset processing ([PR #1927](https://github.com/versatica/mediasoup/pull/1927)).
9
+
5
10
  ### 3.27.0
6
11
 
7
12
  - Worker: New `RateCalculator` ([PR #1899](https://github.com/versatica/mediasoup/pull/1899)).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mediasoup",
3
- "version": "3.27.0",
3
+ "version": "3.27.1",
4
4
  "description": "Cutting Edge WebRTC Video Conferencing",
5
5
  "contributors": [
6
6
  "Iñaki Baz Castillo <ibc@aliax.net> (https://inakibaz.me)",
@@ -0,0 +1,25 @@
1
+ # The generator writes a single header per schema, with the same base name and
2
+ # a .h extension since the empty --filename-suffix removes the default one.
3
+ flatbuffers_headers = []
4
+
5
+ foreach schema : flatbuffers_schemas
6
+ flatbuffers_headers += schema.replace('.fbs', '.h')
7
+ endforeach
8
+
9
+ flatc = find_program('flatc')
10
+
11
+ flatbuffers_generator = custom_target('flatbuffers-generator',
12
+ output: flatbuffers_headers,
13
+ input: flatbuffers_schema_files,
14
+ command : [
15
+ flatc,
16
+ '--cpp',
17
+ '--cpp-field-case-style', 'lower',
18
+ '--reflect-names',
19
+ '--scoped-enums',
20
+ '--filename-suffix', '',
21
+ '-o', '@OUTDIR@',
22
+ '@INPUT@'
23
+ ],
24
+ build_by_default: true,
25
+ )
@@ -29,26 +29,23 @@ flatbuffers_schemas = [
29
29
  'worker.fbs',
30
30
  ]
31
31
 
32
- # Directory from which worker code will include the header files.
33
- flatbuffers_cpp_out_dir = 'FBS'
32
+ # The schemas are turned into file objects here because the target that
33
+ # consumes them is declared in the FBS subdirectory, where plain relative names
34
+ # would no longer resolve.
35
+ flatbuffers_schema_files = files(flatbuffers_schemas)
34
36
 
35
- flatc = find_program('flatc')
36
- flatbuffers_generator = custom_target('flatbuffers-generator',
37
- output: flatbuffers_cpp_out_dir,
38
- input: flatbuffers_schemas,
39
- command : [
40
- flatc,
41
- '--cpp',
42
- '--cpp-field-case-style', 'lower',
43
- '--reflect-names',
44
- '--scoped-enums',
45
- '--filename-suffix', '',
46
- '-o', '@OUTPUT@',
47
- '@INPUT@'
48
- ],
49
- build_by_default: true,
50
- )
37
+ # FBS is the directory from which worker code includes the generated header
38
+ # files. The generator target is declared from within that very subdirectory
39
+ # because Meson does not allow path segments in the outputs of a custom target,
40
+ # and the outputs must be the individual headers rather than the directory that
41
+ # holds them. Declaring the directory as the output makes the target dirty
42
+ # forever: running the generator rewrites the headers in place, which never
43
+ # updates the modification time of the directory containing them, so the target
44
+ # never becomes up to date and every build regenerates the headers and
45
+ # recompiles every source file that includes them.
46
+ subdir('FBS')
51
47
 
52
48
  flatbuffers_generator_dep = declare_dependency(
53
49
  include_directories: '.',
50
+ sources: flatbuffers_generator,
54
51
  )
@@ -41,7 +41,7 @@ namespace RTC
41
41
  OVERUSING
42
42
  };
43
43
 
44
- constexpr std::string_view BandwidthUsageToString(BandwidthUsage bandwidthUsage)
44
+ constexpr std::string_view bandwidthUsageToString(BandwidthUsage bandwidthUsage)
45
45
  {
46
46
  switch (bandwidthUsage)
47
47
  {
@@ -0,0 +1,520 @@
1
+ #ifndef MS_RTC_BWE_LOSS_BASED_CONTROLLER_HPP
2
+ #define MS_RTC_BWE_LOSS_BASED_CONTROLLER_HPP
3
+
4
+ #include "common.hpp"
5
+ #include "RTC/BWE/BweTypes.hpp"
6
+ #include <ankerl/unordered_dense.h>
7
+ #include <vector>
8
+
9
+ namespace RTC
10
+ {
11
+ namespace BWE
12
+ {
13
+ /**
14
+ * Tells the loss caused by congestion from the loss a link has by itself.
15
+ *
16
+ * A link can lose packets without being congested at all, which is the normal
17
+ * state of Wi-Fi and mobile links, and reacting to that loss by sending less
18
+ * doesn't reduce it: it just gives away capacity that was there. Telling both
19
+ * apart cannot be done by looking at a loss figure, because the very same
20
+ * figure means different things at different sending rates.
21
+ *
22
+ * So instead of a rule on the reported loss, this is an estimator of two
23
+ * values that together describe the link: how much it loses when it is not
24
+ * congested, and how much it can carry. With those two, the loss to expect
25
+ * from an observation is known: the inherent one while sending below the
26
+ * capacity, plus the share of the excess while sending above it. The pair of
27
+ * values that makes the losses actually observed most likely is the estimate,
28
+ * and the bitrate of that pair is the answer.
29
+ *
30
+ * Candidates slightly above, at and below the current estimate are tried on
31
+ * every update, each refined by a step of Newton's method on the inherent
32
+ * loss, and the most likely one wins. A bias towards higher bitrates keeps
33
+ * the estimate from settling low when the observations cannot tell them
34
+ * apart, and fades away as the observed loss grows.
35
+ *
36
+ * @remarks
37
+ * - This class is a port of the LossBasedBweV2 class in libwebrtc (renamed to
38
+ * a better name).
39
+ */
40
+ class LossBasedController
41
+ {
42
+ public:
43
+ struct LossBasedControllerOptions
44
+ {
45
+ /**
46
+ * Factors applied to the current estimate to build the candidates that
47
+ * are tried on every update.
48
+ */
49
+ std::vector<double> candidateFactors{ 1.02, 1.0, 0.95 };
50
+ /**
51
+ * How much the estimate may grow over the acknowledged bitrate while
52
+ * the link is loss limited.
53
+ */
54
+ double bitrateRampupUpperBoundFactor{ 1.5 };
55
+ /**
56
+ * The same while the estimate is being held, which is more conservative
57
+ * because holding means that a higher bitrate already caused loss.
58
+ */
59
+ double bitrateRampupUpperBoundFactorInHold{ 1.2 };
60
+ /**
61
+ * How far below the held bitrate the acknowledged one has to be for the
62
+ * factor above to be the one applied.
63
+ */
64
+ double bitrateRampupHoldThreshold{ 1.3 };
65
+ /**
66
+ * How much of the acknowledged bitrate the estimate may grow by on top
67
+ * of its usual bound, the longer the more time has passed since it was
68
+ * last reduced. Zero disables that acceleration.
69
+ */
70
+ double rampupAccelerationMaxFactor{ 0.0 };
71
+ /**
72
+ * Time since the last reduction at which that acceleration is at its
73
+ * fullest.
74
+ */
75
+ int64_t rampupAccelerationMaxoutTimeUs{ 60 * 1000 * 1000 };
76
+ /**
77
+ * Weight given to a higher bitrate when choosing among candidates, so
78
+ * that observations which cannot tell them apart don't settle low.
79
+ */
80
+ double higherBitrateBiasFactor{ 0.0002 };
81
+ /**
82
+ * The same, applied to the logarithm of the bitrate, so that the bias
83
+ * doesn't grow without bound.
84
+ */
85
+ double higherLogBitrateBiasFactor{ 0.02 };
86
+ /**
87
+ * Observed loss at which the bias above is gone, since at that much loss
88
+ * preferring a higher bitrate is not defensible anymore.
89
+ */
90
+ double lossThresholdOfHighBitratePreference{ 0.2 };
91
+ /**
92
+ * How abruptly that bias fades as the observed loss approaches the
93
+ * threshold above.
94
+ */
95
+ double bitratePreferenceSmoothingFactor{ 0.002 };
96
+ /**
97
+ * Lowest inherent loss that may be estimated for a link.
98
+ */
99
+ double inherentLossLowerBound{ 1.0e-3 };
100
+ /**
101
+ * Inherent loss that may be estimated at an unbounded bitrate, which
102
+ * grows as the bitrate gets lower by the balance below.
103
+ */
104
+ double inherentLossUpperBoundOffset{ 0.05 };
105
+ /**
106
+ * Bitrate at which the inherent loss upper bound grows by one, so that a
107
+ * low bitrate is allowed to be explained by a lossy link.
108
+ */
109
+ int64_t inherentLossUpperBoundBitrateBalance{ 100000 };
110
+ /**
111
+ * Inherent loss assumed before anything has been observed.
112
+ */
113
+ double initialInherentLossEstimate{ 0.01 };
114
+ /**
115
+ * Steps of Newton's method applied to each candidate.
116
+ */
117
+ int64_t newtonIterations{ 1 };
118
+ /**
119
+ * Fraction of the step that each of those iterations takes.
120
+ */
121
+ double newtonStepSize{ 0.75 };
122
+ /**
123
+ * Whether the acknowledged bitrate is tried as a candidate of its own.
124
+ */
125
+ bool appendAcknowledgedRateCandidate{ true };
126
+ /**
127
+ * Whether the delay based estimate is tried as a candidate of its own
128
+ * while it's above the current one.
129
+ */
130
+ bool appendDelayBasedEstimateCandidate{ true };
131
+ /**
132
+ * Whether the bound that the observed loss puts on the estimate is tried
133
+ * as a candidate while not filling the link, which lets the estimate
134
+ * come down to it in one step instead of gradually.
135
+ */
136
+ bool appendUpperBoundCandidateInAlr{ false };
137
+ /**
138
+ * Shortest span of send times that an observation may cover.
139
+ */
140
+ int64_t observationDurationLowerBoundUs{ 250 * 1000 };
141
+ /**
142
+ * Observations kept, which is how far back the estimate looks.
143
+ */
144
+ int64_t observationWindowSize{ 15 };
145
+ /**
146
+ * Observations needed before this controller may be used at all.
147
+ */
148
+ int64_t minNumObservations{ 3 };
149
+ /**
150
+ * How much the sending rate of an observation is smoothed with the one
151
+ * of the previous observation.
152
+ *
153
+ * @remarks
154
+ * - Zero means no smoothing at all, which is what libwebrtc does. A
155
+ * sender of a couple of streams has a sending rate that only changes
156
+ * when it decides so, while ours is the sum of many streams whose
157
+ * makeup changes on its own, and those changes are not the network.
158
+ */
159
+ double sendingRateSmoothingFactor{ 0.0 };
160
+ /**
161
+ * How much weight each observation loses per observation of age when
162
+ * looking for the most likely pair of values.
163
+ */
164
+ double temporalWeightFactor{ 0.9 };
165
+ /**
166
+ * The same, for the average observed loss that bounds the estimate right
167
+ * away.
168
+ */
169
+ double immediateUpperBoundTemporalWeightFactor{ 0.9 };
170
+ /**
171
+ * Observed loss under which no immediate upper bound is applied.
172
+ */
173
+ double immediateUpperBoundLossOffset{ 0.05 };
174
+ /**
175
+ * Bitrate the immediate upper bound allows per unit of observed loss
176
+ * over the offset above.
177
+ */
178
+ int64_t immediateUpperBoundBitrateBalance{ 100000 };
179
+ /**
180
+ * How much of the acknowledged bitrate the estimate may never go below.
181
+ */
182
+ double lowerBoundByAckedRateFactor{ 1.0 };
183
+ /**
184
+ * Fraction of the acknowledged bitrate taken as a candidate when backing
185
+ * off.
186
+ */
187
+ double bitrateBackoffLowerBoundFactor{ 1.0 };
188
+ /**
189
+ * How much the estimate may grow within the window that follows a
190
+ * decrease.
191
+ */
192
+ double maxIncreaseFactor{ 1.3 };
193
+ /**
194
+ * How long that window lasts.
195
+ */
196
+ int64_t delayedIncreaseWindowUs{ 300 * 1000 };
197
+ /**
198
+ * Whether the estimate is held back while the loss observed is worse
199
+ * than the one the chosen candidate says the link has by itself, since
200
+ * then the excess is ours to fix.
201
+ */
202
+ bool notIncreaseIfInherentLossLessThanAverageLoss{ true };
203
+ /**
204
+ * Whether the acknowledged bitrate stops being a candidate while not
205
+ * filling the link, since then what it delivers says nothing about what
206
+ * it could deliver.
207
+ */
208
+ bool notUseAckedRateInAlr{ true };
209
+ /**
210
+ * Whether this controller may take the estimate over while the target is
211
+ * still in its start phase.
212
+ */
213
+ bool useInStartPhase{ true };
214
+ /**
215
+ * How much each hold lasts compared to the previous one, which makes
216
+ * repeated failures to increase back off for longer.
217
+ */
218
+ double holdDurationFactor{ 2.0 };
219
+ /**
220
+ * Whether loss is measured in bytes rather than in packets, which tells
221
+ * a lost packet of a full frame apart from a lost one carrying almost
222
+ * nothing.
223
+ */
224
+ bool useByteLossRate{ true };
225
+ /**
226
+ * Whether an estimate that had to be brought down to its bounds stops
227
+ * being kept as a description of the link.
228
+ */
229
+ bool boundBestCandidate{ true };
230
+ /**
231
+ * How much the sending rate of an observation has to exceed the median
232
+ * of the window for its loss to be taken at face value instead of as a
233
+ * spike.
234
+ */
235
+ double medianSendingRateFactor{ 2.0 };
236
+ };
237
+
238
+ /**
239
+ * What this controller is doing with the estimate, which the orchestrator
240
+ * needs in order to decide whether to probe.
241
+ */
242
+ enum class State : uint8_t
243
+ {
244
+ /**
245
+ * The link is loss limited and the estimate is growing back.
246
+ */
247
+ INCREASING,
248
+ /**
249
+ * The link is loss limited and the estimate is being reduced.
250
+ */
251
+ DECREASING,
252
+ /**
253
+ * The link is not loss limited, so the delay based estimate rules.
254
+ */
255
+ DELAY_BASED_ESTIMATE
256
+ };
257
+
258
+ struct Result
259
+ {
260
+ int64_t bitrate{ 0 };
261
+ State state{ State::DELAY_BASED_ESTIMATE };
262
+ };
263
+
264
+ private:
265
+ /**
266
+ * The pair of values that describe a link.
267
+ */
268
+ struct ChannelParameters
269
+ {
270
+ /**
271
+ * Loss the link has while not congested at all.
272
+ */
273
+ double inherentLoss{ 0.0 };
274
+ /**
275
+ * Bitrate the link can carry, or zero while it's not known yet.
276
+ */
277
+ int64_t lossLimitedBitrate{ 0 };
278
+ };
279
+
280
+ /**
281
+ * First and second derivatives of the likelihood with respect to the
282
+ * inherent loss, which is what Newton's method needs.
283
+ */
284
+ struct Derivatives
285
+ {
286
+ double first{ 0.0 };
287
+ double second{ 0.0 };
288
+ };
289
+
290
+ /**
291
+ * What was sent and lost over a span of send times, which is the unit this
292
+ * controller reasons about.
293
+ */
294
+ struct Observation
295
+ {
296
+ bool IsInitialized() const
297
+ {
298
+ return this->id != -1;
299
+ }
300
+
301
+ int64_t numPackets{ 0 };
302
+ int64_t numLostPackets{ 0 };
303
+ int64_t numReceivedPackets{ 0 };
304
+ int64_t sendingRate{ 0 };
305
+ int64_t sizeBytes{ 0 };
306
+ int64_t lostSizeBytes{ 0 };
307
+ int64_t id{ -1 };
308
+ };
309
+
310
+ /**
311
+ * Feedback accumulated so far, which becomes an observation once it covers
312
+ * a long enough span of send times.
313
+ */
314
+ struct PartialObservation
315
+ {
316
+ /**
317
+ * Size of the packets reported as lost, by sequence number, so that a
318
+ * packet reported lost and received later stops counting.
319
+ */
320
+ ankerl::unordered_dense::map<int64_t, int64_t> lostPackets;
321
+ int64_t numPackets{ 0 };
322
+ int64_t sizeBytes{ 0 };
323
+ };
324
+
325
+ /**
326
+ * The bitrate the estimate is not allowed to grow above while holding, and
327
+ * for how long.
328
+ */
329
+ struct HoldInfo
330
+ {
331
+ int64_t atUs{ 0 };
332
+ int64_t durationUs{ 0 };
333
+ int64_t bitrate{ Types::BitrateInfinite };
334
+ };
335
+
336
+ public:
337
+ LossBasedController();
338
+
339
+ explicit LossBasedController(LossBasedControllerOptions options);
340
+
341
+ /**
342
+ * Whether enough has been observed for this controller to say anything.
343
+ */
344
+ bool IsReady() const;
345
+
346
+ /**
347
+ * Whether this controller may take the estimate over while the target is
348
+ * still in its start phase.
349
+ */
350
+ bool IsReadyToUseInStartPhase() const;
351
+
352
+ /**
353
+ * Whether this controller is allowed to be used during the start phase at
354
+ * all, regardless of whether it has observed enough to say anything.
355
+ */
356
+ bool IsUsedInStartPhase() const
357
+ {
358
+ return this->options.useInStartPhase;
359
+ }
360
+
361
+ /**
362
+ * Forget everything observed so far, which is what a link that is not the
363
+ * same one anymore calls for.
364
+ */
365
+ void Reset();
366
+
367
+ /**
368
+ * Latest estimate, or the delay based one while this controller cannot say
369
+ * anything yet.
370
+ */
371
+ Result GetResult() const;
372
+
373
+ void SetAcknowledgedBitrate(int64_t acknowledgedBitrate);
374
+
375
+ void SetBitrateLimits(int64_t minBitrate, int64_t maxBitrate);
376
+
377
+ /**
378
+ * Place the estimate at the given bitrate.
379
+ */
380
+ void SetBitrateEstimate(int64_t bitrate);
381
+
382
+ /**
383
+ * Feed the results of a feedback message.
384
+ *
385
+ * @param delayBasedEstimate - Estimate of the delay based path, which
386
+ * bounds this one, or `Types::BitrateInfinite` if there is none.
387
+ * @param inAlr - Whether the sender is not sending enough to fill the link,
388
+ * in which case the acknowledged bitrate says nothing about its capacity.
389
+ */
390
+ void UpdateBitrateEstimate(
391
+ const std::vector<Types::PacketResult>& packetResults, int64_t delayBasedEstimate, bool inAlr);
392
+
393
+ private:
394
+ /**
395
+ * Add the given results to the observation being accumulated, and close it
396
+ * if it already covers a long enough span of send times.
397
+ *
398
+ * @returns Whether an observation was closed, which is when the estimate
399
+ * can be recalculated.
400
+ */
401
+ bool PushBackObservation(const std::vector<Types::PacketResult>& packetResults);
402
+
403
+ /**
404
+ * Candidates to try on this update, each already within bounds.
405
+ */
406
+ std::vector<ChannelParameters> GetCandidates(bool inAlr) const;
407
+
408
+ /**
409
+ * Highest bitrate a candidate may have.
410
+ */
411
+ int64_t GetCandidateBitrateUpperBound() const;
412
+
413
+ /**
414
+ * How likely the losses observed are if the link were as the given pair of
415
+ * values says, plus the bias towards higher bitrates.
416
+ */
417
+ double GetObjective(const ChannelParameters& channelParameters) const;
418
+
419
+ Derivatives GetDerivatives(const ChannelParameters& channelParameters) const;
420
+
421
+ /**
422
+ * Refine the inherent loss of the given candidate.
423
+ */
424
+ void ApplyNewtonsMethod(ChannelParameters& channelParameters) const;
425
+
426
+ /**
427
+ * Bring the inherent loss of the given candidate within what a link at its
428
+ * bitrate could plausibly have.
429
+ */
430
+ double GetFeasibleInherentLoss(const ChannelParameters& channelParameters) const;
431
+
432
+ double GetInherentLossUpperBound(int64_t bitrate) const;
433
+
434
+ double AdjustBiasFactor(double lossRate, double biasFactor) const;
435
+
436
+ double GetHighBitrateBias(int64_t bitrate) const;
437
+
438
+ /**
439
+ * Sending rate an observation is taken to have, which is its own smoothed
440
+ * with the one of the previous observation.
441
+ */
442
+ int64_t GetSendingRate(int64_t instantSendingRate) const;
443
+
444
+ /**
445
+ * Average loss observed over the window, leaving out the highest and the
446
+ * lowest so that a single spike doesn't drag it.
447
+ */
448
+ void UpdateAverageReportedLossRatio();
449
+
450
+ double CalculateAverageReportedPacketLossRatio() const;
451
+
452
+ /**
453
+ * The same by bytes, which tells a lost packet carrying a full frame apart
454
+ * from one carrying almost nothing.
455
+ */
456
+ double CalculateAverageReportedByteLossRatio() const;
457
+
458
+ int64_t GetMedianSendingRate() const;
459
+
460
+ /**
461
+ * Bound that the observed loss puts on the estimate right away, without
462
+ * waiting for it to converge.
463
+ */
464
+ int64_t GetImmediateUpperBoundBitrate() const;
465
+
466
+ void CalculateImmediateUpperBoundBitrate();
467
+
468
+ int64_t GetImmediateLowerBoundBitrate() const;
469
+
470
+ void CalculateImmediateLowerBoundBitrate();
471
+
472
+ void CalculateTemporalWeights();
473
+
474
+ /**
475
+ * Whether the link is loss limited at all, which is what tells this
476
+ * controller's estimate apart from just following the delay based one.
477
+ */
478
+ bool IsInLossLimitedState() const;
479
+
480
+ bool IsEstimateIncreasingWhenLossLimited(int64_t oldEstimate, int64_t newEstimate) const;
481
+
482
+ private:
483
+ // Passed by argument.
484
+ const LossBasedControllerOptions options;
485
+ // Others.
486
+ // Observations of the window, indexed by their id modulo its size.
487
+ std::vector<Observation> observations;
488
+ // Weight of an observation per observation of age.
489
+ std::vector<double> temporalWeights;
490
+ // The same, for the average observed loss.
491
+ std::vector<double> immediateUpperBoundTemporalWeights;
492
+ struct PartialObservation partialObservation;
493
+ struct ChannelParameters currentBestEstimate;
494
+ struct HoldInfo lastHoldInfo;
495
+ struct Result result;
496
+ // Observations closed so far, which never decreases and hence also gives
497
+ // the id of the next one.
498
+ int64_t numObservations{ 0 };
499
+ // Highest send time of the latest observation, which is the clock this
500
+ // controller runs on. Feedback is the only thing that moves it.
501
+ std::optional<int64_t> lastSendTimeOfLatestObservationUs;
502
+ double averageReportedLossRatio{ 0.0 };
503
+ int64_t acknowledgedBitrate{ Types::BitrateInfinite };
504
+ int64_t delayBasedEstimate{ Types::BitrateInfinite };
505
+ int64_t minBitrate{ 0 };
506
+ int64_t maxBitrate{ Types::BitrateInfinite };
507
+ std::optional<int64_t> immediateUpperBoundBitrate;
508
+ std::optional<int64_t> immediateLowerBoundBitrate;
509
+ // Bitrate the estimate may not grow above until the window that follows a
510
+ // decrease is over.
511
+ int64_t bitrateLimitInCurrentWindow{ Types::BitrateInfinite };
512
+ std::optional<int64_t> recoveringAfterLossAtUs;
513
+ // Instant at which the estimate was last brought down, which is what the
514
+ // rampup acceleration grows from.
515
+ std::optional<int64_t> lastBitrateReducedAtUs;
516
+ };
517
+ } // namespace BWE
518
+ } // namespace RTC
519
+
520
+ #endif