xref: /aosp_15_r20/external/openscreen/cast/streaming/sender_unittest.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2020 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "cast/streaming/sender.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <stdint.h>
8*3f982cf4SFabien Sanglard 
9*3f982cf4SFabien Sanglard #include <algorithm>
10*3f982cf4SFabien Sanglard #include <array>
11*3f982cf4SFabien Sanglard #include <chrono>
12*3f982cf4SFabien Sanglard #include <limits>
13*3f982cf4SFabien Sanglard #include <map>
14*3f982cf4SFabien Sanglard #include <set>
15*3f982cf4SFabien Sanglard #include <utility>
16*3f982cf4SFabien Sanglard #include <vector>
17*3f982cf4SFabien Sanglard 
18*3f982cf4SFabien Sanglard #include "absl/types/optional.h"
19*3f982cf4SFabien Sanglard #include "absl/types/span.h"
20*3f982cf4SFabien Sanglard #include "cast/streaming/compound_rtcp_builder.h"
21*3f982cf4SFabien Sanglard #include "cast/streaming/constants.h"
22*3f982cf4SFabien Sanglard #include "cast/streaming/encoded_frame.h"
23*3f982cf4SFabien Sanglard #include "cast/streaming/frame_collector.h"
24*3f982cf4SFabien Sanglard #include "cast/streaming/frame_crypto.h"
25*3f982cf4SFabien Sanglard #include "cast/streaming/frame_id.h"
26*3f982cf4SFabien Sanglard #include "cast/streaming/mock_environment.h"
27*3f982cf4SFabien Sanglard #include "cast/streaming/packet_util.h"
28*3f982cf4SFabien Sanglard #include "cast/streaming/rtcp_session.h"
29*3f982cf4SFabien Sanglard #include "cast/streaming/rtp_defines.h"
30*3f982cf4SFabien Sanglard #include "cast/streaming/rtp_packet_parser.h"
31*3f982cf4SFabien Sanglard #include "cast/streaming/sender_packet_router.h"
32*3f982cf4SFabien Sanglard #include "cast/streaming/sender_report_parser.h"
33*3f982cf4SFabien Sanglard #include "cast/streaming/session_config.h"
34*3f982cf4SFabien Sanglard #include "cast/streaming/ssrc.h"
35*3f982cf4SFabien Sanglard #include "cast/streaming/testing/simple_socket_subscriber.h"
36*3f982cf4SFabien Sanglard #include "gmock/gmock.h"
37*3f982cf4SFabien Sanglard #include "gtest/gtest.h"
38*3f982cf4SFabien Sanglard #include "platform/test/fake_clock.h"
39*3f982cf4SFabien Sanglard #include "platform/test/fake_task_runner.h"
40*3f982cf4SFabien Sanglard #include "util/alarm.h"
41*3f982cf4SFabien Sanglard #include "util/chrono_helpers.h"
42*3f982cf4SFabien Sanglard #include "util/yet_another_bit_vector.h"
43*3f982cf4SFabien Sanglard 
44*3f982cf4SFabien Sanglard using testing::_;
45*3f982cf4SFabien Sanglard using testing::AtLeast;
46*3f982cf4SFabien Sanglard using testing::Invoke;
47*3f982cf4SFabien Sanglard using testing::InvokeWithoutArgs;
48*3f982cf4SFabien Sanglard using testing::Mock;
49*3f982cf4SFabien Sanglard using testing::NiceMock;
50*3f982cf4SFabien Sanglard using testing::Return;
51*3f982cf4SFabien Sanglard using testing::Sequence;
52*3f982cf4SFabien Sanglard 
53*3f982cf4SFabien Sanglard namespace openscreen {
54*3f982cf4SFabien Sanglard namespace cast {
55*3f982cf4SFabien Sanglard namespace {
56*3f982cf4SFabien Sanglard 
57*3f982cf4SFabien Sanglard // Sender configuration.
58*3f982cf4SFabien Sanglard constexpr Ssrc kSenderSsrc = 1;
59*3f982cf4SFabien Sanglard constexpr Ssrc kReceiverSsrc = 2;
60*3f982cf4SFabien Sanglard constexpr int kRtpTimebase = 48000;
61*3f982cf4SFabien Sanglard constexpr milliseconds kTargetPlayoutDelay{400};
62*3f982cf4SFabien Sanglard constexpr auto kAesKey =
63*3f982cf4SFabien Sanglard     std::array<uint8_t, 16>{{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
64*3f982cf4SFabien Sanglard                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}};
65*3f982cf4SFabien Sanglard constexpr auto kCastIvMask =
66*3f982cf4SFabien Sanglard     std::array<uint8_t, 16>{{0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
67*3f982cf4SFabien Sanglard                              0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00}};
68*3f982cf4SFabien Sanglard constexpr RtpPayloadType kRtpPayloadType = RtpPayloadType::kVideoVp8;
69*3f982cf4SFabien Sanglard 
70*3f982cf4SFabien Sanglard // The number of RTP ticks advanced per frame, for 100 FPS media.
71*3f982cf4SFabien Sanglard constexpr int kRtpTicksPerFrame = kRtpTimebase / 100;
72*3f982cf4SFabien Sanglard 
73*3f982cf4SFabien Sanglard // The number of milliseconds advanced per frame, for 100 FPS media.
74*3f982cf4SFabien Sanglard constexpr milliseconds kFrameDuration{1000 / 100};
75*3f982cf4SFabien Sanglard static_assert(kFrameDuration < (kTargetPlayoutDelay / 10),
76*3f982cf4SFabien Sanglard               "Kickstart test assumes frame duration is far less than the "
77*3f982cf4SFabien Sanglard               "playout delay.");
78*3f982cf4SFabien Sanglard 
79*3f982cf4SFabien Sanglard // An Encoded frame that also holds onto its own copy of data.
80*3f982cf4SFabien Sanglard struct EncodedFrameWithBuffer : public EncodedFrame {
81*3f982cf4SFabien Sanglard   // |EncodedFrame::data| always points inside buffer.begin()...buffer.end().
82*3f982cf4SFabien Sanglard   std::vector<uint8_t> buffer;
83*3f982cf4SFabien Sanglard };
84*3f982cf4SFabien Sanglard 
85*3f982cf4SFabien Sanglard // SenderPacketRouter configuration for these tests.
86*3f982cf4SFabien Sanglard constexpr int kNumPacketsPerBurst = 20;
87*3f982cf4SFabien Sanglard constexpr milliseconds kBurstInterval{10};
88*3f982cf4SFabien Sanglard 
89*3f982cf4SFabien Sanglard // An arbitrary value, subtracted from "now," to specify the reference_time on
90*3f982cf4SFabien Sanglard // frames that are about to be enqueued. This simulates that capture+encode
91*3f982cf4SFabien Sanglard // happened in the past, before Sender::EnqueueFrame() is called.
92*3f982cf4SFabien Sanglard constexpr milliseconds kCaptureDelay{11};
93*3f982cf4SFabien Sanglard 
94*3f982cf4SFabien Sanglard // In some tests, the computed time values could be off a little bit due to
95*3f982cf4SFabien Sanglard // imprecision in certain wire-format timestamp types. The following macro
96*3f982cf4SFabien Sanglard // behaves just like Gtest's EXPECT_NEAR(), but works with all the time types
97*3f982cf4SFabien Sanglard // too.
98*3f982cf4SFabien Sanglard #define EXPECT_NEARLY_EQUAL(duration_a, duration_b, epsilon) \
99*3f982cf4SFabien Sanglard   if ((duration_a) >= (duration_b)) {                        \
100*3f982cf4SFabien Sanglard     EXPECT_LE((duration_a), (duration_b) + (epsilon));       \
101*3f982cf4SFabien Sanglard   } else {                                                   \
102*3f982cf4SFabien Sanglard     EXPECT_GE((duration_a), (duration_b) - (epsilon));       \
103*3f982cf4SFabien Sanglard   }
104*3f982cf4SFabien Sanglard 
OverrideRtpTimestamp(int frame_count,EncodedFrame * frame,int fps)105*3f982cf4SFabien Sanglard void OverrideRtpTimestamp(int frame_count, EncodedFrame* frame, int fps) {
106*3f982cf4SFabien Sanglard   const int ticks = frame_count * kRtpTimebase / fps;
107*3f982cf4SFabien Sanglard   frame->rtp_timestamp = RtpTimeTicks() + RtpTimeDelta::FromTicks(ticks);
108*3f982cf4SFabien Sanglard }
109*3f982cf4SFabien Sanglard 
110*3f982cf4SFabien Sanglard // Simulates UDP/IPv6 traffic in one direction (from Sender→Receiver, or
111*3f982cf4SFabien Sanglard // Receiver→Sender), with a settable amount of delay.
112*3f982cf4SFabien Sanglard class SimulatedNetworkPipe {
113*3f982cf4SFabien Sanglard  public:
SimulatedNetworkPipe(TaskRunner * task_runner,Environment::PacketConsumer * remote)114*3f982cf4SFabien Sanglard   SimulatedNetworkPipe(TaskRunner* task_runner,
115*3f982cf4SFabien Sanglard                        Environment::PacketConsumer* remote)
116*3f982cf4SFabien Sanglard       : task_runner_(task_runner), remote_(remote) {
117*3f982cf4SFabien Sanglard     // Create a fake IPv6 address using the "documentative purposes" prefix
118*3f982cf4SFabien Sanglard     // concatenated with the |this| pointer.
119*3f982cf4SFabien Sanglard     std::array<uint16_t, 8> hextets{};
120*3f982cf4SFabien Sanglard     hextets[0] = 0x2001;
121*3f982cf4SFabien Sanglard     hextets[1] = 0x0db8;
122*3f982cf4SFabien Sanglard     auto* const this_pointer = this;
123*3f982cf4SFabien Sanglard     static_assert(sizeof(this_pointer) <= (6 * sizeof(uint16_t)), "");
124*3f982cf4SFabien Sanglard     memcpy(&hextets[2], &this_pointer, sizeof(this_pointer));
125*3f982cf4SFabien Sanglard     local_endpoint_ = IPEndpoint{IPAddress(hextets), 2344};
126*3f982cf4SFabien Sanglard   }
127*3f982cf4SFabien Sanglard 
local_endpoint() const128*3f982cf4SFabien Sanglard   const IPEndpoint& local_endpoint() const { return local_endpoint_; }
129*3f982cf4SFabien Sanglard 
network_delay() const130*3f982cf4SFabien Sanglard   Clock::duration network_delay() const { return network_delay_; }
set_network_delay(Clock::duration delay)131*3f982cf4SFabien Sanglard   void set_network_delay(Clock::duration delay) { network_delay_ = delay; }
132*3f982cf4SFabien Sanglard 
133*3f982cf4SFabien Sanglard   // The caller needs to spin the task runner before |packet| will reach the
134*3f982cf4SFabien Sanglard   // other side.
StartPacketTransmission(std::vector<uint8_t> packet)135*3f982cf4SFabien Sanglard   void StartPacketTransmission(std::vector<uint8_t> packet) {
136*3f982cf4SFabien Sanglard     task_runner_->PostTaskWithDelay(
137*3f982cf4SFabien Sanglard         [this, packet = std::move(packet)]() mutable {
138*3f982cf4SFabien Sanglard           remote_->OnReceivedPacket(local_endpoint_, FakeClock::now(),
139*3f982cf4SFabien Sanglard                                     std::move(packet));
140*3f982cf4SFabien Sanglard         },
141*3f982cf4SFabien Sanglard         network_delay_);
142*3f982cf4SFabien Sanglard   }
143*3f982cf4SFabien Sanglard 
144*3f982cf4SFabien Sanglard  private:
145*3f982cf4SFabien Sanglard   TaskRunner* const task_runner_;
146*3f982cf4SFabien Sanglard   Environment::PacketConsumer* const remote_;
147*3f982cf4SFabien Sanglard 
148*3f982cf4SFabien Sanglard   IPEndpoint local_endpoint_;
149*3f982cf4SFabien Sanglard 
150*3f982cf4SFabien Sanglard   // The amount of time for the packet to transmit over this simulated network
151*3f982cf4SFabien Sanglard   // pipe. Defaults to zero to simplify the tests that don't care about delays.
152*3f982cf4SFabien Sanglard   Clock::duration network_delay_{};
153*3f982cf4SFabien Sanglard };
154*3f982cf4SFabien Sanglard 
155*3f982cf4SFabien Sanglard // Processes packets from the Sender under test, allowing unit tests to set
156*3f982cf4SFabien Sanglard // expectations for parsed RTP or RTCP packets, to confirm proper behavior of
157*3f982cf4SFabien Sanglard // the Sender.
158*3f982cf4SFabien Sanglard class MockReceiver : public Environment::PacketConsumer {
159*3f982cf4SFabien Sanglard  public:
MockReceiver(SimulatedNetworkPipe * pipe_to_sender)160*3f982cf4SFabien Sanglard   explicit MockReceiver(SimulatedNetworkPipe* pipe_to_sender)
161*3f982cf4SFabien Sanglard       : pipe_to_sender_(pipe_to_sender),
162*3f982cf4SFabien Sanglard         rtcp_session_(kSenderSsrc, kReceiverSsrc, FakeClock::now()),
163*3f982cf4SFabien Sanglard         sender_report_parser_(&rtcp_session_),
164*3f982cf4SFabien Sanglard         rtcp_builder_(&rtcp_session_),
165*3f982cf4SFabien Sanglard         rtp_parser_(kSenderSsrc),
166*3f982cf4SFabien Sanglard         crypto_(kAesKey, kCastIvMask) {
167*3f982cf4SFabien Sanglard     rtcp_builder_.SetPlayoutDelay(kTargetPlayoutDelay);
168*3f982cf4SFabien Sanglard   }
169*3f982cf4SFabien Sanglard 
170*3f982cf4SFabien Sanglard   ~MockReceiver() override = default;
171*3f982cf4SFabien Sanglard 
172*3f982cf4SFabien Sanglard   // Simulate the Receiver ACK'ing all frames up to and including the
173*3f982cf4SFabien Sanglard   // |new_checkpoint|.
SetCheckpointFrame(FrameId new_checkpoint)174*3f982cf4SFabien Sanglard   void SetCheckpointFrame(FrameId new_checkpoint) {
175*3f982cf4SFabien Sanglard     OSP_CHECK_GE(new_checkpoint, rtcp_builder_.checkpoint_frame());
176*3f982cf4SFabien Sanglard     rtcp_builder_.SetCheckpointFrame(new_checkpoint);
177*3f982cf4SFabien Sanglard   }
178*3f982cf4SFabien Sanglard 
179*3f982cf4SFabien Sanglard   // Automatically advances the checkpoint based on what is found in
180*3f982cf4SFabien Sanglard   // |complete_frames_|, returning true if the checkpoint moved forward.
AutoAdvanceCheckpoint()181*3f982cf4SFabien Sanglard   bool AutoAdvanceCheckpoint() {
182*3f982cf4SFabien Sanglard     const FrameId old_checkpoint = rtcp_builder_.checkpoint_frame();
183*3f982cf4SFabien Sanglard     FrameId new_checkpoint = old_checkpoint;
184*3f982cf4SFabien Sanglard     for (auto it = complete_frames_.upper_bound(old_checkpoint);
185*3f982cf4SFabien Sanglard          it != complete_frames_.end(); ++it) {
186*3f982cf4SFabien Sanglard       if (it->first != new_checkpoint + 1) {
187*3f982cf4SFabien Sanglard         break;
188*3f982cf4SFabien Sanglard       }
189*3f982cf4SFabien Sanglard       ++new_checkpoint;
190*3f982cf4SFabien Sanglard     }
191*3f982cf4SFabien Sanglard     if (new_checkpoint > old_checkpoint) {
192*3f982cf4SFabien Sanglard       rtcp_builder_.SetCheckpointFrame(new_checkpoint);
193*3f982cf4SFabien Sanglard       return true;
194*3f982cf4SFabien Sanglard     }
195*3f982cf4SFabien Sanglard     return false;
196*3f982cf4SFabien Sanglard   }
197*3f982cf4SFabien Sanglard 
SetPictureLossIndicator(bool picture_is_lost)198*3f982cf4SFabien Sanglard   void SetPictureLossIndicator(bool picture_is_lost) {
199*3f982cf4SFabien Sanglard     rtcp_builder_.SetPictureLossIndicator(picture_is_lost);
200*3f982cf4SFabien Sanglard   }
201*3f982cf4SFabien Sanglard 
SetReceiverReport(StatusReportId reply_for,RtcpReportBlock::Delay processing_delay)202*3f982cf4SFabien Sanglard   void SetReceiverReport(StatusReportId reply_for,
203*3f982cf4SFabien Sanglard                          RtcpReportBlock::Delay processing_delay) {
204*3f982cf4SFabien Sanglard     RtcpReportBlock receiver_report;
205*3f982cf4SFabien Sanglard     receiver_report.ssrc = kSenderSsrc;
206*3f982cf4SFabien Sanglard     receiver_report.last_status_report_id = reply_for;
207*3f982cf4SFabien Sanglard     receiver_report.delay_since_last_report = processing_delay;
208*3f982cf4SFabien Sanglard     rtcp_builder_.IncludeReceiverReportInNextPacket(receiver_report);
209*3f982cf4SFabien Sanglard   }
210*3f982cf4SFabien Sanglard 
SetNacksAndAcks(std::vector<PacketNack> packet_nacks,std::vector<FrameId> frame_acks)211*3f982cf4SFabien Sanglard   void SetNacksAndAcks(std::vector<PacketNack> packet_nacks,
212*3f982cf4SFabien Sanglard                        std::vector<FrameId> frame_acks) {
213*3f982cf4SFabien Sanglard     rtcp_builder_.IncludeFeedbackInNextPacket(std::move(packet_nacks),
214*3f982cf4SFabien Sanglard                                               std::move(frame_acks));
215*3f982cf4SFabien Sanglard   }
216*3f982cf4SFabien Sanglard 
217*3f982cf4SFabien Sanglard   // Builds and sends a RTCP packet containing one or more of: checkpoint, PLI,
218*3f982cf4SFabien Sanglard   // Receiver Report, NACKs, ACKs.
TransmitRtcpFeedbackPacket()219*3f982cf4SFabien Sanglard   void TransmitRtcpFeedbackPacket() {
220*3f982cf4SFabien Sanglard     uint8_t buffer[kMaxRtpPacketSizeForIpv6UdpOnEthernet];
221*3f982cf4SFabien Sanglard     const absl::Span<uint8_t> packet =
222*3f982cf4SFabien Sanglard         rtcp_builder_.BuildPacket(FakeClock::now(), buffer);
223*3f982cf4SFabien Sanglard     pipe_to_sender_->StartPacketTransmission(
224*3f982cf4SFabien Sanglard         std::vector<uint8_t>(packet.begin(), packet.end()));
225*3f982cf4SFabien Sanglard   }
226*3f982cf4SFabien Sanglard 
227*3f982cf4SFabien Sanglard   // Used by tests to simulate the Receiver not seeing specific packets come in
228*3f982cf4SFabien Sanglard   // from the network (e.g., because the network dropped the packets).
SetIgnoreList(std::vector<PacketNack> ignore_list)229*3f982cf4SFabien Sanglard   void SetIgnoreList(std::vector<PacketNack> ignore_list) {
230*3f982cf4SFabien Sanglard     ignore_list_ = ignore_list;
231*3f982cf4SFabien Sanglard   }
232*3f982cf4SFabien Sanglard 
233*3f982cf4SFabien Sanglard   // Environment::PacketConsumer implementation.
234*3f982cf4SFabien Sanglard   //
235*3f982cf4SFabien Sanglard   // Called to process a packet from the Sender, simulating basic RTP frame
236*3f982cf4SFabien Sanglard   // collection and Sender Report parsing/handling.
OnReceivedPacket(const IPEndpoint & source,Clock::time_point arrival_time,std::vector<uint8_t> packet)237*3f982cf4SFabien Sanglard   void OnReceivedPacket(const IPEndpoint& source,
238*3f982cf4SFabien Sanglard                         Clock::time_point arrival_time,
239*3f982cf4SFabien Sanglard                         std::vector<uint8_t> packet) override {
240*3f982cf4SFabien Sanglard     const auto type_and_ssrc = InspectPacketForRouting(packet);
241*3f982cf4SFabien Sanglard     EXPECT_NE(ApparentPacketType::UNKNOWN, type_and_ssrc.first);
242*3f982cf4SFabien Sanglard     EXPECT_EQ(kSenderSsrc, type_and_ssrc.second);
243*3f982cf4SFabien Sanglard     if (type_and_ssrc.first == ApparentPacketType::RTP) {
244*3f982cf4SFabien Sanglard       const absl::optional<RtpPacketParser::ParseResult> part_of_frame =
245*3f982cf4SFabien Sanglard           rtp_parser_.Parse(packet);
246*3f982cf4SFabien Sanglard       ASSERT_TRUE(part_of_frame);
247*3f982cf4SFabien Sanglard 
248*3f982cf4SFabien Sanglard       // Return early if simulating packet drops over the network.
249*3f982cf4SFabien Sanglard       if (std::find_if(ignore_list_.begin(), ignore_list_.end(),
250*3f982cf4SFabien Sanglard                        [&](const PacketNack& baddie) {
251*3f982cf4SFabien Sanglard                          return (
252*3f982cf4SFabien Sanglard                              baddie.frame_id == part_of_frame->frame_id &&
253*3f982cf4SFabien Sanglard                              (baddie.packet_id == kAllPacketsLost ||
254*3f982cf4SFabien Sanglard                               baddie.packet_id == part_of_frame->packet_id));
255*3f982cf4SFabien Sanglard                        }) != ignore_list_.end()) {
256*3f982cf4SFabien Sanglard         return;
257*3f982cf4SFabien Sanglard       }
258*3f982cf4SFabien Sanglard 
259*3f982cf4SFabien Sanglard       OnRtpPacket(*part_of_frame);
260*3f982cf4SFabien Sanglard       CollectRtpPacket(*part_of_frame, std::move(packet));
261*3f982cf4SFabien Sanglard     } else if (type_and_ssrc.first == ApparentPacketType::RTCP) {
262*3f982cf4SFabien Sanglard       absl::optional<SenderReportParser::SenderReportWithId> report =
263*3f982cf4SFabien Sanglard           sender_report_parser_.Parse(packet);
264*3f982cf4SFabien Sanglard       ASSERT_TRUE(report);
265*3f982cf4SFabien Sanglard       OnSenderReport(*report);
266*3f982cf4SFabien Sanglard     }
267*3f982cf4SFabien Sanglard   }
268*3f982cf4SFabien Sanglard 
TakeCompleteFrames()269*3f982cf4SFabien Sanglard   std::map<FrameId, EncodedFrameWithBuffer> TakeCompleteFrames() {
270*3f982cf4SFabien Sanglard     std::map<FrameId, EncodedFrameWithBuffer> result;
271*3f982cf4SFabien Sanglard     result.swap(complete_frames_);
272*3f982cf4SFabien Sanglard     return result;
273*3f982cf4SFabien Sanglard   }
274*3f982cf4SFabien Sanglard 
275*3f982cf4SFabien Sanglard   // Tests set expectations on these mocks to monitor events of interest, and/or
276*3f982cf4SFabien Sanglard   // invoke additional behaviors.
277*3f982cf4SFabien Sanglard   MOCK_METHOD1(OnRtpPacket,
278*3f982cf4SFabien Sanglard                void(const RtpPacketParser::ParseResult& parsed_packet));
279*3f982cf4SFabien Sanglard   MOCK_METHOD1(OnFrameComplete, void(FrameId frame_id));
280*3f982cf4SFabien Sanglard   MOCK_METHOD1(OnSenderReport,
281*3f982cf4SFabien Sanglard                void(const SenderReportParser::SenderReportWithId& report));
282*3f982cf4SFabien Sanglard 
283*3f982cf4SFabien Sanglard  private:
284*3f982cf4SFabien Sanglard   // Collects the individual RTP packets until a whole frame can be formed, then
285*3f982cf4SFabien Sanglard   // calls OnFrameComplete(). Ignores extra RTP packets that are no longer
286*3f982cf4SFabien Sanglard   // needed.
CollectRtpPacket(const RtpPacketParser::ParseResult & part_of_frame,std::vector<uint8_t> packet)287*3f982cf4SFabien Sanglard   void CollectRtpPacket(const RtpPacketParser::ParseResult& part_of_frame,
288*3f982cf4SFabien Sanglard                         std::vector<uint8_t> packet) {
289*3f982cf4SFabien Sanglard     const FrameId frame_id = part_of_frame.frame_id;
290*3f982cf4SFabien Sanglard     if (complete_frames_.find(frame_id) != complete_frames_.end()) {
291*3f982cf4SFabien Sanglard       return;
292*3f982cf4SFabien Sanglard     }
293*3f982cf4SFabien Sanglard     FrameCollector& collector = incomplete_frames_[frame_id];
294*3f982cf4SFabien Sanglard     collector.set_frame_id(frame_id);
295*3f982cf4SFabien Sanglard     EXPECT_TRUE(collector.CollectRtpPacket(part_of_frame, &packet));
296*3f982cf4SFabien Sanglard     if (!collector.is_complete()) {
297*3f982cf4SFabien Sanglard       return;
298*3f982cf4SFabien Sanglard     }
299*3f982cf4SFabien Sanglard     const EncryptedFrame& encrypted = collector.PeekAtAssembledFrame();
300*3f982cf4SFabien Sanglard     EncodedFrameWithBuffer* const decrypted = &complete_frames_[frame_id];
301*3f982cf4SFabien Sanglard     // Note: Not setting decrypted->reference_time here since the logic around
302*3f982cf4SFabien Sanglard     // calculating the playout time is rather complex, and is definitely outside
303*3f982cf4SFabien Sanglard     // the scope of the testing being done in this module. Instead, end-to-end
304*3f982cf4SFabien Sanglard     // testing should exist elsewhere to confirm frame play-out times with real
305*3f982cf4SFabien Sanglard     // Receivers.
306*3f982cf4SFabien Sanglard     decrypted->buffer.resize(FrameCrypto::GetPlaintextSize(encrypted));
307*3f982cf4SFabien Sanglard     decrypted->data = absl::Span<uint8_t>(decrypted->buffer);
308*3f982cf4SFabien Sanglard     crypto_.Decrypt(encrypted, decrypted);
309*3f982cf4SFabien Sanglard     incomplete_frames_.erase(frame_id);
310*3f982cf4SFabien Sanglard     OnFrameComplete(frame_id);
311*3f982cf4SFabien Sanglard   }
312*3f982cf4SFabien Sanglard 
313*3f982cf4SFabien Sanglard   SimulatedNetworkPipe* const pipe_to_sender_;
314*3f982cf4SFabien Sanglard   RtcpSession rtcp_session_;
315*3f982cf4SFabien Sanglard   SenderReportParser sender_report_parser_;
316*3f982cf4SFabien Sanglard   CompoundRtcpBuilder rtcp_builder_;
317*3f982cf4SFabien Sanglard   RtpPacketParser rtp_parser_;
318*3f982cf4SFabien Sanglard   FrameCrypto crypto_;
319*3f982cf4SFabien Sanglard 
320*3f982cf4SFabien Sanglard   std::vector<PacketNack> ignore_list_;
321*3f982cf4SFabien Sanglard   std::map<FrameId, FrameCollector> incomplete_frames_;
322*3f982cf4SFabien Sanglard   std::map<FrameId, EncodedFrameWithBuffer> complete_frames_;
323*3f982cf4SFabien Sanglard };
324*3f982cf4SFabien Sanglard 
325*3f982cf4SFabien Sanglard class MockObserver : public Sender::Observer {
326*3f982cf4SFabien Sanglard  public:
327*3f982cf4SFabien Sanglard   MOCK_METHOD1(OnFrameCanceled, void(FrameId frame_id));
328*3f982cf4SFabien Sanglard   MOCK_METHOD0(OnPictureLost, void());
329*3f982cf4SFabien Sanglard };
330*3f982cf4SFabien Sanglard 
331*3f982cf4SFabien Sanglard class SenderTest : public testing::Test {
332*3f982cf4SFabien Sanglard  public:
SenderTest()333*3f982cf4SFabien Sanglard   SenderTest()
334*3f982cf4SFabien Sanglard       : fake_clock_(Clock::now()),
335*3f982cf4SFabien Sanglard         task_runner_(&fake_clock_),
336*3f982cf4SFabien Sanglard         sender_environment_(&FakeClock::now, &task_runner_),
337*3f982cf4SFabien Sanglard         sender_packet_router_(&sender_environment_,
338*3f982cf4SFabien Sanglard                               kNumPacketsPerBurst,
339*3f982cf4SFabien Sanglard                               kBurstInterval),
340*3f982cf4SFabien Sanglard         sender_(&sender_environment_,
341*3f982cf4SFabien Sanglard                 &sender_packet_router_,
342*3f982cf4SFabien Sanglard                 {/* .sender_ssrc = */ kSenderSsrc,
343*3f982cf4SFabien Sanglard                  /* .receiver_ssrc = */ kReceiverSsrc,
344*3f982cf4SFabien Sanglard                  /* .rtp_timebase = */ kRtpTimebase,
345*3f982cf4SFabien Sanglard                  /* .channels = */ 2,
346*3f982cf4SFabien Sanglard                  /* .target_playout_delay = */ kTargetPlayoutDelay,
347*3f982cf4SFabien Sanglard                  /* .aes_secret_key = */ kAesKey,
348*3f982cf4SFabien Sanglard                  /* .aes_iv_mask = */ kCastIvMask,
349*3f982cf4SFabien Sanglard                  /* .is_pli_enabled = */ true},
350*3f982cf4SFabien Sanglard                 kRtpPayloadType),
351*3f982cf4SFabien Sanglard         receiver_to_sender_pipe_(&task_runner_, &sender_packet_router_),
352*3f982cf4SFabien Sanglard         receiver_(&receiver_to_sender_pipe_),
353*3f982cf4SFabien Sanglard         sender_to_receiver_pipe_(&task_runner_, &receiver_) {
354*3f982cf4SFabien Sanglard     sender_environment_.SetSocketSubscriber(&socket_subscriber_);
355*3f982cf4SFabien Sanglard     sender_environment_.set_remote_endpoint(
356*3f982cf4SFabien Sanglard         receiver_to_sender_pipe_.local_endpoint());
357*3f982cf4SFabien Sanglard     ON_CALL(sender_environment_, SendPacket(_))
__anon6d95d5ef0402(absl::Span<const uint8_t> packet) 358*3f982cf4SFabien Sanglard         .WillByDefault(Invoke([this](absl::Span<const uint8_t> packet) {
359*3f982cf4SFabien Sanglard           sender_to_receiver_pipe_.StartPacketTransmission(
360*3f982cf4SFabien Sanglard               std::vector<uint8_t>(packet.begin(), packet.end()));
361*3f982cf4SFabien Sanglard         }));
362*3f982cf4SFabien Sanglard   }
363*3f982cf4SFabien Sanglard 
364*3f982cf4SFabien Sanglard   ~SenderTest() override = default;
365*3f982cf4SFabien Sanglard 
sender()366*3f982cf4SFabien Sanglard   Sender* sender() { return &sender_; }
receiver()367*3f982cf4SFabien Sanglard   MockReceiver* receiver() { return &receiver_; }
368*3f982cf4SFabien Sanglard 
SetReceiverToSenderNetworkDelay(Clock::duration delay)369*3f982cf4SFabien Sanglard   void SetReceiverToSenderNetworkDelay(Clock::duration delay) {
370*3f982cf4SFabien Sanglard     receiver_to_sender_pipe_.set_network_delay(delay);
371*3f982cf4SFabien Sanglard   }
372*3f982cf4SFabien Sanglard 
SetSenderToReceiverNetworkDelay(Clock::duration delay)373*3f982cf4SFabien Sanglard   void SetSenderToReceiverNetworkDelay(Clock::duration delay) {
374*3f982cf4SFabien Sanglard     sender_to_receiver_pipe_.set_network_delay(delay);
375*3f982cf4SFabien Sanglard   }
376*3f982cf4SFabien Sanglard 
SimulateExecution(Clock::duration how_long=Clock::duration::zero ())377*3f982cf4SFabien Sanglard   void SimulateExecution(Clock::duration how_long = Clock::duration::zero()) {
378*3f982cf4SFabien Sanglard     fake_clock_.Advance(how_long);
379*3f982cf4SFabien Sanglard   }
380*3f982cf4SFabien Sanglard 
PopulateFramePayloadBuffer(int seed,int num_bytes,std::vector<uint8_t> * payload)381*3f982cf4SFabien Sanglard   static void PopulateFramePayloadBuffer(int seed,
382*3f982cf4SFabien Sanglard                                          int num_bytes,
383*3f982cf4SFabien Sanglard                                          std::vector<uint8_t>* payload) {
384*3f982cf4SFabien Sanglard     payload->clear();
385*3f982cf4SFabien Sanglard     payload->reserve(num_bytes);
386*3f982cf4SFabien Sanglard     for (int i = 0; i < num_bytes; ++i) {
387*3f982cf4SFabien Sanglard       payload->push_back(static_cast<uint8_t>(seed + i));
388*3f982cf4SFabien Sanglard     }
389*3f982cf4SFabien Sanglard   }
390*3f982cf4SFabien Sanglard 
PopulateFrameWithDefaults(FrameId frame_id,Clock::time_point reference_time,int seed,int num_payload_bytes,EncodedFrameWithBuffer * frame)391*3f982cf4SFabien Sanglard   static void PopulateFrameWithDefaults(FrameId frame_id,
392*3f982cf4SFabien Sanglard                                         Clock::time_point reference_time,
393*3f982cf4SFabien Sanglard                                         int seed,
394*3f982cf4SFabien Sanglard                                         int num_payload_bytes,
395*3f982cf4SFabien Sanglard                                         EncodedFrameWithBuffer* frame) {
396*3f982cf4SFabien Sanglard     frame->dependency = (frame_id == FrameId::first())
397*3f982cf4SFabien Sanglard                             ? EncodedFrame::KEY_FRAME
398*3f982cf4SFabien Sanglard                             : EncodedFrame::DEPENDS_ON_ANOTHER;
399*3f982cf4SFabien Sanglard     frame->frame_id = frame_id;
400*3f982cf4SFabien Sanglard     frame->referenced_frame_id = frame->frame_id;
401*3f982cf4SFabien Sanglard     if (frame_id != FrameId::first()) {
402*3f982cf4SFabien Sanglard       --frame->referenced_frame_id;
403*3f982cf4SFabien Sanglard     }
404*3f982cf4SFabien Sanglard     frame->rtp_timestamp =
405*3f982cf4SFabien Sanglard         RtpTimeTicks() + (RtpTimeDelta::FromTicks(kRtpTicksPerFrame) *
406*3f982cf4SFabien Sanglard                           (frame_id - FrameId::first()));
407*3f982cf4SFabien Sanglard     frame->reference_time = reference_time;
408*3f982cf4SFabien Sanglard     PopulateFramePayloadBuffer(seed, num_payload_bytes, &frame->buffer);
409*3f982cf4SFabien Sanglard     frame->data = absl::Span<uint8_t>(frame->buffer);
410*3f982cf4SFabien Sanglard   }
411*3f982cf4SFabien Sanglard 
412*3f982cf4SFabien Sanglard   // Confirms that all |sent_frames| exist in |received_frames|, with identical
413*3f982cf4SFabien Sanglard   // data and metadata.
ExpectFramesReceivedCorrectly(absl::Span<EncodedFrameWithBuffer> sent_frames,const std::map<FrameId,EncodedFrameWithBuffer> received_frames)414*3f982cf4SFabien Sanglard   static void ExpectFramesReceivedCorrectly(
415*3f982cf4SFabien Sanglard       absl::Span<EncodedFrameWithBuffer> sent_frames,
416*3f982cf4SFabien Sanglard       const std::map<FrameId, EncodedFrameWithBuffer> received_frames) {
417*3f982cf4SFabien Sanglard     ASSERT_EQ(sent_frames.size(), received_frames.size());
418*3f982cf4SFabien Sanglard 
419*3f982cf4SFabien Sanglard     for (const EncodedFrameWithBuffer& sent_frame : sent_frames) {
420*3f982cf4SFabien Sanglard       SCOPED_TRACE(testing::Message()
421*3f982cf4SFabien Sanglard                    << "Checking sent frame " << sent_frame.frame_id);
422*3f982cf4SFabien Sanglard       const auto received_it = received_frames.find(sent_frame.frame_id);
423*3f982cf4SFabien Sanglard       if (received_it == received_frames.end()) {
424*3f982cf4SFabien Sanglard         ADD_FAILURE() << "Did not receive frame.";
425*3f982cf4SFabien Sanglard         continue;
426*3f982cf4SFabien Sanglard       }
427*3f982cf4SFabien Sanglard       const EncodedFrame& received_frame = received_it->second;
428*3f982cf4SFabien Sanglard       EXPECT_EQ(sent_frame.dependency, received_frame.dependency);
429*3f982cf4SFabien Sanglard       EXPECT_EQ(sent_frame.referenced_frame_id,
430*3f982cf4SFabien Sanglard                 received_frame.referenced_frame_id);
431*3f982cf4SFabien Sanglard       EXPECT_EQ(sent_frame.rtp_timestamp, received_frame.rtp_timestamp);
432*3f982cf4SFabien Sanglard       EXPECT_TRUE(sent_frame.data == received_frame.data);
433*3f982cf4SFabien Sanglard     }
434*3f982cf4SFabien Sanglard   }
435*3f982cf4SFabien Sanglard 
436*3f982cf4SFabien Sanglard  private:
437*3f982cf4SFabien Sanglard   FakeClock fake_clock_;
438*3f982cf4SFabien Sanglard   FakeTaskRunner task_runner_;
439*3f982cf4SFabien Sanglard   NiceMock<MockEnvironment> sender_environment_;
440*3f982cf4SFabien Sanglard   SenderPacketRouter sender_packet_router_;
441*3f982cf4SFabien Sanglard   Sender sender_;
442*3f982cf4SFabien Sanglard   SimulatedNetworkPipe receiver_to_sender_pipe_;
443*3f982cf4SFabien Sanglard   NiceMock<MockReceiver> receiver_;
444*3f982cf4SFabien Sanglard   SimulatedNetworkPipe sender_to_receiver_pipe_;
445*3f982cf4SFabien Sanglard   SimpleSubscriber socket_subscriber_;
446*3f982cf4SFabien Sanglard };
447*3f982cf4SFabien Sanglard 
448*3f982cf4SFabien Sanglard // Tests that the Sender can send EncodedFrames over an ideal network (i.e., low
449*3f982cf4SFabien Sanglard // latency, no loss), and does so without having to transmit the same packet
450*3f982cf4SFabien Sanglard // twice.
TEST_F(SenderTest,SendsFramesEfficiently)451*3f982cf4SFabien Sanglard TEST_F(SenderTest, SendsFramesEfficiently) {
452*3f982cf4SFabien Sanglard   constexpr milliseconds kOneWayNetworkDelay{1};
453*3f982cf4SFabien Sanglard   SetSenderToReceiverNetworkDelay(kOneWayNetworkDelay);
454*3f982cf4SFabien Sanglard   SetReceiverToSenderNetworkDelay(kOneWayNetworkDelay);
455*3f982cf4SFabien Sanglard 
456*3f982cf4SFabien Sanglard   // Expect that each packet is only sent once.
457*3f982cf4SFabien Sanglard   std::set<std::pair<FrameId, FramePacketId>> received_packets;
458*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnRtpPacket(_))
459*3f982cf4SFabien Sanglard       .WillRepeatedly(
460*3f982cf4SFabien Sanglard           Invoke([&](const RtpPacketParser::ParseResult& parsed_packet) {
461*3f982cf4SFabien Sanglard             std::pair<FrameId, FramePacketId> id(parsed_packet.frame_id,
462*3f982cf4SFabien Sanglard                                                  parsed_packet.packet_id);
463*3f982cf4SFabien Sanglard             const auto insert_result = received_packets.insert(id);
464*3f982cf4SFabien Sanglard             EXPECT_TRUE(insert_result.second)
465*3f982cf4SFabien Sanglard                 << "Received duplicate packet: " << id.first << ':'
466*3f982cf4SFabien Sanglard                 << static_cast<int>(id.second);
467*3f982cf4SFabien Sanglard           }));
468*3f982cf4SFabien Sanglard 
469*3f982cf4SFabien Sanglard   // Simulate normal frame ACK'ing behavior.
470*3f982cf4SFabien Sanglard   ON_CALL(*receiver(), OnFrameComplete(_)).WillByDefault(InvokeWithoutArgs([&] {
471*3f982cf4SFabien Sanglard     if (receiver()->AutoAdvanceCheckpoint()) {
472*3f982cf4SFabien Sanglard       receiver()->TransmitRtcpFeedbackPacket();
473*3f982cf4SFabien Sanglard     }
474*3f982cf4SFabien Sanglard   }));
475*3f982cf4SFabien Sanglard 
476*3f982cf4SFabien Sanglard   NiceMock<MockObserver> observer;
477*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(FrameId::first())).Times(1);
478*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(FrameId::first() + 1)).Times(1);
479*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(FrameId::first() + 2)).Times(1);
480*3f982cf4SFabien Sanglard   sender()->SetObserver(&observer);
481*3f982cf4SFabien Sanglard 
482*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer frames[3];
483*3f982cf4SFabien Sanglard   constexpr int kFrameDataSizes[] = {8196, 12, 1900};
484*3f982cf4SFabien Sanglard   for (int i = 0; i < 3; ++i) {
485*3f982cf4SFabien Sanglard     if (i == 0) {
486*3f982cf4SFabien Sanglard       EXPECT_TRUE(sender()->NeedsKeyFrame());
487*3f982cf4SFabien Sanglard     } else {
488*3f982cf4SFabien Sanglard       EXPECT_FALSE(sender()->NeedsKeyFrame());
489*3f982cf4SFabien Sanglard     }
490*3f982cf4SFabien Sanglard     PopulateFrameWithDefaults(FrameId::first() + i,
491*3f982cf4SFabien Sanglard                               FakeClock::now() - kCaptureDelay, 0xbf - i,
492*3f982cf4SFabien Sanglard                               kFrameDataSizes[i], &frames[i]);
493*3f982cf4SFabien Sanglard     ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(frames[i]));
494*3f982cf4SFabien Sanglard     SimulateExecution(kFrameDuration);
495*3f982cf4SFabien Sanglard   }
496*3f982cf4SFabien Sanglard   SimulateExecution(kTargetPlayoutDelay);
497*3f982cf4SFabien Sanglard 
498*3f982cf4SFabien Sanglard   ExpectFramesReceivedCorrectly(frames, receiver()->TakeCompleteFrames());
499*3f982cf4SFabien Sanglard }
500*3f982cf4SFabien Sanglard 
501*3f982cf4SFabien Sanglard // Tests that the Sender correctly computes the current in-flight media
502*3f982cf4SFabien Sanglard // duration, a backlog signal for clients.
TEST_F(SenderTest,ComputesInFlightMediaDuration)503*3f982cf4SFabien Sanglard TEST_F(SenderTest, ComputesInFlightMediaDuration) {
504*3f982cf4SFabien Sanglard   // With no frames enqueued, the in-flight media duration should be zero.
505*3f982cf4SFabien Sanglard   EXPECT_EQ(Clock::duration::zero(),
506*3f982cf4SFabien Sanglard             sender()->GetInFlightMediaDuration(RtpTimeTicks()));
507*3f982cf4SFabien Sanglard   EXPECT_EQ(Clock::duration::zero(),
508*3f982cf4SFabien Sanglard             sender()->GetInFlightMediaDuration(
509*3f982cf4SFabien Sanglard                 RtpTimeTicks() + RtpTimeDelta::FromTicks(kRtpTicksPerFrame)));
510*3f982cf4SFabien Sanglard 
511*3f982cf4SFabien Sanglard   // Enqueue a frame.
512*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer frame;
513*3f982cf4SFabien Sanglard   PopulateFrameWithDefaults(FrameId::first(), FakeClock::now(), 0,
514*3f982cf4SFabien Sanglard                             13 /* bytes */, &frame);
515*3f982cf4SFabien Sanglard   ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(frame));
516*3f982cf4SFabien Sanglard 
517*3f982cf4SFabien Sanglard   // Now, the in-flight media duration should depend on the RTP timestamp of the
518*3f982cf4SFabien Sanglard   // next frame.
519*3f982cf4SFabien Sanglard   EXPECT_EQ(kFrameDuration, sender()->GetInFlightMediaDuration(
520*3f982cf4SFabien Sanglard                                 frame.rtp_timestamp +
521*3f982cf4SFabien Sanglard                                 RtpTimeDelta::FromTicks(kRtpTicksPerFrame)));
522*3f982cf4SFabien Sanglard   EXPECT_EQ(10 * kFrameDuration,
523*3f982cf4SFabien Sanglard             sender()->GetInFlightMediaDuration(
524*3f982cf4SFabien Sanglard                 frame.rtp_timestamp +
525*3f982cf4SFabien Sanglard                 RtpTimeDelta::FromTicks(10 * kRtpTicksPerFrame)));
526*3f982cf4SFabien Sanglard }
527*3f982cf4SFabien Sanglard 
528*3f982cf4SFabien Sanglard // Tests that the Sender computes the maximum in-flight media duration based on
529*3f982cf4SFabien Sanglard // its analysis of current network conditions. By implication, this demonstrates
530*3f982cf4SFabien Sanglard // that the Sender is also measuring the network round-trip time.
TEST_F(SenderTest,RespondsToNetworkLatencyChanges)531*3f982cf4SFabien Sanglard TEST_F(SenderTest, RespondsToNetworkLatencyChanges) {
532*3f982cf4SFabien Sanglard   // The expected maximum error in time calculations is one tick of the RTCP
533*3f982cf4SFabien Sanglard   // report block's delay type.
534*3f982cf4SFabien Sanglard   constexpr auto kEpsilon = to_nanoseconds(RtcpReportBlock::Delay(1));
535*3f982cf4SFabien Sanglard 
536*3f982cf4SFabien Sanglard   // Before the Sender has the necessary information to compute the network
537*3f982cf4SFabien Sanglard   // round-trip time, GetMaxInFlightMediaDuration() will return half the target
538*3f982cf4SFabien Sanglard   // playout delay.
539*3f982cf4SFabien Sanglard   EXPECT_NEARLY_EQUAL(kTargetPlayoutDelay / 2,
540*3f982cf4SFabien Sanglard                       sender()->GetMaxInFlightMediaDuration(), kEpsilon);
541*3f982cf4SFabien Sanglard 
542*3f982cf4SFabien Sanglard   // No network is perfect. Simulate different one-way network delays.
543*3f982cf4SFabien Sanglard   constexpr milliseconds kOutboundDelay{2};
544*3f982cf4SFabien Sanglard   constexpr milliseconds kInboundDelay{4};
545*3f982cf4SFabien Sanglard   constexpr milliseconds kRoundTripDelay = kOutboundDelay + kInboundDelay;
546*3f982cf4SFabien Sanglard   SetSenderToReceiverNetworkDelay(kOutboundDelay);
547*3f982cf4SFabien Sanglard   SetReceiverToSenderNetworkDelay(kInboundDelay);
548*3f982cf4SFabien Sanglard 
549*3f982cf4SFabien Sanglard   // Enqueue a frame in the Sender to start emitting periodic RTCP reports.
550*3f982cf4SFabien Sanglard   {
551*3f982cf4SFabien Sanglard     EncodedFrameWithBuffer frame;
552*3f982cf4SFabien Sanglard     PopulateFrameWithDefaults(FrameId::first(), FakeClock::now(), 0,
553*3f982cf4SFabien Sanglard                               1 /* byte */, &frame);
554*3f982cf4SFabien Sanglard     ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(frame));
555*3f982cf4SFabien Sanglard   }
556*3f982cf4SFabien Sanglard 
557*3f982cf4SFabien Sanglard   // Run one network round-trip from Sender→Receiver→Sender.
558*3f982cf4SFabien Sanglard   StatusReportId sender_report_id{};
559*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnSenderReport(_))
560*3f982cf4SFabien Sanglard       .WillOnce(Invoke(
561*3f982cf4SFabien Sanglard           [&](const SenderReportParser::SenderReportWithId& sender_report) {
562*3f982cf4SFabien Sanglard             sender_report_id = sender_report.report_id;
563*3f982cf4SFabien Sanglard           }));
564*3f982cf4SFabien Sanglard   // Simulate the passage of time for the Sender Report to reach the Receiver.
565*3f982cf4SFabien Sanglard   SimulateExecution(kOutboundDelay);
566*3f982cf4SFabien Sanglard   // The Receiver should have received the Sender Report at this point.
567*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(receiver());
568*3f982cf4SFabien Sanglard   ASSERT_NE(StatusReportId{}, sender_report_id);
569*3f982cf4SFabien Sanglard   // Simulate the passage of time in the Receiver doing "other tasks" before
570*3f982cf4SFabien Sanglard   // replying back to the Sender. This delay is included in the Receiver Report
571*3f982cf4SFabien Sanglard   // so that the Sender can isolate the delays caused by the network.
572*3f982cf4SFabien Sanglard   constexpr milliseconds kReceiverProcessingDelay{2};
573*3f982cf4SFabien Sanglard   SimulateExecution(kReceiverProcessingDelay);
574*3f982cf4SFabien Sanglard   // Create the Receiver Report "reply," and simulate it being sent across the
575*3f982cf4SFabien Sanglard   // network, back to the Sender.
576*3f982cf4SFabien Sanglard   receiver()->SetReceiverReport(
577*3f982cf4SFabien Sanglard       sender_report_id, std::chrono::duration_cast<RtcpReportBlock::Delay>(
578*3f982cf4SFabien Sanglard                             kReceiverProcessingDelay));
579*3f982cf4SFabien Sanglard   receiver()->TransmitRtcpFeedbackPacket();
580*3f982cf4SFabien Sanglard   SimulateExecution(kInboundDelay);
581*3f982cf4SFabien Sanglard 
582*3f982cf4SFabien Sanglard   // At this point, the Sender should have computed the network round-trip time,
583*3f982cf4SFabien Sanglard   // and so GetMaxInFlightMediaDuration() will return half the target playout
584*3f982cf4SFabien Sanglard   // delay PLUS half the network round-trip time.
585*3f982cf4SFabien Sanglard   EXPECT_NEARLY_EQUAL(kTargetPlayoutDelay / 2 + kRoundTripDelay / 2,
586*3f982cf4SFabien Sanglard                       sender()->GetMaxInFlightMediaDuration(), kEpsilon);
587*3f982cf4SFabien Sanglard 
588*3f982cf4SFabien Sanglard   // Increase the outbound delay, which will increase the total round-trip time.
589*3f982cf4SFabien Sanglard   constexpr milliseconds kIncreasedOutboundDelay{6};
590*3f982cf4SFabien Sanglard   constexpr milliseconds kIncreasedRoundTripDelay =
591*3f982cf4SFabien Sanglard       kIncreasedOutboundDelay + kInboundDelay;
592*3f982cf4SFabien Sanglard   SetSenderToReceiverNetworkDelay(kIncreasedOutboundDelay);
593*3f982cf4SFabien Sanglard 
594*3f982cf4SFabien Sanglard   // With increased network delay, run several more network round-trips. Expect
595*3f982cf4SFabien Sanglard   // the Sender to gradually converge towards the new network round-trip time.
596*3f982cf4SFabien Sanglard   constexpr int kNumReportIntervals = 50;
597*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnSenderReport(_))
598*3f982cf4SFabien Sanglard       .Times(kNumReportIntervals)
599*3f982cf4SFabien Sanglard       .WillRepeatedly(Invoke(
600*3f982cf4SFabien Sanglard           [&](const SenderReportParser::SenderReportWithId& sender_report) {
601*3f982cf4SFabien Sanglard             receiver()->SetReceiverReport(sender_report.report_id,
602*3f982cf4SFabien Sanglard                                           RtcpReportBlock::Delay::zero());
603*3f982cf4SFabien Sanglard             receiver()->TransmitRtcpFeedbackPacket();
604*3f982cf4SFabien Sanglard           }));
605*3f982cf4SFabien Sanglard   Clock::duration last_max = sender()->GetMaxInFlightMediaDuration();
606*3f982cf4SFabien Sanglard   for (int i = 0; i < kNumReportIntervals; ++i) {
607*3f982cf4SFabien Sanglard     SimulateExecution(kRtcpReportInterval);
608*3f982cf4SFabien Sanglard     const Clock::duration updated_value =
609*3f982cf4SFabien Sanglard         sender()->GetMaxInFlightMediaDuration();
610*3f982cf4SFabien Sanglard     EXPECT_LE(last_max, updated_value);
611*3f982cf4SFabien Sanglard     last_max = updated_value;
612*3f982cf4SFabien Sanglard   }
613*3f982cf4SFabien Sanglard   EXPECT_NEARLY_EQUAL(kTargetPlayoutDelay / 2 + kIncreasedRoundTripDelay / 2,
614*3f982cf4SFabien Sanglard                       sender()->GetMaxInFlightMediaDuration(), kEpsilon);
615*3f982cf4SFabien Sanglard }
616*3f982cf4SFabien Sanglard 
617*3f982cf4SFabien Sanglard // Tests that the Sender rejects frames if too large a span of FrameIds would be
618*3f982cf4SFabien Sanglard // in-flight at once.
TEST_F(SenderTest,RejectsEnqueuingBeforeProtocolDesignLimit)619*3f982cf4SFabien Sanglard TEST_F(SenderTest, RejectsEnqueuingBeforeProtocolDesignLimit) {
620*3f982cf4SFabien Sanglard   // For this test, use 1000 FPS. This makes the frames all one millisecond
621*3f982cf4SFabien Sanglard   // apart to avoid triggering the media-duration rejection logic.
622*3f982cf4SFabien Sanglard   constexpr int kFramesPerSecond = 1000;
623*3f982cf4SFabien Sanglard   constexpr milliseconds kFrameDuration{1};
624*3f982cf4SFabien Sanglard 
625*3f982cf4SFabien Sanglard   // Send the absolute design-limit maximum number of frames.
626*3f982cf4SFabien Sanglard   int frame_count = 0;
627*3f982cf4SFabien Sanglard   for (; frame_count < kMaxUnackedFrames; ++frame_count) {
628*3f982cf4SFabien Sanglard     EncodedFrameWithBuffer frame;
629*3f982cf4SFabien Sanglard     PopulateFrameWithDefaults(sender()->GetNextFrameId(), FakeClock::now(), 0,
630*3f982cf4SFabien Sanglard                               13 /* bytes */, &frame);
631*3f982cf4SFabien Sanglard     OverrideRtpTimestamp(frame_count, &frame, kFramesPerSecond);
632*3f982cf4SFabien Sanglard     ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(frame));
633*3f982cf4SFabien Sanglard     SimulateExecution(kFrameDuration);
634*3f982cf4SFabien Sanglard   }
635*3f982cf4SFabien Sanglard 
636*3f982cf4SFabien Sanglard   // Now, attempting to enqueue just one more frame should fail.
637*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer one_frame_too_much;
638*3f982cf4SFabien Sanglard   PopulateFrameWithDefaults(sender()->GetNextFrameId(), FakeClock::now(), 0,
639*3f982cf4SFabien Sanglard                             13 /* bytes */, &one_frame_too_much);
640*3f982cf4SFabien Sanglard   OverrideRtpTimestamp(frame_count++, &one_frame_too_much, kFramesPerSecond);
641*3f982cf4SFabien Sanglard   EXPECT_EQ(Sender::REACHED_ID_SPAN_LIMIT,
642*3f982cf4SFabien Sanglard             sender()->EnqueueFrame(one_frame_too_much));
643*3f982cf4SFabien Sanglard   SimulateExecution(kFrameDuration);
644*3f982cf4SFabien Sanglard 
645*3f982cf4SFabien Sanglard   // Now, simulate the Receiver ACKing the first frame, and enqueuing should
646*3f982cf4SFabien Sanglard   // then succeed again.
647*3f982cf4SFabien Sanglard   receiver()->SetCheckpointFrame(FrameId::first());
648*3f982cf4SFabien Sanglard   receiver()->TransmitRtcpFeedbackPacket();
649*3f982cf4SFabien Sanglard   SimulateExecution();  // RTCP transmitted to Sender.
650*3f982cf4SFabien Sanglard   EXPECT_EQ(Sender::OK, sender()->EnqueueFrame(one_frame_too_much));
651*3f982cf4SFabien Sanglard   SimulateExecution(kFrameDuration);
652*3f982cf4SFabien Sanglard 
653*3f982cf4SFabien Sanglard   // Finally, attempting to enqueue another frame should fail again.
654*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer another_frame_too_much;
655*3f982cf4SFabien Sanglard   PopulateFrameWithDefaults(sender()->GetNextFrameId(), FakeClock::now(), 0,
656*3f982cf4SFabien Sanglard                             13 /* bytes */, &another_frame_too_much);
657*3f982cf4SFabien Sanglard   OverrideRtpTimestamp(frame_count++, &another_frame_too_much,
658*3f982cf4SFabien Sanglard                        kFramesPerSecond);
659*3f982cf4SFabien Sanglard   EXPECT_EQ(Sender::REACHED_ID_SPAN_LIMIT,
660*3f982cf4SFabien Sanglard             sender()->EnqueueFrame(another_frame_too_much));
661*3f982cf4SFabien Sanglard   SimulateExecution(kFrameDuration);
662*3f982cf4SFabien Sanglard }
663*3f982cf4SFabien Sanglard 
TEST_F(SenderTest,CanCancelAllInFlightFrames)664*3f982cf4SFabien Sanglard TEST_F(SenderTest, CanCancelAllInFlightFrames) {
665*3f982cf4SFabien Sanglard   NiceMock<MockObserver> observer;
666*3f982cf4SFabien Sanglard   sender()->SetObserver(&observer);
667*3f982cf4SFabien Sanglard 
668*3f982cf4SFabien Sanglard   // Send the absolute design-limit maximum number of frames.
669*3f982cf4SFabien Sanglard   for (int i = 0; i < kMaxUnackedFrames; ++i) {
670*3f982cf4SFabien Sanglard     EncodedFrameWithBuffer frame;
671*3f982cf4SFabien Sanglard     PopulateFrameWithDefaults(sender()->GetNextFrameId(), FakeClock::now(), 0,
672*3f982cf4SFabien Sanglard                               13 /* bytes */, &frame);
673*3f982cf4SFabien Sanglard     OverrideRtpTimestamp(i, &frame, 1000 /* fps */);
674*3f982cf4SFabien Sanglard     ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(frame));
675*3f982cf4SFabien Sanglard     SimulateExecution(kFrameDuration);
676*3f982cf4SFabien Sanglard   }
677*3f982cf4SFabien Sanglard 
678*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(_)).Times(kMaxUnackedFrames);
679*3f982cf4SFabien Sanglard   sender()->CancelInFlightData();
680*3f982cf4SFabien Sanglard }
681*3f982cf4SFabien Sanglard 
682*3f982cf4SFabien Sanglard // Tests that the Sender rejects frames if too-long a media duration is
683*3f982cf4SFabien Sanglard // in-flight. This is the Sender's primary flow control mechanism.
TEST_F(SenderTest,RejectsEnqueuingIfTooLongMediaDurationIsInFlight)684*3f982cf4SFabien Sanglard TEST_F(SenderTest, RejectsEnqueuingIfTooLongMediaDurationIsInFlight) {
685*3f982cf4SFabien Sanglard   // For this test, use 20 FPS. This makes all frames 50 ms apart, which should
686*3f982cf4SFabien Sanglard   // make it easy to trigger the media-duration rejection logic.
687*3f982cf4SFabien Sanglard   constexpr int kFramesPerSecond = 20;
688*3f982cf4SFabien Sanglard   constexpr milliseconds kFrameDuration{50};
689*3f982cf4SFabien Sanglard 
690*3f982cf4SFabien Sanglard   // Enqueue frames until one is rejected because the in-flight duration would
691*3f982cf4SFabien Sanglard   // be too high.
692*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer frame;
693*3f982cf4SFabien Sanglard   int frame_count = 0;
694*3f982cf4SFabien Sanglard   for (; frame_count < kMaxUnackedFrames; ++frame_count) {
695*3f982cf4SFabien Sanglard     PopulateFrameWithDefaults(sender()->GetNextFrameId(), FakeClock::now(), 0,
696*3f982cf4SFabien Sanglard                               13 /* bytes */, &frame);
697*3f982cf4SFabien Sanglard     OverrideRtpTimestamp(frame_count, &frame, kFramesPerSecond);
698*3f982cf4SFabien Sanglard     const auto result = sender()->EnqueueFrame(frame);
699*3f982cf4SFabien Sanglard     SimulateExecution(kFrameDuration);
700*3f982cf4SFabien Sanglard     if (result == Sender::MAX_DURATION_IN_FLIGHT) {
701*3f982cf4SFabien Sanglard       break;
702*3f982cf4SFabien Sanglard     }
703*3f982cf4SFabien Sanglard     ASSERT_EQ(Sender::OK, result);
704*3f982cf4SFabien Sanglard   }
705*3f982cf4SFabien Sanglard 
706*3f982cf4SFabien Sanglard   // Now, simulate the Receiver ACKing the first frame, and enqueuing should
707*3f982cf4SFabien Sanglard   // then succeed again.
708*3f982cf4SFabien Sanglard   receiver()->SetCheckpointFrame(FrameId::first());
709*3f982cf4SFabien Sanglard   receiver()->TransmitRtcpFeedbackPacket();
710*3f982cf4SFabien Sanglard   SimulateExecution();  // RTCP transmitted to Sender.
711*3f982cf4SFabien Sanglard   EXPECT_EQ(Sender::OK, sender()->EnqueueFrame(frame));
712*3f982cf4SFabien Sanglard   SimulateExecution(kFrameDuration);
713*3f982cf4SFabien Sanglard 
714*3f982cf4SFabien Sanglard   // However, attempting to enqueue another frame should fail again.
715*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer one_frame_too_much;
716*3f982cf4SFabien Sanglard   PopulateFrameWithDefaults(sender()->GetNextFrameId(), FakeClock::now(), 0,
717*3f982cf4SFabien Sanglard                             13 /* bytes */, &one_frame_too_much);
718*3f982cf4SFabien Sanglard   OverrideRtpTimestamp(++frame_count, &one_frame_too_much, kFramesPerSecond);
719*3f982cf4SFabien Sanglard   EXPECT_EQ(Sender::MAX_DURATION_IN_FLIGHT,
720*3f982cf4SFabien Sanglard             sender()->EnqueueFrame(one_frame_too_much));
721*3f982cf4SFabien Sanglard   SimulateExecution(kFrameDuration);
722*3f982cf4SFabien Sanglard }
723*3f982cf4SFabien Sanglard 
724*3f982cf4SFabien Sanglard // Tests that the Sender propagates the Receiver's picture loss indicator to the
725*3f982cf4SFabien Sanglard // Observer::OnPictureLost(), and via calls to NeedsKeyFrame(); but only when
726*3f982cf4SFabien Sanglard // producing a key frame is absolutely necessary.
TEST_F(SenderTest,ManagesReceiverPictureLossWorkflow)727*3f982cf4SFabien Sanglard TEST_F(SenderTest, ManagesReceiverPictureLossWorkflow) {
728*3f982cf4SFabien Sanglard   NiceMock<MockObserver> observer;
729*3f982cf4SFabien Sanglard   sender()->SetObserver(&observer);
730*3f982cf4SFabien Sanglard 
731*3f982cf4SFabien Sanglard   // Send three frames...
732*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer frames[6];
733*3f982cf4SFabien Sanglard   for (int i = 0; i < 3; ++i) {
734*3f982cf4SFabien Sanglard     if (i == 0) {
735*3f982cf4SFabien Sanglard       EXPECT_TRUE(sender()->NeedsKeyFrame());
736*3f982cf4SFabien Sanglard     } else {
737*3f982cf4SFabien Sanglard       EXPECT_FALSE(sender()->NeedsKeyFrame());
738*3f982cf4SFabien Sanglard     }
739*3f982cf4SFabien Sanglard     PopulateFrameWithDefaults(FrameId::first() + i,
740*3f982cf4SFabien Sanglard                               FakeClock::now() - kCaptureDelay, 0,
741*3f982cf4SFabien Sanglard                               24 /* bytes */, &frames[i]);
742*3f982cf4SFabien Sanglard     ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(frames[i]));
743*3f982cf4SFabien Sanglard     SimulateExecution(kFrameDuration);
744*3f982cf4SFabien Sanglard   }
745*3f982cf4SFabien Sanglard   SimulateExecution(kTargetPlayoutDelay);
746*3f982cf4SFabien Sanglard 
747*3f982cf4SFabien Sanglard   // Simulate the Receiver ACK'ing the first three frames.
748*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(FrameId::first())).Times(1);
749*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(FrameId::first() + 1)).Times(1);
750*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(FrameId::first() + 2)).Times(1);
751*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnPictureLost()).Times(0);
752*3f982cf4SFabien Sanglard   receiver()->SetCheckpointFrame(frames[2].frame_id);
753*3f982cf4SFabien Sanglard   receiver()->TransmitRtcpFeedbackPacket();
754*3f982cf4SFabien Sanglard   SimulateExecution();  // RTCP transmitted to Sender.
755*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(&observer);
756*3f982cf4SFabien Sanglard 
757*3f982cf4SFabien Sanglard   // Simulate something going wrong in the Receiver, and have it report picture
758*3f982cf4SFabien Sanglard   // loss to the Sender. The Sender should then propagate this to its Observer
759*3f982cf4SFabien Sanglard   // and return true when NeedsKeyFrame() is called.
760*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(_)).Times(0);
761*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnPictureLost()).Times(1);
762*3f982cf4SFabien Sanglard   EXPECT_FALSE(sender()->NeedsKeyFrame());
763*3f982cf4SFabien Sanglard   receiver()->SetPictureLossIndicator(true);
764*3f982cf4SFabien Sanglard   receiver()->TransmitRtcpFeedbackPacket();
765*3f982cf4SFabien Sanglard   SimulateExecution();  // RTCP transmitted to Sender.
766*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(&observer);
767*3f982cf4SFabien Sanglard   EXPECT_TRUE(sender()->NeedsKeyFrame());
768*3f982cf4SFabien Sanglard 
769*3f982cf4SFabien Sanglard   // Send a non-key frame, and expect NeedsKeyFrame() still returns true. The
770*3f982cf4SFabien Sanglard   // Observer is not re-notified. This accounts for the case where a client's
771*3f982cf4SFabien Sanglard   // media encoder had frames in its processing pipeline before NeedsKeyFrame()
772*3f982cf4SFabien Sanglard   // began returning true.
773*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(_)).Times(0);
774*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnPictureLost()).Times(0);
775*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer& nonkey_frame = frames[3];
776*3f982cf4SFabien Sanglard   PopulateFrameWithDefaults(FrameId::first() + 3,
777*3f982cf4SFabien Sanglard                             FakeClock::now() - kCaptureDelay, 0, 24 /* bytes */,
778*3f982cf4SFabien Sanglard                             &nonkey_frame);
779*3f982cf4SFabien Sanglard   ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(nonkey_frame));
780*3f982cf4SFabien Sanglard   SimulateExecution(kFrameDuration);
781*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(&observer);
782*3f982cf4SFabien Sanglard   EXPECT_TRUE(sender()->NeedsKeyFrame());
783*3f982cf4SFabien Sanglard 
784*3f982cf4SFabien Sanglard   // Now send a key frame, and expect NeedsKeyFrame() returns false. Note that
785*3f982cf4SFabien Sanglard   // the Receiver hasn't cleared the PLI condition, but the Sender knows more
786*3f982cf4SFabien Sanglard   // key frames won't be needed.
787*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(_)).Times(0);
788*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnPictureLost()).Times(0);
789*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer& recovery_frame = frames[4];
790*3f982cf4SFabien Sanglard   PopulateFrameWithDefaults(FrameId::first() + 4,
791*3f982cf4SFabien Sanglard                             FakeClock::now() - kCaptureDelay, 0, 24 /* bytes */,
792*3f982cf4SFabien Sanglard                             &recovery_frame);
793*3f982cf4SFabien Sanglard   recovery_frame.dependency = EncodedFrame::KEY_FRAME;
794*3f982cf4SFabien Sanglard   recovery_frame.referenced_frame_id = recovery_frame.frame_id;
795*3f982cf4SFabien Sanglard   ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(recovery_frame));
796*3f982cf4SFabien Sanglard   SimulateExecution(kFrameDuration);
797*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(&observer);
798*3f982cf4SFabien Sanglard   EXPECT_FALSE(sender()->NeedsKeyFrame());
799*3f982cf4SFabien Sanglard 
800*3f982cf4SFabien Sanglard   // Let's say the Receiver hasn't received the key frame yet, and it reports
801*3f982cf4SFabien Sanglard   // its picture loss again to the Sender. Observer::OnPictureLost() should not
802*3f982cf4SFabien Sanglard   // be called, and NeedsKeyFrame() should NOT return true, because the Sender
803*3f982cf4SFabien Sanglard   // knows the Receiver hasn't acknowledged the key frame (just sent) yet.
804*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(nonkey_frame.frame_id)).Times(1);
805*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnPictureLost()).Times(0);
806*3f982cf4SFabien Sanglard   receiver()->SetCheckpointFrame(nonkey_frame.frame_id);
807*3f982cf4SFabien Sanglard   receiver()->SetPictureLossIndicator(true);
808*3f982cf4SFabien Sanglard   receiver()->TransmitRtcpFeedbackPacket();
809*3f982cf4SFabien Sanglard   SimulateExecution();  // RTCP transmitted to Sender.
810*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(&observer);
811*3f982cf4SFabien Sanglard   EXPECT_FALSE(sender()->NeedsKeyFrame());
812*3f982cf4SFabien Sanglard 
813*3f982cf4SFabien Sanglard   // Now, simulate the Receiver getting the key frame, but NOT recovering. This
814*3f982cf4SFabien Sanglard   // should cause Observer::OnPictureLost() to be called, and cause
815*3f982cf4SFabien Sanglard   // NeedsKeyFrame() to return true again.
816*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(recovery_frame.frame_id)).Times(1);
817*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnPictureLost()).Times(1);
818*3f982cf4SFabien Sanglard   receiver()->SetCheckpointFrame(recovery_frame.frame_id);
819*3f982cf4SFabien Sanglard   receiver()->SetPictureLossIndicator(true);
820*3f982cf4SFabien Sanglard   receiver()->TransmitRtcpFeedbackPacket();
821*3f982cf4SFabien Sanglard   SimulateExecution();  // RTCP transmitted to Sender.
822*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(&observer);
823*3f982cf4SFabien Sanglard   EXPECT_TRUE(sender()->NeedsKeyFrame());
824*3f982cf4SFabien Sanglard 
825*3f982cf4SFabien Sanglard   // Send another key frame, and expect NeedsKeyFrame() returns false.
826*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(_)).Times(0);
827*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnPictureLost()).Times(0);
828*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer& another_recovery_frame = frames[5];
829*3f982cf4SFabien Sanglard   PopulateFrameWithDefaults(FrameId::first() + 5,
830*3f982cf4SFabien Sanglard                             FakeClock::now() - kCaptureDelay, 0, 24 /* bytes */,
831*3f982cf4SFabien Sanglard                             &another_recovery_frame);
832*3f982cf4SFabien Sanglard   another_recovery_frame.dependency = EncodedFrame::KEY_FRAME;
833*3f982cf4SFabien Sanglard   another_recovery_frame.referenced_frame_id = another_recovery_frame.frame_id;
834*3f982cf4SFabien Sanglard   ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(another_recovery_frame));
835*3f982cf4SFabien Sanglard   SimulateExecution(kFrameDuration);
836*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(&observer);
837*3f982cf4SFabien Sanglard   EXPECT_FALSE(sender()->NeedsKeyFrame());
838*3f982cf4SFabien Sanglard 
839*3f982cf4SFabien Sanglard   // Now, simulate the Receiver recovering. It will report this to the Sender,
840*3f982cf4SFabien Sanglard   // and NeedsKeyFrame() will still return false.
841*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(another_recovery_frame.frame_id))
842*3f982cf4SFabien Sanglard       .Times(1);
843*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnPictureLost()).Times(0);
844*3f982cf4SFabien Sanglard   receiver()->SetCheckpointFrame(another_recovery_frame.frame_id);
845*3f982cf4SFabien Sanglard   receiver()->SetPictureLossIndicator(false);
846*3f982cf4SFabien Sanglard   receiver()->TransmitRtcpFeedbackPacket();
847*3f982cf4SFabien Sanglard   SimulateExecution();  // RTCP transmitted to Sender.
848*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(&observer);
849*3f982cf4SFabien Sanglard   EXPECT_FALSE(sender()->NeedsKeyFrame());
850*3f982cf4SFabien Sanglard 
851*3f982cf4SFabien Sanglard   ExpectFramesReceivedCorrectly(frames, receiver()->TakeCompleteFrames());
852*3f982cf4SFabien Sanglard }
853*3f982cf4SFabien Sanglard 
854*3f982cf4SFabien Sanglard // Tests that the Receiver should get a Sender Report just before the first RTP
855*3f982cf4SFabien Sanglard // packet, and at regular intervals thereafter. The Sender Report contains the
856*3f982cf4SFabien Sanglard // lip-sync information necessary for play-out timing.
TEST_F(SenderTest,ProvidesSenderReports)857*3f982cf4SFabien Sanglard TEST_F(SenderTest, ProvidesSenderReports) {
858*3f982cf4SFabien Sanglard   std::vector<SenderReportParser::SenderReportWithId> sender_reports;
859*3f982cf4SFabien Sanglard   Sequence packet_sequence;
860*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnSenderReport(_))
861*3f982cf4SFabien Sanglard       .InSequence(packet_sequence)
862*3f982cf4SFabien Sanglard       .WillOnce(
863*3f982cf4SFabien Sanglard           Invoke([&](const SenderReportParser::SenderReportWithId& report) {
864*3f982cf4SFabien Sanglard             sender_reports.push_back(report);
865*3f982cf4SFabien Sanglard           }))
866*3f982cf4SFabien Sanglard       .RetiresOnSaturation();
867*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnRtpPacket(_)).Times(1).InSequence(packet_sequence);
868*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnSenderReport(_))
869*3f982cf4SFabien Sanglard       .Times(3)
870*3f982cf4SFabien Sanglard       .InSequence(packet_sequence)
871*3f982cf4SFabien Sanglard       .WillRepeatedly(
872*3f982cf4SFabien Sanglard           Invoke([&](const SenderReportParser::SenderReportWithId& report) {
873*3f982cf4SFabien Sanglard             sender_reports.push_back(report);
874*3f982cf4SFabien Sanglard           }));
875*3f982cf4SFabien Sanglard 
876*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer frame;
877*3f982cf4SFabien Sanglard   constexpr int kFrameDataSize = 250;
878*3f982cf4SFabien Sanglard   PopulateFrameWithDefaults(FrameId::first(), FakeClock::now(), 0,
879*3f982cf4SFabien Sanglard                             kFrameDataSize, &frame);
880*3f982cf4SFabien Sanglard   ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(frame));
881*3f982cf4SFabien Sanglard   SimulateExecution();  // Should send one Sender Report + one RTP packet.
882*3f982cf4SFabien Sanglard   EXPECT_EQ(size_t{1}, sender_reports.size());
883*3f982cf4SFabien Sanglard 
884*3f982cf4SFabien Sanglard   // Have the Receiver ACK the frame to prevent retransmitting the RTP packet.
885*3f982cf4SFabien Sanglard   receiver()->SetCheckpointFrame(FrameId::first());
886*3f982cf4SFabien Sanglard   receiver()->TransmitRtcpFeedbackPacket();
887*3f982cf4SFabien Sanglard   SimulateExecution();  // RTCP transmitted to Sender.
888*3f982cf4SFabien Sanglard 
889*3f982cf4SFabien Sanglard   // Advance through three more reporting intervals. One Sender Report should be
890*3f982cf4SFabien Sanglard   // sent each interval, making a total of 4 reports sent.
891*3f982cf4SFabien Sanglard   constexpr auto kThreeReportIntervals = 3 * kRtcpReportInterval;
892*3f982cf4SFabien Sanglard   SimulateExecution(kThreeReportIntervals);  // Three more Sender Reports.
893*3f982cf4SFabien Sanglard   ASSERT_EQ(size_t{4}, sender_reports.size());
894*3f982cf4SFabien Sanglard 
895*3f982cf4SFabien Sanglard   // The first report should contain the same timestamps as the frame because
896*3f982cf4SFabien Sanglard   // the Clock did not advance. Also, its packet count and octet count fields
897*3f982cf4SFabien Sanglard   // should be zero since the report was sent before the RTP packet.
898*3f982cf4SFabien Sanglard   EXPECT_EQ(frame.reference_time, sender_reports.front().reference_time);
899*3f982cf4SFabien Sanglard   EXPECT_EQ(frame.rtp_timestamp, sender_reports.front().rtp_timestamp);
900*3f982cf4SFabien Sanglard   EXPECT_EQ(uint32_t{0}, sender_reports.front().send_packet_count);
901*3f982cf4SFabien Sanglard   EXPECT_EQ(uint32_t{0}, sender_reports.front().send_octet_count);
902*3f982cf4SFabien Sanglard 
903*3f982cf4SFabien Sanglard   // The last report should contain the timestamps extrapolated into the future
904*3f982cf4SFabien Sanglard   // because the Clock did move forward. Also, the packet count and octet fields
905*3f982cf4SFabien Sanglard   // should now be non-zero because the report was sent after the RTP packet.
906*3f982cf4SFabien Sanglard   EXPECT_EQ(frame.reference_time + kThreeReportIntervals,
907*3f982cf4SFabien Sanglard             sender_reports.back().reference_time);
908*3f982cf4SFabien Sanglard   EXPECT_EQ(frame.rtp_timestamp +
909*3f982cf4SFabien Sanglard                 RtpTimeDelta::FromDuration(kThreeReportIntervals, kRtpTimebase),
910*3f982cf4SFabien Sanglard             sender_reports.back().rtp_timestamp);
911*3f982cf4SFabien Sanglard   EXPECT_EQ(uint32_t{1}, sender_reports.back().send_packet_count);
912*3f982cf4SFabien Sanglard   EXPECT_EQ(uint32_t{kFrameDataSize}, sender_reports.back().send_octet_count);
913*3f982cf4SFabien Sanglard }
914*3f982cf4SFabien Sanglard 
915*3f982cf4SFabien Sanglard // Tests that the Sender provides Kickstart packets whenever the Receiver may
916*3f982cf4SFabien Sanglard // not know about new frames.
TEST_F(SenderTest,ProvidesKickstartPacketsIfReceiverDoesNotACK)917*3f982cf4SFabien Sanglard TEST_F(SenderTest, ProvidesKickstartPacketsIfReceiverDoesNotACK) {
918*3f982cf4SFabien Sanglard   // Have the Receiver move the checkpoint forward only for the first frame, and
919*3f982cf4SFabien Sanglard   // none of the later frames. This will force the Sender to eventually send a
920*3f982cf4SFabien Sanglard   // Kickstart packet.
921*3f982cf4SFabien Sanglard   ON_CALL(*receiver(), OnFrameComplete(_))
922*3f982cf4SFabien Sanglard       .WillByDefault(Invoke([&](FrameId frame_id) {
923*3f982cf4SFabien Sanglard         if (frame_id == FrameId::first()) {
924*3f982cf4SFabien Sanglard           receiver()->SetCheckpointFrame(FrameId::first());
925*3f982cf4SFabien Sanglard           receiver()->TransmitRtcpFeedbackPacket();
926*3f982cf4SFabien Sanglard         }
927*3f982cf4SFabien Sanglard       }));
928*3f982cf4SFabien Sanglard 
929*3f982cf4SFabien Sanglard   // Send three frames, paced to the media.
930*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer frames[3];
931*3f982cf4SFabien Sanglard   for (int i = 0; i < 3; ++i) {
932*3f982cf4SFabien Sanglard     PopulateFrameWithDefaults(FrameId::first() + i,
933*3f982cf4SFabien Sanglard                               FakeClock::now() - kCaptureDelay, i,
934*3f982cf4SFabien Sanglard                               48 /* bytes */, &frames[i]);
935*3f982cf4SFabien Sanglard     ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(frames[i]));
936*3f982cf4SFabien Sanglard     SimulateExecution(kFrameDuration);
937*3f982cf4SFabien Sanglard   }
938*3f982cf4SFabien Sanglard 
939*3f982cf4SFabien Sanglard   // Now, do nothing for a while. Because the Receiver isn't moving the
940*3f982cf4SFabien Sanglard   // checkpoint forward, the Sender will have sent all the RTP packets at least
941*3f982cf4SFabien Sanglard   // once, and then will start sending just Kickstart packets.
942*3f982cf4SFabien Sanglard   SimulateExecution(kTargetPlayoutDelay);
943*3f982cf4SFabien Sanglard 
944*3f982cf4SFabien Sanglard   // Keep doing nothing for a while, and confirm the Sender is just sending the
945*3f982cf4SFabien Sanglard   // same Kickstart packet over and over. The Kickstart packet is supposed to be
946*3f982cf4SFabien Sanglard   // the last packet of the latest frame.
947*3f982cf4SFabien Sanglard   std::set<std::pair<FrameId, FramePacketId>> unique_received_packet_ids;
948*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnRtpPacket(_))
949*3f982cf4SFabien Sanglard       .WillRepeatedly(
950*3f982cf4SFabien Sanglard           Invoke([&](const RtpPacketParser::ParseResult& parsed_packet) {
951*3f982cf4SFabien Sanglard             unique_received_packet_ids.emplace(parsed_packet.frame_id,
952*3f982cf4SFabien Sanglard                                                parsed_packet.packet_id);
953*3f982cf4SFabien Sanglard           }));
954*3f982cf4SFabien Sanglard   SimulateExecution(kTargetPlayoutDelay);
955*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(receiver());
956*3f982cf4SFabien Sanglard   EXPECT_EQ(size_t{1}, unique_received_packet_ids.size());
957*3f982cf4SFabien Sanglard   EXPECT_EQ(frames[2].frame_id, unique_received_packet_ids.begin()->first);
958*3f982cf4SFabien Sanglard 
959*3f982cf4SFabien Sanglard   // Now, simulate the Receiver ACKing all the frames.
960*3f982cf4SFabien Sanglard   receiver()->SetCheckpointFrame(frames[2].frame_id);
961*3f982cf4SFabien Sanglard   receiver()->TransmitRtcpFeedbackPacket();
962*3f982cf4SFabien Sanglard   SimulateExecution();  // RTCP transmitted to Sender.
963*3f982cf4SFabien Sanglard 
964*3f982cf4SFabien Sanglard   // With all the frames sent, the Sender should not be transmitting anything.
965*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnRtpPacket(_)).Times(0);
966*3f982cf4SFabien Sanglard   SimulateExecution(10 * kTargetPlayoutDelay);
967*3f982cf4SFabien Sanglard 
968*3f982cf4SFabien Sanglard   ExpectFramesReceivedCorrectly(frames, receiver()->TakeCompleteFrames());
969*3f982cf4SFabien Sanglard }
970*3f982cf4SFabien Sanglard 
971*3f982cf4SFabien Sanglard // Tests that the Sender only retransmits packets specifically NACK'ed by the
972*3f982cf4SFabien Sanglard // Receiver.
TEST_F(SenderTest,ResendsIndividuallyNackedPackets)973*3f982cf4SFabien Sanglard TEST_F(SenderTest, ResendsIndividuallyNackedPackets) {
974*3f982cf4SFabien Sanglard   // Populate the frame data in each frame with enough bytes to force at least
975*3f982cf4SFabien Sanglard   // three RTP packets per frame.
976*3f982cf4SFabien Sanglard   constexpr int kFrameDataSize = 3 * kMaxRtpPacketSizeForIpv6UdpOnEthernet;
977*3f982cf4SFabien Sanglard 
978*3f982cf4SFabien Sanglard   // Use a 1ms network delay in each direction to make the sequence of events
979*3f982cf4SFabien Sanglard   // clearer in this test.
980*3f982cf4SFabien Sanglard   constexpr milliseconds kOneWayNetworkDelay{1};
981*3f982cf4SFabien Sanglard   SetSenderToReceiverNetworkDelay(kOneWayNetworkDelay);
982*3f982cf4SFabien Sanglard   SetReceiverToSenderNetworkDelay(kOneWayNetworkDelay);
983*3f982cf4SFabien Sanglard 
984*3f982cf4SFabien Sanglard   // Simulate that three specific packets will be dropped by the network, one
985*3f982cf4SFabien Sanglard   // from each frame (about to be sent).
986*3f982cf4SFabien Sanglard   const std::vector<PacketNack> dropped_packets{
987*3f982cf4SFabien Sanglard       {FrameId::first(), FramePacketId{2}},
988*3f982cf4SFabien Sanglard       {FrameId::first() + 1, FramePacketId{1}},
989*3f982cf4SFabien Sanglard       {FrameId::first() + 2, FramePacketId{0}},
990*3f982cf4SFabien Sanglard   };
991*3f982cf4SFabien Sanglard   receiver()->SetIgnoreList(dropped_packets);
992*3f982cf4SFabien Sanglard 
993*3f982cf4SFabien Sanglard   // Send three frames, paced to the media. The Receiver won't completely
994*3f982cf4SFabien Sanglard   // receive any of these frames due to dropped packets.
995*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnFrameComplete(_)).Times(0);
996*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer frames[3];
997*3f982cf4SFabien Sanglard   for (int i = 0; i < 3; ++i) {
998*3f982cf4SFabien Sanglard     PopulateFrameWithDefaults(FrameId::first() + i,
999*3f982cf4SFabien Sanglard                               FakeClock::now() - kCaptureDelay, i,
1000*3f982cf4SFabien Sanglard                               kFrameDataSize, &frames[i]);
1001*3f982cf4SFabien Sanglard     ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(frames[i]));
1002*3f982cf4SFabien Sanglard     SimulateExecution(kFrameDuration);
1003*3f982cf4SFabien Sanglard   }
1004*3f982cf4SFabien Sanglard   SimulateExecution(kTargetPlayoutDelay);
1005*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(receiver());
1006*3f982cf4SFabien Sanglard   EXPECT_EQ(3, sender()->GetInFlightFrameCount());
1007*3f982cf4SFabien Sanglard 
1008*3f982cf4SFabien Sanglard   // The Receiver NACKs the three dropped packets...
1009*3f982cf4SFabien Sanglard   receiver()->SetNacksAndAcks(dropped_packets, {});
1010*3f982cf4SFabien Sanglard   receiver()->TransmitRtcpFeedbackPacket();
1011*3f982cf4SFabien Sanglard 
1012*3f982cf4SFabien Sanglard   // In the meantime, the network recovers (i.e., no more dropped packets)...
1013*3f982cf4SFabien Sanglard   receiver()->SetIgnoreList({});
1014*3f982cf4SFabien Sanglard 
1015*3f982cf4SFabien Sanglard   // The NACKs reach the Sender, and it acts on them by retransmitting.
1016*3f982cf4SFabien Sanglard   SimulateExecution(kOneWayNetworkDelay);
1017*3f982cf4SFabien Sanglard 
1018*3f982cf4SFabien Sanglard   // As each retransmitted packet arrives at the Receiver, advance the
1019*3f982cf4SFabien Sanglard   // checkpoint forward to notify the Sender of frames that are now completely
1020*3f982cf4SFabien Sanglard   // received. Also, confirm that only the three specifically-NACK'ed packets
1021*3f982cf4SFabien Sanglard   // were retransmitted.
1022*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnFrameComplete(_))
1023*3f982cf4SFabien Sanglard       .Times(3)
1024*3f982cf4SFabien Sanglard       .WillRepeatedly(InvokeWithoutArgs([&] {
1025*3f982cf4SFabien Sanglard         if (receiver()->AutoAdvanceCheckpoint()) {
1026*3f982cf4SFabien Sanglard           receiver()->TransmitRtcpFeedbackPacket();
1027*3f982cf4SFabien Sanglard         }
1028*3f982cf4SFabien Sanglard       }));
1029*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnRtpPacket(_))
1030*3f982cf4SFabien Sanglard       .Times(3)
1031*3f982cf4SFabien Sanglard       .WillRepeatedly(Invoke([&](const RtpPacketParser::ParseResult& packet) {
1032*3f982cf4SFabien Sanglard         EXPECT_FALSE(std::find(dropped_packets.begin(), dropped_packets.end(),
1033*3f982cf4SFabien Sanglard                                PacketNack{packet.frame_id, packet.packet_id}) ==
1034*3f982cf4SFabien Sanglard                      dropped_packets.end());
1035*3f982cf4SFabien Sanglard       }));
1036*3f982cf4SFabien Sanglard   SimulateExecution(kOneWayNetworkDelay);
1037*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(receiver());
1038*3f982cf4SFabien Sanglard 
1039*3f982cf4SFabien Sanglard   // The Receiver checkpoint feedback(s) travel back to the Sender, and there
1040*3f982cf4SFabien Sanglard   // should no longer be any frames in-flight.
1041*3f982cf4SFabien Sanglard   SimulateExecution(kOneWayNetworkDelay);
1042*3f982cf4SFabien Sanglard   EXPECT_EQ(0, sender()->GetInFlightFrameCount());
1043*3f982cf4SFabien Sanglard 
1044*3f982cf4SFabien Sanglard   // The Sender should not be transmitting anything from now on since all frames
1045*3f982cf4SFabien Sanglard   // are known to have been completely received.
1046*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnRtpPacket(_)).Times(0);
1047*3f982cf4SFabien Sanglard   SimulateExecution(10 * kTargetPlayoutDelay);
1048*3f982cf4SFabien Sanglard 
1049*3f982cf4SFabien Sanglard   ExpectFramesReceivedCorrectly(frames, receiver()->TakeCompleteFrames());
1050*3f982cf4SFabien Sanglard }
1051*3f982cf4SFabien Sanglard 
1052*3f982cf4SFabien Sanglard // Tests that the Sender retransmits an entire frame if the Receiver requests it
1053*3f982cf4SFabien Sanglard // (i.e., a full frame NACK), but does not retransmit any packets for frames
1054*3f982cf4SFabien Sanglard // (before or after) that have been acknowledged.
TEST_F(SenderTest,ResendsMissingFrames)1055*3f982cf4SFabien Sanglard TEST_F(SenderTest, ResendsMissingFrames) {
1056*3f982cf4SFabien Sanglard   // Populate the frame data in each frame with enough bytes to force at least
1057*3f982cf4SFabien Sanglard   // three RTP packets per frame.
1058*3f982cf4SFabien Sanglard   constexpr int kFrameDataSize = 3 * kMaxRtpPacketSizeForIpv6UdpOnEthernet;
1059*3f982cf4SFabien Sanglard 
1060*3f982cf4SFabien Sanglard   // Use a 1ms network delay in each direction to make the sequence of events
1061*3f982cf4SFabien Sanglard   // clearer in this test.
1062*3f982cf4SFabien Sanglard   constexpr milliseconds kOneWayNetworkDelay{1};
1063*3f982cf4SFabien Sanglard   SetSenderToReceiverNetworkDelay(kOneWayNetworkDelay);
1064*3f982cf4SFabien Sanglard   SetReceiverToSenderNetworkDelay(kOneWayNetworkDelay);
1065*3f982cf4SFabien Sanglard 
1066*3f982cf4SFabien Sanglard   // Simulate that all of the packets for the second frame will be dropped by
1067*3f982cf4SFabien Sanglard   // the network, but only the packets for that frame.
1068*3f982cf4SFabien Sanglard   const std::vector<PacketNack> dropped_packets{
1069*3f982cf4SFabien Sanglard       {FrameId::first() + 1, kAllPacketsLost},
1070*3f982cf4SFabien Sanglard   };
1071*3f982cf4SFabien Sanglard   receiver()->SetIgnoreList(dropped_packets);
1072*3f982cf4SFabien Sanglard 
1073*3f982cf4SFabien Sanglard   NiceMock<MockObserver> observer;
1074*3f982cf4SFabien Sanglard   sender()->SetObserver(&observer);
1075*3f982cf4SFabien Sanglard 
1076*3f982cf4SFabien Sanglard   // The expectations below track the story and execute simulated Receiver
1077*3f982cf4SFabien Sanglard   // responses. The Sender will have three frames enqueued by its client, and
1078*3f982cf4SFabien Sanglard   // then...
1079*3f982cf4SFabien Sanglard   //
1080*3f982cf4SFabien Sanglard   // The first frame is received and the Receiver ACKs it by moving the
1081*3f982cf4SFabien Sanglard   // checkpoint forward.
1082*3f982cf4SFabien Sanglard   Sequence completion_sequence;
1083*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnFrameComplete(FrameId::first()))
1084*3f982cf4SFabien Sanglard       .InSequence(completion_sequence)
1085*3f982cf4SFabien Sanglard       .WillOnce(InvokeWithoutArgs([&] {
1086*3f982cf4SFabien Sanglard         receiver()->SetCheckpointFrame(FrameId::first());
1087*3f982cf4SFabien Sanglard         receiver()->TransmitRtcpFeedbackPacket();
1088*3f982cf4SFabien Sanglard       }));
1089*3f982cf4SFabien Sanglard   // Since all of the packets for the second frame are being dropped, the third
1090*3f982cf4SFabien Sanglard   // frame will finish next. The Receiver responds by NACKing the second frame
1091*3f982cf4SFabien Sanglard   // and ACKing the third frame. The checkpoint does not move forward because
1092*3f982cf4SFabien Sanglard   // the second frame has not been received yet.
1093*3f982cf4SFabien Sanglard   //
1094*3f982cf4SFabien Sanglard   // NETWORK CHANGE: After the third frame is received, stop dropping packets.
1095*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnFrameComplete(FrameId::first() + 2))
1096*3f982cf4SFabien Sanglard       .InSequence(completion_sequence)
1097*3f982cf4SFabien Sanglard       .WillOnce(InvokeWithoutArgs([&] {
1098*3f982cf4SFabien Sanglard         receiver()->SetNacksAndAcks(dropped_packets,
1099*3f982cf4SFabien Sanglard                                     std::vector<FrameId>{FrameId::first() + 2});
1100*3f982cf4SFabien Sanglard         receiver()->TransmitRtcpFeedbackPacket();
1101*3f982cf4SFabien Sanglard         receiver()->SetIgnoreList({});
1102*3f982cf4SFabien Sanglard       }));
1103*3f982cf4SFabien Sanglard   // Finally, the Sender should respond to the whole-frame NACK by re-sending
1104*3f982cf4SFabien Sanglard   // all of the packets for the second frame, and so the Receiver should
1105*3f982cf4SFabien Sanglard   // completely receive the frame.
1106*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnFrameComplete(FrameId::first() + 1))
1107*3f982cf4SFabien Sanglard       .InSequence(completion_sequence)
1108*3f982cf4SFabien Sanglard       .WillOnce(InvokeWithoutArgs([&] {
1109*3f982cf4SFabien Sanglard         receiver()->SetCheckpointFrame(FrameId::first() + 2);
1110*3f982cf4SFabien Sanglard         receiver()->TransmitRtcpFeedbackPacket();
1111*3f982cf4SFabien Sanglard       }));
1112*3f982cf4SFabien Sanglard 
1113*3f982cf4SFabien Sanglard   // From the Sender's perspective, the Receiver will ACK the first frame, then
1114*3f982cf4SFabien Sanglard   // the third frame, then the second frame.
1115*3f982cf4SFabien Sanglard   Sequence cancel_sequence;
1116*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(FrameId::first()))
1117*3f982cf4SFabien Sanglard       .Times(1)
1118*3f982cf4SFabien Sanglard       .InSequence(cancel_sequence);
1119*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(FrameId::first() + 2))
1120*3f982cf4SFabien Sanglard       .Times(1)
1121*3f982cf4SFabien Sanglard       .InSequence(cancel_sequence);
1122*3f982cf4SFabien Sanglard   EXPECT_CALL(observer, OnFrameCanceled(FrameId::first() + 1))
1123*3f982cf4SFabien Sanglard       .Times(1)
1124*3f982cf4SFabien Sanglard       .InSequence(cancel_sequence);
1125*3f982cf4SFabien Sanglard 
1126*3f982cf4SFabien Sanglard   // With all the expectations/sequences in-place, let 'er rip!
1127*3f982cf4SFabien Sanglard   EncodedFrameWithBuffer frames[3];
1128*3f982cf4SFabien Sanglard   for (int i = 0; i < 3; ++i) {
1129*3f982cf4SFabien Sanglard     PopulateFrameWithDefaults(FrameId::first() + i,
1130*3f982cf4SFabien Sanglard                               FakeClock::now() - kCaptureDelay, i,
1131*3f982cf4SFabien Sanglard                               kFrameDataSize, &frames[i]);
1132*3f982cf4SFabien Sanglard     ASSERT_EQ(Sender::OK, sender()->EnqueueFrame(frames[i]));
1133*3f982cf4SFabien Sanglard     SimulateExecution(kFrameDuration);
1134*3f982cf4SFabien Sanglard   }
1135*3f982cf4SFabien Sanglard   SimulateExecution(kTargetPlayoutDelay);
1136*3f982cf4SFabien Sanglard   Mock::VerifyAndClearExpectations(receiver());
1137*3f982cf4SFabien Sanglard   EXPECT_EQ(0, sender()->GetInFlightFrameCount());
1138*3f982cf4SFabien Sanglard 
1139*3f982cf4SFabien Sanglard   // The Sender should not be transmitting anything from now on since all frames
1140*3f982cf4SFabien Sanglard   // are known to have been completely received.
1141*3f982cf4SFabien Sanglard   EXPECT_CALL(*receiver(), OnRtpPacket(_)).Times(0);
1142*3f982cf4SFabien Sanglard   SimulateExecution(10 * kTargetPlayoutDelay);
1143*3f982cf4SFabien Sanglard 
1144*3f982cf4SFabien Sanglard   ExpectFramesReceivedCorrectly(frames, receiver()->TakeCompleteFrames());
1145*3f982cf4SFabien Sanglard }
1146*3f982cf4SFabien Sanglard 
1147*3f982cf4SFabien Sanglard }  // namespace
1148*3f982cf4SFabien Sanglard }  // namespace cast
1149*3f982cf4SFabien Sanglard }  // namespace openscreen
1150