Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(295)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtcp_packet/feedback_packet_unittest.cc

Issue 1175263002: Add packetization and coding/decoding of feedback message format. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Fixed rounding of negative deltas Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2015 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 <limits>
12
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/feedback_packet.h"
16
17 using webrtc::rtcp::FeedbackPacket;
18
19 namespace webrtc {
20 namespace {
21
22 static const int kHeaderSize = 8;
23 static const int kStatusChunkSize = 2;
24 static const int kSmallDeltaSize = 1;
25 static const int kLargeDeltaSize = 2;
26
27 static const int64_t kDeltaLimit = 0xFF * FeedbackPacket::kDeltaScaleFactor;
28
29 class FeedbackTester {
30 public:
31 FeedbackTester()
32 : base_time_(-1),
33 expected_size_(kAnySize),
34 default_delta_(FeedbackPacket::kDeltaScaleFactor * 4) {}
35
36 void WithBaseTime(int64_t base_time) { base_time_ = base_time; }
37
38 void WithExpectedSize(size_t expected_size) {
39 expected_size_ = expected_size;
40 }
41
42 void WithDefaultDelta(int64_t delta) { default_delta_ = delta; }
43
44 void WithInput(const uint16_t received_seq[],
45 const int64_t received_ts[],
46 uint16_t length) {
47 rtc::scoped_ptr<int64_t[]> temp_deltas;
48 if (received_ts == nullptr) {
49 temp_deltas.reset(new int64_t[length]);
50 GenerateDeltas(received_seq, length, temp_deltas.get());
51 received_ts = temp_deltas.get();
52 }
53
54 if (base_time_ == -1)
55 base_time_ = received_ts[0] - (FeedbackPacket::kDeltaScaleFactor * 300);
56
57 expected_seq_.clear();
58 expected_deltas_.clear();
59 feedback_.reset(new FeedbackPacket());
60
61 feedback_->WithBase(received_seq[0], base_time_, received_ts[0]);
62 int64_t last_time = base_time_;
63 for (int i = 0; i < length; ++i) {
64 int64_t time = received_ts[i];
65 EXPECT_TRUE(feedback_->WithReceivedPacket(received_seq[i], time));
66
67 if (last_time != -1) {
68 int64_t delta = time - last_time;
69 expected_deltas_.push_back(delta);
70 }
71 last_time = time;
72 }
73 expected_seq_.insert(expected_seq_.begin(), &received_seq[0],
74 &received_seq[length]);
75 }
76
77 void VerifyPacket() {
78 serialized_ = feedback_->Build();
79 VerifyInternal();
80 feedback_ =
81 FeedbackPacket::ParseFrom(serialized_->Buffer(), serialized_->Length());
82 ASSERT_NE(nullptr, feedback_.get());
83 VerifyInternal();
84 }
85
86 static const size_t kAnySize = static_cast<size_t>(0) - 1;
87
88 private:
89 void VerifyInternal() {
90 if (expected_size_ != kAnySize) {
91 // Round up to whole 32-bit words.
92 size_t expected_size_words = (expected_size_ + 3) / 4;
93 size_t expected_size_bytes = expected_size_words * 4;
94 EXPECT_EQ(expected_size_bytes, serialized_->Length());
95 }
96
97 std::vector<FeedbackPacket::StatusSymbol> symbols =
98 feedback_->GetStatusVector();
99 uint16_t seq = feedback_->GetBaseSequence();
100 auto seq_it = expected_seq_.begin();
101 for (FeedbackPacket::StatusSymbol symbol : symbols) {
102 bool received =
103 (symbol == FeedbackPacket::StatusSymbol::kReceivedSmallDelta ||
104 symbol == FeedbackPacket::StatusSymbol::kReceivedLargeDelta);
105 if (seq_it != expected_seq_.end()) {
106 if (seq == *seq_it) {
107 ASSERT_NE(expected_seq_.end(), seq_it);
108 ASSERT_TRUE(received) << "Expected received packet @ " << seq;
109 ++seq_it;
110 } else {
111 ASSERT_FALSE(received) << "Did not expect received packet @ " << seq;
112 }
113 }
114 ++seq;
115 }
116 ASSERT_EQ(expected_seq_.end(), seq_it);
117
118 std::vector<int64_t> deltas = feedback_->GetReceiveDeltasUs();
119 ASSERT_EQ(expected_deltas_.size(), deltas.size());
120 for (size_t i = 0; i < expected_deltas_.size(); ++i)
121 EXPECT_EQ(expected_deltas_[i], deltas[i]) << "Delta mismatch @ " << i;
122 }
123
124 void GenerateDeltas(const uint16_t seq[],
125 const size_t length,
126 int64_t* deltas) {
127 uint16_t last_seq = seq[0];
128 int64_t offset = 0;
129
130 for (size_t i = 0; i < length; ++i) {
131 if (seq[i] < last_seq)
132 offset += 0x10000 * default_delta_;
133 last_seq = seq[i];
134
135 deltas[i] = offset + (last_seq * default_delta_);
136 }
137 }
138
139 int64_t base_time_;
140 std::vector<uint16_t> expected_seq_;
141 std::vector<int64_t> expected_deltas_;
142 size_t expected_size_;
143 int64_t default_delta_;
144 rtc::scoped_ptr<FeedbackPacket> feedback_;
145 rtc::scoped_ptr<rtcp::RawPacket> serialized_;
146 };
147
148 TEST(RtcpPacketTest, FeedbackPacket_OneBitVector) {
149 const uint16_t kReceived[] = {1, 2, 7, 8, 9, 10, 13};
150 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
151 const size_t kExpectedSizeBytes =
152 kHeaderSize + kStatusChunkSize + (kLength * kSmallDeltaSize);
153
154 FeedbackTester test;
155 test.WithExpectedSize(kExpectedSizeBytes);
156 test.WithInput(kReceived, nullptr, kLength);
157 test.VerifyPacket();
158 }
159
160 TEST(RtcpPacketTest, FeedbackPacket_FullOneBitVector) {
161 const uint16_t kReceived[] = {1, 2, 7, 8, 9, 10, 13, 14};
162 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
163 const size_t kExpectedSizeBytes =
164 kHeaderSize + kStatusChunkSize + (kLength * kSmallDeltaSize);
165
166 FeedbackTester test;
167 test.WithExpectedSize(kExpectedSizeBytes);
168 test.WithInput(kReceived, nullptr, kLength);
169 test.VerifyPacket();
170 }
171
172 TEST(RtcpPacketTest, FeedbackPacket_OneBitVector_WrapReceived) {
173 const uint16_t kMax = 0xFFFF;
174 const uint16_t kReceived[] = {kMax - 2, kMax - 1, kMax, 0, 1, 2};
175 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
176 const size_t kExpectedSizeBytes =
177 kHeaderSize + kStatusChunkSize + (kLength * kSmallDeltaSize);
178
179 FeedbackTester test;
180 test.WithExpectedSize(kExpectedSizeBytes);
181 test.WithInput(kReceived, nullptr, kLength);
182 test.VerifyPacket();
183 }
184
185 TEST(RtcpPacketTest, FeedbackPacket_OneBitVector_WrapMissing) {
186 const uint16_t kMax = 0xFFFF;
187 const uint16_t kReceived[] = {kMax - 2, kMax - 1, 1, 2};
188 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
189 const size_t kExpectedSizeBytes =
190 kHeaderSize + kStatusChunkSize + (kLength * kSmallDeltaSize);
191
192 FeedbackTester test;
193 test.WithExpectedSize(kExpectedSizeBytes);
194 test.WithInput(kReceived, nullptr, kLength);
195 test.VerifyPacket();
196 }
197
198 TEST(RtcpPacketTest, FeedbackPacket_TwoBitVector) {
199 const uint16_t kReceived[] = {1, 2, 6, 7};
200 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
201 const size_t kExpectedSizeBytes =
202 kHeaderSize + kStatusChunkSize + (kLength * kLargeDeltaSize);
203
204 FeedbackTester test;
205 test.WithExpectedSize(kExpectedSizeBytes);
206 test.WithDefaultDelta(kDeltaLimit + FeedbackPacket::kDeltaScaleFactor);
207 test.WithInput(kReceived, nullptr, kLength);
208 test.VerifyPacket();
209 }
210
211 TEST(RtcpPacketTest, FeedbackPacket_TwoBitVectorFull) {
212 const uint16_t kReceived[] = {1, 2, 6, 7, 8};
213 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
214 const size_t kExpectedSizeBytes =
215 kHeaderSize + (2 * kStatusChunkSize) + (kLength * kLargeDeltaSize);
216
217 FeedbackTester test;
218 test.WithExpectedSize(kExpectedSizeBytes);
219 test.WithDefaultDelta(kDeltaLimit + FeedbackPacket::kDeltaScaleFactor);
220 test.WithInput(kReceived, nullptr, kLength);
221 test.VerifyPacket();
222 }
223
224 TEST(RtcpPacketTest, FeedbackPacket_LargeAndNegativeDeltas) {
225 const uint16_t kReceived[] = {1, 2, 6, 7, 8};
226 const int64_t kReceiveTimes[] = {
227 2000, 1000, 4000, 3000,
228 3000 + FeedbackPacket::kDeltaScaleFactor * (1 << 8)};
229 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
230 const size_t kExpectedSizeBytes =
231 kHeaderSize + kStatusChunkSize + (3 * kLargeDeltaSize) + kSmallDeltaSize;
232
233 FeedbackTester test;
234 test.WithExpectedSize(kExpectedSizeBytes);
235 test.WithInput(kReceived, kReceiveTimes, kLength);
236 test.VerifyPacket();
237 }
238
239 TEST(RtcpPacketTest, FeedbackPacket_MaxRle) {
240 // Expected chunks created:
241 // * 1-bit vector chunk (1xreceived + 13xdropped)
242 // * RLE chunk of max length for dropped symbol
243 // * 1-bit vector chunk (1xreceived + 13xdropped)
244
245 const size_t kPacketCount = (1 << 13) - 1 + 14;
246 const uint16_t kReceived[] = {0, kPacketCount};
247 const int64_t kReceiveTimes[] = {1000, 2000};
248 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
249 const size_t kExpectedSizeBytes =
250 kHeaderSize + (3 * kStatusChunkSize) + (kLength * kSmallDeltaSize);
251
252 FeedbackTester test;
253 test.WithExpectedSize(kExpectedSizeBytes);
254 test.WithInput(kReceived, kReceiveTimes, kLength);
255 test.VerifyPacket();
256 }
257
258 TEST(RtcpPacketTest, FeedbackPacket_MinRle) {
259 // Expected chunks created:
260 // * 1-bit vector chunk (1xreceived + 13xdropped)
261 // * RLE chunk of length 15 for dropped symbol
262 // * 1-bit vector chunk (1xreceived + 13xdropped)
263
264 const uint16_t kReceived[] = {0, (14 * 2) + 1};
265 const int64_t kReceiveTimes[] = {1000, 2000};
266 const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
267 const size_t kExpectedSizeBytes =
268 kHeaderSize + (3 * kStatusChunkSize) + (kLength * kSmallDeltaSize);
269
270 FeedbackTester test;
271 test.WithExpectedSize(kExpectedSizeBytes);
272 test.WithInput(kReceived, kReceiveTimes, kLength);
273 test.VerifyPacket();
274 }
275
276 TEST(RtcpPacketTest, FeedbackPacket_OneToTwoBitVector) {
277 const size_t kTwoBitVectorCapacity = 7;
278
279 FeedbackPacket feedback;
280 feedback.WithBase(0, 0, 0);
281
282 EXPECT_TRUE(feedback.WithReceivedPacket(0, 0));
283 EXPECT_TRUE(feedback.WithUntimedPacket(kTwoBitVectorCapacity - 1));
284
285 rtc::scoped_ptr<rtcp::RawPacket> packet(feedback.Build());
286 const size_t kExpectedSizeBytes =
287 kHeaderSize + kStatusChunkSize + kSmallDeltaSize;
288 const size_t kExpectedSizeWords = (kExpectedSizeBytes + 3) / 4;
289
290 EXPECT_EQ(kExpectedSizeWords * 4, packet->Length());
291 EXPECT_EQ(kTwoBitVectorCapacity, feedback.GetStatusVector().size());
292 }
293
294 TEST(RtcpPacketTest, FeedbackPacket_OneToTwoBitVectorSplit) {
295 const size_t kTwoBitVectorCapacity = 7;
296
297 FeedbackPacket feedback;
298 feedback.WithBase(0, 0, 0);
299
300 EXPECT_TRUE(feedback.WithReceivedPacket(0, 0));
301 EXPECT_TRUE(feedback.WithUntimedPacket(kTwoBitVectorCapacity));
302
303 rtc::scoped_ptr<rtcp::RawPacket> packet(feedback.Build());
304 const size_t kExpectedSizeBytes =
305 kHeaderSize + (kStatusChunkSize * 2) + kSmallDeltaSize;
306 const size_t kExpectedSizeWords = (kExpectedSizeBytes + 3) / 4;
307
308 EXPECT_EQ(kExpectedSizeWords * 4, packet->Length());
309 EXPECT_EQ(kTwoBitVectorCapacity + 1, feedback.GetStatusVector().size());
310 }
311
312 TEST(RtcpPacketTest, FeedbackPacket_Aliasing) {
313 FeedbackPacket feedback;
314 feedback.WithBase(0, 0, 0);
315
316 const int kSamples = 100;
317 const int64_t kTooSmallDelta = FeedbackPacket::kDeltaScaleFactor / 3;
318
319 for (int i = 0; i < kSamples; ++i)
320 feedback.WithReceivedPacket(i, i * kTooSmallDelta);
321
322 feedback.Build();
323 std::vector<int64_t> deltas = feedback.GetReceiveDeltasUs();
324
325 int64_t accumulated_delta = 0;
326 int num_samples = 0;
327 for (int64_t delta : deltas) {
328 accumulated_delta += delta;
329 int64_t expected_time = num_samples * kTooSmallDelta;
330 ++num_samples;
331
332 EXPECT_NEAR(expected_time, accumulated_delta,
333 FeedbackPacket::kDeltaScaleFactor / 2);
334 }
335 }
336
337 TEST(RtcpPacketTest, FeedbackPacket_Limits) {
338 // Sequence number wrap above 0x8FFF.
339 rtc::scoped_ptr<FeedbackPacket> packet(new FeedbackPacket());
340 packet->WithBase(0, 0, 0);
341 EXPECT_TRUE(packet->WithReceivedPacket(0x8FFF, 1000));
342
343 packet.reset(new FeedbackPacket());
344 packet->WithBase(0, 0, 0);
345 EXPECT_FALSE(packet->WithReceivedPacket(0x8FFF + 1, 1000));
346
347 // Packet status count max 0xFFFF.
348 packet.reset(new FeedbackPacket());
349 packet->WithBase(0, 0, 0);
350 EXPECT_TRUE(packet->WithReceivedPacket(0x8FFF, 1000));
351 EXPECT_TRUE(packet->WithReceivedPacket(0xFFFF, 2000));
352 EXPECT_FALSE(packet->WithReceivedPacket(0, 3000));
353
354 // Reference delta within range(int16_t) * 2 ^ 8 * 250us.
355 const int64_t kMaxBaseDelta =
356 (static_cast<int64_t>(std::numeric_limits<int16_t>::max()) << 8) *
357 FeedbackPacket::kDeltaScaleFactor;
358 packet.reset(new FeedbackPacket());
359 packet->WithBase(0, 0, kMaxBaseDelta);
360
361 const int64_t kMinBaseDelta =
362 (static_cast<int64_t>(std::numeric_limits<int16_t>::min()) << 8) *
363 FeedbackPacket::kDeltaScaleFactor;
364 packet.reset(new FeedbackPacket());
365 packet->WithBase(0, 0, kMinBaseDelta);
366
367 // Packet size max 0xFF 32-bit words.
368 const size_t kMaxDeltas = (0xFF * 4) - kStatusChunkSize;
369 packet.reset(new FeedbackPacket());
370 packet->WithBase(0, 0, 0);
371 for (size_t i = 0; i < kMaxDeltas; ++i)
372 EXPECT_TRUE(packet->WithReceivedPacket(i, i * 1000));
373
374 EXPECT_FALSE(packet->WithReceivedPacket(kMaxDeltas, kMaxDeltas * 1000));
375 }
376
377 TEST(RtcpPacketTest, FeedbackPacket_Padding) {
378 const size_t kExpectedSizeBytes =
379 kHeaderSize + kStatusChunkSize + kSmallDeltaSize;
380 const size_t kExpectedSizeWords = (kExpectedSizeBytes + 3) / 4;
381
382 FeedbackPacket feedback;
383 feedback.WithBase(0, 0, 0);
384 EXPECT_TRUE(feedback.WithReceivedPacket(0, 0));
385
386 rtc::scoped_ptr<rtcp::RawPacket> packet(feedback.Build());
387 EXPECT_EQ(kExpectedSizeWords * 4, packet->Length());
388 ASSERT_GT(kExpectedSizeWords * 4, kExpectedSizeBytes);
389 for (size_t i = kExpectedSizeBytes; i < kExpectedSizeWords * 4; ++i)
390 EXPECT_EQ(0u, packet->Buffer()[i]);
391 }
392
393 } // namespace
394 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698