1 /*
2 * Copyright (c) 2013 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 "webrtc/modules/remote_bitrate_estimator/inter_arrival.h"
12
13 #include <algorithm>
14 #include <cassert>
15
16 #include "webrtc/base/logging.h"
17 #include "webrtc/modules/include/module_common_types.h"
18
19 namespace webrtc {
20
21 static const int kBurstDeltaThresholdMs = 5;
22
InterArrival(uint32_t timestamp_group_length_ticks,double timestamp_to_ms_coeff,bool enable_burst_grouping)23 InterArrival::InterArrival(uint32_t timestamp_group_length_ticks,
24 double timestamp_to_ms_coeff,
25 bool enable_burst_grouping)
26 : kTimestampGroupLengthTicks(timestamp_group_length_ticks),
27 current_timestamp_group_(),
28 prev_timestamp_group_(),
29 timestamp_to_ms_coeff_(timestamp_to_ms_coeff),
30 burst_grouping_(enable_burst_grouping) {}
31
ComputeDeltas(uint32_t timestamp,int64_t arrival_time_ms,size_t packet_size,uint32_t * timestamp_delta,int64_t * arrival_time_delta_ms,int * packet_size_delta)32 bool InterArrival::ComputeDeltas(uint32_t timestamp,
33 int64_t arrival_time_ms,
34 size_t packet_size,
35 uint32_t* timestamp_delta,
36 int64_t* arrival_time_delta_ms,
37 int* packet_size_delta) {
38 assert(timestamp_delta != NULL);
39 assert(arrival_time_delta_ms != NULL);
40 assert(packet_size_delta != NULL);
41 bool calculated_deltas = false;
42 if (current_timestamp_group_.IsFirstPacket()) {
43 // We don't have enough data to update the filter, so we store it until we
44 // have two frames of data to process.
45 current_timestamp_group_.timestamp = timestamp;
46 current_timestamp_group_.first_timestamp = timestamp;
47 } else if (!PacketInOrder(timestamp)) {
48 return false;
49 } else if (NewTimestampGroup(arrival_time_ms, timestamp)) {
50 // First packet of a later frame, the previous frame sample is ready.
51 if (prev_timestamp_group_.complete_time_ms >= 0) {
52 *timestamp_delta = current_timestamp_group_.timestamp -
53 prev_timestamp_group_.timestamp;
54 *arrival_time_delta_ms = current_timestamp_group_.complete_time_ms -
55 prev_timestamp_group_.complete_time_ms;
56 if (*arrival_time_delta_ms < 0) {
57 // The group of packets has been reordered since receiving its local
58 // arrival timestamp.
59 LOG(LS_WARNING) << "Packets are being reordered on the path from the "
60 "socket to the bandwidth estimator. Ignoring this "
61 "packet for bandwidth estimation.";
62 return false;
63 }
64 assert(*arrival_time_delta_ms >= 0);
65 *packet_size_delta = static_cast<int>(current_timestamp_group_.size) -
66 static_cast<int>(prev_timestamp_group_.size);
67 calculated_deltas = true;
68 }
69 prev_timestamp_group_ = current_timestamp_group_;
70 // The new timestamp is now the current frame.
71 current_timestamp_group_.first_timestamp = timestamp;
72 current_timestamp_group_.timestamp = timestamp;
73 current_timestamp_group_.size = 0;
74 } else {
75 current_timestamp_group_.timestamp = LatestTimestamp(
76 current_timestamp_group_.timestamp, timestamp);
77 }
78 // Accumulate the frame size.
79 current_timestamp_group_.size += packet_size;
80 current_timestamp_group_.complete_time_ms = arrival_time_ms;
81
82 return calculated_deltas;
83 }
84
PacketInOrder(uint32_t timestamp)85 bool InterArrival::PacketInOrder(uint32_t timestamp) {
86 if (current_timestamp_group_.IsFirstPacket()) {
87 return true;
88 } else {
89 // Assume that a diff which is bigger than half the timestamp interval
90 // (32 bits) must be due to reordering. This code is almost identical to
91 // that in IsNewerTimestamp() in module_common_types.h.
92 uint32_t timestamp_diff = timestamp -
93 current_timestamp_group_.first_timestamp;
94 return timestamp_diff < 0x80000000;
95 }
96 }
97
98 // Assumes that |timestamp| is not reordered compared to
99 // |current_timestamp_group_|.
NewTimestampGroup(int64_t arrival_time_ms,uint32_t timestamp) const100 bool InterArrival::NewTimestampGroup(int64_t arrival_time_ms,
101 uint32_t timestamp) const {
102 if (current_timestamp_group_.IsFirstPacket()) {
103 return false;
104 } else if (BelongsToBurst(arrival_time_ms, timestamp)) {
105 return false;
106 } else {
107 uint32_t timestamp_diff = timestamp -
108 current_timestamp_group_.first_timestamp;
109 return timestamp_diff > kTimestampGroupLengthTicks;
110 }
111 }
112
BelongsToBurst(int64_t arrival_time_ms,uint32_t timestamp) const113 bool InterArrival::BelongsToBurst(int64_t arrival_time_ms,
114 uint32_t timestamp) const {
115 if (!burst_grouping_) {
116 return false;
117 }
118 assert(current_timestamp_group_.complete_time_ms >= 0);
119 int64_t arrival_time_delta_ms = arrival_time_ms -
120 current_timestamp_group_.complete_time_ms;
121 uint32_t timestamp_diff = timestamp - current_timestamp_group_.timestamp;
122 int64_t ts_delta_ms = timestamp_to_ms_coeff_ * timestamp_diff + 0.5;
123 if (ts_delta_ms == 0)
124 return true;
125 int propagation_delta_ms = arrival_time_delta_ms - ts_delta_ms;
126 return propagation_delta_ms < 0 &&
127 arrival_time_delta_ms <= kBurstDeltaThresholdMs;
128 }
129 } // namespace webrtc
130