1 /*
2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "modules/audio_coding/neteq/reorder_optimizer.h"
12
13 #include <algorithm>
14 #include <limits>
15 #include <vector>
16
17 namespace webrtc {
18
19 namespace {
20
21 constexpr int kDelayBuckets = 100;
22 constexpr int kBucketSizeMs = 20;
23
24 } // namespace
25
ReorderOptimizer(int forget_factor,int ms_per_loss_percent,absl::optional<int> start_forget_weight)26 ReorderOptimizer::ReorderOptimizer(int forget_factor,
27 int ms_per_loss_percent,
28 absl::optional<int> start_forget_weight)
29 : histogram_(kDelayBuckets, forget_factor, start_forget_weight),
30 ms_per_loss_percent_(ms_per_loss_percent) {}
31
Update(int relative_delay_ms,bool reordered,int base_delay_ms)32 void ReorderOptimizer::Update(int relative_delay_ms,
33 bool reordered,
34 int base_delay_ms) {
35 const int index = reordered ? relative_delay_ms / kBucketSizeMs : 0;
36 if (index < histogram_.NumBuckets()) {
37 // Maximum delay to register is 2000 ms.
38 histogram_.Add(index);
39 }
40 int bucket_index = MinimizeCostFunction(base_delay_ms);
41 optimal_delay_ms_ = (1 + bucket_index) * kBucketSizeMs;
42 }
43
Reset()44 void ReorderOptimizer::Reset() {
45 histogram_.Reset();
46 optimal_delay_ms_.reset();
47 }
48
MinimizeCostFunction(int base_delay_ms) const49 int ReorderOptimizer::MinimizeCostFunction(int base_delay_ms) const {
50 const std::vector<int>& buckets = histogram_.buckets();
51
52 // Values are calculated in Q30.
53 int64_t loss_probability = 1 << 30;
54 int64_t min_cost = std::numeric_limits<int64_t>::max();
55 int min_bucket = 0;
56 for (int i = 0; i < static_cast<int>(buckets.size()); ++i) {
57 loss_probability -= buckets[i];
58 int64_t delay_ms =
59 static_cast<int64_t>(std::max(0, i * kBucketSizeMs - base_delay_ms))
60 << 30;
61 int64_t cost = delay_ms + 100 * ms_per_loss_percent_ * loss_probability;
62
63 if (cost < min_cost) {
64 min_cost = cost;
65 min_bucket = i;
66 }
67 if (loss_probability == 0) {
68 break;
69 }
70 }
71
72 return min_bucket;
73 }
74
75 } // namespace webrtc
76