blob: 9c4e715b4fa1f9423b34f09c31501dea49fdb85f [file] [log] [blame]
Elad Alon10874b22019-02-21 16:25:40 +01001/*
2 * Copyright (c) 2019 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 "modules/video_coding/loss_notification_controller.h"
12
Danil Chapovalov159c4142020-01-23 15:17:52 +010013#include <stdint.h>
14
Elad Alon10874b22019-02-21 16:25:40 +010015#include <limits>
16#include <string>
17#include <tuple>
Danil Chapovalov159c4142020-01-23 15:17:52 +010018#include <utility>
Elad Alon10874b22019-02-21 16:25:40 +010019#include <vector>
20
21#include "absl/types/optional.h"
22#include "test/gtest.h"
23
24namespace webrtc {
25namespace {
Niels Möllera7401422019-09-13 14:18:58 +020026
27// The information about an RTP packet that is relevant in these tests.
28struct Packet {
29 uint16_t seq_num;
Danil Chapovalov159c4142020-01-23 15:17:52 +010030 bool first_in_frame;
31 bool is_keyframe;
32 int64_t frame_id;
33 std::vector<int64_t> frame_dependencies;
Niels Möllera7401422019-09-13 14:18:58 +020034};
35
36Packet CreatePacket(
Elad Alon10874b22019-02-21 16:25:40 +010037 bool first_in_frame,
38 bool last_in_frame,
39 uint16_t seq_num,
40 uint16_t frame_id,
41 bool is_key_frame,
Danil Chapovalov159c4142020-01-23 15:17:52 +010042 std::vector<int64_t> ref_frame_ids = std::vector<int64_t>()) {
43 Packet packet;
44 packet.seq_num = seq_num;
45 packet.first_in_frame = first_in_frame;
Elad Alon10874b22019-02-21 16:25:40 +010046 if (first_in_frame) {
Danil Chapovalov159c4142020-01-23 15:17:52 +010047 packet.is_keyframe = is_key_frame;
48 packet.frame_id = frame_id;
49 RTC_DCHECK(!is_key_frame || ref_frame_ids.empty());
50 packet.frame_dependencies = std::move(ref_frame_ids);
Elad Alon10874b22019-02-21 16:25:40 +010051 }
Danil Chapovalov159c4142020-01-23 15:17:52 +010052 return packet;
Elad Alon10874b22019-02-21 16:25:40 +010053}
54
55class PacketStreamCreator final {
56 public:
57 PacketStreamCreator() : seq_num_(0), frame_id_(0), next_is_key_frame_(true) {}
58
Niels Möllera7401422019-09-13 14:18:58 +020059 Packet NextPacket() {
Danil Chapovalov159c4142020-01-23 15:17:52 +010060 std::vector<int64_t> ref_frame_ids;
Elad Alon10874b22019-02-21 16:25:40 +010061 if (!next_is_key_frame_) {
62 ref_frame_ids.push_back(frame_id_ - 1);
63 }
64
Niels Möllera7401422019-09-13 14:18:58 +020065 Packet packet = CreatePacket(true, true, seq_num_++, frame_id_++,
66 next_is_key_frame_, ref_frame_ids);
Elad Alon10874b22019-02-21 16:25:40 +010067
68 next_is_key_frame_ = false;
69
70 return packet;
71 }
72
73 private:
74 uint16_t seq_num_;
Danil Chapovalov159c4142020-01-23 15:17:52 +010075 int64_t frame_id_;
Elad Alon10874b22019-02-21 16:25:40 +010076 bool next_is_key_frame_;
77};
78} // namespace
79
80// Most of the logic for the tests is here. Subclasses allow parameterizing
81// the test, or adding some more specific logic.
82class LossNotificationControllerBaseTest : public ::testing::Test,
83 public KeyFrameRequestSender,
84 public LossNotificationSender {
85 protected:
86 LossNotificationControllerBaseTest()
87 : uut_(this, this), key_frame_requested_(false) {}
88
89 ~LossNotificationControllerBaseTest() override {
90 EXPECT_FALSE(LastKeyFrameRequest());
91 EXPECT_FALSE(LastLossNotification());
92 }
93
94 // KeyFrameRequestSender implementation.
95 void RequestKeyFrame() override {
96 EXPECT_FALSE(LastKeyFrameRequest());
97 EXPECT_FALSE(LastLossNotification());
98 key_frame_requested_ = true;
99 }
100
101 // LossNotificationSender implementation.
102 void SendLossNotification(uint16_t last_decoded_seq_num,
103 uint16_t last_received_seq_num,
Elad Alone86af2c2019-06-03 14:37:50 +0200104 bool decodability_flag,
105 bool buffering_allowed) override {
106 EXPECT_TRUE(buffering_allowed); // (Flag useful elsewhere.)
Elad Alon10874b22019-02-21 16:25:40 +0100107 EXPECT_FALSE(LastKeyFrameRequest());
108 EXPECT_FALSE(LastLossNotification());
109 last_loss_notification_.emplace(last_decoded_seq_num, last_received_seq_num,
110 decodability_flag);
111 }
112
Niels Möllera7401422019-09-13 14:18:58 +0200113 void OnReceivedPacket(const Packet& packet) {
Elad Alon10874b22019-02-21 16:25:40 +0100114 EXPECT_FALSE(LastKeyFrameRequest());
115 EXPECT_FALSE(LastLossNotification());
116
Danil Chapovalov159c4142020-01-23 15:17:52 +0100117 if (packet.first_in_frame) {
Elad Alon10874b22019-02-21 16:25:40 +0100118 previous_first_packet_in_frame_ = packet;
Danil Chapovalov159c4142020-01-23 15:17:52 +0100119 LossNotificationController::FrameDetails frame;
120 frame.is_keyframe = packet.is_keyframe;
121 frame.frame_id = packet.frame_id;
122 frame.frame_dependencies = packet.frame_dependencies;
123 uut_.OnReceivedPacket(packet.seq_num, &frame);
124 } else {
125 uut_.OnReceivedPacket(packet.seq_num, nullptr);
Elad Alon10874b22019-02-21 16:25:40 +0100126 }
Elad Alon10874b22019-02-21 16:25:40 +0100127 }
128
129 void OnAssembledFrame(uint16_t first_seq_num,
Danil Chapovalov159c4142020-01-23 15:17:52 +0100130 int64_t frame_id,
Elad Alon10874b22019-02-21 16:25:40 +0100131 bool discardable) {
132 EXPECT_FALSE(LastKeyFrameRequest());
133 EXPECT_FALSE(LastLossNotification());
134
135 ASSERT_TRUE(previous_first_packet_in_frame_);
Elad Alon10874b22019-02-21 16:25:40 +0100136 uut_.OnAssembledFrame(first_seq_num, frame_id, discardable,
Danil Chapovalov159c4142020-01-23 15:17:52 +0100137 previous_first_packet_in_frame_->frame_dependencies);
Elad Alon10874b22019-02-21 16:25:40 +0100138 }
139
140 void ExpectKeyFrameRequest() {
141 EXPECT_EQ(LastLossNotification(), absl::nullopt);
142 EXPECT_TRUE(LastKeyFrameRequest());
143 }
144
145 void ExpectLossNotification(uint16_t last_decoded_seq_num,
146 uint16_t last_received_seq_num,
147 bool decodability_flag) {
148 EXPECT_FALSE(LastKeyFrameRequest());
149 const auto last_ln = LastLossNotification();
150 ASSERT_TRUE(last_ln);
151 const LossNotification expected_ln(
152 last_decoded_seq_num, last_received_seq_num, decodability_flag);
153 EXPECT_EQ(expected_ln, *last_ln)
154 << "Expected loss notification (" << expected_ln.ToString()
155 << ") != received loss notification (" << last_ln->ToString() + ")";
156 }
157
158 struct LossNotification {
159 LossNotification(uint16_t last_decoded_seq_num,
160 uint16_t last_received_seq_num,
161 bool decodability_flag)
162 : last_decoded_seq_num(last_decoded_seq_num),
163 last_received_seq_num(last_received_seq_num),
164 decodability_flag(decodability_flag) {}
165
166 LossNotification& operator=(const LossNotification& other) = default;
167
168 bool operator==(const LossNotification& other) const {
169 return last_decoded_seq_num == other.last_decoded_seq_num &&
170 last_received_seq_num == other.last_received_seq_num &&
171 decodability_flag == other.decodability_flag;
172 }
173
174 std::string ToString() const {
175 return std::to_string(last_decoded_seq_num) + ", " +
176 std::to_string(last_received_seq_num) + ", " +
177 std::to_string(decodability_flag);
178 }
179
180 uint16_t last_decoded_seq_num;
181 uint16_t last_received_seq_num;
182 bool decodability_flag;
183 };
184
185 bool LastKeyFrameRequest() {
186 const bool result = key_frame_requested_;
187 key_frame_requested_ = false;
188 return result;
189 }
190
191 absl::optional<LossNotification> LastLossNotification() {
192 const absl::optional<LossNotification> result = last_loss_notification_;
193 last_loss_notification_ = absl::nullopt;
194 return result;
195 }
196
197 LossNotificationController uut_; // Unit under test.
198
199 bool key_frame_requested_;
200
201 absl::optional<LossNotification> last_loss_notification_;
202
203 // First packet of last frame. (Note that if a test skips the first packet
204 // of a subsequent frame, OnAssembledFrame is not called, and so this is
205 // note read. Therefore, it's not a problem if it is not cleared when
206 // the frame changes.)
Niels Möllera7401422019-09-13 14:18:58 +0200207 absl::optional<Packet> previous_first_packet_in_frame_;
Elad Alon10874b22019-02-21 16:25:40 +0100208};
209
210class LossNotificationControllerTest
211 : public LossNotificationControllerBaseTest,
212 public ::testing::WithParamInterface<std::tuple<bool, bool, bool>> {
213 protected:
214 // Arbitrary parameterized values, to be used by the tests whenever they
215 // wish to either check some combinations, or wish to demonstrate that
216 // a particular arbitrary value is unimportant.
217 template <size_t N>
218 bool Bool() const {
219 return std::get<N>(GetParam());
220 }
221};
222
223INSTANTIATE_TEST_SUITE_P(_,
224 LossNotificationControllerTest,
225 ::testing::Combine(::testing::Bool(),
226 ::testing::Bool(),
227 ::testing::Bool()));
228
229// If the first frame, which is a key frame, is lost, then a new key frame
230// is requested.
231TEST_P(LossNotificationControllerTest,
232 PacketLossBeforeFirstFrameAssembledTriggersKeyFrameRequest) {
233 OnReceivedPacket(CreatePacket(true, false, 100, 0, true));
234 OnReceivedPacket(CreatePacket(Bool<0>(), Bool<1>(), 103, 1, false, {0}));
235 ExpectKeyFrameRequest();
236}
237
238// If packet loss occurs (but not of the first packet), then a loss notification
239// is issued.
240TEST_P(LossNotificationControllerTest,
241 PacketLossAfterFirstFrameAssembledTriggersLossNotification) {
242 OnReceivedPacket(CreatePacket(true, true, 100, 0, true));
243 OnAssembledFrame(100, 0, false);
244 const bool first = Bool<0>();
245 const bool last = Bool<1>();
246 OnReceivedPacket(CreatePacket(first, last, 103, 1, false, {0}));
247 const bool expected_decodability_flag = first;
248 ExpectLossNotification(100, 103, expected_decodability_flag);
249}
250
251// No key frame or loss notifications issued due to an innocuous wrap-around
252// of the sequence number.
253TEST_P(LossNotificationControllerTest, SeqNumWrapAround) {
254 uint16_t seq_num = std::numeric_limits<uint16_t>::max();
255 OnReceivedPacket(CreatePacket(true, true, seq_num, 0, true));
256 OnAssembledFrame(seq_num, 0, false);
257 const bool first = Bool<0>();
258 const bool last = Bool<1>();
259 OnReceivedPacket(CreatePacket(first, last, ++seq_num, 1, false, {0}));
260}
261
Elad Alon10874b22019-02-21 16:25:40 +0100262TEST_F(LossNotificationControllerTest,
263 KeyFrameAfterPacketLossProducesNoLossNotifications) {
264 OnReceivedPacket(CreatePacket(true, true, 100, 1, true));
265 OnAssembledFrame(100, 1, false);
266 OnReceivedPacket(CreatePacket(true, true, 108, 8, true));
267}
268
269TEST_P(LossNotificationControllerTest, LostReferenceProducesLossNotification) {
270 OnReceivedPacket(CreatePacket(true, true, 100, 0, true));
271 OnAssembledFrame(100, 0, false);
272 uint16_t last_decodable_non_discardable_seq_num = 100;
273
274 // RTP gap produces loss notification - not the focus of this test.
275 const bool first = Bool<0>();
276 const bool last = Bool<1>();
277 const bool discardable = Bool<2>();
278 const bool decodable = first; // Depends on assemblability.
279 OnReceivedPacket(CreatePacket(first, last, 107, 3, false, {0}));
280 ExpectLossNotification(100, 107, decodable);
281 OnAssembledFrame(107, 3, discardable);
282 if (!discardable) {
283 last_decodable_non_discardable_seq_num = 107;
284 }
285
286 // Test focus - a loss notification is produced because of the missing
287 // dependency (frame ID 2), despite the RTP sequence number being the
288 // next expected one.
289 OnReceivedPacket(CreatePacket(true, true, 108, 4, false, {2, 0}));
290 ExpectLossNotification(last_decodable_non_discardable_seq_num, 108, false);
291}
292
293// The difference between this test and the previous one, is that in this test,
294// although the reference frame was received, it was not decodable.
295TEST_P(LossNotificationControllerTest,
296 UndecodableReferenceProducesLossNotification) {
297 OnReceivedPacket(CreatePacket(true, true, 100, 0, true));
298 OnAssembledFrame(100, 0, false);
299 uint16_t last_decodable_non_discardable_seq_num = 100;
300
301 // RTP gap produces loss notification - not the focus of this test.
302 // Also, not decodable; this is important for later in the test.
303 OnReceivedPacket(CreatePacket(true, true, 107, 3, false, {2}));
304 ExpectLossNotification(100, 107, false);
305 const bool discardable = Bool<0>();
306 OnAssembledFrame(107, 3, discardable);
307
308 // Test focus - a loss notification is produced because of the undecodable
309 // dependency (frame ID 3, which depended on the missing frame ID 2).
310 OnReceivedPacket(CreatePacket(true, true, 108, 4, false, {3, 0}));
311 ExpectLossNotification(last_decodable_non_discardable_seq_num, 108, false);
312}
313
314TEST_P(LossNotificationControllerTest, RobustnessAgainstHighInitialRefFrameId) {
315 constexpr uint16_t max_uint16_t = std::numeric_limits<uint16_t>::max();
316 OnReceivedPacket(CreatePacket(true, true, 100, 0, true));
317 OnAssembledFrame(100, 0, false);
318 OnReceivedPacket(CreatePacket(true, true, 101, 1, false, {max_uint16_t}));
319 ExpectLossNotification(100, 101, false);
320 OnAssembledFrame(101, max_uint16_t, Bool<0>());
321}
322
323TEST_P(LossNotificationControllerTest, RepeatedPacketsAreIgnored) {
324 PacketStreamCreator packet_stream;
325
326 const auto key_frame_packet = packet_stream.NextPacket();
327 OnReceivedPacket(key_frame_packet);
Danil Chapovalov159c4142020-01-23 15:17:52 +0100328 OnAssembledFrame(key_frame_packet.seq_num, key_frame_packet.frame_id, false);
Elad Alon10874b22019-02-21 16:25:40 +0100329
330 const bool gap = Bool<0>();
331
332 if (gap) {
333 // Lose one packet.
334 packet_stream.NextPacket();
335 }
336
337 auto repeated_packet = packet_stream.NextPacket();
338 OnReceivedPacket(repeated_packet);
339 if (gap) {
340 // Loss notification issued because of the gap. This is not the focus of
341 // the test.
Niels Möllera7401422019-09-13 14:18:58 +0200342 ExpectLossNotification(key_frame_packet.seq_num, repeated_packet.seq_num,
Elad Alon10874b22019-02-21 16:25:40 +0100343 false);
344 }
345 OnReceivedPacket(repeated_packet);
346}
347
Danil Chapovalov159c4142020-01-23 15:17:52 +0100348TEST_F(LossNotificationControllerTest,
349 RecognizesDependencyAcrossIntraFrameThatIsNotAKeyframe) {
350 int last_seq_num = 1;
351 auto receive = [&](bool is_key_frame, int64_t frame_id,
352 std::vector<int64_t> ref_frame_ids) {
353 ++last_seq_num;
354 OnReceivedPacket(CreatePacket(
355 /*first_in_frame=*/true, /*last_in_frame=*/true, last_seq_num, frame_id,
356 is_key_frame, std::move(ref_frame_ids)));
357 OnAssembledFrame(last_seq_num, frame_id, /*discardable=*/false);
358 };
359 // 11 -- 13
360 // | |
361 // 10 12
362 receive(/*is_key_frame=*/true, /*frame_id=*/10, /*ref_frame_ids=*/{});
363 receive(/*is_key_frame=*/false, /*frame_id=*/11, /*ref_frame_ids=*/{10});
364 receive(/*is_key_frame=*/false, /*frame_id=*/12, /*ref_frame_ids=*/{});
365 receive(/*is_key_frame=*/false, /*frame_id=*/13, /*ref_frame_ids=*/{11, 12});
366 EXPECT_FALSE(LastLossNotification());
367}
368
Elad Alon10874b22019-02-21 16:25:40 +0100369class LossNotificationControllerTestDecodabilityFlag
370 : public LossNotificationControllerBaseTest {
371 protected:
372 LossNotificationControllerTestDecodabilityFlag()
373 : key_frame_seq_num_(100),
374 key_frame_frame_id_(0),
375 never_received_frame_id_(key_frame_frame_id_ + 1),
376 seq_num_(0),
377 frame_id_(0) {}
378
379 void ReceiveKeyFrame() {
380 RTC_DCHECK_NE(key_frame_frame_id_, never_received_frame_id_);
381 OnReceivedPacket(CreatePacket(true, true, key_frame_seq_num_,
382 key_frame_frame_id_, true));
383 OnAssembledFrame(key_frame_seq_num_, key_frame_frame_id_, false);
384 seq_num_ = key_frame_seq_num_;
385 frame_id_ = key_frame_frame_id_;
386 }
387
388 void ReceivePacket(bool first_packet_in_frame,
389 bool last_packet_in_frame,
Danil Chapovalov159c4142020-01-23 15:17:52 +0100390 const std::vector<int64_t>& ref_frame_ids) {
Elad Alon10874b22019-02-21 16:25:40 +0100391 if (first_packet_in_frame) {
392 frame_id_ += 1;
393 }
394 RTC_DCHECK_NE(frame_id_, never_received_frame_id_);
395 constexpr bool is_key_frame = false;
396 OnReceivedPacket(CreatePacket(first_packet_in_frame, last_packet_in_frame,
397 ++seq_num_, frame_id_, is_key_frame,
398 ref_frame_ids));
399 }
400
401 void CreateGap() {
402 seq_num_ += 50;
403 frame_id_ += 10;
404 }
405
406 const uint16_t key_frame_seq_num_;
407 const uint16_t key_frame_frame_id_;
408
409 // The tests intentionally never receive this, and can therefore always
410 // use this as an unsatisfied dependency.
Danil Chapovalov159c4142020-01-23 15:17:52 +0100411 const int64_t never_received_frame_id_ = 123;
Elad Alon10874b22019-02-21 16:25:40 +0100412
413 uint16_t seq_num_;
Danil Chapovalov159c4142020-01-23 15:17:52 +0100414 int64_t frame_id_;
Elad Alon10874b22019-02-21 16:25:40 +0100415};
416
417TEST_F(LossNotificationControllerTestDecodabilityFlag,
418 SinglePacketFrameWithDecodableDependencies) {
419 ReceiveKeyFrame();
420 CreateGap();
421
Danil Chapovalov159c4142020-01-23 15:17:52 +0100422 const std::vector<int64_t> ref_frame_ids = {key_frame_frame_id_};
Elad Alon10874b22019-02-21 16:25:40 +0100423 ReceivePacket(true, true, ref_frame_ids);
424
425 const bool expected_decodability_flag = true;
426 ExpectLossNotification(key_frame_seq_num_, seq_num_,
427 expected_decodability_flag);
428}
429
430TEST_F(LossNotificationControllerTestDecodabilityFlag,
431 SinglePacketFrameWithUndecodableDependencies) {
432 ReceiveKeyFrame();
433 CreateGap();
434
Danil Chapovalov159c4142020-01-23 15:17:52 +0100435 const std::vector<int64_t> ref_frame_ids = {never_received_frame_id_};
Elad Alon10874b22019-02-21 16:25:40 +0100436 ReceivePacket(true, true, ref_frame_ids);
437
438 const bool expected_decodability_flag = false;
439 ExpectLossNotification(key_frame_seq_num_, seq_num_,
440 expected_decodability_flag);
441}
442
443TEST_F(LossNotificationControllerTestDecodabilityFlag,
444 FirstPacketOfMultiPacketFrameWithDecodableDependencies) {
445 ReceiveKeyFrame();
446 CreateGap();
447
Danil Chapovalov159c4142020-01-23 15:17:52 +0100448 const std::vector<int64_t> ref_frame_ids = {key_frame_frame_id_};
Elad Alon10874b22019-02-21 16:25:40 +0100449 ReceivePacket(true, false, ref_frame_ids);
450
451 const bool expected_decodability_flag = true;
452 ExpectLossNotification(key_frame_seq_num_, seq_num_,
453 expected_decodability_flag);
454}
455
456TEST_F(LossNotificationControllerTestDecodabilityFlag,
457 FirstPacketOfMultiPacketFrameWithUndecodableDependencies) {
458 ReceiveKeyFrame();
459 CreateGap();
460
Danil Chapovalov159c4142020-01-23 15:17:52 +0100461 const std::vector<int64_t> ref_frame_ids = {never_received_frame_id_};
Elad Alon10874b22019-02-21 16:25:40 +0100462 ReceivePacket(true, false, ref_frame_ids);
463
464 const bool expected_decodability_flag = false;
465 ExpectLossNotification(key_frame_seq_num_, seq_num_,
466 expected_decodability_flag);
467}
468
469TEST_F(LossNotificationControllerTestDecodabilityFlag,
470 MiddlePacketOfMultiPacketFrameWithDecodableDependenciesIfFirstMissed) {
471 ReceiveKeyFrame();
472 CreateGap();
473
Danil Chapovalov159c4142020-01-23 15:17:52 +0100474 const std::vector<int64_t> ref_frame_ids = {key_frame_frame_id_};
Elad Alon10874b22019-02-21 16:25:40 +0100475 ReceivePacket(false, false, ref_frame_ids);
476
477 const bool expected_decodability_flag = false;
478 ExpectLossNotification(key_frame_seq_num_, seq_num_,
479 expected_decodability_flag);
480}
481
482TEST_F(LossNotificationControllerTestDecodabilityFlag,
483 MiddlePacketOfMultiPacketFrameWithUndecodableDependenciesIfFirstMissed) {
484 ReceiveKeyFrame();
485 CreateGap();
486
Danil Chapovalov159c4142020-01-23 15:17:52 +0100487 const std::vector<int64_t> ref_frame_ids = {never_received_frame_id_};
Elad Alon10874b22019-02-21 16:25:40 +0100488 ReceivePacket(false, false, ref_frame_ids);
489
490 const bool expected_decodability_flag = false;
491 ExpectLossNotification(key_frame_seq_num_, seq_num_,
492 expected_decodability_flag);
493}
494
495TEST_F(LossNotificationControllerTestDecodabilityFlag,
496 MiddlePacketOfMultiPacketFrameWithDecodableDependenciesIfFirstReceived) {
497 ReceiveKeyFrame();
498 CreateGap();
499
500 // First packet in multi-packet frame. A loss notification is produced
501 // because of the gap in RTP sequence numbers.
Danil Chapovalov159c4142020-01-23 15:17:52 +0100502 const std::vector<int64_t> ref_frame_ids = {key_frame_frame_id_};
Elad Alon10874b22019-02-21 16:25:40 +0100503 ReceivePacket(true, false, ref_frame_ids);
504 const bool expected_decodability_flag_first = true;
505 ExpectLossNotification(key_frame_seq_num_, seq_num_,
506 expected_decodability_flag_first);
507
508 // Middle packet in multi-packet frame. No additional gap and the frame is
509 // still potentially decodable, so no additional loss indication.
510 ReceivePacket(false, false, ref_frame_ids);
511 EXPECT_FALSE(LastKeyFrameRequest());
512 EXPECT_FALSE(LastLossNotification());
513}
514
515TEST_F(
516 LossNotificationControllerTestDecodabilityFlag,
517 MiddlePacketOfMultiPacketFrameWithUndecodableDependenciesIfFirstReceived) {
518 ReceiveKeyFrame();
519 CreateGap();
520
521 // First packet in multi-packet frame. A loss notification is produced
522 // because of the gap in RTP sequence numbers. The frame is also recognized
523 // as having non-decodable dependencies.
Danil Chapovalov159c4142020-01-23 15:17:52 +0100524 const std::vector<int64_t> ref_frame_ids = {never_received_frame_id_};
Elad Alon10874b22019-02-21 16:25:40 +0100525 ReceivePacket(true, false, ref_frame_ids);
526 const bool expected_decodability_flag_first = false;
527 ExpectLossNotification(key_frame_seq_num_, seq_num_,
528 expected_decodability_flag_first);
529
530 // Middle packet in multi-packet frame. No additional gap, but the frame is
531 // known to be non-decodable, so we keep issuing loss indications.
532 ReceivePacket(false, false, ref_frame_ids);
533 const bool expected_decodability_flag_middle = false;
534 ExpectLossNotification(key_frame_seq_num_, seq_num_,
535 expected_decodability_flag_middle);
536}
537
538TEST_F(LossNotificationControllerTestDecodabilityFlag,
539 LastPacketOfMultiPacketFrameWithDecodableDependenciesIfAllPrevMissed) {
540 ReceiveKeyFrame();
541 CreateGap();
542
Danil Chapovalov159c4142020-01-23 15:17:52 +0100543 const std::vector<int64_t> ref_frame_ids = {key_frame_frame_id_};
Elad Alon10874b22019-02-21 16:25:40 +0100544 ReceivePacket(false, true, ref_frame_ids);
545
546 const bool expected_decodability_flag = false;
547 ExpectLossNotification(key_frame_seq_num_, seq_num_,
548 expected_decodability_flag);
549}
550
551TEST_F(LossNotificationControllerTestDecodabilityFlag,
552 LastPacketOfMultiPacketFrameWithUndecodableDependenciesIfAllPrevMissed) {
553 ReceiveKeyFrame();
554 CreateGap();
555
Danil Chapovalov159c4142020-01-23 15:17:52 +0100556 const std::vector<int64_t> ref_frame_ids = {never_received_frame_id_};
Elad Alon10874b22019-02-21 16:25:40 +0100557 ReceivePacket(false, true, ref_frame_ids);
558
559 const bool expected_decodability_flag = false;
560 ExpectLossNotification(key_frame_seq_num_, seq_num_,
561 expected_decodability_flag);
562}
563
564TEST_F(LossNotificationControllerTestDecodabilityFlag,
565 LastPacketOfMultiPacketFrameWithDecodableDependenciesIfAllPrevReceived) {
566 ReceiveKeyFrame();
567 CreateGap();
568
569 // First packet in multi-packet frame. A loss notification is produced
570 // because of the gap in RTP sequence numbers.
Danil Chapovalov159c4142020-01-23 15:17:52 +0100571 const std::vector<int64_t> ref_frame_ids = {key_frame_frame_id_};
Elad Alon10874b22019-02-21 16:25:40 +0100572 ReceivePacket(true, false, ref_frame_ids);
573 const bool expected_decodability_flag_first = true;
574 ExpectLossNotification(key_frame_seq_num_, seq_num_,
575 expected_decodability_flag_first);
576
577 // Last packet in multi-packet frame. No additional gap and the frame is
578 // still potentially decodable, so no additional loss indication.
579 ReceivePacket(false, true, ref_frame_ids);
580 EXPECT_FALSE(LastKeyFrameRequest());
581 EXPECT_FALSE(LastLossNotification());
582}
583
584TEST_F(
585 LossNotificationControllerTestDecodabilityFlag,
586 LastPacketOfMultiPacketFrameWithUndecodableDependenciesIfAllPrevReceived) {
587 ReceiveKeyFrame();
588 CreateGap();
589
590 // First packet in multi-packet frame. A loss notification is produced
591 // because of the gap in RTP sequence numbers. The frame is also recognized
592 // as having non-decodable dependencies.
Danil Chapovalov159c4142020-01-23 15:17:52 +0100593 const std::vector<int64_t> ref_frame_ids = {never_received_frame_id_};
Elad Alon10874b22019-02-21 16:25:40 +0100594 ReceivePacket(true, false, ref_frame_ids);
595 const bool expected_decodability_flag_first = false;
596 ExpectLossNotification(key_frame_seq_num_, seq_num_,
597 expected_decodability_flag_first);
598
599 // Last packet in multi-packet frame. No additional gap, but the frame is
600 // known to be non-decodable, so we keep issuing loss indications.
601 ReceivePacket(false, true, ref_frame_ids);
602 const bool expected_decodability_flag_last = false;
603 ExpectLossNotification(key_frame_seq_num_, seq_num_,
604 expected_decodability_flag_last);
605}
606
607} // namespace webrtc