blob: da2bed649bff1947745edb9cf5e79200249ca681 [file] [log] [blame]
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +00001/*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "call/rtp_video_sender.h"
12
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +010013#include <atomic>
kwiberg27f982b2016-03-01 11:52:33 -080014#include <memory>
Åsa Persson4bece9a2017-10-06 10:04:04 +020015#include <string>
Tommi6fba6b72022-01-28 09:00:01 +010016#include <utility>
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +010017
Danil Chapovalovb7128ed2022-07-06 18:35:01 +020018#include "absl/functional/any_invocable.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020019#include "call/rtp_transport_controller_send.h"
Erik Språng490d76c2019-05-07 09:29:15 -070020#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
21#include "modules/rtp_rtcp/source/byte_io.h"
22#include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
Danil Chapovalov2272f202020-02-18 12:09:43 +010023#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h"
Erik Språng490d76c2019-05-07 09:29:15 -070024#include "modules/rtp_rtcp/source/rtp_packet.h"
Stefan Holmer64be7fa2018-10-04 15:21:55 +020025#include "modules/video_coding/fec_controller_default.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "modules/video_coding/include/video_codec_interface.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020027#include "rtc_base/rate_limiter.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "test/gmock.h"
29#include "test/gtest.h"
Marina Ciocea1148fd52020-04-29 22:39:13 +020030#include "test/mock_frame_transformer.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020031#include "test/mock_transport.h"
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +010032#include "test/scenario/scenario.h"
Jonas Orelandc7f691a2022-03-09 15:12:07 +010033#include "test/scoped_key_value_config.h"
Erik Språng00cc8362019-11-25 12:21:46 +010034#include "test/time_controller/simulated_time_controller.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020035#include "video/send_delay_stats.h"
36#include "video/send_statistics_proxy.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000037
Emil Lundmark6c81a422022-05-18 17:13:34 +020038namespace webrtc {
39namespace {
40
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000041using ::testing::_;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000042using ::testing::NiceMock;
Niels Möller949f0fd2019-01-29 09:44:24 +010043using ::testing::SaveArg;
Danil Chapovalov2272f202020-02-18 12:09:43 +010044using ::testing::SizeIs;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000045
Åsa Persson4bece9a2017-10-06 10:04:04 +020046const int8_t kPayloadType = 96;
47const uint32_t kSsrc1 = 12345;
48const uint32_t kSsrc2 = 23456;
Erik Språng490d76c2019-05-07 09:29:15 -070049const uint32_t kRtxSsrc1 = 34567;
50const uint32_t kRtxSsrc2 = 45678;
Åsa Persson4bece9a2017-10-06 10:04:04 +020051const int16_t kInitialPictureId1 = 222;
52const int16_t kInitialPictureId2 = 44;
Niels Möllerbb894ff2018-03-15 12:28:53 +010053const int16_t kInitialTl0PicIdx1 = 99;
54const int16_t kInitialTl0PicIdx2 = 199;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020055const int64_t kRetransmitWindowSizeMs = 500;
Erik Språng845c6aa2019-05-29 13:02:24 +020056const int kTransportsSequenceExtensionId = 7;
Danil Chapovalov2272f202020-02-18 12:09:43 +010057const int kDependencyDescriptorExtensionId = 8;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020058
59class MockRtcpIntraFrameObserver : public RtcpIntraFrameObserver {
60 public:
Danil Chapovalov9a5efe92020-05-14 22:06:18 +020061 MOCK_METHOD(void, OnReceivedIntraFrameRequest, (uint32_t), (override));
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020062};
63
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020064RtpSenderObservers CreateObservers(
65 RtcpRttStats* rtcp_rtt_stats,
66 RtcpIntraFrameObserver* intra_frame_callback,
Henrik Boström87e3f9d2019-05-27 10:44:24 +020067 ReportBlockDataObserver* report_block_data_observer,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020068 StreamDataCountersCallback* rtp_stats,
69 BitrateStatisticsObserver* bitrate_observer,
70 FrameCountObserver* frame_count_observer,
71 RtcpPacketTypeCounterObserver* rtcp_type_observer,
72 SendSideDelayObserver* send_delay_observer,
Stefan Holmer64be7fa2018-10-04 15:21:55 +020073 SendPacketObserver* send_packet_observer) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020074 RtpSenderObservers observers;
75 observers.rtcp_rtt_stats = rtcp_rtt_stats;
76 observers.intra_frame_callback = intra_frame_callback;
Erik Språng490d76c2019-05-07 09:29:15 -070077 observers.rtcp_loss_notification_observer = nullptr;
Henrik Boström87e3f9d2019-05-27 10:44:24 +020078 observers.report_block_data_observer = report_block_data_observer;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020079 observers.rtp_stats = rtp_stats;
80 observers.bitrate_observer = bitrate_observer;
81 observers.frame_count_observer = frame_count_observer;
82 observers.rtcp_type_observer = rtcp_type_observer;
83 observers.send_delay_observer = send_delay_observer;
84 observers.send_packet_observer = send_packet_observer;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020085 return observers;
86}
87
Erik Språng490d76c2019-05-07 09:29:15 -070088BitrateConstraints GetBitrateConfig() {
89 BitrateConstraints bitrate_config;
90 bitrate_config.min_bitrate_bps = 30000;
91 bitrate_config.start_bitrate_bps = 300000;
92 bitrate_config.max_bitrate_bps = 3000000;
93 return bitrate_config;
94}
95
96VideoSendStream::Config CreateVideoSendStreamConfig(
97 Transport* transport,
98 const std::vector<uint32_t>& ssrcs,
99 const std::vector<uint32_t>& rtx_ssrcs,
100 int payload_type) {
101 VideoSendStream::Config config(transport);
102 config.rtp.ssrcs = ssrcs;
103 config.rtp.rtx.ssrcs = rtx_ssrcs;
104 config.rtp.payload_type = payload_type;
105 config.rtp.rtx.payload_type = payload_type + 1;
106 config.rtp.nack.rtp_history_ms = 1000;
Erik Språng845c6aa2019-05-29 13:02:24 +0200107 config.rtp.extensions.emplace_back(RtpExtension::kTransportSequenceNumberUri,
108 kTransportsSequenceExtensionId);
Danil Chapovalovd0321c52021-09-14 12:58:51 +0200109 config.rtp.extensions.emplace_back(RtpDependencyDescriptorExtension::Uri(),
Danil Chapovalov2272f202020-02-18 12:09:43 +0100110 kDependencyDescriptorExtensionId);
Danil Chapovalov748550d2021-04-29 11:42:54 +0200111 config.rtp.extmap_allow_mixed = true;
Erik Språng490d76c2019-05-07 09:29:15 -0700112 return config;
113}
114
Stefan Holmer9416ef82018-07-19 10:34:38 +0200115class RtpVideoSenderTestFixture {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200116 public:
Stefan Holmer9416ef82018-07-19 10:34:38 +0200117 RtpVideoSenderTestFixture(
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200118 const std::vector<uint32_t>& ssrcs,
Erik Språng490d76c2019-05-07 09:29:15 -0700119 const std::vector<uint32_t>& rtx_ssrcs,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200120 int payload_type,
Niels Möller949f0fd2019-01-29 09:44:24 +0100121 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
Marina Cioceadc69fd22020-04-10 20:19:14 +0200122 FrameCountObserver* frame_count_observer,
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100123 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
Jonas Orelande62c2f22022-03-29 11:04:48 +0200124 const FieldTrialsView* field_trials = nullptr)
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100125 : time_controller_(Timestamp::Millis(1000000)),
Erik Språng490d76c2019-05-07 09:29:15 -0700126 config_(CreateVideoSendStreamConfig(&transport_,
127 ssrcs,
128 rtx_ssrcs,
129 payload_type)),
Erik Språng00cc8362019-11-25 12:21:46 +0100130 send_delay_stats_(time_controller_.GetClock()),
Erik Språng490d76c2019-05-07 09:29:15 -0700131 bitrate_config_(GetBitrateConfig()),
Henrik Boströmda4c1022022-11-15 15:45:41 +0100132 transport_controller_(
133 time_controller_.GetClock(),
134 RtpTransportConfig{
135 .bitrate_config = bitrate_config_,
136 .event_log = &event_log_,
137 .task_queue_factory = time_controller_.GetTaskQueueFactory(),
138 .trials = field_trials ? field_trials : &field_trials_,
139 }),
Erik Språng00cc8362019-11-25 12:21:46 +0100140 stats_proxy_(time_controller_.GetClock(),
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200141 config_,
Jonas Oreland8ca06132022-03-14 12:52:48 +0100142 VideoEncoderConfig::ContentType::kRealtimeVideo,
143 field_trials ? *field_trials : field_trials_),
Erik Språng00cc8362019-11-25 12:21:46 +0100144 retransmission_rate_limiter_(time_controller_.GetClock(),
145 kRetransmitWindowSizeMs) {
Erik Språng7703f232020-09-14 11:03:13 +0200146 transport_controller_.EnsureStarted();
Mirko Bonadeif18f9202019-12-10 13:24:56 +0000147 std::map<uint32_t, RtpState> suspended_ssrcs;
148 router_ = std::make_unique<RtpVideoSender>(
149 time_controller_.GetClock(), suspended_ssrcs, suspended_payload_states,
150 config_.rtp, config_.rtcp_report_interval_ms, &transport_,
Niels Möller98d9c302020-12-16 11:53:09 +0100151 CreateObservers(nullptr, &encoder_feedback_, &stats_proxy_,
Danil Chapovalovf01c2c92021-05-14 15:39:23 +0200152 &stats_proxy_, &stats_proxy_, frame_count_observer,
153 &stats_proxy_, &stats_proxy_, &send_delay_stats_),
Mirko Bonadeif18f9202019-12-10 13:24:56 +0000154 &transport_controller_, &event_log_, &retransmission_rate_limiter_,
155 std::make_unique<FecControllerDefault>(time_controller_.GetClock()),
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100156 nullptr, CryptoOptions{}, frame_transformer,
Evan Shrubsole9b643d42022-10-07 14:22:44 +0000157 field_trials ? *field_trials : field_trials_,
158 time_controller_.GetTaskQueueFactory());
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200159 }
Marina Cioceadc69fd22020-04-10 20:19:14 +0200160
161 RtpVideoSenderTestFixture(
162 const std::vector<uint32_t>& ssrcs,
163 const std::vector<uint32_t>& rtx_ssrcs,
164 int payload_type,
165 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100166 FrameCountObserver* frame_count_observer,
Jonas Orelande62c2f22022-03-29 11:04:48 +0200167 const FieldTrialsView* field_trials = nullptr)
Marina Cioceadc69fd22020-04-10 20:19:14 +0200168 : RtpVideoSenderTestFixture(ssrcs,
169 rtx_ssrcs,
170 payload_type,
171 suspended_payload_states,
172 frame_count_observer,
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100173 /*frame_transformer=*/nullptr,
174 field_trials) {}
Marina Cioceadc69fd22020-04-10 20:19:14 +0200175
Niels Möller949f0fd2019-01-29 09:44:24 +0100176 RtpVideoSenderTestFixture(
177 const std::vector<uint32_t>& ssrcs,
Erik Språng490d76c2019-05-07 09:29:15 -0700178 const std::vector<uint32_t>& rtx_ssrcs,
Niels Möller949f0fd2019-01-29 09:44:24 +0100179 int payload_type,
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100180 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
Jonas Orelande62c2f22022-03-29 11:04:48 +0200181 const FieldTrialsView* field_trials = nullptr)
Niels Möller949f0fd2019-01-29 09:44:24 +0100182 : RtpVideoSenderTestFixture(ssrcs,
Erik Språng490d76c2019-05-07 09:29:15 -0700183 rtx_ssrcs,
Niels Möller949f0fd2019-01-29 09:44:24 +0100184 payload_type,
185 suspended_payload_states,
Marina Cioceadc69fd22020-04-10 20:19:14 +0200186 /*frame_count_observer=*/nullptr,
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100187 /*frame_transformer=*/nullptr,
188 field_trials) {}
Mirko Bonadeif18f9202019-12-10 13:24:56 +0000189
Per Kjellander59ade012022-12-02 08:09:37 +0000190 ~RtpVideoSenderTestFixture() { Stop(); }
Tommi6fba6b72022-01-28 09:00:01 +0100191
Stefan Holmer9416ef82018-07-19 10:34:38 +0200192 RtpVideoSender* router() { return router_.get(); }
Erik Språng490d76c2019-05-07 09:29:15 -0700193 MockTransport& transport() { return transport_; }
Markus Handell486cc552019-12-03 14:37:28 +0100194 void AdvanceTime(TimeDelta delta) { time_controller_.AdvanceTime(delta); }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200195
Per Kjellander59ade012022-12-02 08:09:37 +0000196 void Stop() {
197 RunOnTransportQueue([&]() { router_->Stop(); });
Tommi6fba6b72022-01-28 09:00:01 +0100198 }
199
200 void SetActiveModules(const std::vector<bool>& active_modules) {
201 RunOnTransportQueue([&]() { router_->SetActiveModules(active_modules); });
202 }
203
204 // Several RtpVideoSender methods expect to be called on the task queue as
205 // owned by the send transport. While the SequenceChecker may pick up the
206 // default thread as the transport queue, explicit checks for the transport
207 // queue (not just using a SequenceChecker) aren't possible unless such a
208 // queue is actually active. So RunOnTransportQueue is a convenience function
Danil Chapovalovb7128ed2022-07-06 18:35:01 +0200209 // that allow for running a `task` on the transport queue, similar to
Tommi6fba6b72022-01-28 09:00:01 +0100210 // SendTask().
Danil Chapovalovb7128ed2022-07-06 18:35:01 +0200211 void RunOnTransportQueue(absl::AnyInvocable<void() &&> task) {
Per Kjellander828ef912022-10-10 12:53:41 +0200212 transport_controller_.GetWorkerQueue()->RunOrPost(std::move(task));
Philipp Hanckea204ad22022-07-08 18:43:25 +0200213 AdvanceTime(TimeDelta::Zero());
Tommi6fba6b72022-01-28 09:00:01 +0100214 }
215
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200216 private:
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100217 test::ScopedKeyValueConfig field_trials_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200218 NiceMock<MockTransport> transport_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200219 NiceMock<MockRtcpIntraFrameObserver> encoder_feedback_;
Erik Språng00cc8362019-11-25 12:21:46 +0100220 GlobalSimulatedTimeController time_controller_;
Danil Chapovalov83bbe912019-08-07 12:24:53 +0200221 RtcEventLogNull event_log_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200222 VideoSendStream::Config config_;
223 SendDelayStats send_delay_stats_;
224 BitrateConstraints bitrate_config_;
225 RtpTransportControllerSend transport_controller_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200226 SendStatisticsProxy stats_proxy_;
227 RateLimiter retransmission_rate_limiter_;
Stefan Holmer9416ef82018-07-19 10:34:38 +0200228 std::unique_ptr<RtpVideoSender> router_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200229};
Jakob Ivarsson9a12ee52020-11-26 16:04:18 +0100230
231BitrateAllocationUpdate CreateBitrateAllocationUpdate(int target_bitrate_bps) {
232 BitrateAllocationUpdate update;
233 update.target_bitrate = DataRate::BitsPerSec(target_bitrate_bps);
234 update.round_trip_time = TimeDelta::Zero();
235 return update;
236}
237
Åsa Persson4bece9a2017-10-06 10:04:04 +0200238} // namespace
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000239
Sebastian Jansson63470292019-02-01 10:13:43 +0100240TEST(RtpVideoSenderTest, SendOnOneModule) {
Niels Möller663844d2019-02-14 16:15:54 +0100241 constexpr uint8_t kPayload = 'a';
kjellander02b3d272016-04-20 05:05:54 -0700242 EncodedImage encoded_image;
Niels Möller23775882018-08-16 10:24:12 +0200243 encoded_image.SetTimestamp(1);
kjellander02b3d272016-04-20 05:05:54 -0700244 encoded_image.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 15:43:58 +0100245 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200246 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
kjellander02b3d272016-04-20 05:05:54 -0700247
Erik Språng490d76c2019-05-07 09:29:15 -0700248 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200249 EXPECT_NE(EncodedImageCallback::Result::OK,
250 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000251
Per Kjellander59ade012022-12-02 08:09:37 +0000252 test.SetActiveModules({true});
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200253 EXPECT_EQ(EncodedImageCallback::Result::OK,
254 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000255
Per Kjellander59ade012022-12-02 08:09:37 +0000256 test.SetActiveModules({false});
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200257 EXPECT_NE(EncodedImageCallback::Result::OK,
258 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000259
Per Kjellander59ade012022-12-02 08:09:37 +0000260 test.SetActiveModules({true});
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200261 EXPECT_EQ(EncodedImageCallback::Result::OK,
262 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000263}
264
Sebastian Jansson63470292019-02-01 10:13:43 +0100265TEST(RtpVideoSenderTest, SendSimulcastSetActive) {
Niels Möller663844d2019-02-14 16:15:54 +0100266 constexpr uint8_t kPayload = 'a';
Niels Möllerd3b8c632018-08-27 15:33:42 +0200267 EncodedImage encoded_image_1;
268 encoded_image_1.SetTimestamp(1);
269 encoded_image_1.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 15:43:58 +0100270 encoded_image_1._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200271 encoded_image_1.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
kjellander02b3d272016-04-20 05:05:54 -0700272
Erik Språng490d76c2019-05-07 09:29:15 -0700273 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
274 kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000275
Niels Möllerd3b8c632018-08-27 15:33:42 +0200276 CodecSpecificInfo codec_info;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200277 codec_info.codecType = kVideoCodecVP8;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000278
Per Kjellander59ade012022-12-02 08:09:37 +0000279 test.SetActiveModules({true, true});
sergeyu2cb155a2016-11-04 11:39:29 -0700280 EXPECT_EQ(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200281 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000282
Niels Möllerd3b8c632018-08-27 15:33:42 +0200283 EncodedImage encoded_image_2(encoded_image_1);
284 encoded_image_2.SetSpatialIndex(1);
sergeyu2cb155a2016-11-04 11:39:29 -0700285 EXPECT_EQ(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200286 test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000287
mflodman@webrtc.org50e28162015-02-23 07:45:11 +0000288 // Inactive.
Per Kjellander59ade012022-12-02 08:09:37 +0000289 test.Stop();
sergeyu2cb155a2016-11-04 11:39:29 -0700290 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200291 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
sergeyu2cb155a2016-11-04 11:39:29 -0700292 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200293 test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000294}
295
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800296// Tests how setting individual rtp modules to active affects the overall
297// behavior of the payload router. First sets one module to active and checks
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200298// that outgoing data can be sent on this module, and checks that no data can
299// be sent if both modules are inactive.
Sebastian Jansson63470292019-02-01 10:13:43 +0100300TEST(RtpVideoSenderTest, SendSimulcastSetActiveModules) {
Niels Möller663844d2019-02-14 16:15:54 +0100301 constexpr uint8_t kPayload = 'a';
Niels Möllerd3b8c632018-08-27 15:33:42 +0200302 EncodedImage encoded_image_1;
303 encoded_image_1.SetTimestamp(1);
304 encoded_image_1.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 15:43:58 +0100305 encoded_image_1._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200306 encoded_image_1.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Niels Möller77536a22019-01-15 08:50:01 +0100307
Niels Möllerd3b8c632018-08-27 15:33:42 +0200308 EncodedImage encoded_image_2(encoded_image_1);
309 encoded_image_2.SetSpatialIndex(1);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200310
Erik Språng490d76c2019-05-07 09:29:15 -0700311 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
312 kPayloadType, {});
Niels Möllerd3b8c632018-08-27 15:33:42 +0200313 CodecSpecificInfo codec_info;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200314 codec_info.codecType = kVideoCodecVP8;
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800315
316 // Only setting one stream to active will still set the payload router to
317 // active and allow sending data on the active stream.
318 std::vector<bool> active_modules({true, false});
Tommi6fba6b72022-01-28 09:00:01 +0100319 test.SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800320 EXPECT_EQ(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200321 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800322
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200323 // Setting both streams to inactive will turn the payload router to
324 // inactive.
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800325 active_modules = {false, false};
Tommi6fba6b72022-01-28 09:00:01 +0100326 test.SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800327 // An incoming encoded image will not ask the module to send outgoing data
328 // because the payload router is inactive.
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800329 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200330 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800331 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200332 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800333}
334
Per Kjellanderfb8641c2022-08-11 09:25:00 +0200335TEST(
336 RtpVideoSenderTest,
337 DiscardsHigherSpatialVideoFramesAfterLayerDisabledInVideoLayersAllocation) {
338 constexpr uint8_t kPayload = 'a';
339 EncodedImage encoded_image_1;
340 encoded_image_1.SetTimestamp(1);
341 encoded_image_1.capture_time_ms_ = 2;
342 encoded_image_1._frameType = VideoFrameType::kVideoFrameKey;
343 encoded_image_1.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
344 EncodedImage encoded_image_2(encoded_image_1);
345 encoded_image_2.SetSpatialIndex(1);
346 CodecSpecificInfo codec_info;
347 codec_info.codecType = kVideoCodecVP8;
348 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
349 kPayloadType, {});
350 test.SetActiveModules({true, true});
351 // A layer is sent on both rtp streams.
352 test.router()->OnVideoLayersAllocationUpdated(
353 {.active_spatial_layers = {{.rtp_stream_index = 0},
354 {.rtp_stream_index = 1}}});
355
356 EXPECT_EQ(EncodedImageCallback::Result::OK,
357 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
358 EXPECT_EQ(EncodedImageCallback::Result::OK,
359 test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
360
361 // Only rtp stream index 0 is configured to send a stream.
362 test.router()->OnVideoLayersAllocationUpdated(
363 {.active_spatial_layers = {{.rtp_stream_index = 0}}});
364 EXPECT_EQ(EncodedImageCallback::Result::OK,
365 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
366 EXPECT_NE(EncodedImageCallback::Result::OK,
367 test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
368}
369
Sebastian Jansson63470292019-02-01 10:13:43 +0100370TEST(RtpVideoSenderTest, CreateWithNoPreviousStates) {
Erik Språng490d76c2019-05-07 09:29:15 -0700371 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
372 kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37 +0000373 test.SetActiveModules({true, true});
Åsa Persson4bece9a2017-10-06 10:04:04 +0200374
375 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200376 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 10:04:04 +0200377 EXPECT_EQ(2u, initial_states.size());
378 EXPECT_NE(initial_states.find(kSsrc1), initial_states.end());
379 EXPECT_NE(initial_states.find(kSsrc2), initial_states.end());
380}
381
Sebastian Jansson63470292019-02-01 10:13:43 +0100382TEST(RtpVideoSenderTest, CreateWithPreviousStates) {
philipel25d31ec2018-08-08 16:33:01 +0200383 const int64_t kState1SharedFrameId = 123;
384 const int64_t kState2SharedFrameId = 234;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200385 RtpPayloadState state1;
386 state1.picture_id = kInitialPictureId1;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100387 state1.tl0_pic_idx = kInitialTl0PicIdx1;
philipel25d31ec2018-08-08 16:33:01 +0200388 state1.shared_frame_id = kState1SharedFrameId;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200389 RtpPayloadState state2;
390 state2.picture_id = kInitialPictureId2;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100391 state2.tl0_pic_idx = kInitialTl0PicIdx2;
philipel25d31ec2018-08-08 16:33:01 +0200392 state2.shared_frame_id = kState2SharedFrameId;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200393 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
394 {kSsrc2, state2}};
395
Erik Språng490d76c2019-05-07 09:29:15 -0700396 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
397 kPayloadType, states);
Per Kjellander59ade012022-12-02 08:09:37 +0000398 test.SetActiveModules({true, true});
Åsa Persson4bece9a2017-10-06 10:04:04 +0200399
400 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200401 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 10:04:04 +0200402 EXPECT_EQ(2u, initial_states.size());
403 EXPECT_EQ(kInitialPictureId1, initial_states[kSsrc1].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100404 EXPECT_EQ(kInitialTl0PicIdx1, initial_states[kSsrc1].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200405 EXPECT_EQ(kInitialPictureId2, initial_states[kSsrc2].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100406 EXPECT_EQ(kInitialTl0PicIdx2, initial_states[kSsrc2].tl0_pic_idx);
philipel25d31ec2018-08-08 16:33:01 +0200407 EXPECT_EQ(kState2SharedFrameId, initial_states[kSsrc1].shared_frame_id);
408 EXPECT_EQ(kState2SharedFrameId, initial_states[kSsrc2].shared_frame_id);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200409}
Niels Möller949f0fd2019-01-29 09:44:24 +0100410
Sebastian Jansson63470292019-02-01 10:13:43 +0100411TEST(RtpVideoSenderTest, FrameCountCallbacks) {
Niels Möller949f0fd2019-01-29 09:44:24 +0100412 class MockFrameCountObserver : public FrameCountObserver {
413 public:
Danil Chapovalov9a5efe92020-05-14 22:06:18 +0200414 MOCK_METHOD(void,
415 FrameCountUpdated,
416 (const FrameCounts& frame_counts, uint32_t ssrc),
417 (override));
Niels Möller949f0fd2019-01-29 09:44:24 +0100418 } callback;
419
Erik Språng490d76c2019-05-07 09:29:15 -0700420 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {},
421 &callback);
Niels Möller949f0fd2019-01-29 09:44:24 +0100422
Niels Möller663844d2019-02-14 16:15:54 +0100423 constexpr uint8_t kPayload = 'a';
Niels Möller949f0fd2019-01-29 09:44:24 +0100424 EncodedImage encoded_image;
425 encoded_image.SetTimestamp(1);
426 encoded_image.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 15:43:58 +0100427 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200428 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Niels Möller949f0fd2019-01-29 09:44:24 +0100429
Niels Möller8f7ce222019-03-21 15:43:58 +0100430 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller949f0fd2019-01-29 09:44:24 +0100431
432 // No callbacks when not active.
433 EXPECT_CALL(callback, FrameCountUpdated).Times(0);
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200434 EXPECT_NE(EncodedImageCallback::Result::OK,
435 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200436 ::testing::Mock::VerifyAndClearExpectations(&callback);
Niels Möller949f0fd2019-01-29 09:44:24 +0100437
Per Kjellander59ade012022-12-02 08:09:37 +0000438 test.SetActiveModules({true});
Niels Möller949f0fd2019-01-29 09:44:24 +0100439
440 FrameCounts frame_counts;
441 EXPECT_CALL(callback, FrameCountUpdated(_, kSsrc1))
442 .WillOnce(SaveArg<0>(&frame_counts));
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200443 EXPECT_EQ(EncodedImageCallback::Result::OK,
444 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Niels Möller949f0fd2019-01-29 09:44:24 +0100445
446 EXPECT_EQ(1, frame_counts.key_frames);
447 EXPECT_EQ(0, frame_counts.delta_frames);
448
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200449 ::testing::Mock::VerifyAndClearExpectations(&callback);
Niels Möller949f0fd2019-01-29 09:44:24 +0100450
Niels Möller8f7ce222019-03-21 15:43:58 +0100451 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
Niels Möller949f0fd2019-01-29 09:44:24 +0100452 EXPECT_CALL(callback, FrameCountUpdated(_, kSsrc1))
453 .WillOnce(SaveArg<0>(&frame_counts));
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200454 EXPECT_EQ(EncodedImageCallback::Result::OK,
455 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Niels Möller949f0fd2019-01-29 09:44:24 +0100456
457 EXPECT_EQ(1, frame_counts.key_frames);
458 EXPECT_EQ(1, frame_counts.delta_frames);
459}
460
Erik Språng490d76c2019-05-07 09:29:15 -0700461// Integration test verifying that ack of packet via TransportFeedback means
Erik Språng845c6aa2019-05-29 13:02:24 +0200462// that the packet is removed from RtpPacketHistory and won't be retransmitted
Erik Språng490d76c2019-05-07 09:29:15 -0700463// again.
464TEST(RtpVideoSenderTest, DoesNotRetrasmitAckedPackets) {
Erik Språng490d76c2019-05-07 09:29:15 -0700465 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
466 kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37 +0000467 test.SetActiveModules({true, true});
Erik Språng490d76c2019-05-07 09:29:15 -0700468
469 constexpr uint8_t kPayload = 'a';
470 EncodedImage encoded_image;
471 encoded_image.SetTimestamp(1);
472 encoded_image.capture_time_ms_ = 2;
473 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200474 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Erik Språng490d76c2019-05-07 09:29:15 -0700475
476 // Send two tiny images, mapping to two RTP packets. Capture sequence numbers.
Erik Språng490d76c2019-05-07 09:29:15 -0700477 std::vector<uint16_t> rtp_sequence_numbers;
478 std::vector<uint16_t> transport_sequence_numbers;
479 EXPECT_CALL(test.transport(), SendRtp)
480 .Times(2)
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100481 .WillRepeatedly([&rtp_sequence_numbers, &transport_sequence_numbers](
482 const uint8_t* packet, size_t length,
483 const PacketOptions& options) {
484 RtpPacket rtp_packet;
485 EXPECT_TRUE(rtp_packet.Parse(packet, length));
486 rtp_sequence_numbers.push_back(rtp_packet.SequenceNumber());
487 transport_sequence_numbers.push_back(options.packet_id);
488 return true;
489 });
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200490 EXPECT_EQ(EncodedImageCallback::Result::OK,
491 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Erik Språng490d76c2019-05-07 09:29:15 -0700492 encoded_image.SetTimestamp(2);
493 encoded_image.capture_time_ms_ = 3;
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200494 EXPECT_EQ(EncodedImageCallback::Result::OK,
495 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Erik Språngbd7046c2019-05-07 14:54:29 -0700496
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100497 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 09:29:15 -0700498
Erik Språng490d76c2019-05-07 09:29:15 -0700499 // Construct a NACK message for requesting retransmission of both packet.
500 rtcp::Nack nack;
501 nack.SetMediaSsrc(kSsrc1);
502 nack.SetPacketIds(rtp_sequence_numbers);
503 rtc::Buffer nack_buffer = nack.Build();
504
505 std::vector<uint16_t> retransmitted_rtp_sequence_numbers;
506 EXPECT_CALL(test.transport(), SendRtp)
507 .Times(2)
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100508 .WillRepeatedly([&retransmitted_rtp_sequence_numbers](
Erik Språng490d76c2019-05-07 09:29:15 -0700509 const uint8_t* packet, size_t length,
510 const PacketOptions& options) {
511 RtpPacket rtp_packet;
512 EXPECT_TRUE(rtp_packet.Parse(packet, length));
513 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
514 // Capture the retransmitted sequence number from the RTX header.
515 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
516 retransmitted_rtp_sequence_numbers.push_back(
517 ByteReader<uint16_t>::ReadBigEndian(payload.data()));
Erik Språng490d76c2019-05-07 09:29:15 -0700518 return true;
519 });
520 test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size());
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100521 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 09:29:15 -0700522
523 // Verify that both packets were retransmitted.
524 EXPECT_EQ(retransmitted_rtp_sequence_numbers, rtp_sequence_numbers);
525
526 // Simulate transport feedback indicating fist packet received, next packet
Erik Språng00cc8362019-11-25 12:21:46 +0100527 // lost (not other way around as that would trigger early retransmit).
Sebastian Janssonf2988552019-10-29 17:18:51 +0100528 StreamFeedbackObserver::StreamPacketInfo lost_packet_feedback;
Erik Språng00cc8362019-11-25 12:21:46 +0100529 lost_packet_feedback.rtp_sequence_number = rtp_sequence_numbers[0];
Erik Språng490d76c2019-05-07 09:29:15 -0700530 lost_packet_feedback.ssrc = kSsrc1;
Sebastian Janssonf2988552019-10-29 17:18:51 +0100531 lost_packet_feedback.received = false;
Erik Språng6a0a5592021-06-15 19:04:24 +0200532 lost_packet_feedback.is_retransmission = false;
Erik Språng490d76c2019-05-07 09:29:15 -0700533
Erik Språng00cc8362019-11-25 12:21:46 +0100534 StreamFeedbackObserver::StreamPacketInfo received_packet_feedback;
535 received_packet_feedback.rtp_sequence_number = rtp_sequence_numbers[1];
536 received_packet_feedback.ssrc = kSsrc1;
537 received_packet_feedback.received = true;
Erik Språng6a0a5592021-06-15 19:04:24 +0200538 lost_packet_feedback.is_retransmission = false;
Erik Språng00cc8362019-11-25 12:21:46 +0100539
Sebastian Janssonf2988552019-10-29 17:18:51 +0100540 test.router()->OnPacketFeedbackVector(
Erik Språng00cc8362019-11-25 12:21:46 +0100541 {lost_packet_feedback, received_packet_feedback});
Erik Språng490d76c2019-05-07 09:29:15 -0700542
543 // Advance time to make sure retransmission would be allowed and try again.
544 // This time the retransmission should not happen for the first packet since
545 // the history has been notified of the ack and removed the packet. The
546 // second packet, included in the feedback but not marked as received, should
547 // still be retransmitted.
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100548 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 09:29:15 -0700549 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100550 .WillOnce([&lost_packet_feedback](const uint8_t* packet, size_t length,
551 const PacketOptions& options) {
Erik Språng490d76c2019-05-07 09:29:15 -0700552 RtpPacket rtp_packet;
553 EXPECT_TRUE(rtp_packet.Parse(packet, length));
554 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
555 // Capture the retransmitted sequence number from the RTX header.
556 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
557 EXPECT_EQ(lost_packet_feedback.rtp_sequence_number,
558 ByteReader<uint16_t>::ReadBigEndian(payload.data()));
Erik Språng490d76c2019-05-07 09:29:15 -0700559 return true;
560 });
561 test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size());
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100562 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 09:29:15 -0700563}
Erik Språng845c6aa2019-05-29 13:02:24 +0200564
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100565// This tests that we utilize transport wide feedback to retransmit lost
Tommi6fba6b72022-01-28 09:00:01 +0100566// packets. This is tested by dropping all ordinary packets from a "lossy"
567// stream sent along with a secondary untouched stream. The transport wide
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100568// feedback packets from the secondary stream allows the sending side to
569// detect and retreansmit the lost packets from the lossy stream.
570TEST(RtpVideoSenderTest, RetransmitsOnTransportWideLossInfo) {
571 int rtx_packets;
572 test::Scenario s(test_info_);
573 test::CallClientConfig call_conf;
574 // Keeping the bitrate fixed to avoid RTX due to probing.
Danil Chapovalovcad3e0e2020-02-17 18:46:07 +0100575 call_conf.transport.rates.max_rate = DataRate::KilobitsPerSec(300);
576 call_conf.transport.rates.start_rate = DataRate::KilobitsPerSec(300);
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100577 test::NetworkSimulationConfig net_conf;
Danil Chapovalovcad3e0e2020-02-17 18:46:07 +0100578 net_conf.bandwidth = DataRate::KilobitsPerSec(300);
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100579 auto send_node = s.CreateSimulationNode(net_conf);
Tommi3c9bcc12020-04-15 16:45:47 +0200580 auto* callee = s.CreateClient("return", call_conf);
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100581 auto* route = s.CreateRoutes(s.CreateClient("send", call_conf), {send_node},
Tommi3c9bcc12020-04-15 16:45:47 +0200582 callee, {s.CreateSimulationNode(net_conf)});
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100583
584 test::VideoStreamConfig lossy_config;
585 lossy_config.source.framerate = 5;
586 auto* lossy = s.CreateVideoStream(route->forward(), lossy_config);
587 // The secondary stream acts a driver for transport feedback messages,
588 // ensuring that lost packets on the lossy stream are retransmitted.
589 s.CreateVideoStream(route->forward(), test::VideoStreamConfig());
590
591 send_node->router()->SetFilter([&](const EmulatedIpPacket& packet) {
592 RtpPacket rtp;
593 if (rtp.Parse(packet.data)) {
594 // Drops all regular packets for the lossy stream and counts all RTX
595 // packets. Since no packets are let trough, NACKs can't be triggered
596 // by the receiving side.
597 if (lossy->send()->UsingSsrc(rtp.Ssrc())) {
598 return false;
599 } else if (lossy->send()->UsingRtxSsrc(rtp.Ssrc())) {
600 ++rtx_packets;
601 }
602 }
603 return true;
604 });
605
606 // Run for a short duration and reset counters to avoid counting RTX packets
607 // from initial probing.
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100608 s.RunFor(TimeDelta::Seconds(1));
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100609 rtx_packets = 0;
Tommi3c9bcc12020-04-15 16:45:47 +0200610 int decoded_baseline = 0;
611 callee->SendTask([&decoded_baseline, &lossy]() {
612 decoded_baseline = lossy->receive()->GetStats().frames_decoded;
613 });
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100614 s.RunFor(TimeDelta::Seconds(1));
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100615 // We expect both that RTX packets were sent and that an appropriate number of
616 // frames were received. This is somewhat redundant but reduces the risk of
617 // false positives in future regressions (e.g. RTX is send due to probing).
618 EXPECT_GE(rtx_packets, 1);
Tommi3c9bcc12020-04-15 16:45:47 +0200619 int frames_decoded = 0;
620 callee->SendTask([&decoded_baseline, &frames_decoded, &lossy]() {
621 frames_decoded =
622 lossy->receive()->GetStats().frames_decoded - decoded_baseline;
623 });
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100624 EXPECT_EQ(frames_decoded, 5);
625}
626
Erik Språng845c6aa2019-05-29 13:02:24 +0200627// Integration test verifying that retransmissions are sent for packets which
628// can be detected as lost early, using transport wide feedback.
629TEST(RtpVideoSenderTest, EarlyRetransmits) {
Erik Språng845c6aa2019-05-29 13:02:24 +0200630 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
631 kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37 +0000632 test.SetActiveModules({true, true});
Erik Språng845c6aa2019-05-29 13:02:24 +0200633
Niels Möllerb9bfe652019-10-03 08:43:53 +0200634 const uint8_t kPayload[1] = {'a'};
Erik Språng845c6aa2019-05-29 13:02:24 +0200635 EncodedImage encoded_image;
636 encoded_image.SetTimestamp(1);
637 encoded_image.capture_time_ms_ = 2;
638 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möllerb9bfe652019-10-03 08:43:53 +0200639 encoded_image.SetEncodedData(
640 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
Erik Språng845c6aa2019-05-29 13:02:24 +0200641 encoded_image.SetSpatialIndex(0);
642
643 CodecSpecificInfo codec_specific;
644 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
645
646 // Send two tiny images, mapping to single RTP packets. Capture sequence
647 // numbers.
Erik Språng845c6aa2019-05-29 13:02:24 +0200648 uint16_t frame1_rtp_sequence_number = 0;
649 uint16_t frame1_transport_sequence_number = 0;
650 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100651 .WillOnce(
652 [&frame1_rtp_sequence_number, &frame1_transport_sequence_number](
653 const uint8_t* packet, size_t length,
654 const PacketOptions& options) {
655 RtpPacket rtp_packet;
656 EXPECT_TRUE(rtp_packet.Parse(packet, length));
657 frame1_rtp_sequence_number = rtp_packet.SequenceNumber();
658 frame1_transport_sequence_number = options.packet_id;
659 EXPECT_EQ(rtp_packet.Ssrc(), kSsrc1);
660 return true;
661 });
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200662 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Erik Språng845c6aa2019-05-29 13:02:24 +0200663 EncodedImageCallback::Result::OK);
Erik Språng845c6aa2019-05-29 13:02:24 +0200664
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100665 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng845c6aa2019-05-29 13:02:24 +0200666
667 uint16_t frame2_rtp_sequence_number = 0;
668 uint16_t frame2_transport_sequence_number = 0;
669 encoded_image.SetSpatialIndex(1);
670 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100671 .WillOnce(
672 [&frame2_rtp_sequence_number, &frame2_transport_sequence_number](
673 const uint8_t* packet, size_t length,
674 const PacketOptions& options) {
675 RtpPacket rtp_packet;
676 EXPECT_TRUE(rtp_packet.Parse(packet, length));
677 frame2_rtp_sequence_number = rtp_packet.SequenceNumber();
678 frame2_transport_sequence_number = options.packet_id;
679 EXPECT_EQ(rtp_packet.Ssrc(), kSsrc2);
680 return true;
681 });
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200682 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Erik Språng845c6aa2019-05-29 13:02:24 +0200683 EncodedImageCallback::Result::OK);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100684 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng845c6aa2019-05-29 13:02:24 +0200685
686 EXPECT_NE(frame1_transport_sequence_number, frame2_transport_sequence_number);
687
688 // Inject a transport feedback where the packet for the first frame is lost,
689 // expect a retransmission for it.
690 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100691 .WillOnce([&frame1_rtp_sequence_number](const uint8_t* packet,
692 size_t length,
693 const PacketOptions& options) {
Erik Språng845c6aa2019-05-29 13:02:24 +0200694 RtpPacket rtp_packet;
695 EXPECT_TRUE(rtp_packet.Parse(packet, length));
Sebastian Janssonf2988552019-10-29 17:18:51 +0100696 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
Erik Språng845c6aa2019-05-29 13:02:24 +0200697
698 // Retransmitted sequence number from the RTX header should match
699 // the lost packet.
700 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
701 EXPECT_EQ(ByteReader<uint16_t>::ReadBigEndian(payload.data()),
702 frame1_rtp_sequence_number);
Erik Språng845c6aa2019-05-29 13:02:24 +0200703 return true;
704 });
705
Sebastian Janssonf2988552019-10-29 17:18:51 +0100706 StreamFeedbackObserver::StreamPacketInfo first_packet_feedback;
Erik Språng845c6aa2019-05-29 13:02:24 +0200707 first_packet_feedback.rtp_sequence_number = frame1_rtp_sequence_number;
708 first_packet_feedback.ssrc = kSsrc1;
Sebastian Janssonf2988552019-10-29 17:18:51 +0100709 first_packet_feedback.received = false;
Erik Språng6a0a5592021-06-15 19:04:24 +0200710 first_packet_feedback.is_retransmission = false;
Erik Språng845c6aa2019-05-29 13:02:24 +0200711
Sebastian Janssonf2988552019-10-29 17:18:51 +0100712 StreamFeedbackObserver::StreamPacketInfo second_packet_feedback;
713 second_packet_feedback.rtp_sequence_number = frame2_rtp_sequence_number;
714 second_packet_feedback.ssrc = kSsrc2;
715 second_packet_feedback.received = true;
Erik Språng6a0a5592021-06-15 19:04:24 +0200716 first_packet_feedback.is_retransmission = false;
Erik Språng845c6aa2019-05-29 13:02:24 +0200717
Sebastian Janssonf2988552019-10-29 17:18:51 +0100718 test.router()->OnPacketFeedbackVector(
719 {first_packet_feedback, second_packet_feedback});
Erik Språng845c6aa2019-05-29 13:02:24 +0200720
721 // Wait for pacer to run and send the RTX packet.
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100722 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng845c6aa2019-05-29 13:02:24 +0200723}
Sebastian Janssoncf41eb12019-06-10 11:30:59 +0200724
Danil Chapovalov2272f202020-02-18 12:09:43 +0100725TEST(RtpVideoSenderTest, SupportsDependencyDescriptor) {
Danil Chapovalov2272f202020-02-18 12:09:43 +0100726 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37 +0000727 test.SetActiveModules({true});
Danil Chapovalov2272f202020-02-18 12:09:43 +0100728
729 RtpHeaderExtensionMap extensions;
730 extensions.Register<RtpDependencyDescriptorExtension>(
731 kDependencyDescriptorExtensionId);
732 std::vector<RtpPacket> sent_packets;
733 ON_CALL(test.transport(), SendRtp)
734 .WillByDefault([&](const uint8_t* packet, size_t length,
735 const PacketOptions& options) {
736 sent_packets.emplace_back(&extensions);
737 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
738 return true;
739 });
740
741 const uint8_t kPayload[1] = {'a'};
742 EncodedImage encoded_image;
743 encoded_image.SetTimestamp(1);
744 encoded_image.capture_time_ms_ = 2;
745 encoded_image.SetEncodedData(
746 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
747
748 CodecSpecificInfo codec_specific;
749 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
750 codec_specific.template_structure.emplace();
751 codec_specific.template_structure->num_decode_targets = 1;
752 codec_specific.template_structure->templates = {
Danil Chapovalov24263f42020-06-11 13:23:45 +0200753 FrameDependencyTemplate().T(0).Dtis("S"),
754 FrameDependencyTemplate().T(0).Dtis("S").FrameDiffs({2}),
755 FrameDependencyTemplate().T(1).Dtis("D").FrameDiffs({1}),
Danil Chapovalov2272f202020-02-18 12:09:43 +0100756 };
757
758 // Send two tiny images, mapping to single RTP packets.
759 // Send in key frame.
760 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
761 codec_specific.generic_frame_info =
762 GenericFrameInfo::Builder().T(0).Dtis("S").Build();
763 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200764 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 12:09:43 +0100765 EncodedImageCallback::Result::OK);
766 test.AdvanceTime(TimeDelta::Millis(33));
767 ASSERT_THAT(sent_packets, SizeIs(1));
768 EXPECT_TRUE(
769 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
770
771 // Send in delta frame.
772 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
773 codec_specific.template_structure = absl::nullopt;
774 codec_specific.generic_frame_info =
775 GenericFrameInfo::Builder().T(1).Dtis("D").Build();
776 codec_specific.generic_frame_info->encoder_buffers = {{0, true, false}};
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200777 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 12:09:43 +0100778 EncodedImageCallback::Result::OK);
779 test.AdvanceTime(TimeDelta::Millis(33));
780 ASSERT_THAT(sent_packets, SizeIs(2));
781 EXPECT_TRUE(
782 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
783}
784
Emil Lundmark6c81a422022-05-18 17:13:34 +0200785TEST(RtpVideoSenderTest,
786 SupportsDependencyDescriptorForVp8NotProvidedByEncoder) {
787 constexpr uint8_t kPayload[1] = {'a'};
788 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
789 RtpHeaderExtensionMap extensions;
790 extensions.Register<RtpDependencyDescriptorExtension>(
791 kDependencyDescriptorExtensionId);
792 std::vector<RtpPacket> sent_packets;
793 ON_CALL(test.transport(), SendRtp)
794 .WillByDefault(
795 [&](const uint8_t* packet, size_t length, const PacketOptions&) {
796 EXPECT_TRUE(
797 sent_packets.emplace_back(&extensions).Parse(packet, length));
798 return true;
799 });
Per Kjellander59ade012022-12-02 08:09:37 +0000800 test.SetActiveModules({true});
Emil Lundmark6c81a422022-05-18 17:13:34 +0200801
802 EncodedImage key_frame_image;
803 key_frame_image._frameType = VideoFrameType::kVideoFrameKey;
804 key_frame_image.SetEncodedData(
805 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
806 CodecSpecificInfo key_frame_info;
807 key_frame_info.codecType = VideoCodecType::kVideoCodecVP8;
808 ASSERT_EQ(
809 test.router()->OnEncodedImage(key_frame_image, &key_frame_info).error,
810 EncodedImageCallback::Result::OK);
811
812 EncodedImage delta_image;
813 delta_image._frameType = VideoFrameType::kVideoFrameDelta;
814 delta_image.SetEncodedData(
815 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
816 CodecSpecificInfo delta_info;
817 delta_info.codecType = VideoCodecType::kVideoCodecVP8;
818 ASSERT_EQ(test.router()->OnEncodedImage(delta_image, &delta_info).error,
819 EncodedImageCallback::Result::OK);
820
821 test.AdvanceTime(TimeDelta::Millis(123));
822
823 DependencyDescriptor key_frame_dd;
824 DependencyDescriptor delta_dd;
825 ASSERT_THAT(sent_packets, SizeIs(2));
826 EXPECT_TRUE(sent_packets[0].GetExtension<RtpDependencyDescriptorExtension>(
827 /*structure=*/nullptr, &key_frame_dd));
828 EXPECT_TRUE(sent_packets[1].GetExtension<RtpDependencyDescriptorExtension>(
829 key_frame_dd.attached_structure.get(), &delta_dd));
830}
831
Danil Chapovalov0be18462021-01-20 12:11:29 +0100832TEST(RtpVideoSenderTest, SupportsDependencyDescriptorForVp9) {
833 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37 +0000834 test.SetActiveModules({true});
Danil Chapovalov0be18462021-01-20 12:11:29 +0100835
836 RtpHeaderExtensionMap extensions;
837 extensions.Register<RtpDependencyDescriptorExtension>(
838 kDependencyDescriptorExtensionId);
839 std::vector<RtpPacket> sent_packets;
840 ON_CALL(test.transport(), SendRtp)
841 .WillByDefault([&](const uint8_t* packet, size_t length,
842 const PacketOptions& options) {
843 sent_packets.emplace_back(&extensions);
844 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
845 return true;
846 });
847
848 const uint8_t kPayload[1] = {'a'};
849 EncodedImage encoded_image;
850 encoded_image.SetTimestamp(1);
851 encoded_image.capture_time_ms_ = 2;
852 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
853 encoded_image.SetEncodedData(
854 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
855
856 CodecSpecificInfo codec_specific;
857 codec_specific.codecType = VideoCodecType::kVideoCodecVP9;
858 codec_specific.template_structure.emplace();
859 codec_specific.template_structure->num_decode_targets = 2;
860 codec_specific.template_structure->templates = {
861 FrameDependencyTemplate().S(0).Dtis("SS"),
862 FrameDependencyTemplate().S(1).Dtis("-S").FrameDiffs({1}),
863 };
864
865 // Send two tiny images, each mapping to single RTP packet.
866 // Send in key frame for the base spatial layer.
867 codec_specific.generic_frame_info =
868 GenericFrameInfo::Builder().S(0).Dtis("SS").Build();
869 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
870 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
871 EncodedImageCallback::Result::OK);
872 // Send in 2nd spatial layer.
873 codec_specific.template_structure = absl::nullopt;
874 codec_specific.generic_frame_info =
875 GenericFrameInfo::Builder().S(1).Dtis("-S").Build();
876 codec_specific.generic_frame_info->encoder_buffers = {{0, true, false},
877 {1, false, true}};
878 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
879 EncodedImageCallback::Result::OK);
880
881 test.AdvanceTime(TimeDelta::Millis(33));
882 ASSERT_THAT(sent_packets, SizeIs(2));
883 EXPECT_TRUE(sent_packets[0].HasExtension<RtpDependencyDescriptorExtension>());
884 EXPECT_TRUE(sent_packets[1].HasExtension<RtpDependencyDescriptorExtension>());
885}
886
Danil Chapovalov748550d2021-04-29 11:42:54 +0200887TEST(RtpVideoSenderTest,
888 SupportsDependencyDescriptorForVp9NotProvidedByEncoder) {
Danil Chapovalov748550d2021-04-29 11:42:54 +0200889 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37 +0000890 test.SetActiveModules({true});
Danil Chapovalov748550d2021-04-29 11:42:54 +0200891
892 RtpHeaderExtensionMap extensions;
893 extensions.Register<RtpDependencyDescriptorExtension>(
894 kDependencyDescriptorExtensionId);
895 std::vector<RtpPacket> sent_packets;
896 ON_CALL(test.transport(), SendRtp)
897 .WillByDefault([&](const uint8_t* packet, size_t length,
898 const PacketOptions& options) {
899 sent_packets.emplace_back(&extensions);
900 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
901 return true;
902 });
903
904 const uint8_t kPayload[1] = {'a'};
905 EncodedImage encoded_image;
906 encoded_image.SetTimestamp(1);
907 encoded_image.capture_time_ms_ = 2;
908 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
909 encoded_image._encodedWidth = 320;
910 encoded_image._encodedHeight = 180;
911 encoded_image.SetEncodedData(
912 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
913
914 CodecSpecificInfo codec_specific;
915 codec_specific.codecType = VideoCodecType::kVideoCodecVP9;
916 codec_specific.codecSpecific.VP9.num_spatial_layers = 1;
917 codec_specific.codecSpecific.VP9.temporal_idx = kNoTemporalIdx;
918 codec_specific.codecSpecific.VP9.first_frame_in_picture = true;
919 codec_specific.end_of_picture = true;
920 codec_specific.codecSpecific.VP9.inter_pic_predicted = false;
921
922 // Send two tiny images, each mapping to single RTP packet.
923 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
924 EncodedImageCallback::Result::OK);
925
926 // Send in 2nd picture.
927 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
928 encoded_image.SetTimestamp(3000);
929 codec_specific.codecSpecific.VP9.inter_pic_predicted = true;
930 codec_specific.codecSpecific.VP9.num_ref_pics = 1;
931 codec_specific.codecSpecific.VP9.p_diff[0] = 1;
932 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
933 EncodedImageCallback::Result::OK);
934
935 test.AdvanceTime(TimeDelta::Millis(33));
936 ASSERT_THAT(sent_packets, SizeIs(2));
937 EXPECT_TRUE(sent_packets[0].HasExtension<RtpDependencyDescriptorExtension>());
938 EXPECT_TRUE(sent_packets[1].HasExtension<RtpDependencyDescriptorExtension>());
939}
940
philipel5b231de2021-09-01 15:21:16 +0200941TEST(RtpVideoSenderTest, GenerateDependecyDescriptorForGenericCodecs) {
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100942 test::ScopedKeyValueConfig field_trials(
philipel5b231de2021-09-01 15:21:16 +0200943 "WebRTC-GenericCodecDependencyDescriptor/Enabled/");
Jonas Orelandc7f691a2022-03-09 15:12:07 +0100944 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {}, &field_trials);
Per Kjellander59ade012022-12-02 08:09:37 +0000945 test.SetActiveModules({true});
philipel5b231de2021-09-01 15:21:16 +0200946
947 RtpHeaderExtensionMap extensions;
948 extensions.Register<RtpDependencyDescriptorExtension>(
949 kDependencyDescriptorExtensionId);
950 std::vector<RtpPacket> sent_packets;
951 ON_CALL(test.transport(), SendRtp)
952 .WillByDefault([&](const uint8_t* packet, size_t length,
953 const PacketOptions& options) {
954 sent_packets.emplace_back(&extensions);
955 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
956 return true;
957 });
958
959 const uint8_t kPayload[1] = {'a'};
960 EncodedImage encoded_image;
961 encoded_image.SetTimestamp(1);
962 encoded_image.capture_time_ms_ = 2;
963 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
964 encoded_image._encodedWidth = 320;
965 encoded_image._encodedHeight = 180;
966 encoded_image.SetEncodedData(
967 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
968
969 CodecSpecificInfo codec_specific;
970 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
971 codec_specific.end_of_picture = true;
972
973 // Send two tiny images, each mapping to single RTP packet.
974 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
975 EncodedImageCallback::Result::OK);
976
977 // Send in 2nd picture.
978 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
979 encoded_image.SetTimestamp(3000);
980 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
981 EncodedImageCallback::Result::OK);
982
983 test.AdvanceTime(TimeDelta::Millis(33));
984 ASSERT_THAT(sent_packets, SizeIs(2));
985 EXPECT_TRUE(sent_packets[0].HasExtension<RtpDependencyDescriptorExtension>());
986 EXPECT_TRUE(sent_packets[1].HasExtension<RtpDependencyDescriptorExtension>());
987}
988
Danil Chapovalov2272f202020-02-18 12:09:43 +0100989TEST(RtpVideoSenderTest, SupportsStoppingUsingDependencyDescriptor) {
Danil Chapovalov2272f202020-02-18 12:09:43 +0100990 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37 +0000991 test.SetActiveModules({true});
Danil Chapovalov2272f202020-02-18 12:09:43 +0100992
993 RtpHeaderExtensionMap extensions;
994 extensions.Register<RtpDependencyDescriptorExtension>(
995 kDependencyDescriptorExtensionId);
996 std::vector<RtpPacket> sent_packets;
997 ON_CALL(test.transport(), SendRtp)
998 .WillByDefault([&](const uint8_t* packet, size_t length,
999 const PacketOptions& options) {
1000 sent_packets.emplace_back(&extensions);
1001 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
1002 return true;
1003 });
1004
1005 const uint8_t kPayload[1] = {'a'};
1006 EncodedImage encoded_image;
1007 encoded_image.SetTimestamp(1);
1008 encoded_image.capture_time_ms_ = 2;
1009 encoded_image.SetEncodedData(
1010 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
1011
1012 CodecSpecificInfo codec_specific;
1013 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
1014 codec_specific.template_structure.emplace();
1015 codec_specific.template_structure->num_decode_targets = 1;
1016 codec_specific.template_structure->templates = {
Danil Chapovalov24263f42020-06-11 13:23:45 +02001017 FrameDependencyTemplate().T(0).Dtis("S"),
1018 FrameDependencyTemplate().T(0).Dtis("S").FrameDiffs({2}),
1019 FrameDependencyTemplate().T(1).Dtis("D").FrameDiffs({1}),
Danil Chapovalov2272f202020-02-18 12:09:43 +01001020 };
1021
1022 // Send two tiny images, mapping to single RTP packets.
1023 // Send in a key frame.
1024 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
1025 codec_specific.generic_frame_info =
1026 GenericFrameInfo::Builder().T(0).Dtis("S").Build();
1027 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
Danil Chapovalov383f2cf2020-08-12 11:06:53 +02001028 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 12:09:43 +01001029 EncodedImageCallback::Result::OK);
1030 test.AdvanceTime(TimeDelta::Millis(33));
1031 ASSERT_THAT(sent_packets, SizeIs(1));
1032 EXPECT_TRUE(
1033 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
1034
1035 // Send in a new key frame without the support for the dependency descriptor.
1036 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
1037 codec_specific.template_structure = absl::nullopt;
Danil Chapovalov383f2cf2020-08-12 11:06:53 +02001038 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 12:09:43 +01001039 EncodedImageCallback::Result::OK);
1040 test.AdvanceTime(TimeDelta::Millis(33));
1041 ASSERT_THAT(sent_packets, SizeIs(2));
1042 EXPECT_FALSE(
1043 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
1044}
1045
Jakob Ivarsson9a12ee52020-11-26 16:04:18 +01001046TEST(RtpVideoSenderTest, CanSetZeroBitrate) {
Sebastian Janssoncf41eb12019-06-10 11:30:59 +02001047 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
Jakob Ivarsson9a12ee52020-11-26 16:04:18 +01001048 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(0),
1049 /*framerate*/ 0);
Sebastian Janssoncf41eb12019-06-10 11:30:59 +02001050}
Marina Cioceadc69fd22020-04-10 20:19:14 +02001051
1052TEST(RtpVideoSenderTest, SimulcastSenderRegistersFrameTransformers) {
Marina Cioceadc69fd22020-04-10 20:19:14 +02001053 rtc::scoped_refptr<MockFrameTransformer> transformer =
Tomas Gunnarssonc1d58912021-04-22 19:21:43 +02001054 rtc::make_ref_counted<MockFrameTransformer>();
Marina Cioceadc69fd22020-04-10 20:19:14 +02001055
1056 EXPECT_CALL(*transformer, RegisterTransformedFrameSinkCallback(_, kSsrc1));
1057 EXPECT_CALL(*transformer, RegisterTransformedFrameSinkCallback(_, kSsrc2));
1058 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
1059 kPayloadType, {}, nullptr, transformer);
1060
1061 EXPECT_CALL(*transformer, UnregisterTransformedFrameSinkCallback(kSsrc1));
1062 EXPECT_CALL(*transformer, UnregisterTransformedFrameSinkCallback(kSsrc2));
1063}
Jakob Ivarsson9a12ee52020-11-26 16:04:18 +01001064
1065TEST(RtpVideoSenderTest, OverheadIsSubtractedFromTargetBitrate) {
Jonas Orelandc7f691a2022-03-09 15:12:07 +01001066 test::ScopedKeyValueConfig field_trials(
Jakob Ivarsson9a12ee52020-11-26 16:04:18 +01001067 "WebRTC-Video-UseFrameRateForOverhead/Enabled/");
1068
1069 // TODO(jakobi): RTP header size should not be hard coded.
1070 constexpr uint32_t kRtpHeaderSizeBytes = 20;
1071 constexpr uint32_t kTransportPacketOverheadBytes = 40;
1072 constexpr uint32_t kOverheadPerPacketBytes =
1073 kRtpHeaderSizeBytes + kTransportPacketOverheadBytes;
Jonas Orelandc7f691a2022-03-09 15:12:07 +01001074 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {}, &field_trials);
Jakob Ivarsson9a12ee52020-11-26 16:04:18 +01001075 test.router()->OnTransportOverheadChanged(kTransportPacketOverheadBytes);
Per Kjellander59ade012022-12-02 08:09:37 +00001076 test.SetActiveModules({true});
Jakob Ivarsson9a12ee52020-11-26 16:04:18 +01001077
1078 {
1079 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(300000),
1080 /*framerate*/ 15);
1081 // 1 packet per frame.
1082 EXPECT_EQ(test.router()->GetPayloadBitrateBps(),
1083 300000 - kOverheadPerPacketBytes * 8 * 30);
1084 }
1085 {
1086 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(150000),
1087 /*framerate*/ 15);
1088 // 1 packet per frame.
1089 EXPECT_EQ(test.router()->GetPayloadBitrateBps(),
1090 150000 - kOverheadPerPacketBytes * 8 * 15);
1091 }
1092 {
1093 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(1000000),
1094 /*framerate*/ 30);
1095 // 3 packets per frame.
1096 EXPECT_EQ(test.router()->GetPayloadBitrateBps(),
1097 1000000 - kOverheadPerPacketBytes * 8 * 30 * 3);
1098 }
1099}
1100
Erik Språng1b11b582022-12-09 21:38:44 +01001101TEST(RtpVideoSenderTest, ClearsPendingPacketsOnInactivation) {
1102 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
1103 test.SetActiveModules({true});
1104
1105 RtpHeaderExtensionMap extensions;
1106 extensions.Register<RtpDependencyDescriptorExtension>(
1107 kDependencyDescriptorExtensionId);
1108 std::vector<RtpPacket> sent_packets;
1109 ON_CALL(test.transport(), SendRtp)
1110 .WillByDefault([&](const uint8_t* packet, size_t length,
1111 const PacketOptions& options) {
1112 sent_packets.emplace_back(&extensions);
1113 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
1114 return true;
1115 });
1116
1117 // Set a very low bitrate.
1118 test.router()->OnBitrateUpdated(
1119 CreateBitrateAllocationUpdate(/*rate_bps=*/30'000),
1120 /*framerate=*/30);
1121
1122 // Create and send a large keyframe.
1123 const size_t kImageSizeBytes = 10000;
1124 constexpr uint8_t kPayload[kImageSizeBytes] = {'a'};
1125 EncodedImage encoded_image;
1126 encoded_image.SetTimestamp(1);
1127 encoded_image.capture_time_ms_ = 2;
1128 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
1129 encoded_image.SetEncodedData(
1130 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
1131 EXPECT_EQ(test.router()
1132 ->OnEncodedImage(encoded_image, /*codec_specific=*/nullptr)
1133 .error,
1134 EncodedImageCallback::Result::OK);
1135
1136 // Advance time a small amount, check that sent data is only part of the
1137 // image.
1138 test.AdvanceTime(TimeDelta::Millis(5));
1139 DataSize transmittedPayload = DataSize::Zero();
1140 for (const RtpPacket& packet : sent_packets) {
1141 transmittedPayload += DataSize::Bytes(packet.payload_size());
1142 // Make sure we don't see the end of the frame.
1143 EXPECT_FALSE(packet.Marker());
1144 }
1145 EXPECT_GT(transmittedPayload, DataSize::Zero());
1146 EXPECT_LT(transmittedPayload, DataSize::Bytes(kImageSizeBytes / 4));
1147
1148 // Record the RTP timestamp of the first frame.
1149 const uint32_t first_frame_timestamp = sent_packets[0].Timestamp();
1150 sent_packets.clear();
1151
1152 // Disable the sending module and advance time slightly. No packets should be
1153 // sent.
1154 test.SetActiveModules({false});
1155 test.AdvanceTime(TimeDelta::Millis(20));
1156 EXPECT_TRUE(sent_packets.empty());
1157
1158 // Reactive the send module - any packets should have been removed, so nothing
1159 // should be transmitted.
1160 test.SetActiveModules({true});
1161 test.AdvanceTime(TimeDelta::Millis(33));
1162 EXPECT_TRUE(sent_packets.empty());
1163
1164 // Send a new frame.
1165 encoded_image.SetTimestamp(3);
1166 encoded_image.capture_time_ms_ = 4;
1167 EXPECT_EQ(test.router()
1168 ->OnEncodedImage(encoded_image, /*codec_specific=*/nullptr)
1169 .error,
1170 EncodedImageCallback::Result::OK);
1171 test.AdvanceTime(TimeDelta::Millis(33));
1172
1173 // Advance time, check we get new packets - but only for the second frame.
1174 EXPECT_FALSE(sent_packets.empty());
1175 EXPECT_NE(sent_packets[0].Timestamp(), first_frame_timestamp);
1176}
1177
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +00001178} // namespace webrtc