xref: /aosp_15_r20/external/webrtc/modules/video_coding/loss_notification_controller_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
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 
13 #include <stdint.h>
14 
15 #include <limits>
16 #include <string>
17 #include <tuple>
18 #include <utility>
19 #include <vector>
20 
21 #include "absl/types/optional.h"
22 #include "test/gtest.h"
23 
24 namespace webrtc {
25 namespace {
26 
27 // The information about an RTP packet that is relevant in these tests.
28 struct Packet {
29   uint16_t seq_num;
30   bool first_in_frame;
31   bool is_keyframe;
32   int64_t frame_id;
33   std::vector<int64_t> frame_dependencies;
34 };
35 
CreatePacket(bool first_in_frame,bool last_in_frame,uint16_t seq_num,uint16_t frame_id,bool is_key_frame,std::vector<int64_t> ref_frame_ids=std::vector<int64_t> ())36 Packet CreatePacket(
37     bool first_in_frame,
38     bool last_in_frame,
39     uint16_t seq_num,
40     uint16_t frame_id,
41     bool is_key_frame,
42     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;
46   if (first_in_frame) {
47     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);
51   }
52   return packet;
53 }
54 
55 class PacketStreamCreator final {
56  public:
PacketStreamCreator()57   PacketStreamCreator() : seq_num_(0), frame_id_(0), next_is_key_frame_(true) {}
58 
NextPacket()59   Packet NextPacket() {
60     std::vector<int64_t> ref_frame_ids;
61     if (!next_is_key_frame_) {
62       ref_frame_ids.push_back(frame_id_ - 1);
63     }
64 
65     Packet packet = CreatePacket(true, true, seq_num_++, frame_id_++,
66                                  next_is_key_frame_, ref_frame_ids);
67 
68     next_is_key_frame_ = false;
69 
70     return packet;
71   }
72 
73  private:
74   uint16_t seq_num_;
75   int64_t frame_id_;
76   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.
82 class LossNotificationControllerBaseTest : public ::testing::Test,
83                                            public KeyFrameRequestSender,
84                                            public LossNotificationSender {
85  protected:
LossNotificationControllerBaseTest()86   LossNotificationControllerBaseTest()
87       : uut_(this, this), key_frame_requested_(false) {}
88 
~LossNotificationControllerBaseTest()89   ~LossNotificationControllerBaseTest() override {
90     EXPECT_FALSE(LastKeyFrameRequest());
91     EXPECT_FALSE(LastLossNotification());
92   }
93 
94   // KeyFrameRequestSender implementation.
RequestKeyFrame()95   void RequestKeyFrame() override {
96     EXPECT_FALSE(LastKeyFrameRequest());
97     EXPECT_FALSE(LastLossNotification());
98     key_frame_requested_ = true;
99   }
100 
101   // LossNotificationSender implementation.
SendLossNotification(uint16_t last_decoded_seq_num,uint16_t last_received_seq_num,bool decodability_flag,bool buffering_allowed)102   void SendLossNotification(uint16_t last_decoded_seq_num,
103                             uint16_t last_received_seq_num,
104                             bool decodability_flag,
105                             bool buffering_allowed) override {
106     EXPECT_TRUE(buffering_allowed);  // (Flag useful elsewhere.)
107     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 
OnReceivedPacket(const Packet & packet)113   void OnReceivedPacket(const Packet& packet) {
114     EXPECT_FALSE(LastKeyFrameRequest());
115     EXPECT_FALSE(LastLossNotification());
116 
117     if (packet.first_in_frame) {
118       previous_first_packet_in_frame_ = packet;
119       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);
126     }
127   }
128 
OnAssembledFrame(uint16_t first_seq_num,int64_t frame_id,bool discardable)129   void OnAssembledFrame(uint16_t first_seq_num,
130                         int64_t frame_id,
131                         bool discardable) {
132     EXPECT_FALSE(LastKeyFrameRequest());
133     EXPECT_FALSE(LastLossNotification());
134 
135     ASSERT_TRUE(previous_first_packet_in_frame_);
136     uut_.OnAssembledFrame(first_seq_num, frame_id, discardable,
137                           previous_first_packet_in_frame_->frame_dependencies);
138   }
139 
ExpectKeyFrameRequest()140   void ExpectKeyFrameRequest() {
141     EXPECT_EQ(LastLossNotification(), absl::nullopt);
142     EXPECT_TRUE(LastKeyFrameRequest());
143   }
144 
ExpectLossNotification(uint16_t last_decoded_seq_num,uint16_t last_received_seq_num,bool decodability_flag)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 {
LossNotificationwebrtc::LossNotificationControllerBaseTest::LossNotification159     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 
operator ==webrtc::LossNotificationControllerBaseTest::LossNotification168     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 
ToStringwebrtc::LossNotificationControllerBaseTest::LossNotification174     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 
LastKeyFrameRequest()185   bool LastKeyFrameRequest() {
186     const bool result = key_frame_requested_;
187     key_frame_requested_ = false;
188     return result;
189   }
190 
LastLossNotification()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.)
207   absl::optional<Packet> previous_first_packet_in_frame_;
208 };
209 
210 class 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>
Bool() const218   bool Bool() const {
219     return std::get<N>(GetParam());
220   }
221 };
222 
223 INSTANTIATE_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.
TEST_P(LossNotificationControllerTest,PacketLossBeforeFirstFrameAssembledTriggersKeyFrameRequest)231 TEST_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.
TEST_P(LossNotificationControllerTest,PacketLossAfterFirstFrameAssembledTriggersLossNotification)240 TEST_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.
TEST_P(LossNotificationControllerTest,SeqNumWrapAround)253 TEST_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 
TEST_F(LossNotificationControllerTest,KeyFrameAfterPacketLossProducesNoLossNotifications)262 TEST_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 
TEST_P(LossNotificationControllerTest,LostReferenceProducesLossNotification)269 TEST_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.
TEST_P(LossNotificationControllerTest,UndecodableReferenceProducesLossNotification)295 TEST_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 
TEST_P(LossNotificationControllerTest,RobustnessAgainstHighInitialRefFrameId)314 TEST_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 
TEST_P(LossNotificationControllerTest,RepeatedPacketsAreIgnored)323 TEST_P(LossNotificationControllerTest, RepeatedPacketsAreIgnored) {
324   PacketStreamCreator packet_stream;
325 
326   const auto key_frame_packet = packet_stream.NextPacket();
327   OnReceivedPacket(key_frame_packet);
328   OnAssembledFrame(key_frame_packet.seq_num, key_frame_packet.frame_id, false);
329 
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.
342     ExpectLossNotification(key_frame_packet.seq_num, repeated_packet.seq_num,
343                            false);
344   }
345   OnReceivedPacket(repeated_packet);
346 }
347 
TEST_F(LossNotificationControllerTest,RecognizesDependencyAcrossIntraFrameThatIsNotAKeyframe)348 TEST_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 
369 class LossNotificationControllerTestDecodabilityFlag
370     : public LossNotificationControllerBaseTest {
371  protected:
LossNotificationControllerTestDecodabilityFlag()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 
ReceiveKeyFrame()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 
ReceivePacket(bool first_packet_in_frame,bool last_packet_in_frame,const std::vector<int64_t> & ref_frame_ids)388   void ReceivePacket(bool first_packet_in_frame,
389                      bool last_packet_in_frame,
390                      const std::vector<int64_t>& ref_frame_ids) {
391     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 
CreateGap()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.
411   const int64_t never_received_frame_id_ = 123;
412 
413   uint16_t seq_num_;
414   int64_t frame_id_;
415 };
416 
TEST_F(LossNotificationControllerTestDecodabilityFlag,SinglePacketFrameWithDecodableDependencies)417 TEST_F(LossNotificationControllerTestDecodabilityFlag,
418        SinglePacketFrameWithDecodableDependencies) {
419   ReceiveKeyFrame();
420   CreateGap();
421 
422   const std::vector<int64_t> ref_frame_ids = {key_frame_frame_id_};
423   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 
TEST_F(LossNotificationControllerTestDecodabilityFlag,SinglePacketFrameWithUndecodableDependencies)430 TEST_F(LossNotificationControllerTestDecodabilityFlag,
431        SinglePacketFrameWithUndecodableDependencies) {
432   ReceiveKeyFrame();
433   CreateGap();
434 
435   const std::vector<int64_t> ref_frame_ids = {never_received_frame_id_};
436   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 
TEST_F(LossNotificationControllerTestDecodabilityFlag,FirstPacketOfMultiPacketFrameWithDecodableDependencies)443 TEST_F(LossNotificationControllerTestDecodabilityFlag,
444        FirstPacketOfMultiPacketFrameWithDecodableDependencies) {
445   ReceiveKeyFrame();
446   CreateGap();
447 
448   const std::vector<int64_t> ref_frame_ids = {key_frame_frame_id_};
449   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 
TEST_F(LossNotificationControllerTestDecodabilityFlag,FirstPacketOfMultiPacketFrameWithUndecodableDependencies)456 TEST_F(LossNotificationControllerTestDecodabilityFlag,
457        FirstPacketOfMultiPacketFrameWithUndecodableDependencies) {
458   ReceiveKeyFrame();
459   CreateGap();
460 
461   const std::vector<int64_t> ref_frame_ids = {never_received_frame_id_};
462   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 
TEST_F(LossNotificationControllerTestDecodabilityFlag,MiddlePacketOfMultiPacketFrameWithDecodableDependenciesIfFirstMissed)469 TEST_F(LossNotificationControllerTestDecodabilityFlag,
470        MiddlePacketOfMultiPacketFrameWithDecodableDependenciesIfFirstMissed) {
471   ReceiveKeyFrame();
472   CreateGap();
473 
474   const std::vector<int64_t> ref_frame_ids = {key_frame_frame_id_};
475   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 
TEST_F(LossNotificationControllerTestDecodabilityFlag,MiddlePacketOfMultiPacketFrameWithUndecodableDependenciesIfFirstMissed)482 TEST_F(LossNotificationControllerTestDecodabilityFlag,
483        MiddlePacketOfMultiPacketFrameWithUndecodableDependenciesIfFirstMissed) {
484   ReceiveKeyFrame();
485   CreateGap();
486 
487   const std::vector<int64_t> ref_frame_ids = {never_received_frame_id_};
488   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 
TEST_F(LossNotificationControllerTestDecodabilityFlag,MiddlePacketOfMultiPacketFrameWithDecodableDependenciesIfFirstReceived)495 TEST_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.
502   const std::vector<int64_t> ref_frame_ids = {key_frame_frame_id_};
503   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 
TEST_F(LossNotificationControllerTestDecodabilityFlag,MiddlePacketOfMultiPacketFrameWithUndecodableDependenciesIfFirstReceived)515 TEST_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.
524   const std::vector<int64_t> ref_frame_ids = {never_received_frame_id_};
525   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 
TEST_F(LossNotificationControllerTestDecodabilityFlag,LastPacketOfMultiPacketFrameWithDecodableDependenciesIfAllPrevMissed)538 TEST_F(LossNotificationControllerTestDecodabilityFlag,
539        LastPacketOfMultiPacketFrameWithDecodableDependenciesIfAllPrevMissed) {
540   ReceiveKeyFrame();
541   CreateGap();
542 
543   const std::vector<int64_t> ref_frame_ids = {key_frame_frame_id_};
544   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 
TEST_F(LossNotificationControllerTestDecodabilityFlag,LastPacketOfMultiPacketFrameWithUndecodableDependenciesIfAllPrevMissed)551 TEST_F(LossNotificationControllerTestDecodabilityFlag,
552        LastPacketOfMultiPacketFrameWithUndecodableDependenciesIfAllPrevMissed) {
553   ReceiveKeyFrame();
554   CreateGap();
555 
556   const std::vector<int64_t> ref_frame_ids = {never_received_frame_id_};
557   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 
TEST_F(LossNotificationControllerTestDecodabilityFlag,LastPacketOfMultiPacketFrameWithDecodableDependenciesIfAllPrevReceived)564 TEST_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.
571   const std::vector<int64_t> ref_frame_ids = {key_frame_frame_id_};
572   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 
TEST_F(LossNotificationControllerTestDecodabilityFlag,LastPacketOfMultiPacketFrameWithUndecodableDependenciesIfAllPrevReceived)584 TEST_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.
593   const std::vector<int64_t> ref_frame_ids = {never_received_frame_id_};
594   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
608