blob: 16d0e54110ec3de6e6924cd6069fa3776544ee85 [file] [log] [blame]
mflodman@webrtc.org02270cd2015-02-06 13:10:191/*
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 17:08:3311#include "call/rtp_video_sender.h"
12
Sebastian Jansson3d4d94a2020-01-14 13:25:4113#include <atomic>
kwiberg27f982b2016-03-01 19:52:3314#include <memory>
Åsa Persson4bece9a2017-10-06 08:04:0415#include <string>
Tommi6fba6b72022-01-28 08:00:0116#include <utility>
Sebastian Jansson3d4d94a2020-01-14 13:25:4117
Danil Chapovalovb7128ed2022-07-06 16:35:0118#include "absl/functional/any_invocable.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4619#include "call/rtp_transport_controller_send.h"
Erik Språng490d76c2019-05-07 16:29:1520#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 11:09:4323#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h"
Erik Språng490d76c2019-05-07 16:29:1524#include "modules/rtp_rtcp/source/rtp_packet.h"
Stefan Holmer64be7fa2018-10-04 13:21:5525#include "modules/video_coding/fec_controller_default.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3126#include "modules/video_coding/include/video_codec_interface.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4627#include "rtc_base/rate_limiter.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3128#include "test/gmock.h"
29#include "test/gtest.h"
Marina Ciocea1148fd52020-04-29 20:39:1330#include "test/mock_frame_transformer.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4631#include "test/mock_transport.h"
Sebastian Jansson3d4d94a2020-01-14 13:25:4132#include "test/scenario/scenario.h"
Jonas Orelandc7f691a2022-03-09 14:12:0733#include "test/scoped_key_value_config.h"
Erik Språng00cc8362019-11-25 11:21:4634#include "test/time_controller/simulated_time_controller.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4635#include "video/send_delay_stats.h"
36#include "video/send_statistics_proxy.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:1937
Emil Lundmark6c81a422022-05-18 15:13:3438namespace webrtc {
39namespace {
40
mflodman@webrtc.org02270cd2015-02-06 13:10:1941using ::testing::_;
mflodman@webrtc.org02270cd2015-02-06 13:10:1942using ::testing::NiceMock;
Niels Möller949f0fd2019-01-29 08:44:2443using ::testing::SaveArg;
Danil Chapovalov2272f202020-02-18 11:09:4344using ::testing::SizeIs;
mflodman@webrtc.org02270cd2015-02-06 13:10:1945
Åsa Persson4bece9a2017-10-06 08:04:0446const int8_t kPayloadType = 96;
47const uint32_t kSsrc1 = 12345;
48const uint32_t kSsrc2 = 23456;
Erik Språng490d76c2019-05-07 16:29:1549const uint32_t kRtxSsrc1 = 34567;
50const uint32_t kRtxSsrc2 = 45678;
Åsa Persson4bece9a2017-10-06 08:04:0451const int16_t kInitialPictureId1 = 222;
52const int16_t kInitialPictureId2 = 44;
Niels Möllerbb894ff2018-03-15 11:28:5353const int16_t kInitialTl0PicIdx1 = 99;
54const int16_t kInitialTl0PicIdx2 = 199;
Stefan Holmerdbdb3a02018-07-17 14:03:4655const int64_t kRetransmitWindowSizeMs = 500;
Erik Språng845c6aa2019-05-29 11:02:2456const int kTransportsSequenceExtensionId = 7;
Danil Chapovalov2272f202020-02-18 11:09:4357const int kDependencyDescriptorExtensionId = 8;
Stefan Holmerdbdb3a02018-07-17 14:03:4658
59class MockRtcpIntraFrameObserver : public RtcpIntraFrameObserver {
60 public:
Danil Chapovalov9a5efe92020-05-14 20:06:1861 MOCK_METHOD(void, OnReceivedIntraFrameRequest, (uint32_t), (override));
Stefan Holmerdbdb3a02018-07-17 14:03:4662};
63
Stefan Holmerdbdb3a02018-07-17 14:03:4664RtpSenderObservers CreateObservers(
65 RtcpRttStats* rtcp_rtt_stats,
66 RtcpIntraFrameObserver* intra_frame_callback,
Henrik Boström87e3f9d2019-05-27 08:44:2467 ReportBlockDataObserver* report_block_data_observer,
Stefan Holmerdbdb3a02018-07-17 14:03:4668 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 13:21:5573 SendPacketObserver* send_packet_observer) {
Stefan Holmerdbdb3a02018-07-17 14:03:4674 RtpSenderObservers observers;
75 observers.rtcp_rtt_stats = rtcp_rtt_stats;
76 observers.intra_frame_callback = intra_frame_callback;
Erik Språng490d76c2019-05-07 16:29:1577 observers.rtcp_loss_notification_observer = nullptr;
Henrik Boström87e3f9d2019-05-27 08:44:2478 observers.report_block_data_observer = report_block_data_observer;
Stefan Holmerdbdb3a02018-07-17 14:03:4679 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 14:03:4685 return observers;
86}
87
Erik Språng490d76c2019-05-07 16:29:1588BitrateConstraints 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 11:02:24107 config.rtp.extensions.emplace_back(RtpExtension::kTransportSequenceNumberUri,
108 kTransportsSequenceExtensionId);
Danil Chapovalovd0321c52021-09-14 10:58:51109 config.rtp.extensions.emplace_back(RtpDependencyDescriptorExtension::Uri(),
Danil Chapovalov2272f202020-02-18 11:09:43110 kDependencyDescriptorExtensionId);
Danil Chapovalov748550d2021-04-29 09:42:54111 config.rtp.extmap_allow_mixed = true;
Erik Språng490d76c2019-05-07 16:29:15112 return config;
113}
114
Stefan Holmer9416ef82018-07-19 08:34:38115class RtpVideoSenderTestFixture {
Stefan Holmerdbdb3a02018-07-17 14:03:46116 public:
Stefan Holmer9416ef82018-07-19 08:34:38117 RtpVideoSenderTestFixture(
Stefan Holmerdbdb3a02018-07-17 14:03:46118 const std::vector<uint32_t>& ssrcs,
Erik Språng490d76c2019-05-07 16:29:15119 const std::vector<uint32_t>& rtx_ssrcs,
Stefan Holmerdbdb3a02018-07-17 14:03:46120 int payload_type,
Niels Möller949f0fd2019-01-29 08:44:24121 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
Marina Cioceadc69fd22020-04-10 18:19:14122 FrameCountObserver* frame_count_observer,
Jonas Orelandc7f691a2022-03-09 14:12:07123 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
Jonas Orelande62c2f22022-03-29 09:04:48124 const FieldTrialsView* field_trials = nullptr)
Danil Chapovalov0c626af2020-02-10 10:16:00125 : time_controller_(Timestamp::Millis(1000000)),
Erik Språng490d76c2019-05-07 16:29:15126 config_(CreateVideoSendStreamConfig(&transport_,
127 ssrcs,
128 rtx_ssrcs,
129 payload_type)),
Erik Språng00cc8362019-11-25 11:21:46130 send_delay_stats_(time_controller_.GetClock()),
Erik Språng490d76c2019-05-07 16:29:15131 bitrate_config_(GetBitrateConfig()),
Henrik Boströmda4c1022022-11-15 14:45:41132 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 11:21:46140 stats_proxy_(time_controller_.GetClock(),
Stefan Holmerdbdb3a02018-07-17 14:03:46141 config_,
Jonas Oreland8ca06132022-03-14 11:52:48142 VideoEncoderConfig::ContentType::kRealtimeVideo,
143 field_trials ? *field_trials : field_trials_),
Erik Språng00cc8362019-11-25 11:21:46144 retransmission_rate_limiter_(time_controller_.GetClock(),
145 kRetransmitWindowSizeMs) {
Erik Språng7703f232020-09-14 09:03:13146 transport_controller_.EnsureStarted();
Mirko Bonadeif18f9202019-12-10 13:24:56147 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 10:53:09151 CreateObservers(nullptr, &encoder_feedback_, &stats_proxy_,
Danil Chapovalovf01c2c92021-05-14 13:39:23152 &stats_proxy_, &stats_proxy_, frame_count_observer,
153 &stats_proxy_, &stats_proxy_, &send_delay_stats_),
Mirko Bonadeif18f9202019-12-10 13:24:56154 &transport_controller_, &event_log_, &retransmission_rate_limiter_,
155 std::make_unique<FecControllerDefault>(time_controller_.GetClock()),
Jonas Orelandc7f691a2022-03-09 14:12:07156 nullptr, CryptoOptions{}, frame_transformer,
Evan Shrubsole9b643d42022-10-07 14:22:44157 field_trials ? *field_trials : field_trials_,
158 time_controller_.GetTaskQueueFactory());
Stefan Holmerdbdb3a02018-07-17 14:03:46159 }
Marina Cioceadc69fd22020-04-10 18:19:14160
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 14:12:07166 FrameCountObserver* frame_count_observer,
Jonas Orelande62c2f22022-03-29 09:04:48167 const FieldTrialsView* field_trials = nullptr)
Marina Cioceadc69fd22020-04-10 18:19:14168 : RtpVideoSenderTestFixture(ssrcs,
169 rtx_ssrcs,
170 payload_type,
171 suspended_payload_states,
172 frame_count_observer,
Jonas Orelandc7f691a2022-03-09 14:12:07173 /*frame_transformer=*/nullptr,
174 field_trials) {}
Marina Cioceadc69fd22020-04-10 18:19:14175
Niels Möller949f0fd2019-01-29 08:44:24176 RtpVideoSenderTestFixture(
177 const std::vector<uint32_t>& ssrcs,
Erik Språng490d76c2019-05-07 16:29:15178 const std::vector<uint32_t>& rtx_ssrcs,
Niels Möller949f0fd2019-01-29 08:44:24179 int payload_type,
Jonas Orelandc7f691a2022-03-09 14:12:07180 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
Jonas Orelande62c2f22022-03-29 09:04:48181 const FieldTrialsView* field_trials = nullptr)
Niels Möller949f0fd2019-01-29 08:44:24182 : RtpVideoSenderTestFixture(ssrcs,
Erik Språng490d76c2019-05-07 16:29:15183 rtx_ssrcs,
Niels Möller949f0fd2019-01-29 08:44:24184 payload_type,
185 suspended_payload_states,
Marina Cioceadc69fd22020-04-10 18:19:14186 /*frame_count_observer=*/nullptr,
Jonas Orelandc7f691a2022-03-09 14:12:07187 /*frame_transformer=*/nullptr,
188 field_trials) {}
Mirko Bonadeif18f9202019-12-10 13:24:56189
Per Kjellander59ade012022-12-02 08:09:37190 ~RtpVideoSenderTestFixture() { Stop(); }
Tommi6fba6b72022-01-28 08:00:01191
Stefan Holmer9416ef82018-07-19 08:34:38192 RtpVideoSender* router() { return router_.get(); }
Erik Språng490d76c2019-05-07 16:29:15193 MockTransport& transport() { return transport_; }
Markus Handell486cc552019-12-03 13:37:28194 void AdvanceTime(TimeDelta delta) { time_controller_.AdvanceTime(delta); }
Stefan Holmerdbdb3a02018-07-17 14:03:46195
Per K37879e92023-04-13 06:59:19196 void Stop() { router_->Stop(); }
Tommi6fba6b72022-01-28 08:00:01197
198 void SetActiveModules(const std::vector<bool>& active_modules) {
Per K37879e92023-04-13 06:59:19199 router_->SetActiveModules(active_modules);
Tommi6fba6b72022-01-28 08:00:01200 }
201
Stefan Holmerdbdb3a02018-07-17 14:03:46202 private:
Jonas Orelandc7f691a2022-03-09 14:12:07203 test::ScopedKeyValueConfig field_trials_;
Stefan Holmerdbdb3a02018-07-17 14:03:46204 NiceMock<MockTransport> transport_;
Stefan Holmerdbdb3a02018-07-17 14:03:46205 NiceMock<MockRtcpIntraFrameObserver> encoder_feedback_;
Erik Språng00cc8362019-11-25 11:21:46206 GlobalSimulatedTimeController time_controller_;
Danil Chapovalov83bbe912019-08-07 10:24:53207 RtcEventLogNull event_log_;
Stefan Holmerdbdb3a02018-07-17 14:03:46208 VideoSendStream::Config config_;
209 SendDelayStats send_delay_stats_;
210 BitrateConstraints bitrate_config_;
211 RtpTransportControllerSend transport_controller_;
Stefan Holmerdbdb3a02018-07-17 14:03:46212 SendStatisticsProxy stats_proxy_;
213 RateLimiter retransmission_rate_limiter_;
Stefan Holmer9416ef82018-07-19 08:34:38214 std::unique_ptr<RtpVideoSender> router_;
Stefan Holmerdbdb3a02018-07-17 14:03:46215};
Jakob Ivarsson9a12ee52020-11-26 15:04:18216
217BitrateAllocationUpdate CreateBitrateAllocationUpdate(int target_bitrate_bps) {
218 BitrateAllocationUpdate update;
219 update.target_bitrate = DataRate::BitsPerSec(target_bitrate_bps);
220 update.round_trip_time = TimeDelta::Zero();
221 return update;
222}
223
Åsa Persson4bece9a2017-10-06 08:04:04224} // namespace
mflodman@webrtc.org02270cd2015-02-06 13:10:19225
Sebastian Jansson63470292019-02-01 09:13:43226TEST(RtpVideoSenderTest, SendOnOneModule) {
Niels Möller663844d2019-02-14 15:15:54227 constexpr uint8_t kPayload = 'a';
kjellander02b3d272016-04-20 12:05:54228 EncodedImage encoded_image;
Niels Möller23775882018-08-16 08:24:12229 encoded_image.SetTimestamp(1);
kjellander02b3d272016-04-20 12:05:54230 encoded_image.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 14:43:58231 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 13:56:56232 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
kjellander02b3d272016-04-20 12:05:54233
Erik Språng490d76c2019-05-07 16:29:15234 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
Danil Chapovalov383f2cf2020-08-12 09:06:53235 EXPECT_NE(EncodedImageCallback::Result::OK,
236 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19237
Per Kjellander59ade012022-12-02 08:09:37238 test.SetActiveModules({true});
Danil Chapovalov383f2cf2020-08-12 09:06:53239 EXPECT_EQ(EncodedImageCallback::Result::OK,
240 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19241
Per Kjellander59ade012022-12-02 08:09:37242 test.SetActiveModules({false});
Danil Chapovalov383f2cf2020-08-12 09:06:53243 EXPECT_NE(EncodedImageCallback::Result::OK,
244 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19245
Per Kjellander59ade012022-12-02 08:09:37246 test.SetActiveModules({true});
Danil Chapovalov383f2cf2020-08-12 09:06:53247 EXPECT_EQ(EncodedImageCallback::Result::OK,
248 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19249}
250
Sebastian Jansson63470292019-02-01 09:13:43251TEST(RtpVideoSenderTest, SendSimulcastSetActive) {
Niels Möller663844d2019-02-14 15:15:54252 constexpr uint8_t kPayload = 'a';
Niels Möllerd3b8c632018-08-27 13:33:42253 EncodedImage encoded_image_1;
254 encoded_image_1.SetTimestamp(1);
255 encoded_image_1.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 14:43:58256 encoded_image_1._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 13:56:56257 encoded_image_1.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
kjellander02b3d272016-04-20 12:05:54258
Erik Språng490d76c2019-05-07 16:29:15259 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
260 kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19261
Niels Möllerd3b8c632018-08-27 13:33:42262 CodecSpecificInfo codec_info;
Niels Möllerd3b8c632018-08-27 13:33:42263 codec_info.codecType = kVideoCodecVP8;
mflodman@webrtc.org02270cd2015-02-06 13:10:19264
Per Kjellander59ade012022-12-02 08:09:37265 test.SetActiveModules({true, true});
sergeyu2cb155a2016-11-04 18:39:29266 EXPECT_EQ(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53267 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19268
Niels Möllerd3b8c632018-08-27 13:33:42269 EncodedImage encoded_image_2(encoded_image_1);
Henrik Boström2e540a22023-02-15 13:48:09270 encoded_image_2.SetSimulcastIndex(1);
sergeyu2cb155a2016-11-04 18:39:29271 EXPECT_EQ(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53272 test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19273
mflodman@webrtc.org50e28162015-02-23 07:45:11274 // Inactive.
Per Kjellander59ade012022-12-02 08:09:37275 test.Stop();
sergeyu2cb155a2016-11-04 18:39:29276 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53277 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
sergeyu2cb155a2016-11-04 18:39:29278 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53279 test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19280}
281
Seth Hampsoncc7125f2018-02-02 16:46:16282// Tests how setting individual rtp modules to active affects the overall
283// behavior of the payload router. First sets one module to active and checks
Stefan Holmerdbdb3a02018-07-17 14:03:46284// that outgoing data can be sent on this module, and checks that no data can
285// be sent if both modules are inactive.
Sebastian Jansson63470292019-02-01 09:13:43286TEST(RtpVideoSenderTest, SendSimulcastSetActiveModules) {
Niels Möller663844d2019-02-14 15:15:54287 constexpr uint8_t kPayload = 'a';
Niels Möllerd3b8c632018-08-27 13:33:42288 EncodedImage encoded_image_1;
289 encoded_image_1.SetTimestamp(1);
290 encoded_image_1.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 14:43:58291 encoded_image_1._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 13:56:56292 encoded_image_1.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Niels Möller77536a22019-01-15 07:50:01293
Niels Möllerd3b8c632018-08-27 13:33:42294 EncodedImage encoded_image_2(encoded_image_1);
Henrik Boström2e540a22023-02-15 13:48:09295 encoded_image_2.SetSimulcastIndex(1);
Stefan Holmerdbdb3a02018-07-17 14:03:46296
Erik Språng490d76c2019-05-07 16:29:15297 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
298 kPayloadType, {});
Niels Möllerd3b8c632018-08-27 13:33:42299 CodecSpecificInfo codec_info;
Niels Möllerd3b8c632018-08-27 13:33:42300 codec_info.codecType = kVideoCodecVP8;
Seth Hampsoncc7125f2018-02-02 16:46:16301
302 // Only setting one stream to active will still set the payload router to
303 // active and allow sending data on the active stream.
304 std::vector<bool> active_modules({true, false});
Tommi6fba6b72022-01-28 08:00:01305 test.SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 16:46:16306 EXPECT_EQ(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53307 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
Seth Hampsoncc7125f2018-02-02 16:46:16308
Stefan Holmerdbdb3a02018-07-17 14:03:46309 // Setting both streams to inactive will turn the payload router to
310 // inactive.
Seth Hampsoncc7125f2018-02-02 16:46:16311 active_modules = {false, false};
Tommi6fba6b72022-01-28 08:00:01312 test.SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 16:46:16313 // An incoming encoded image will not ask the module to send outgoing data
314 // because the payload router is inactive.
Seth Hampsoncc7125f2018-02-02 16:46:16315 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53316 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
Seth Hampsoncc7125f2018-02-02 16:46:16317 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53318 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
Seth Hampsoncc7125f2018-02-02 16:46:16319}
320
Henrik Boström2e540a22023-02-15 13:48:09321TEST(RtpVideoSenderTest,
322 DiscardsHigherSimulcastFramesAfterLayerDisabledInVideoLayersAllocation) {
Per Kjellanderfb8641c2022-08-11 07:25:00323 constexpr uint8_t kPayload = 'a';
324 EncodedImage encoded_image_1;
325 encoded_image_1.SetTimestamp(1);
326 encoded_image_1.capture_time_ms_ = 2;
327 encoded_image_1._frameType = VideoFrameType::kVideoFrameKey;
328 encoded_image_1.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
329 EncodedImage encoded_image_2(encoded_image_1);
Henrik Boström2e540a22023-02-15 13:48:09330 encoded_image_2.SetSimulcastIndex(1);
Per Kjellanderfb8641c2022-08-11 07:25:00331 CodecSpecificInfo codec_info;
332 codec_info.codecType = kVideoCodecVP8;
333 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
334 kPayloadType, {});
335 test.SetActiveModules({true, true});
336 // A layer is sent on both rtp streams.
337 test.router()->OnVideoLayersAllocationUpdated(
338 {.active_spatial_layers = {{.rtp_stream_index = 0},
339 {.rtp_stream_index = 1}}});
340
341 EXPECT_EQ(EncodedImageCallback::Result::OK,
342 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
343 EXPECT_EQ(EncodedImageCallback::Result::OK,
344 test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
345
346 // Only rtp stream index 0 is configured to send a stream.
347 test.router()->OnVideoLayersAllocationUpdated(
348 {.active_spatial_layers = {{.rtp_stream_index = 0}}});
349 EXPECT_EQ(EncodedImageCallback::Result::OK,
350 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
351 EXPECT_NE(EncodedImageCallback::Result::OK,
352 test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
353}
354
Sebastian Jansson63470292019-02-01 09:13:43355TEST(RtpVideoSenderTest, CreateWithNoPreviousStates) {
Erik Språng490d76c2019-05-07 16:29:15356 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
357 kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37358 test.SetActiveModules({true, true});
Åsa Persson4bece9a2017-10-06 08:04:04359
360 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 14:03:46361 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 08:04:04362 EXPECT_EQ(2u, initial_states.size());
363 EXPECT_NE(initial_states.find(kSsrc1), initial_states.end());
364 EXPECT_NE(initial_states.find(kSsrc2), initial_states.end());
365}
366
Sebastian Jansson63470292019-02-01 09:13:43367TEST(RtpVideoSenderTest, CreateWithPreviousStates) {
philipel25d31ec2018-08-08 14:33:01368 const int64_t kState1SharedFrameId = 123;
369 const int64_t kState2SharedFrameId = 234;
Åsa Persson4bece9a2017-10-06 08:04:04370 RtpPayloadState state1;
371 state1.picture_id = kInitialPictureId1;
Niels Möllerbb894ff2018-03-15 11:28:53372 state1.tl0_pic_idx = kInitialTl0PicIdx1;
philipel25d31ec2018-08-08 14:33:01373 state1.shared_frame_id = kState1SharedFrameId;
Åsa Persson4bece9a2017-10-06 08:04:04374 RtpPayloadState state2;
375 state2.picture_id = kInitialPictureId2;
Niels Möllerbb894ff2018-03-15 11:28:53376 state2.tl0_pic_idx = kInitialTl0PicIdx2;
philipel25d31ec2018-08-08 14:33:01377 state2.shared_frame_id = kState2SharedFrameId;
Åsa Persson4bece9a2017-10-06 08:04:04378 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
379 {kSsrc2, state2}};
380
Erik Språng490d76c2019-05-07 16:29:15381 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
382 kPayloadType, states);
Per Kjellander59ade012022-12-02 08:09:37383 test.SetActiveModules({true, true});
Åsa Persson4bece9a2017-10-06 08:04:04384
385 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 14:03:46386 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 08:04:04387 EXPECT_EQ(2u, initial_states.size());
388 EXPECT_EQ(kInitialPictureId1, initial_states[kSsrc1].picture_id);
Niels Möllerbb894ff2018-03-15 11:28:53389 EXPECT_EQ(kInitialTl0PicIdx1, initial_states[kSsrc1].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 08:04:04390 EXPECT_EQ(kInitialPictureId2, initial_states[kSsrc2].picture_id);
Niels Möllerbb894ff2018-03-15 11:28:53391 EXPECT_EQ(kInitialTl0PicIdx2, initial_states[kSsrc2].tl0_pic_idx);
philipel25d31ec2018-08-08 14:33:01392 EXPECT_EQ(kState2SharedFrameId, initial_states[kSsrc1].shared_frame_id);
393 EXPECT_EQ(kState2SharedFrameId, initial_states[kSsrc2].shared_frame_id);
Åsa Persson4bece9a2017-10-06 08:04:04394}
Niels Möller949f0fd2019-01-29 08:44:24395
Sebastian Jansson63470292019-02-01 09:13:43396TEST(RtpVideoSenderTest, FrameCountCallbacks) {
Niels Möller949f0fd2019-01-29 08:44:24397 class MockFrameCountObserver : public FrameCountObserver {
398 public:
Danil Chapovalov9a5efe92020-05-14 20:06:18399 MOCK_METHOD(void,
400 FrameCountUpdated,
401 (const FrameCounts& frame_counts, uint32_t ssrc),
402 (override));
Niels Möller949f0fd2019-01-29 08:44:24403 } callback;
404
Erik Språng490d76c2019-05-07 16:29:15405 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {},
406 &callback);
Niels Möller949f0fd2019-01-29 08:44:24407
Niels Möller663844d2019-02-14 15:15:54408 constexpr uint8_t kPayload = 'a';
Niels Möller949f0fd2019-01-29 08:44:24409 EncodedImage encoded_image;
410 encoded_image.SetTimestamp(1);
411 encoded_image.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 14:43:58412 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 13:56:56413 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Niels Möller949f0fd2019-01-29 08:44:24414
Niels Möller8f7ce222019-03-21 14:43:58415 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller949f0fd2019-01-29 08:44:24416
417 // No callbacks when not active.
418 EXPECT_CALL(callback, FrameCountUpdated).Times(0);
Danil Chapovalov383f2cf2020-08-12 09:06:53419 EXPECT_NE(EncodedImageCallback::Result::OK,
420 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Mirko Bonadei6a489f22019-04-09 13:11:12421 ::testing::Mock::VerifyAndClearExpectations(&callback);
Niels Möller949f0fd2019-01-29 08:44:24422
Per Kjellander59ade012022-12-02 08:09:37423 test.SetActiveModules({true});
Niels Möller949f0fd2019-01-29 08:44:24424
425 FrameCounts frame_counts;
426 EXPECT_CALL(callback, FrameCountUpdated(_, kSsrc1))
427 .WillOnce(SaveArg<0>(&frame_counts));
Danil Chapovalov383f2cf2020-08-12 09:06:53428 EXPECT_EQ(EncodedImageCallback::Result::OK,
429 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Niels Möller949f0fd2019-01-29 08:44:24430
431 EXPECT_EQ(1, frame_counts.key_frames);
432 EXPECT_EQ(0, frame_counts.delta_frames);
433
Mirko Bonadei6a489f22019-04-09 13:11:12434 ::testing::Mock::VerifyAndClearExpectations(&callback);
Niels Möller949f0fd2019-01-29 08:44:24435
Niels Möller8f7ce222019-03-21 14:43:58436 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
Niels Möller949f0fd2019-01-29 08:44:24437 EXPECT_CALL(callback, FrameCountUpdated(_, kSsrc1))
438 .WillOnce(SaveArg<0>(&frame_counts));
Danil Chapovalov383f2cf2020-08-12 09:06:53439 EXPECT_EQ(EncodedImageCallback::Result::OK,
440 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Niels Möller949f0fd2019-01-29 08:44:24441
442 EXPECT_EQ(1, frame_counts.key_frames);
443 EXPECT_EQ(1, frame_counts.delta_frames);
444}
445
Erik Språng490d76c2019-05-07 16:29:15446// Integration test verifying that ack of packet via TransportFeedback means
Erik Språng845c6aa2019-05-29 11:02:24447// that the packet is removed from RtpPacketHistory and won't be retransmitted
Erik Språng490d76c2019-05-07 16:29:15448// again.
449TEST(RtpVideoSenderTest, DoesNotRetrasmitAckedPackets) {
Erik Språng490d76c2019-05-07 16:29:15450 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
451 kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37452 test.SetActiveModules({true, true});
Erik Språng490d76c2019-05-07 16:29:15453
454 constexpr uint8_t kPayload = 'a';
455 EncodedImage encoded_image;
456 encoded_image.SetTimestamp(1);
457 encoded_image.capture_time_ms_ = 2;
458 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 13:56:56459 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Erik Språng490d76c2019-05-07 16:29:15460
461 // Send two tiny images, mapping to two RTP packets. Capture sequence numbers.
Erik Språng490d76c2019-05-07 16:29:15462 std::vector<uint16_t> rtp_sequence_numbers;
463 std::vector<uint16_t> transport_sequence_numbers;
464 EXPECT_CALL(test.transport(), SendRtp)
465 .Times(2)
Danil Chapovalova68eb8c2020-02-17 15:13:14466 .WillRepeatedly([&rtp_sequence_numbers, &transport_sequence_numbers](
467 const uint8_t* packet, size_t length,
468 const PacketOptions& options) {
469 RtpPacket rtp_packet;
470 EXPECT_TRUE(rtp_packet.Parse(packet, length));
471 rtp_sequence_numbers.push_back(rtp_packet.SequenceNumber());
472 transport_sequence_numbers.push_back(options.packet_id);
473 return true;
474 });
Danil Chapovalov383f2cf2020-08-12 09:06:53475 EXPECT_EQ(EncodedImageCallback::Result::OK,
476 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Erik Språng490d76c2019-05-07 16:29:15477 encoded_image.SetTimestamp(2);
478 encoded_image.capture_time_ms_ = 3;
Danil Chapovalov383f2cf2020-08-12 09:06:53479 EXPECT_EQ(EncodedImageCallback::Result::OK,
480 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Erik Språngbd7046c2019-05-07 21:54:29481
Danil Chapovalov0c626af2020-02-10 10:16:00482 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 16:29:15483
Erik Språng490d76c2019-05-07 16:29:15484 // Construct a NACK message for requesting retransmission of both packet.
485 rtcp::Nack nack;
486 nack.SetMediaSsrc(kSsrc1);
487 nack.SetPacketIds(rtp_sequence_numbers);
488 rtc::Buffer nack_buffer = nack.Build();
489
490 std::vector<uint16_t> retransmitted_rtp_sequence_numbers;
491 EXPECT_CALL(test.transport(), SendRtp)
492 .Times(2)
Danil Chapovalova68eb8c2020-02-17 15:13:14493 .WillRepeatedly([&retransmitted_rtp_sequence_numbers](
Erik Språng490d76c2019-05-07 16:29:15494 const uint8_t* packet, size_t length,
495 const PacketOptions& options) {
496 RtpPacket rtp_packet;
497 EXPECT_TRUE(rtp_packet.Parse(packet, length));
498 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
499 // Capture the retransmitted sequence number from the RTX header.
500 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
501 retransmitted_rtp_sequence_numbers.push_back(
502 ByteReader<uint16_t>::ReadBigEndian(payload.data()));
Erik Språng490d76c2019-05-07 16:29:15503 return true;
504 });
505 test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size());
Danil Chapovalov0c626af2020-02-10 10:16:00506 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 16:29:15507
508 // Verify that both packets were retransmitted.
509 EXPECT_EQ(retransmitted_rtp_sequence_numbers, rtp_sequence_numbers);
510
511 // Simulate transport feedback indicating fist packet received, next packet
Erik Språng00cc8362019-11-25 11:21:46512 // lost (not other way around as that would trigger early retransmit).
Sebastian Janssonf2988552019-10-29 16:18:51513 StreamFeedbackObserver::StreamPacketInfo lost_packet_feedback;
Erik Språng00cc8362019-11-25 11:21:46514 lost_packet_feedback.rtp_sequence_number = rtp_sequence_numbers[0];
Erik Språng490d76c2019-05-07 16:29:15515 lost_packet_feedback.ssrc = kSsrc1;
Sebastian Janssonf2988552019-10-29 16:18:51516 lost_packet_feedback.received = false;
Erik Språng6a0a5592021-06-15 17:04:24517 lost_packet_feedback.is_retransmission = false;
Erik Språng490d76c2019-05-07 16:29:15518
Erik Språng00cc8362019-11-25 11:21:46519 StreamFeedbackObserver::StreamPacketInfo received_packet_feedback;
520 received_packet_feedback.rtp_sequence_number = rtp_sequence_numbers[1];
521 received_packet_feedback.ssrc = kSsrc1;
522 received_packet_feedback.received = true;
Erik Språng6a0a5592021-06-15 17:04:24523 lost_packet_feedback.is_retransmission = false;
Erik Språng00cc8362019-11-25 11:21:46524
Sebastian Janssonf2988552019-10-29 16:18:51525 test.router()->OnPacketFeedbackVector(
Erik Språng00cc8362019-11-25 11:21:46526 {lost_packet_feedback, received_packet_feedback});
Erik Språng490d76c2019-05-07 16:29:15527
528 // Advance time to make sure retransmission would be allowed and try again.
529 // This time the retransmission should not happen for the first packet since
530 // the history has been notified of the ack and removed the packet. The
531 // second packet, included in the feedback but not marked as received, should
532 // still be retransmitted.
Danil Chapovalov0c626af2020-02-10 10:16:00533 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 16:29:15534 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 15:13:14535 .WillOnce([&lost_packet_feedback](const uint8_t* packet, size_t length,
536 const PacketOptions& options) {
Erik Språng490d76c2019-05-07 16:29:15537 RtpPacket rtp_packet;
538 EXPECT_TRUE(rtp_packet.Parse(packet, length));
539 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
540 // Capture the retransmitted sequence number from the RTX header.
541 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
542 EXPECT_EQ(lost_packet_feedback.rtp_sequence_number,
543 ByteReader<uint16_t>::ReadBigEndian(payload.data()));
Erik Språng490d76c2019-05-07 16:29:15544 return true;
545 });
546 test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size());
Danil Chapovalov0c626af2020-02-10 10:16:00547 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 16:29:15548}
Erik Språng845c6aa2019-05-29 11:02:24549
Sebastian Jansson3d4d94a2020-01-14 13:25:41550// This tests that we utilize transport wide feedback to retransmit lost
Tommi6fba6b72022-01-28 08:00:01551// packets. This is tested by dropping all ordinary packets from a "lossy"
552// stream sent along with a secondary untouched stream. The transport wide
Sebastian Jansson3d4d94a2020-01-14 13:25:41553// feedback packets from the secondary stream allows the sending side to
554// detect and retreansmit the lost packets from the lossy stream.
555TEST(RtpVideoSenderTest, RetransmitsOnTransportWideLossInfo) {
556 int rtx_packets;
557 test::Scenario s(test_info_);
558 test::CallClientConfig call_conf;
559 // Keeping the bitrate fixed to avoid RTX due to probing.
Danil Chapovalovcad3e0e2020-02-17 17:46:07560 call_conf.transport.rates.max_rate = DataRate::KilobitsPerSec(300);
561 call_conf.transport.rates.start_rate = DataRate::KilobitsPerSec(300);
Sebastian Jansson3d4d94a2020-01-14 13:25:41562 test::NetworkSimulationConfig net_conf;
Danil Chapovalovcad3e0e2020-02-17 17:46:07563 net_conf.bandwidth = DataRate::KilobitsPerSec(300);
Sebastian Jansson3d4d94a2020-01-14 13:25:41564 auto send_node = s.CreateSimulationNode(net_conf);
Tommi3c9bcc12020-04-15 14:45:47565 auto* callee = s.CreateClient("return", call_conf);
Sebastian Jansson3d4d94a2020-01-14 13:25:41566 auto* route = s.CreateRoutes(s.CreateClient("send", call_conf), {send_node},
Tommi3c9bcc12020-04-15 14:45:47567 callee, {s.CreateSimulationNode(net_conf)});
Sebastian Jansson3d4d94a2020-01-14 13:25:41568
569 test::VideoStreamConfig lossy_config;
570 lossy_config.source.framerate = 5;
571 auto* lossy = s.CreateVideoStream(route->forward(), lossy_config);
572 // The secondary stream acts a driver for transport feedback messages,
573 // ensuring that lost packets on the lossy stream are retransmitted.
574 s.CreateVideoStream(route->forward(), test::VideoStreamConfig());
575
576 send_node->router()->SetFilter([&](const EmulatedIpPacket& packet) {
577 RtpPacket rtp;
578 if (rtp.Parse(packet.data)) {
579 // Drops all regular packets for the lossy stream and counts all RTX
580 // packets. Since no packets are let trough, NACKs can't be triggered
581 // by the receiving side.
582 if (lossy->send()->UsingSsrc(rtp.Ssrc())) {
583 return false;
584 } else if (lossy->send()->UsingRtxSsrc(rtp.Ssrc())) {
585 ++rtx_packets;
586 }
587 }
588 return true;
589 });
590
591 // Run for a short duration and reset counters to avoid counting RTX packets
592 // from initial probing.
Danil Chapovalov0c626af2020-02-10 10:16:00593 s.RunFor(TimeDelta::Seconds(1));
Sebastian Jansson3d4d94a2020-01-14 13:25:41594 rtx_packets = 0;
Tommi3c9bcc12020-04-15 14:45:47595 int decoded_baseline = 0;
596 callee->SendTask([&decoded_baseline, &lossy]() {
597 decoded_baseline = lossy->receive()->GetStats().frames_decoded;
598 });
Danil Chapovalov0c626af2020-02-10 10:16:00599 s.RunFor(TimeDelta::Seconds(1));
Sebastian Jansson3d4d94a2020-01-14 13:25:41600 // We expect both that RTX packets were sent and that an appropriate number of
601 // frames were received. This is somewhat redundant but reduces the risk of
602 // false positives in future regressions (e.g. RTX is send due to probing).
603 EXPECT_GE(rtx_packets, 1);
Tommi3c9bcc12020-04-15 14:45:47604 int frames_decoded = 0;
605 callee->SendTask([&decoded_baseline, &frames_decoded, &lossy]() {
606 frames_decoded =
607 lossy->receive()->GetStats().frames_decoded - decoded_baseline;
608 });
Sebastian Jansson3d4d94a2020-01-14 13:25:41609 EXPECT_EQ(frames_decoded, 5);
610}
611
Erik Språng845c6aa2019-05-29 11:02:24612// Integration test verifying that retransmissions are sent for packets which
613// can be detected as lost early, using transport wide feedback.
614TEST(RtpVideoSenderTest, EarlyRetransmits) {
Erik Språng845c6aa2019-05-29 11:02:24615 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
616 kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37617 test.SetActiveModules({true, true});
Erik Språng845c6aa2019-05-29 11:02:24618
Niels Möllerb9bfe652019-10-03 06:43:53619 const uint8_t kPayload[1] = {'a'};
Erik Språng845c6aa2019-05-29 11:02:24620 EncodedImage encoded_image;
621 encoded_image.SetTimestamp(1);
622 encoded_image.capture_time_ms_ = 2;
623 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möllerb9bfe652019-10-03 06:43:53624 encoded_image.SetEncodedData(
625 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
Henrik Boström2e540a22023-02-15 13:48:09626 encoded_image.SetSimulcastIndex(0);
Erik Språng845c6aa2019-05-29 11:02:24627
628 CodecSpecificInfo codec_specific;
629 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
630
631 // Send two tiny images, mapping to single RTP packets. Capture sequence
632 // numbers.
Erik Språng845c6aa2019-05-29 11:02:24633 uint16_t frame1_rtp_sequence_number = 0;
634 uint16_t frame1_transport_sequence_number = 0;
635 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 15:13:14636 .WillOnce(
637 [&frame1_rtp_sequence_number, &frame1_transport_sequence_number](
638 const uint8_t* packet, size_t length,
639 const PacketOptions& options) {
640 RtpPacket rtp_packet;
641 EXPECT_TRUE(rtp_packet.Parse(packet, length));
642 frame1_rtp_sequence_number = rtp_packet.SequenceNumber();
643 frame1_transport_sequence_number = options.packet_id;
644 EXPECT_EQ(rtp_packet.Ssrc(), kSsrc1);
645 return true;
646 });
Danil Chapovalov383f2cf2020-08-12 09:06:53647 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Erik Språng845c6aa2019-05-29 11:02:24648 EncodedImageCallback::Result::OK);
Erik Språng845c6aa2019-05-29 11:02:24649
Danil Chapovalov0c626af2020-02-10 10:16:00650 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng845c6aa2019-05-29 11:02:24651
652 uint16_t frame2_rtp_sequence_number = 0;
653 uint16_t frame2_transport_sequence_number = 0;
Henrik Boström2e540a22023-02-15 13:48:09654 encoded_image.SetSimulcastIndex(1);
Erik Språng845c6aa2019-05-29 11:02:24655 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 15:13:14656 .WillOnce(
657 [&frame2_rtp_sequence_number, &frame2_transport_sequence_number](
658 const uint8_t* packet, size_t length,
659 const PacketOptions& options) {
660 RtpPacket rtp_packet;
661 EXPECT_TRUE(rtp_packet.Parse(packet, length));
662 frame2_rtp_sequence_number = rtp_packet.SequenceNumber();
663 frame2_transport_sequence_number = options.packet_id;
664 EXPECT_EQ(rtp_packet.Ssrc(), kSsrc2);
665 return true;
666 });
Danil Chapovalov383f2cf2020-08-12 09:06:53667 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Erik Språng845c6aa2019-05-29 11:02:24668 EncodedImageCallback::Result::OK);
Danil Chapovalov0c626af2020-02-10 10:16:00669 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng845c6aa2019-05-29 11:02:24670
671 EXPECT_NE(frame1_transport_sequence_number, frame2_transport_sequence_number);
672
673 // Inject a transport feedback where the packet for the first frame is lost,
674 // expect a retransmission for it.
675 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 15:13:14676 .WillOnce([&frame1_rtp_sequence_number](const uint8_t* packet,
677 size_t length,
678 const PacketOptions& options) {
Erik Språng845c6aa2019-05-29 11:02:24679 RtpPacket rtp_packet;
680 EXPECT_TRUE(rtp_packet.Parse(packet, length));
Sebastian Janssonf2988552019-10-29 16:18:51681 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
Erik Språng845c6aa2019-05-29 11:02:24682
683 // Retransmitted sequence number from the RTX header should match
684 // the lost packet.
685 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
686 EXPECT_EQ(ByteReader<uint16_t>::ReadBigEndian(payload.data()),
687 frame1_rtp_sequence_number);
Erik Språng845c6aa2019-05-29 11:02:24688 return true;
689 });
690
Sebastian Janssonf2988552019-10-29 16:18:51691 StreamFeedbackObserver::StreamPacketInfo first_packet_feedback;
Erik Språng845c6aa2019-05-29 11:02:24692 first_packet_feedback.rtp_sequence_number = frame1_rtp_sequence_number;
693 first_packet_feedback.ssrc = kSsrc1;
Sebastian Janssonf2988552019-10-29 16:18:51694 first_packet_feedback.received = false;
Erik Språng6a0a5592021-06-15 17:04:24695 first_packet_feedback.is_retransmission = false;
Erik Språng845c6aa2019-05-29 11:02:24696
Sebastian Janssonf2988552019-10-29 16:18:51697 StreamFeedbackObserver::StreamPacketInfo second_packet_feedback;
698 second_packet_feedback.rtp_sequence_number = frame2_rtp_sequence_number;
699 second_packet_feedback.ssrc = kSsrc2;
700 second_packet_feedback.received = true;
Erik Språng6a0a5592021-06-15 17:04:24701 first_packet_feedback.is_retransmission = false;
Erik Språng845c6aa2019-05-29 11:02:24702
Sebastian Janssonf2988552019-10-29 16:18:51703 test.router()->OnPacketFeedbackVector(
704 {first_packet_feedback, second_packet_feedback});
Erik Språng845c6aa2019-05-29 11:02:24705
706 // Wait for pacer to run and send the RTX packet.
Danil Chapovalov0c626af2020-02-10 10:16:00707 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng845c6aa2019-05-29 11:02:24708}
Sebastian Janssoncf41eb12019-06-10 09:30:59709
Danil Chapovalov2272f202020-02-18 11:09:43710TEST(RtpVideoSenderTest, SupportsDependencyDescriptor) {
Danil Chapovalov2272f202020-02-18 11:09:43711 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37712 test.SetActiveModules({true});
Danil Chapovalov2272f202020-02-18 11:09:43713
714 RtpHeaderExtensionMap extensions;
715 extensions.Register<RtpDependencyDescriptorExtension>(
716 kDependencyDescriptorExtensionId);
717 std::vector<RtpPacket> sent_packets;
718 ON_CALL(test.transport(), SendRtp)
719 .WillByDefault([&](const uint8_t* packet, size_t length,
720 const PacketOptions& options) {
721 sent_packets.emplace_back(&extensions);
722 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
723 return true;
724 });
725
726 const uint8_t kPayload[1] = {'a'};
727 EncodedImage encoded_image;
728 encoded_image.SetTimestamp(1);
729 encoded_image.capture_time_ms_ = 2;
730 encoded_image.SetEncodedData(
731 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
732
733 CodecSpecificInfo codec_specific;
734 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
735 codec_specific.template_structure.emplace();
736 codec_specific.template_structure->num_decode_targets = 1;
737 codec_specific.template_structure->templates = {
Danil Chapovalov24263f42020-06-11 11:23:45738 FrameDependencyTemplate().T(0).Dtis("S"),
739 FrameDependencyTemplate().T(0).Dtis("S").FrameDiffs({2}),
740 FrameDependencyTemplate().T(1).Dtis("D").FrameDiffs({1}),
Danil Chapovalov2272f202020-02-18 11:09:43741 };
742
743 // Send two tiny images, mapping to single RTP packets.
744 // Send in key frame.
745 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
746 codec_specific.generic_frame_info =
747 GenericFrameInfo::Builder().T(0).Dtis("S").Build();
748 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
Danil Chapovalov383f2cf2020-08-12 09:06:53749 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 11:09:43750 EncodedImageCallback::Result::OK);
751 test.AdvanceTime(TimeDelta::Millis(33));
752 ASSERT_THAT(sent_packets, SizeIs(1));
753 EXPECT_TRUE(
754 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
755
756 // Send in delta frame.
757 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
758 codec_specific.template_structure = absl::nullopt;
759 codec_specific.generic_frame_info =
760 GenericFrameInfo::Builder().T(1).Dtis("D").Build();
761 codec_specific.generic_frame_info->encoder_buffers = {{0, true, false}};
Danil Chapovalov383f2cf2020-08-12 09:06:53762 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 11:09:43763 EncodedImageCallback::Result::OK);
764 test.AdvanceTime(TimeDelta::Millis(33));
765 ASSERT_THAT(sent_packets, SizeIs(2));
766 EXPECT_TRUE(
767 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
768}
769
Emil Lundmark6c81a422022-05-18 15:13:34770TEST(RtpVideoSenderTest,
771 SupportsDependencyDescriptorForVp8NotProvidedByEncoder) {
772 constexpr uint8_t kPayload[1] = {'a'};
773 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
774 RtpHeaderExtensionMap extensions;
775 extensions.Register<RtpDependencyDescriptorExtension>(
776 kDependencyDescriptorExtensionId);
777 std::vector<RtpPacket> sent_packets;
778 ON_CALL(test.transport(), SendRtp)
779 .WillByDefault(
780 [&](const uint8_t* packet, size_t length, const PacketOptions&) {
781 EXPECT_TRUE(
782 sent_packets.emplace_back(&extensions).Parse(packet, length));
783 return true;
784 });
Per Kjellander59ade012022-12-02 08:09:37785 test.SetActiveModules({true});
Emil Lundmark6c81a422022-05-18 15:13:34786
787 EncodedImage key_frame_image;
788 key_frame_image._frameType = VideoFrameType::kVideoFrameKey;
789 key_frame_image.SetEncodedData(
790 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
791 CodecSpecificInfo key_frame_info;
792 key_frame_info.codecType = VideoCodecType::kVideoCodecVP8;
793 ASSERT_EQ(
794 test.router()->OnEncodedImage(key_frame_image, &key_frame_info).error,
795 EncodedImageCallback::Result::OK);
796
797 EncodedImage delta_image;
798 delta_image._frameType = VideoFrameType::kVideoFrameDelta;
799 delta_image.SetEncodedData(
800 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
801 CodecSpecificInfo delta_info;
802 delta_info.codecType = VideoCodecType::kVideoCodecVP8;
803 ASSERT_EQ(test.router()->OnEncodedImage(delta_image, &delta_info).error,
804 EncodedImageCallback::Result::OK);
805
806 test.AdvanceTime(TimeDelta::Millis(123));
807
808 DependencyDescriptor key_frame_dd;
809 DependencyDescriptor delta_dd;
810 ASSERT_THAT(sent_packets, SizeIs(2));
811 EXPECT_TRUE(sent_packets[0].GetExtension<RtpDependencyDescriptorExtension>(
812 /*structure=*/nullptr, &key_frame_dd));
813 EXPECT_TRUE(sent_packets[1].GetExtension<RtpDependencyDescriptorExtension>(
814 key_frame_dd.attached_structure.get(), &delta_dd));
815}
816
Danil Chapovalov0be18462021-01-20 11:11:29817TEST(RtpVideoSenderTest, SupportsDependencyDescriptorForVp9) {
818 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37819 test.SetActiveModules({true});
Danil Chapovalov0be18462021-01-20 11:11:29820
821 RtpHeaderExtensionMap extensions;
822 extensions.Register<RtpDependencyDescriptorExtension>(
823 kDependencyDescriptorExtensionId);
824 std::vector<RtpPacket> sent_packets;
825 ON_CALL(test.transport(), SendRtp)
826 .WillByDefault([&](const uint8_t* packet, size_t length,
827 const PacketOptions& options) {
828 sent_packets.emplace_back(&extensions);
829 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
830 return true;
831 });
832
833 const uint8_t kPayload[1] = {'a'};
834 EncodedImage encoded_image;
835 encoded_image.SetTimestamp(1);
836 encoded_image.capture_time_ms_ = 2;
837 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
838 encoded_image.SetEncodedData(
839 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
840
841 CodecSpecificInfo codec_specific;
842 codec_specific.codecType = VideoCodecType::kVideoCodecVP9;
843 codec_specific.template_structure.emplace();
844 codec_specific.template_structure->num_decode_targets = 2;
845 codec_specific.template_structure->templates = {
846 FrameDependencyTemplate().S(0).Dtis("SS"),
847 FrameDependencyTemplate().S(1).Dtis("-S").FrameDiffs({1}),
848 };
849
850 // Send two tiny images, each mapping to single RTP packet.
851 // Send in key frame for the base spatial layer.
852 codec_specific.generic_frame_info =
853 GenericFrameInfo::Builder().S(0).Dtis("SS").Build();
854 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
855 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
856 EncodedImageCallback::Result::OK);
857 // Send in 2nd spatial layer.
858 codec_specific.template_structure = absl::nullopt;
859 codec_specific.generic_frame_info =
860 GenericFrameInfo::Builder().S(1).Dtis("-S").Build();
861 codec_specific.generic_frame_info->encoder_buffers = {{0, true, false},
862 {1, false, true}};
863 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
864 EncodedImageCallback::Result::OK);
865
866 test.AdvanceTime(TimeDelta::Millis(33));
867 ASSERT_THAT(sent_packets, SizeIs(2));
868 EXPECT_TRUE(sent_packets[0].HasExtension<RtpDependencyDescriptorExtension>());
869 EXPECT_TRUE(sent_packets[1].HasExtension<RtpDependencyDescriptorExtension>());
870}
871
Danil Chapovalov748550d2021-04-29 09:42:54872TEST(RtpVideoSenderTest,
873 SupportsDependencyDescriptorForVp9NotProvidedByEncoder) {
Danil Chapovalov748550d2021-04-29 09:42:54874 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37875 test.SetActiveModules({true});
Danil Chapovalov748550d2021-04-29 09:42:54876
877 RtpHeaderExtensionMap extensions;
878 extensions.Register<RtpDependencyDescriptorExtension>(
879 kDependencyDescriptorExtensionId);
880 std::vector<RtpPacket> sent_packets;
881 ON_CALL(test.transport(), SendRtp)
882 .WillByDefault([&](const uint8_t* packet, size_t length,
883 const PacketOptions& options) {
884 sent_packets.emplace_back(&extensions);
885 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
886 return true;
887 });
888
889 const uint8_t kPayload[1] = {'a'};
890 EncodedImage encoded_image;
891 encoded_image.SetTimestamp(1);
892 encoded_image.capture_time_ms_ = 2;
893 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
894 encoded_image._encodedWidth = 320;
895 encoded_image._encodedHeight = 180;
896 encoded_image.SetEncodedData(
897 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
898
899 CodecSpecificInfo codec_specific;
900 codec_specific.codecType = VideoCodecType::kVideoCodecVP9;
901 codec_specific.codecSpecific.VP9.num_spatial_layers = 1;
902 codec_specific.codecSpecific.VP9.temporal_idx = kNoTemporalIdx;
903 codec_specific.codecSpecific.VP9.first_frame_in_picture = true;
904 codec_specific.end_of_picture = true;
905 codec_specific.codecSpecific.VP9.inter_pic_predicted = false;
906
907 // Send two tiny images, each mapping to single RTP packet.
908 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
909 EncodedImageCallback::Result::OK);
910
911 // Send in 2nd picture.
912 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
913 encoded_image.SetTimestamp(3000);
914 codec_specific.codecSpecific.VP9.inter_pic_predicted = true;
915 codec_specific.codecSpecific.VP9.num_ref_pics = 1;
916 codec_specific.codecSpecific.VP9.p_diff[0] = 1;
917 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
918 EncodedImageCallback::Result::OK);
919
920 test.AdvanceTime(TimeDelta::Millis(33));
921 ASSERT_THAT(sent_packets, SizeIs(2));
922 EXPECT_TRUE(sent_packets[0].HasExtension<RtpDependencyDescriptorExtension>());
923 EXPECT_TRUE(sent_packets[1].HasExtension<RtpDependencyDescriptorExtension>());
924}
925
philipel5b231de2021-09-01 13:21:16926TEST(RtpVideoSenderTest, GenerateDependecyDescriptorForGenericCodecs) {
Jonas Orelandc7f691a2022-03-09 14:12:07927 test::ScopedKeyValueConfig field_trials(
philipel5b231de2021-09-01 13:21:16928 "WebRTC-GenericCodecDependencyDescriptor/Enabled/");
Jonas Orelandc7f691a2022-03-09 14:12:07929 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {}, &field_trials);
Per Kjellander59ade012022-12-02 08:09:37930 test.SetActiveModules({true});
philipel5b231de2021-09-01 13:21:16931
932 RtpHeaderExtensionMap extensions;
933 extensions.Register<RtpDependencyDescriptorExtension>(
934 kDependencyDescriptorExtensionId);
935 std::vector<RtpPacket> sent_packets;
936 ON_CALL(test.transport(), SendRtp)
937 .WillByDefault([&](const uint8_t* packet, size_t length,
938 const PacketOptions& options) {
939 sent_packets.emplace_back(&extensions);
940 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
941 return true;
942 });
943
944 const uint8_t kPayload[1] = {'a'};
945 EncodedImage encoded_image;
946 encoded_image.SetTimestamp(1);
947 encoded_image.capture_time_ms_ = 2;
948 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
949 encoded_image._encodedWidth = 320;
950 encoded_image._encodedHeight = 180;
951 encoded_image.SetEncodedData(
952 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
953
954 CodecSpecificInfo codec_specific;
955 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
956 codec_specific.end_of_picture = true;
957
958 // Send two tiny images, each mapping to single RTP packet.
959 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
960 EncodedImageCallback::Result::OK);
961
962 // Send in 2nd picture.
963 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
964 encoded_image.SetTimestamp(3000);
965 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
966 EncodedImageCallback::Result::OK);
967
968 test.AdvanceTime(TimeDelta::Millis(33));
969 ASSERT_THAT(sent_packets, SizeIs(2));
970 EXPECT_TRUE(sent_packets[0].HasExtension<RtpDependencyDescriptorExtension>());
971 EXPECT_TRUE(sent_packets[1].HasExtension<RtpDependencyDescriptorExtension>());
972}
973
Danil Chapovalov2272f202020-02-18 11:09:43974TEST(RtpVideoSenderTest, SupportsStoppingUsingDependencyDescriptor) {
Danil Chapovalov2272f202020-02-18 11:09:43975 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
Per Kjellander59ade012022-12-02 08:09:37976 test.SetActiveModules({true});
Danil Chapovalov2272f202020-02-18 11:09:43977
978 RtpHeaderExtensionMap extensions;
979 extensions.Register<RtpDependencyDescriptorExtension>(
980 kDependencyDescriptorExtensionId);
981 std::vector<RtpPacket> sent_packets;
982 ON_CALL(test.transport(), SendRtp)
983 .WillByDefault([&](const uint8_t* packet, size_t length,
984 const PacketOptions& options) {
985 sent_packets.emplace_back(&extensions);
986 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
987 return true;
988 });
989
990 const uint8_t kPayload[1] = {'a'};
991 EncodedImage encoded_image;
992 encoded_image.SetTimestamp(1);
993 encoded_image.capture_time_ms_ = 2;
994 encoded_image.SetEncodedData(
995 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
996
997 CodecSpecificInfo codec_specific;
998 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
999 codec_specific.template_structure.emplace();
1000 codec_specific.template_structure->num_decode_targets = 1;
1001 codec_specific.template_structure->templates = {
Danil Chapovalov24263f42020-06-11 11:23:451002 FrameDependencyTemplate().T(0).Dtis("S"),
1003 FrameDependencyTemplate().T(0).Dtis("S").FrameDiffs({2}),
1004 FrameDependencyTemplate().T(1).Dtis("D").FrameDiffs({1}),
Danil Chapovalov2272f202020-02-18 11:09:431005 };
1006
1007 // Send two tiny images, mapping to single RTP packets.
1008 // Send in a key frame.
1009 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
1010 codec_specific.generic_frame_info =
1011 GenericFrameInfo::Builder().T(0).Dtis("S").Build();
1012 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
Danil Chapovalov383f2cf2020-08-12 09:06:531013 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 11:09:431014 EncodedImageCallback::Result::OK);
1015 test.AdvanceTime(TimeDelta::Millis(33));
1016 ASSERT_THAT(sent_packets, SizeIs(1));
1017 EXPECT_TRUE(
1018 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
1019
1020 // Send in a new key frame without the support for the dependency descriptor.
1021 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
1022 codec_specific.template_structure = absl::nullopt;
Danil Chapovalov383f2cf2020-08-12 09:06:531023 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 11:09:431024 EncodedImageCallback::Result::OK);
1025 test.AdvanceTime(TimeDelta::Millis(33));
1026 ASSERT_THAT(sent_packets, SizeIs(2));
1027 EXPECT_FALSE(
1028 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
1029}
1030
Jakob Ivarsson9a12ee52020-11-26 15:04:181031TEST(RtpVideoSenderTest, CanSetZeroBitrate) {
Sebastian Janssoncf41eb12019-06-10 09:30:591032 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
Jakob Ivarsson9a12ee52020-11-26 15:04:181033 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(0),
1034 /*framerate*/ 0);
Sebastian Janssoncf41eb12019-06-10 09:30:591035}
Marina Cioceadc69fd22020-04-10 18:19:141036
1037TEST(RtpVideoSenderTest, SimulcastSenderRegistersFrameTransformers) {
Marina Cioceadc69fd22020-04-10 18:19:141038 rtc::scoped_refptr<MockFrameTransformer> transformer =
Tomas Gunnarssonc1d58912021-04-22 17:21:431039 rtc::make_ref_counted<MockFrameTransformer>();
Marina Cioceadc69fd22020-04-10 18:19:141040
1041 EXPECT_CALL(*transformer, RegisterTransformedFrameSinkCallback(_, kSsrc1));
1042 EXPECT_CALL(*transformer, RegisterTransformedFrameSinkCallback(_, kSsrc2));
1043 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
1044 kPayloadType, {}, nullptr, transformer);
1045
1046 EXPECT_CALL(*transformer, UnregisterTransformedFrameSinkCallback(kSsrc1));
1047 EXPECT_CALL(*transformer, UnregisterTransformedFrameSinkCallback(kSsrc2));
1048}
Jakob Ivarsson9a12ee52020-11-26 15:04:181049
1050TEST(RtpVideoSenderTest, OverheadIsSubtractedFromTargetBitrate) {
Jonas Orelandc7f691a2022-03-09 14:12:071051 test::ScopedKeyValueConfig field_trials(
Jakob Ivarsson9a12ee52020-11-26 15:04:181052 "WebRTC-Video-UseFrameRateForOverhead/Enabled/");
1053
1054 // TODO(jakobi): RTP header size should not be hard coded.
1055 constexpr uint32_t kRtpHeaderSizeBytes = 20;
1056 constexpr uint32_t kTransportPacketOverheadBytes = 40;
1057 constexpr uint32_t kOverheadPerPacketBytes =
1058 kRtpHeaderSizeBytes + kTransportPacketOverheadBytes;
Jonas Orelandc7f691a2022-03-09 14:12:071059 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {}, &field_trials);
Jakob Ivarsson9a12ee52020-11-26 15:04:181060 test.router()->OnTransportOverheadChanged(kTransportPacketOverheadBytes);
Per Kjellander59ade012022-12-02 08:09:371061 test.SetActiveModules({true});
Jakob Ivarsson9a12ee52020-11-26 15:04:181062
1063 {
1064 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(300000),
1065 /*framerate*/ 15);
1066 // 1 packet per frame.
1067 EXPECT_EQ(test.router()->GetPayloadBitrateBps(),
1068 300000 - kOverheadPerPacketBytes * 8 * 30);
1069 }
1070 {
1071 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(150000),
1072 /*framerate*/ 15);
1073 // 1 packet per frame.
1074 EXPECT_EQ(test.router()->GetPayloadBitrateBps(),
1075 150000 - kOverheadPerPacketBytes * 8 * 15);
1076 }
1077 {
1078 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(1000000),
1079 /*framerate*/ 30);
1080 // 3 packets per frame.
1081 EXPECT_EQ(test.router()->GetPayloadBitrateBps(),
1082 1000000 - kOverheadPerPacketBytes * 8 * 30 * 3);
1083 }
1084}
1085
Erik Språng1b11b582022-12-09 20:38:441086TEST(RtpVideoSenderTest, ClearsPendingPacketsOnInactivation) {
1087 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
1088 test.SetActiveModules({true});
1089
1090 RtpHeaderExtensionMap extensions;
1091 extensions.Register<RtpDependencyDescriptorExtension>(
1092 kDependencyDescriptorExtensionId);
1093 std::vector<RtpPacket> sent_packets;
1094 ON_CALL(test.transport(), SendRtp)
1095 .WillByDefault([&](const uint8_t* packet, size_t length,
1096 const PacketOptions& options) {
1097 sent_packets.emplace_back(&extensions);
1098 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
1099 return true;
1100 });
1101
1102 // Set a very low bitrate.
1103 test.router()->OnBitrateUpdated(
1104 CreateBitrateAllocationUpdate(/*rate_bps=*/30'000),
1105 /*framerate=*/30);
1106
1107 // Create and send a large keyframe.
1108 const size_t kImageSizeBytes = 10000;
1109 constexpr uint8_t kPayload[kImageSizeBytes] = {'a'};
1110 EncodedImage encoded_image;
1111 encoded_image.SetTimestamp(1);
1112 encoded_image.capture_time_ms_ = 2;
1113 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
1114 encoded_image.SetEncodedData(
1115 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
1116 EXPECT_EQ(test.router()
1117 ->OnEncodedImage(encoded_image, /*codec_specific=*/nullptr)
1118 .error,
1119 EncodedImageCallback::Result::OK);
1120
1121 // Advance time a small amount, check that sent data is only part of the
1122 // image.
1123 test.AdvanceTime(TimeDelta::Millis(5));
1124 DataSize transmittedPayload = DataSize::Zero();
1125 for (const RtpPacket& packet : sent_packets) {
1126 transmittedPayload += DataSize::Bytes(packet.payload_size());
1127 // Make sure we don't see the end of the frame.
1128 EXPECT_FALSE(packet.Marker());
1129 }
1130 EXPECT_GT(transmittedPayload, DataSize::Zero());
1131 EXPECT_LT(transmittedPayload, DataSize::Bytes(kImageSizeBytes / 4));
1132
1133 // Record the RTP timestamp of the first frame.
1134 const uint32_t first_frame_timestamp = sent_packets[0].Timestamp();
1135 sent_packets.clear();
1136
1137 // Disable the sending module and advance time slightly. No packets should be
1138 // sent.
1139 test.SetActiveModules({false});
1140 test.AdvanceTime(TimeDelta::Millis(20));
1141 EXPECT_TRUE(sent_packets.empty());
1142
1143 // Reactive the send module - any packets should have been removed, so nothing
1144 // should be transmitted.
1145 test.SetActiveModules({true});
1146 test.AdvanceTime(TimeDelta::Millis(33));
1147 EXPECT_TRUE(sent_packets.empty());
1148
1149 // Send a new frame.
1150 encoded_image.SetTimestamp(3);
1151 encoded_image.capture_time_ms_ = 4;
1152 EXPECT_EQ(test.router()
1153 ->OnEncodedImage(encoded_image, /*codec_specific=*/nullptr)
1154 .error,
1155 EncodedImageCallback::Result::OK);
1156 test.AdvanceTime(TimeDelta::Millis(33));
1157
1158 // Advance time, check we get new packets - but only for the second frame.
1159 EXPECT_FALSE(sent_packets.empty());
1160 EXPECT_NE(sent_packets[0].Timestamp(), first_frame_timestamp);
1161}
1162
Ying Wang2d598532023-06-01 05:55:361163// Integration test verifying that when retransmission mode is set to
1164// kRetransmitBaseLayer,only base layer is retransmitted.
1165TEST(RtpVideoSenderTest, RetransmitsBaseLayerOnly) {
1166 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
1167 kPayloadType, {});
1168 test.SetActiveModules({true, true});
1169
1170 test.router()->SetRetransmissionMode(kRetransmitBaseLayer);
1171 constexpr uint8_t kPayload = 'a';
1172 EncodedImage encoded_image;
1173 encoded_image.SetTimestamp(1);
1174 encoded_image.capture_time_ms_ = 2;
1175 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
1176 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
1177
1178 // Send two tiny images, mapping to two RTP packets. Capture sequence numbers.
1179 std::vector<uint16_t> rtp_sequence_numbers;
1180 std::vector<uint16_t> transport_sequence_numbers;
1181 std::vector<uint16_t> base_sequence_numbers;
1182 EXPECT_CALL(test.transport(), SendRtp)
1183 .Times(2)
1184 .WillRepeatedly([&rtp_sequence_numbers, &transport_sequence_numbers](
1185 const uint8_t* packet, size_t length,
1186 const PacketOptions& options) {
1187 RtpPacket rtp_packet;
1188 EXPECT_TRUE(rtp_packet.Parse(packet, length));
1189 rtp_sequence_numbers.push_back(rtp_packet.SequenceNumber());
1190 transport_sequence_numbers.push_back(options.packet_id);
1191 return true;
1192 });
1193 CodecSpecificInfo key_codec_info;
1194 key_codec_info.codecType = kVideoCodecVP8;
1195 key_codec_info.codecSpecific.VP8.temporalIdx = 0;
1196 EXPECT_EQ(EncodedImageCallback::Result::OK,
1197 test.router()->OnEncodedImage(
1198 encoded_image, &key_codec_info).error);
1199 encoded_image.SetTimestamp(2);
1200 encoded_image.capture_time_ms_ = 3;
1201 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
1202 CodecSpecificInfo delta_codec_info;
1203 delta_codec_info.codecType = kVideoCodecVP8;
1204 delta_codec_info.codecSpecific.VP8.temporalIdx = 1;
1205 EXPECT_EQ(EncodedImageCallback::Result::OK,
1206 test.router()->OnEncodedImage(
1207 encoded_image, &delta_codec_info).error);
1208
1209 test.AdvanceTime(TimeDelta::Millis(33));
1210
1211 // Construct a NACK message for requesting retransmission of both packet.
1212 rtcp::Nack nack;
1213 nack.SetMediaSsrc(kSsrc1);
1214 nack.SetPacketIds(rtp_sequence_numbers);
1215 rtc::Buffer nack_buffer = nack.Build();
1216
1217 std::vector<uint16_t> retransmitted_rtp_sequence_numbers;
1218 EXPECT_CALL(test.transport(), SendRtp)
1219 .Times(1)
1220 .WillRepeatedly([&retransmitted_rtp_sequence_numbers](
1221 const uint8_t* packet, size_t length,
1222 const PacketOptions& options) {
1223 RtpPacket rtp_packet;
1224 EXPECT_TRUE(rtp_packet.Parse(packet, length));
1225 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
1226 // Capture the retransmitted sequence number from the RTX header.
1227 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
1228 retransmitted_rtp_sequence_numbers.push_back(
1229 ByteReader<uint16_t>::ReadBigEndian(payload.data()));
1230 return true;
1231 });
1232 test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size());
1233 test.AdvanceTime(TimeDelta::Millis(33));
1234
1235 // Verify that only base layer packet was retransmitted.
1236 std::vector<uint16_t> base_rtp_sequence_numbers(rtp_sequence_numbers.begin(),
1237 rtp_sequence_numbers.begin() + 1);
1238 EXPECT_EQ(retransmitted_rtp_sequence_numbers, base_rtp_sequence_numbers);
1239}
1240
mflodman@webrtc.org02270cd2015-02-06 13:10:191241} // namespace webrtc