OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #ifndef WEBRTC_MODULES_VIDEO_CODING_SEQUENCE_NUMBER_UTIL_H_ | 11 #ifndef WEBRTC_MODULES_VIDEO_CODING_SEQUENCE_NUMBER_UTIL_H_ |
12 #define WEBRTC_MODULES_VIDEO_CODING_SEQUENCE_NUMBER_UTIL_H_ | 12 #define WEBRTC_MODULES_VIDEO_CODING_SEQUENCE_NUMBER_UTIL_H_ |
13 | 13 |
14 #include <limits> | 14 #include <limits> |
15 #include <type_traits> | 15 #include <type_traits> |
16 | 16 |
17 #include "webrtc/rtc_base/mod_ops.h" | 17 #include "webrtc/rtc_base/mod_ops.h" |
18 #include "webrtc/rtc_base/optional.h" | |
19 #include "webrtc/rtc_base/safe_compare.h" | |
18 | 20 |
19 namespace webrtc { | 21 namespace webrtc { |
20 | 22 |
21 // Test if the sequence number |a| is ahead or at sequence number |b|. | 23 // Test if the sequence number |a| is ahead or at sequence number |b|. |
22 // | 24 // |
23 // If |M| is an even number and the two sequence numbers are at max distance | 25 // If |M| is an even number and the two sequence numbers are at max distance |
24 // from each other, then the sequence number with the highest value is | 26 // from each other, then the sequence number with the highest value is |
25 // considered to be ahead. | 27 // considered to be ahead. |
26 template <typename T, T M> | 28 template <typename T, T M> |
27 inline bool AheadOrAt(T a, T b) { | 29 inline typename std::enable_if<(M > 0), bool>::type AheadOrAt(T a, T b) { |
28 static_assert(std::is_unsigned<T>::value, | 30 static_assert(std::is_unsigned<T>::value, |
29 "Type must be an unsigned integer."); | 31 "Type must be an unsigned integer."); |
30 const T maxDist = M / 2; | 32 const T maxDist = M / 2; |
31 if (!(M & 1) && MinDiff<T, M>(a, b) == maxDist) | 33 if (!(M & 1) && MinDiff<T, M>(a, b) == maxDist) |
32 return b < a; | 34 return b < a; |
33 return ForwardDiff<T, M>(b, a) <= maxDist; | 35 return ForwardDiff<T, M>(b, a) <= maxDist; |
34 } | 36 } |
35 | 37 |
36 template <typename T> | 38 template <typename T, T M> |
37 inline bool AheadOrAt(T a, T b) { | 39 inline typename std::enable_if<(M == 0), bool>::type AheadOrAt(T a, T b) { |
38 static_assert(std::is_unsigned<T>::value, | 40 static_assert(std::is_unsigned<T>::value, |
39 "Type must be an unsigned integer."); | 41 "Type must be an unsigned integer."); |
40 const T maxDist = std::numeric_limits<T>::max() / 2 + T(1); | 42 const T maxDist = std::numeric_limits<T>::max() / 2 + T(1); |
41 if (a - b == maxDist) | 43 if (a - b == maxDist) |
42 return b < a; | 44 return b < a; |
43 return ForwardDiff(b, a) < maxDist; | 45 return ForwardDiff(b, a) < maxDist; |
44 } | 46 } |
45 | 47 |
48 template <typename T, typename M = void> | |
49 inline bool AheadOrAt(T a, T b) { | |
50 return AheadOrAt<T, 0>(a, b); | |
51 } | |
52 | |
46 // Test if the sequence number |a| is ahead of sequence number |b|. | 53 // Test if the sequence number |a| is ahead of sequence number |b|. |
47 // | 54 // |
48 // If |M| is an even number and the two sequence numbers are at max distance | 55 // If |M| is an even number and the two sequence numbers are at max distance |
49 // from each other, then the sequence number with the highest value is | 56 // from each other, then the sequence number with the highest value is |
50 // considered to be ahead. | 57 // considered to be ahead. |
51 template <typename T, T M> | 58 template <typename T, T M = 0> |
52 inline bool AheadOf(T a, T b) { | 59 inline bool AheadOf(T a, T b) { |
53 static_assert(std::is_unsigned<T>::value, | 60 static_assert(std::is_unsigned<T>::value, |
54 "Type must be an unsigned integer."); | 61 "Type must be an unsigned integer."); |
55 return a != b && AheadOrAt<T, M>(a, b); | 62 return a != b && AheadOrAt<T, M>(a, b); |
56 } | 63 } |
57 | 64 |
58 template <typename T> | |
59 inline bool AheadOf(T a, T b) { | |
60 static_assert(std::is_unsigned<T>::value, | |
61 "Type must be an unsigned integer."); | |
62 return a != b && AheadOrAt(a, b); | |
63 } | |
64 | |
65 namespace internal { | |
66 | |
67 template <typename T, typename M> | |
68 struct SeqNumComp; | |
69 | |
70 template <typename T, T M> | |
71 struct SeqNumComp<T, std::integral_constant<T, M>> { | |
72 bool operator()(T a, T b) const { return AheadOf<T, M>(a, b); } | |
73 }; | |
74 | |
75 template <typename T> | |
76 struct SeqNumComp<T, std::integral_constant<T, T(0)>> { | |
77 bool operator()(T a, T b) const { return AheadOf<T>(a, b); } | |
78 }; | |
79 | |
80 } // namespace internal | |
81 | |
82 // Comparator used to compare sequence numbers in a continuous fashion. | 65 // Comparator used to compare sequence numbers in a continuous fashion. |
83 // | 66 // |
84 // WARNING! If used to sort sequence numbers of length M then the interval | 67 // WARNING! If used to sort sequence numbers of length M then the interval |
85 // covered by the sequence numbers may not be larger than floor(M/2). | 68 // covered by the sequence numbers may not be larger than floor(M/2). |
86 template <typename T, T M = 0> | 69 template <typename T, T M = 0> |
87 struct AscendingSeqNumComp | 70 struct AscendingSeqNumComp { |
88 : private internal::SeqNumComp<T, std::integral_constant<T, M>> { | 71 bool operator()(T a, T b) const { return AheadOf<T, M>(a, b); } |
89 bool operator()(T a, T b) const { | |
90 return internal::SeqNumComp<T, std::integral_constant<T, M>>::operator()(a, | |
91 b); | |
92 } | |
93 }; | 72 }; |
94 | 73 |
95 // Comparator used to compare sequence numbers in a continuous fashion. | 74 // Comparator used to compare sequence numbers in a continuous fashion. |
96 // | 75 // |
97 // WARNING! If used to sort sequence numbers of length M then the interval | 76 // WARNING! If used to sort sequence numbers of length M then the interval |
98 // covered by the sequence numbers may not be larger than floor(M/2). | 77 // covered by the sequence numbers may not be larger than floor(M/2). |
99 template <typename T, T M = 0> | 78 template <typename T, T M = 0> |
100 struct DescendingSeqNumComp | 79 struct DescendingSeqNumComp { |
101 : private internal::SeqNumComp<T, std::integral_constant<T, M>> { | 80 bool operator()(T a, T b) const { return AheadOf<T, M>(b, a); } |
102 bool operator()(T a, T b) const { | 81 }; |
103 return internal::SeqNumComp<T, std::integral_constant<T, M>>::operator()(b, | 82 |
104 a); | 83 template <typename T, T M = 0> |
84 class SeqNumUnwrapper { | |
terelius
2017/07/10 21:20:23
We already have an Unwrapper in webrtc/modules/inc
philipel
2017/07/11 11:08:30
I updated the CL description with the motivation a
terelius
2017/07/11 12:38:17
Not sure I agree with the reasons for reimplementi
philipel
2017/07/11 12:49:06
If that is the case then I guess we could move seq
| |
85 static_assert( | |
86 std::is_unsigned<T>::value && | |
87 rtc::SafeLt(std::numeric_limits<T>::max(), | |
88 std::numeric_limits<uint64_t>::max()), | |
89 "Type unwrapped must be an unsigned integer smaller than uint64_t."); | |
90 | |
91 public: | |
92 SeqNumUnwrapper() : last_unwrapped_(0) {} | |
93 explicit SeqNumUnwrapper(uint64_t start_at) : last_unwrapped_(start_at) {} | |
94 | |
95 uint64_t Unwrap(T value) { | |
96 if (!last_value_) | |
97 last_value_.emplace(value); | |
98 | |
99 uint64_t unwrapped = 0; | |
100 if (AheadOrAt<T, M>(value, *last_value_)) { | |
101 unwrapped = last_unwrapped_ + ForwardDiff<T, M>(*last_value_, value); | |
102 RTC_CHECK_GE(unwrapped, last_unwrapped_); | |
103 } else { | |
104 unwrapped = last_unwrapped_ - ReverseDiff<T, M>(*last_value_, value); | |
105 RTC_CHECK_LT(unwrapped, last_unwrapped_); | |
106 } | |
107 | |
108 *last_value_ = value; | |
109 last_unwrapped_ = unwrapped; | |
110 return last_unwrapped_; | |
105 } | 111 } |
112 | |
113 private: | |
114 uint64_t last_unwrapped_; | |
115 rtc::Optional<uint64_t> last_value_; | |
106 }; | 116 }; |
107 | 117 |
108 } // namespace webrtc | 118 } // namespace webrtc |
109 | 119 |
110 #endif // WEBRTC_MODULES_VIDEO_CODING_SEQUENCE_NUMBER_UTIL_H_ | 120 #endif // WEBRTC_MODULES_VIDEO_CODING_SEQUENCE_NUMBER_UTIL_H_ |
OLD | NEW |