OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <stdint.h> | |
6 | |
7 #include "base/memory/scoped_ptr.h" | |
8 #include "base/test/simple_test_tick_clock.h" | |
9 #include "media/cast/framer/cast_message_builder.h" | |
10 #include "media/cast/rtcp/rtcp.h" | |
11 #include "media/cast/rtp_receiver/rtp_receiver_defines.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 | |
14 namespace media { | |
15 namespace cast { | |
16 | |
17 namespace { | |
18 static const uint32 kSsrc = 0x1234; | |
19 static const uint32 kShortTimeIncrementMs = 10; | |
20 static const uint32 kLongTimeIncrementMs = 40; | |
21 static const int64 kStartMillisecond = INT64_C(12345678900000); | |
22 | |
23 typedef std::map<uint32, size_t> MissingPacketsMap; | |
24 | |
25 class NackFeedbackVerification : public RtpPayloadFeedback { | |
26 public: | |
27 NackFeedbackVerification() | |
28 : triggered_(false), missing_packets_(), last_frame_acked_(0) {} | |
29 | |
30 virtual void CastFeedback(const RtcpCastMessage& cast_feedback) OVERRIDE { | |
31 EXPECT_EQ(kSsrc, cast_feedback.media_ssrc_); | |
32 | |
33 last_frame_acked_ = cast_feedback.ack_frame_id_; | |
34 | |
35 MissingFramesAndPacketsMap::const_iterator frame_it = | |
36 cast_feedback.missing_frames_and_packets_.begin(); | |
37 | |
38 // Keep track of the number of missing packets per frame. | |
39 missing_packets_.clear(); | |
40 while (frame_it != cast_feedback.missing_frames_and_packets_.end()) { | |
41 // Check for complete frame lost. | |
42 if ((frame_it->second.size() == 1) && | |
43 (*frame_it->second.begin() == kRtcpCastAllPacketsLost)) { | |
44 missing_packets_.insert( | |
45 std::make_pair(frame_it->first, kRtcpCastAllPacketsLost)); | |
46 } else { | |
47 missing_packets_.insert( | |
48 std::make_pair(frame_it->first, frame_it->second.size())); | |
49 } | |
50 ++frame_it; | |
51 } | |
52 triggered_ = true; | |
53 } | |
54 | |
55 size_t num_missing_packets(uint32 frame_id) { | |
56 MissingPacketsMap::iterator it; | |
57 it = missing_packets_.find(frame_id); | |
58 if (it == missing_packets_.end()) | |
59 return 0; | |
60 | |
61 return it->second; | |
62 } | |
63 | |
64 // Holds value for one call. | |
65 bool triggered() { | |
66 bool ret_val = triggered_; | |
67 triggered_ = false; | |
68 return ret_val; | |
69 } | |
70 | |
71 uint32 last_frame_acked() { return last_frame_acked_; } | |
72 | |
73 private: | |
74 bool triggered_; | |
75 MissingPacketsMap missing_packets_; // Missing packets per frame. | |
76 uint32 last_frame_acked_; | |
77 | |
78 DISALLOW_COPY_AND_ASSIGN(NackFeedbackVerification); | |
79 }; | |
80 } // namespace | |
81 | |
82 class CastMessageBuilderTest : public ::testing::Test { | |
83 protected: | |
84 CastMessageBuilderTest() | |
85 : cast_msg_builder_(new CastMessageBuilder(&testing_clock_, | |
86 &feedback_, | |
87 &frame_id_map_, | |
88 kSsrc, | |
89 true, | |
90 0)) { | |
91 rtp_header_.sender_ssrc = kSsrc; | |
92 rtp_header_.is_key_frame = false; | |
93 testing_clock_.Advance( | |
94 base::TimeDelta::FromMilliseconds(kStartMillisecond)); | |
95 } | |
96 | |
97 virtual ~CastMessageBuilderTest() {} | |
98 | |
99 void SetFrameIds(uint32 frame_id, uint32 reference_frame_id) { | |
100 rtp_header_.frame_id = frame_id; | |
101 rtp_header_.reference_frame_id = reference_frame_id; | |
102 } | |
103 | |
104 void SetPacketId(uint16 packet_id) { rtp_header_.packet_id = packet_id; } | |
105 | |
106 void SetMaxPacketId(uint16 max_packet_id) { | |
107 rtp_header_.max_packet_id = max_packet_id; | |
108 } | |
109 | |
110 void SetKeyFrame(bool is_key) { rtp_header_.is_key_frame = is_key; } | |
111 | |
112 void InsertPacket() { | |
113 PacketType packet_type = frame_id_map_.InsertPacket(rtp_header_); | |
114 if (packet_type == kNewPacketCompletingFrame) { | |
115 cast_msg_builder_->CompleteFrameReceived(rtp_header_.frame_id); | |
116 } | |
117 cast_msg_builder_->UpdateCastMessage(); | |
118 } | |
119 | |
120 void SetDecoderSlowerThanMaxFrameRate(int max_unacked_frames) { | |
121 cast_msg_builder_.reset(new CastMessageBuilder(&testing_clock_, | |
122 &feedback_, | |
123 &frame_id_map_, | |
124 kSsrc, | |
125 false, | |
126 max_unacked_frames)); | |
127 } | |
128 | |
129 NackFeedbackVerification feedback_; | |
130 scoped_ptr<CastMessageBuilder> cast_msg_builder_; | |
131 RtpCastHeader rtp_header_; | |
132 FrameIdMap frame_id_map_; | |
133 base::SimpleTestTickClock testing_clock_; | |
134 | |
135 DISALLOW_COPY_AND_ASSIGN(CastMessageBuilderTest); | |
136 }; | |
137 | |
138 TEST_F(CastMessageBuilderTest, OneFrameNackList) { | |
139 SetFrameIds(0, 0); | |
140 SetPacketId(4); | |
141 SetMaxPacketId(10); | |
142 InsertPacket(); | |
143 testing_clock_.Advance( | |
144 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); | |
145 EXPECT_FALSE(feedback_.triggered()); | |
146 testing_clock_.Advance( | |
147 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
148 SetPacketId(5); | |
149 InsertPacket(); | |
150 EXPECT_TRUE(feedback_.triggered()); | |
151 EXPECT_EQ(4u, feedback_.num_missing_packets(0)); | |
152 } | |
153 | |
154 TEST_F(CastMessageBuilderTest, CompleteFrameMissing) { | |
155 SetFrameIds(0, 0); | |
156 SetPacketId(2); | |
157 SetMaxPacketId(5); | |
158 InsertPacket(); | |
159 testing_clock_.Advance( | |
160 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
161 SetFrameIds(2, 1); | |
162 SetPacketId(2); | |
163 SetMaxPacketId(5); | |
164 InsertPacket(); | |
165 EXPECT_TRUE(feedback_.triggered()); | |
166 EXPECT_EQ(kRtcpCastAllPacketsLost, feedback_.num_missing_packets(1)); | |
167 } | |
168 | |
169 TEST_F(CastMessageBuilderTest, RemoveOldFrames) { | |
170 SetFrameIds(1, 0); | |
171 SetPacketId(0); | |
172 SetMaxPacketId(1); | |
173 InsertPacket(); | |
174 EXPECT_FALSE(feedback_.triggered()); | |
175 testing_clock_.Advance( | |
176 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
177 SetFrameIds(2, 1); | |
178 SetPacketId(0); | |
179 SetMaxPacketId(0); | |
180 InsertPacket(); | |
181 EXPECT_TRUE(feedback_.triggered()); | |
182 testing_clock_.Advance( | |
183 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
184 SetFrameIds(3, 2); | |
185 SetPacketId(0); | |
186 SetMaxPacketId(5); | |
187 InsertPacket(); | |
188 EXPECT_TRUE(feedback_.triggered()); | |
189 EXPECT_EQ(2u, feedback_.last_frame_acked()); | |
190 testing_clock_.Advance( | |
191 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
192 SetFrameIds(5, 5); | |
193 SetPacketId(0); | |
194 SetMaxPacketId(0); | |
195 SetKeyFrame(true); | |
196 InsertPacket(); | |
197 testing_clock_.Advance( | |
198 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
199 frame_id_map_.RemoveOldFrames(5); // Simulate 5 being pulled for rendering. | |
200 cast_msg_builder_->UpdateCastMessage(); | |
201 EXPECT_TRUE(feedback_.triggered()); | |
202 EXPECT_EQ(5u, feedback_.last_frame_acked()); | |
203 testing_clock_.Advance( | |
204 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); | |
205 SetFrameIds(1, 0); | |
206 SetPacketId(1); | |
207 SetMaxPacketId(1); | |
208 InsertPacket(); | |
209 EXPECT_FALSE(feedback_.triggered()); | |
210 testing_clock_.Advance( | |
211 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
212 InsertPacket(); | |
213 EXPECT_TRUE(feedback_.triggered()); | |
214 EXPECT_EQ(5u, feedback_.last_frame_acked()); | |
215 } | |
216 | |
217 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacket) { | |
218 SetFrameIds(0, 0); | |
219 SetPacketId(0); | |
220 SetMaxPacketId(20); | |
221 SetKeyFrame(true); | |
222 InsertPacket(); | |
223 testing_clock_.Advance( | |
224 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
225 SetPacketId(5); | |
226 InsertPacket(); | |
227 EXPECT_TRUE(feedback_.triggered()); | |
228 EXPECT_EQ(4u, feedback_.num_missing_packets(0)); | |
229 } | |
230 | |
231 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacketNextFrame) { | |
232 SetFrameIds(0, 0); | |
233 SetPacketId(0); | |
234 SetMaxPacketId(20); | |
235 SetKeyFrame(true); | |
236 InsertPacket(); | |
237 testing_clock_.Advance( | |
238 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
239 SetPacketId(5); | |
240 InsertPacket(); | |
241 testing_clock_.Advance( | |
242 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
243 EXPECT_TRUE(feedback_.triggered()); | |
244 EXPECT_EQ(4u, feedback_.num_missing_packets(0)); | |
245 SetFrameIds(1, 0); | |
246 SetMaxPacketId(2); | |
247 SetPacketId(0); | |
248 SetKeyFrame(false); | |
249 InsertPacket(); | |
250 testing_clock_.Advance( | |
251 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
252 EXPECT_TRUE(feedback_.triggered()); | |
253 EXPECT_EQ(19u, feedback_.num_missing_packets(0)); | |
254 } | |
255 | |
256 TEST_F(CastMessageBuilderTest, NackUntilMaxReceivedPacketNextKey) { | |
257 SetFrameIds(0, 0); | |
258 SetPacketId(0); | |
259 SetMaxPacketId(20); | |
260 SetKeyFrame(true); | |
261 InsertPacket(); | |
262 testing_clock_.Advance( | |
263 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
264 SetPacketId(5); | |
265 InsertPacket(); | |
266 testing_clock_.Advance( | |
267 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
268 EXPECT_TRUE(feedback_.triggered()); | |
269 EXPECT_EQ(4u, feedback_.num_missing_packets(0)); | |
270 SetFrameIds(1, 1); | |
271 SetMaxPacketId(0); | |
272 SetPacketId(0); | |
273 SetKeyFrame(true); | |
274 InsertPacket(); | |
275 testing_clock_.Advance( | |
276 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
277 EXPECT_TRUE(feedback_.triggered()); | |
278 EXPECT_EQ(0u, feedback_.num_missing_packets(0)); | |
279 } | |
280 | |
281 TEST_F(CastMessageBuilderTest, Reset) { | |
282 InsertPacket(); | |
283 testing_clock_.Advance( | |
284 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
285 cast_msg_builder_->Reset(); | |
286 frame_id_map_.Clear(); | |
287 // Should reset nack list state and request a key frame. | |
288 cast_msg_builder_->UpdateCastMessage(); | |
289 EXPECT_TRUE(feedback_.triggered()); | |
290 EXPECT_EQ(0u, feedback_.num_missing_packets(0)); | |
291 } | |
292 | |
293 TEST_F(CastMessageBuilderTest, DeltaAfterReset) { | |
294 SetFrameIds(0, 0); | |
295 SetPacketId(0); | |
296 SetMaxPacketId(0); | |
297 SetKeyFrame(true); | |
298 InsertPacket(); | |
299 EXPECT_TRUE(feedback_.triggered()); | |
300 EXPECT_EQ(0u, feedback_.num_missing_packets(0)); | |
301 testing_clock_.Advance( | |
302 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
303 cast_msg_builder_->Reset(); | |
304 SetFrameIds(1, 0); | |
305 SetPacketId(0); | |
306 SetMaxPacketId(0); | |
307 SetKeyFrame(true); | |
308 EXPECT_FALSE(feedback_.triggered()); | |
309 } | |
310 | |
311 TEST_F(CastMessageBuilderTest, BasicRps) { | |
312 SetFrameIds(0, 0); | |
313 SetPacketId(0); | |
314 SetMaxPacketId(0); | |
315 SetKeyFrame(true); | |
316 InsertPacket(); | |
317 testing_clock_.Advance( | |
318 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
319 EXPECT_TRUE(feedback_.triggered()); | |
320 EXPECT_EQ(0u, feedback_.last_frame_acked()); | |
321 SetFrameIds(3, 0); | |
322 SetKeyFrame(false); | |
323 InsertPacket(); | |
324 EXPECT_TRUE(feedback_.triggered()); | |
325 EXPECT_EQ(3u, feedback_.last_frame_acked()); | |
326 testing_clock_.Advance( | |
327 base::TimeDelta::FromMilliseconds(kLongTimeIncrementMs)); | |
328 frame_id_map_.RemoveOldFrames(3); // Simulate 3 being pulled for rendering. | |
329 cast_msg_builder_->UpdateCastMessage(); | |
330 EXPECT_TRUE(feedback_.triggered()); | |
331 EXPECT_EQ(3u, feedback_.last_frame_acked()); | |
332 } | |
333 | |
334 TEST_F(CastMessageBuilderTest, InOrderRps) { | |
335 // Create a pattern - skip to rps, and don't look back. | |
336 SetFrameIds(0, 0); | |
337 SetPacketId(0); | |
338 SetMaxPacketId(0); | |
339 SetKeyFrame(true); | |
340 InsertPacket(); | |
341 testing_clock_.Advance( | |
342 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); | |
343 EXPECT_TRUE(feedback_.triggered()); | |
344 EXPECT_EQ(0u, feedback_.last_frame_acked()); | |
345 SetFrameIds(1, 0); | |
346 SetPacketId(0); | |
347 SetMaxPacketId(1); | |
348 SetKeyFrame(false); | |
349 InsertPacket(); | |
350 testing_clock_.Advance( | |
351 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); | |
352 EXPECT_FALSE(feedback_.triggered()); | |
353 SetFrameIds(3, 0); | |
354 SetPacketId(0); | |
355 SetMaxPacketId(0); | |
356 SetKeyFrame(false); | |
357 InsertPacket(); | |
358 testing_clock_.Advance( | |
359 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); | |
360 frame_id_map_.RemoveOldFrames(3); // Simulate 3 being pulled for rendering. | |
361 testing_clock_.Advance( | |
362 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); | |
363 cast_msg_builder_->UpdateCastMessage(); | |
364 EXPECT_TRUE(feedback_.triggered()); | |
365 EXPECT_EQ(3u, feedback_.last_frame_acked()); | |
366 // Make an old frame complete - should not trigger an ack. | |
367 SetFrameIds(1, 0); | |
368 SetPacketId(1); | |
369 SetMaxPacketId(1); | |
370 SetKeyFrame(false); | |
371 InsertPacket(); | |
372 testing_clock_.Advance( | |
373 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); | |
374 EXPECT_FALSE(feedback_.triggered()); | |
375 EXPECT_EQ(3u, feedback_.last_frame_acked()); | |
376 } | |
377 | |
378 TEST_F(CastMessageBuilderTest, SlowDownAck) { | |
379 SetDecoderSlowerThanMaxFrameRate(3); | |
380 SetFrameIds(0, 0); | |
381 SetPacketId(0); | |
382 SetMaxPacketId(0); | |
383 SetKeyFrame(true); | |
384 InsertPacket(); | |
385 | |
386 uint32 frame_id; | |
387 testing_clock_.Advance( | |
388 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); | |
389 SetKeyFrame(false); | |
390 for (frame_id = 1; frame_id < 3; ++frame_id) { | |
391 EXPECT_TRUE(feedback_.triggered()); | |
392 EXPECT_EQ(frame_id - 1, feedback_.last_frame_acked()); | |
393 SetFrameIds(frame_id, frame_id - 1); | |
394 InsertPacket(); | |
395 testing_clock_.Advance( | |
396 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); | |
397 } | |
398 // We should now have entered the slowdown ACK state. | |
399 uint32 expected_frame_id = 1; | |
400 for (; frame_id < 10; ++frame_id) { | |
401 if (frame_id % 2) { | |
402 ++expected_frame_id; | |
403 EXPECT_TRUE(feedback_.triggered()); | |
404 } else { | |
405 EXPECT_FALSE(feedback_.triggered()); | |
406 } | |
407 EXPECT_EQ(expected_frame_id, feedback_.last_frame_acked()); | |
408 SetFrameIds(frame_id, frame_id - 1); | |
409 InsertPacket(); | |
410 testing_clock_.Advance( | |
411 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); | |
412 } | |
413 EXPECT_FALSE(feedback_.triggered()); | |
414 EXPECT_EQ(expected_frame_id, feedback_.last_frame_acked()); | |
415 | |
416 // Simulate frame_id being pulled for rendering. | |
417 frame_id_map_.RemoveOldFrames(frame_id); | |
418 // We should now leave the slowdown ACK state. | |
419 ++frame_id; | |
420 SetFrameIds(frame_id, frame_id - 1); | |
421 InsertPacket(); | |
422 testing_clock_.Advance( | |
423 base::TimeDelta::FromMilliseconds(kShortTimeIncrementMs)); | |
424 EXPECT_TRUE(feedback_.triggered()); | |
425 EXPECT_EQ(frame_id, feedback_.last_frame_acked()); | |
426 } | |
427 | |
428 } // namespace cast | |
429 } // namespace media | |
OLD | NEW |