Index: webrtc/modules/include/module_common_types.h |
diff --git a/webrtc/modules/include/module_common_types.h b/webrtc/modules/include/module_common_types.h |
index a16c9392a2ec62a3d46ae42a47223c092c141745..4976a2a2a163d98491449ae8947e2d43c45d9ac3 100644 |
--- a/webrtc/modules/include/module_common_types.h |
+++ b/webrtc/modules/include/module_common_types.h |
@@ -20,11 +20,12 @@ |
#include "webrtc/api/video/video_rotation.h" |
#include "webrtc/base/constructormagic.h" |
#include "webrtc/base/deprecation.h" |
+#include "webrtc/base/optional.h" |
#include "webrtc/base/safe_conversions.h" |
#include "webrtc/common_types.h" |
+#include "webrtc/modules/video_coding/codecs/h264/include/h264_globals.h" |
#include "webrtc/modules/video_coding/codecs/vp8/include/vp8_globals.h" |
#include "webrtc/modules/video_coding/codecs/vp9/include/vp9_globals.h" |
-#include "webrtc/modules/video_coding/codecs/h264/include/h264_globals.h" |
#include "webrtc/typedefs.h" |
namespace webrtc { |
@@ -474,28 +475,30 @@ inline AudioFrame& AudioFrame::operator+=(const AudioFrame& rhs) { |
return *this; |
} |
+template <typename U> |
+inline bool IsNewer(U value, U prev_value) { |
+ static_assert(!std::numeric_limits<U>::is_signed, "U must be unsigned"); |
+ // kBreakpoint is the half-way mark for the type U. For instance, for a |
+ // uint16_t it will be 0x8000, and for a uint32_t, it will be 0x8000000. |
+ constexpr U kBreakpoint = (std::numeric_limits<U>::max() >> 1) + 1; |
+ // Distinguish between elements that are exactly kBreakpoint apart. |
+ // If t1>t2 and |t1-t2| = kBreakpoint: IsNewer(t1,t2)=true, |
+ // IsNewer(t2,t1)=false |
+ // rather than having IsNewer(t1,t2) = IsNewer(t2,t1) = false. |
+ if (value - prev_value == kBreakpoint) { |
+ return value > prev_value; |
+ } |
+ return value != prev_value && |
+ static_cast<U>(value - prev_value) < kBreakpoint; |
+} |
+ |
inline bool IsNewerSequenceNumber(uint16_t sequence_number, |
uint16_t prev_sequence_number) { |
- // Distinguish between elements that are exactly 0x8000 apart. |
- // If s1>s2 and |s1-s2| = 0x8000: IsNewer(s1,s2)=true, IsNewer(s2,s1)=false |
- // rather than having IsNewer(s1,s2) = IsNewer(s2,s1) = false. |
- if (static_cast<uint16_t>(sequence_number - prev_sequence_number) == 0x8000) { |
- return sequence_number > prev_sequence_number; |
- } |
- return sequence_number != prev_sequence_number && |
- static_cast<uint16_t>(sequence_number - prev_sequence_number) < 0x8000; |
+ return IsNewer(sequence_number, prev_sequence_number); |
} |
inline bool IsNewerTimestamp(uint32_t timestamp, uint32_t prev_timestamp) { |
- // Distinguish between elements that are exactly 0x80000000 apart. |
- // If t1>t2 and |t1-t2| = 0x80000000: IsNewer(t1,t2)=true, |
- // IsNewer(t2,t1)=false |
- // rather than having IsNewer(t1,t2) = IsNewer(t2,t1) = false. |
- if (static_cast<uint32_t>(timestamp - prev_timestamp) == 0x80000000) { |
- return timestamp > prev_timestamp; |
- } |
- return timestamp != prev_timestamp && |
- static_cast<uint32_t>(timestamp - prev_timestamp) < 0x80000000; |
+ return IsNewer(timestamp, prev_timestamp); |
} |
inline uint16_t LatestSequenceNumber(uint16_t sequence_number1, |
@@ -509,46 +512,57 @@ inline uint32_t LatestTimestamp(uint32_t timestamp1, uint32_t timestamp2) { |
return IsNewerTimestamp(timestamp1, timestamp2) ? timestamp1 : timestamp2; |
} |
-// Utility class to unwrap a sequence number to a larger type, for easier |
-// handling large ranges. Note that sequence numbers will never be unwrapped |
-// to a negative value. |
-class SequenceNumberUnwrapper { |
+// Utility class to unwrap a number to a larger type. The numbers will never be |
+// unwrapped to a negative value. |
+template <typename U> |
+class Unwrapper { |
+ static_assert(!std::numeric_limits<U>::is_signed, "U must be unsigned"); |
+ static_assert(std::numeric_limits<U>::max() <= |
+ std::numeric_limits<uint32_t>::max(), |
+ "U must not be wider than 32 bits"); |
+ |
public: |
- SequenceNumberUnwrapper() : last_seq_(-1) {} |
+ // Get the unwrapped value, but don't update the internal state. |
+ int64_t UnwrapWithoutUpdate(U value) { |
+ if (!last_value_) |
+ return value; |
- // Get the unwrapped sequence, but don't update the internal state. |
- int64_t UnwrapWithoutUpdate(uint16_t sequence_number) { |
- if (last_seq_ == -1) |
- return sequence_number; |
+ constexpr int64_t kMaxPlusOne = |
+ static_cast<int64_t>(std::numeric_limits<U>::max()) + 1; |
- uint16_t cropped_last = static_cast<uint16_t>(last_seq_); |
- int64_t delta = sequence_number - cropped_last; |
- if (IsNewerSequenceNumber(sequence_number, cropped_last)) { |
+ U cropped_last = static_cast<U>(*last_value_); |
+ int64_t delta = value - cropped_last; |
+ if (IsNewer(value, cropped_last)) { |
if (delta < 0) |
- delta += (1 << 16); // Wrap forwards. |
- } else if (delta > 0 && (last_seq_ + delta - (1 << 16)) >= 0) { |
- // If sequence_number is older but delta is positive, this is a backwards |
+ delta += kMaxPlusOne; // Wrap forwards. |
+ } else if (delta > 0 && (*last_value_ + delta - kMaxPlusOne) >= 0) { |
+ // If value is older but delta is positive, this is a backwards |
// wrap-around. However, don't wrap backwards past 0 (unwrapped). |
- delta -= (1 << 16); |
+ delta -= kMaxPlusOne; |
} |
- return last_seq_ + delta; |
+ return *last_value_ + delta; |
} |
- // Only update the internal state to the specified last (unwrapped) sequence. |
- void UpdateLast(int64_t last_sequence) { last_seq_ = last_sequence; } |
+ // Only update the internal state to the specified last (unwrapped) value. |
+ void UpdateLast(int64_t last_value) { |
+ last_value_ = rtc::Optional<int64_t>(last_value); |
+ } |
- // Unwrap the sequence number and update the internal state. |
- int64_t Unwrap(uint16_t sequence_number) { |
- int64_t unwrapped = UnwrapWithoutUpdate(sequence_number); |
+ // Unwrap the value and update the internal state. |
+ int64_t Unwrap(U value) { |
+ int64_t unwrapped = UnwrapWithoutUpdate(value); |
UpdateLast(unwrapped); |
return unwrapped; |
} |
private: |
- int64_t last_seq_; |
+ rtc::Optional<int64_t> last_value_; |
}; |
+using SequenceNumberUnwrapper = Unwrapper<uint16_t>; |
+using TimestampUnwrapper = Unwrapper<uint32_t>; |
+ |
struct PacedPacketInfo { |
PacedPacketInfo() {} |
PacedPacketInfo(int probe_cluster_id, |