blob: 25e08368c855df42e18a6e45d24e86a5c342b454 [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>
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +010016
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020017#include "call/rtp_transport_controller_send.h"
Erik Språng490d76c2019-05-07 09:29:15 -070018#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
19#include "modules/rtp_rtcp/source/byte_io.h"
20#include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
Danil Chapovalov2272f202020-02-18 12:09:43 +010021#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h"
Erik Språng490d76c2019-05-07 09:29:15 -070022#include "modules/rtp_rtcp/source/rtp_packet.h"
Stefan Holmer64be7fa2018-10-04 15:21:55 +020023#include "modules/video_coding/fec_controller_default.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "modules/video_coding/include/video_codec_interface.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020025#include "rtc_base/rate_limiter.h"
Åsa Persson4bece9a2017-10-06 10:04:04 +020026#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "test/gmock.h"
28#include "test/gtest.h"
Marina Ciocea1148fd52020-04-29 22:39:13 +020029#include "test/mock_frame_transformer.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020030#include "test/mock_transport.h"
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +010031#include "test/scenario/scenario.h"
Erik Språng00cc8362019-11-25 12:21:46 +010032#include "test/time_controller/simulated_time_controller.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020033#include "video/send_delay_stats.h"
34#include "video/send_statistics_proxy.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000035
36using ::testing::_;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000037using ::testing::NiceMock;
Niels Möller949f0fd2019-01-29 09:44:24 +010038using ::testing::SaveArg;
Danil Chapovalov2272f202020-02-18 12:09:43 +010039using ::testing::SizeIs;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000040
41namespace webrtc {
Åsa Persson4bece9a2017-10-06 10:04:04 +020042namespace {
43const int8_t kPayloadType = 96;
44const uint32_t kSsrc1 = 12345;
45const uint32_t kSsrc2 = 23456;
Erik Språng490d76c2019-05-07 09:29:15 -070046const uint32_t kRtxSsrc1 = 34567;
47const uint32_t kRtxSsrc2 = 45678;
Åsa Persson4bece9a2017-10-06 10:04:04 +020048const int16_t kInitialPictureId1 = 222;
49const int16_t kInitialPictureId2 = 44;
Niels Möllerbb894ff2018-03-15 12:28:53 +010050const int16_t kInitialTl0PicIdx1 = 99;
51const int16_t kInitialTl0PicIdx2 = 199;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020052const int64_t kRetransmitWindowSizeMs = 500;
Erik Språng845c6aa2019-05-29 13:02:24 +020053const int kTransportsSequenceExtensionId = 7;
Danil Chapovalov2272f202020-02-18 12:09:43 +010054const int kDependencyDescriptorExtensionId = 8;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020055
56class MockRtcpIntraFrameObserver : public RtcpIntraFrameObserver {
57 public:
Danil Chapovalov9a5efe92020-05-14 22:06:18 +020058 MOCK_METHOD(void, OnReceivedIntraFrameRequest, (uint32_t), (override));
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020059};
60
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020061RtpSenderObservers CreateObservers(
62 RtcpRttStats* rtcp_rtt_stats,
63 RtcpIntraFrameObserver* intra_frame_callback,
64 RtcpStatisticsCallback* rtcp_stats,
Henrik Boström87e3f9d2019-05-27 10:44:24 +020065 ReportBlockDataObserver* report_block_data_observer,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020066 StreamDataCountersCallback* rtp_stats,
67 BitrateStatisticsObserver* bitrate_observer,
68 FrameCountObserver* frame_count_observer,
69 RtcpPacketTypeCounterObserver* rtcp_type_observer,
70 SendSideDelayObserver* send_delay_observer,
Stefan Holmer64be7fa2018-10-04 15:21:55 +020071 SendPacketObserver* send_packet_observer) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020072 RtpSenderObservers observers;
73 observers.rtcp_rtt_stats = rtcp_rtt_stats;
74 observers.intra_frame_callback = intra_frame_callback;
Erik Språng490d76c2019-05-07 09:29:15 -070075 observers.rtcp_loss_notification_observer = nullptr;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020076 observers.rtcp_stats = rtcp_stats;
Henrik Boström87e3f9d2019-05-27 10:44:24 +020077 observers.report_block_data_observer = report_block_data_observer;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020078 observers.rtp_stats = rtp_stats;
79 observers.bitrate_observer = bitrate_observer;
80 observers.frame_count_observer = frame_count_observer;
81 observers.rtcp_type_observer = rtcp_type_observer;
82 observers.send_delay_observer = send_delay_observer;
83 observers.send_packet_observer = send_packet_observer;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020084 return observers;
85}
86
Erik Språng490d76c2019-05-07 09:29:15 -070087BitrateConstraints GetBitrateConfig() {
88 BitrateConstraints bitrate_config;
89 bitrate_config.min_bitrate_bps = 30000;
90 bitrate_config.start_bitrate_bps = 300000;
91 bitrate_config.max_bitrate_bps = 3000000;
92 return bitrate_config;
93}
94
95VideoSendStream::Config CreateVideoSendStreamConfig(
96 Transport* transport,
97 const std::vector<uint32_t>& ssrcs,
98 const std::vector<uint32_t>& rtx_ssrcs,
99 int payload_type) {
100 VideoSendStream::Config config(transport);
101 config.rtp.ssrcs = ssrcs;
102 config.rtp.rtx.ssrcs = rtx_ssrcs;
103 config.rtp.payload_type = payload_type;
104 config.rtp.rtx.payload_type = payload_type + 1;
105 config.rtp.nack.rtp_history_ms = 1000;
Erik Språng845c6aa2019-05-29 13:02:24 +0200106 config.rtp.extensions.emplace_back(RtpExtension::kTransportSequenceNumberUri,
107 kTransportsSequenceExtensionId);
Danil Chapovalov2272f202020-02-18 12:09:43 +0100108 config.rtp.extensions.emplace_back(RtpDependencyDescriptorExtension::kUri,
109 kDependencyDescriptorExtensionId);
Erik Språng490d76c2019-05-07 09:29:15 -0700110 return config;
111}
112
Stefan Holmer9416ef82018-07-19 10:34:38 +0200113class RtpVideoSenderTestFixture {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200114 public:
Stefan Holmer9416ef82018-07-19 10:34:38 +0200115 RtpVideoSenderTestFixture(
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200116 const std::vector<uint32_t>& ssrcs,
Erik Språng490d76c2019-05-07 09:29:15 -0700117 const std::vector<uint32_t>& rtx_ssrcs,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200118 int payload_type,
Niels Möller949f0fd2019-01-29 09:44:24 +0100119 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
Marina Cioceadc69fd22020-04-10 20:19:14 +0200120 FrameCountObserver* frame_count_observer,
121 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer)
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100122 : time_controller_(Timestamp::Millis(1000000)),
Erik Språng490d76c2019-05-07 09:29:15 -0700123 config_(CreateVideoSendStreamConfig(&transport_,
124 ssrcs,
125 rtx_ssrcs,
126 payload_type)),
Erik Språng00cc8362019-11-25 12:21:46 +0100127 send_delay_stats_(time_controller_.GetClock()),
Erik Språng490d76c2019-05-07 09:29:15 -0700128 bitrate_config_(GetBitrateConfig()),
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100129 transport_controller_(
130 time_controller_.GetClock(),
131 &event_log_,
132 nullptr,
133 nullptr,
134 bitrate_config_,
135 time_controller_.CreateProcessThread("PacerThread"),
136 time_controller_.GetTaskQueueFactory(),
137 &field_trials_),
Erik Språng00cc8362019-11-25 12:21:46 +0100138 stats_proxy_(time_controller_.GetClock(),
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200139 config_,
140 VideoEncoderConfig::ContentType::kRealtimeVideo),
Erik Språng00cc8362019-11-25 12:21:46 +0100141 retransmission_rate_limiter_(time_controller_.GetClock(),
142 kRetransmitWindowSizeMs) {
Erik Språng7703f232020-09-14 11:03:13 +0200143 transport_controller_.EnsureStarted();
Mirko Bonadeif18f9202019-12-10 13:24:56 +0000144 std::map<uint32_t, RtpState> suspended_ssrcs;
145 router_ = std::make_unique<RtpVideoSender>(
146 time_controller_.GetClock(), suspended_ssrcs, suspended_payload_states,
147 config_.rtp, config_.rtcp_report_interval_ms, &transport_,
Niels Möller98d9c302020-12-16 11:53:09 +0100148 CreateObservers(nullptr, &encoder_feedback_, &stats_proxy_,
Mirko Bonadeif18f9202019-12-10 13:24:56 +0000149 &stats_proxy_, &stats_proxy_, &stats_proxy_,
150 frame_count_observer, &stats_proxy_, &stats_proxy_,
151 &send_delay_stats_),
152 &transport_controller_, &event_log_, &retransmission_rate_limiter_,
153 std::make_unique<FecControllerDefault>(time_controller_.GetClock()),
Marina Cioceadc69fd22020-04-10 20:19:14 +0200154 nullptr, CryptoOptions{}, frame_transformer);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200155 }
Marina Cioceadc69fd22020-04-10 20:19:14 +0200156
157 RtpVideoSenderTestFixture(
158 const std::vector<uint32_t>& ssrcs,
159 const std::vector<uint32_t>& rtx_ssrcs,
160 int payload_type,
161 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
162 FrameCountObserver* frame_count_observer)
163 : RtpVideoSenderTestFixture(ssrcs,
164 rtx_ssrcs,
165 payload_type,
166 suspended_payload_states,
167 frame_count_observer,
168 /*frame_transformer=*/nullptr) {}
169
Niels Möller949f0fd2019-01-29 09:44:24 +0100170 RtpVideoSenderTestFixture(
171 const std::vector<uint32_t>& ssrcs,
Erik Språng490d76c2019-05-07 09:29:15 -0700172 const std::vector<uint32_t>& rtx_ssrcs,
Niels Möller949f0fd2019-01-29 09:44:24 +0100173 int payload_type,
174 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states)
175 : RtpVideoSenderTestFixture(ssrcs,
Erik Språng490d76c2019-05-07 09:29:15 -0700176 rtx_ssrcs,
Niels Möller949f0fd2019-01-29 09:44:24 +0100177 payload_type,
178 suspended_payload_states,
Marina Cioceadc69fd22020-04-10 20:19:14 +0200179 /*frame_count_observer=*/nullptr,
180 /*frame_transformer=*/nullptr) {}
Mirko Bonadeif18f9202019-12-10 13:24:56 +0000181
Stefan Holmer9416ef82018-07-19 10:34:38 +0200182 RtpVideoSender* router() { return router_.get(); }
Erik Språng490d76c2019-05-07 09:29:15 -0700183 MockTransport& transport() { return transport_; }
Markus Handell486cc552019-12-03 14:37:28 +0100184 void AdvanceTime(TimeDelta delta) { time_controller_.AdvanceTime(delta); }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200185
186 private:
187 NiceMock<MockTransport> transport_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200188 NiceMock<MockRtcpIntraFrameObserver> encoder_feedback_;
Erik Språng00cc8362019-11-25 12:21:46 +0100189 GlobalSimulatedTimeController time_controller_;
Danil Chapovalov83bbe912019-08-07 12:24:53 +0200190 RtcEventLogNull event_log_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200191 VideoSendStream::Config config_;
192 SendDelayStats send_delay_stats_;
193 BitrateConstraints bitrate_config_;
Erik Språng662678d2019-11-15 17:18:52 +0100194 const FieldTrialBasedConfig field_trials_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200195 RtpTransportControllerSend transport_controller_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200196 SendStatisticsProxy stats_proxy_;
197 RateLimiter retransmission_rate_limiter_;
Stefan Holmer9416ef82018-07-19 10:34:38 +0200198 std::unique_ptr<RtpVideoSender> router_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200199};
Jakob Ivarsson9a12ee52020-11-26 16:04:18 +0100200
201BitrateAllocationUpdate CreateBitrateAllocationUpdate(int target_bitrate_bps) {
202 BitrateAllocationUpdate update;
203 update.target_bitrate = DataRate::BitsPerSec(target_bitrate_bps);
204 update.round_trip_time = TimeDelta::Zero();
205 return update;
206}
207
Åsa Persson4bece9a2017-10-06 10:04:04 +0200208} // namespace
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000209
Sebastian Jansson63470292019-02-01 10:13:43 +0100210TEST(RtpVideoSenderTest, SendOnOneModule) {
Niels Möller663844d2019-02-14 16:15:54 +0100211 constexpr uint8_t kPayload = 'a';
kjellander02b3d272016-04-20 05:05:54 -0700212 EncodedImage encoded_image;
Niels Möller23775882018-08-16 10:24:12 +0200213 encoded_image.SetTimestamp(1);
kjellander02b3d272016-04-20 05:05:54 -0700214 encoded_image.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 15:43:58 +0100215 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200216 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
kjellander02b3d272016-04-20 05:05:54 -0700217
Erik Språng490d76c2019-05-07 09:29:15 -0700218 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200219 EXPECT_NE(EncodedImageCallback::Result::OK,
220 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000221
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200222 test.router()->SetActive(true);
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200223 EXPECT_EQ(EncodedImageCallback::Result::OK,
224 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000225
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200226 test.router()->SetActive(false);
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200227 EXPECT_NE(EncodedImageCallback::Result::OK,
228 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000229
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200230 test.router()->SetActive(true);
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200231 EXPECT_EQ(EncodedImageCallback::Result::OK,
232 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000233}
234
Sebastian Jansson63470292019-02-01 10:13:43 +0100235TEST(RtpVideoSenderTest, SendSimulcastSetActive) {
Niels Möller663844d2019-02-14 16:15:54 +0100236 constexpr uint8_t kPayload = 'a';
Niels Möllerd3b8c632018-08-27 15:33:42 +0200237 EncodedImage encoded_image_1;
238 encoded_image_1.SetTimestamp(1);
239 encoded_image_1.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 15:43:58 +0100240 encoded_image_1._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200241 encoded_image_1.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
kjellander02b3d272016-04-20 05:05:54 -0700242
Erik Språng490d76c2019-05-07 09:29:15 -0700243 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
244 kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000245
Niels Möllerd3b8c632018-08-27 15:33:42 +0200246 CodecSpecificInfo codec_info;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200247 codec_info.codecType = kVideoCodecVP8;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000248
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200249 test.router()->SetActive(true);
sergeyu2cb155a2016-11-04 11:39:29 -0700250 EXPECT_EQ(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200251 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000252
Niels Möllerd3b8c632018-08-27 15:33:42 +0200253 EncodedImage encoded_image_2(encoded_image_1);
254 encoded_image_2.SetSpatialIndex(1);
sergeyu2cb155a2016-11-04 11:39:29 -0700255 EXPECT_EQ(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200256 test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000257
mflodman@webrtc.org50e28162015-02-23 07:45:11 +0000258 // Inactive.
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200259 test.router()->SetActive(false);
sergeyu2cb155a2016-11-04 11:39:29 -0700260 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200261 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
sergeyu2cb155a2016-11-04 11:39:29 -0700262 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200263 test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000264}
265
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800266// Tests how setting individual rtp modules to active affects the overall
267// behavior of the payload router. First sets one module to active and checks
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200268// that outgoing data can be sent on this module, and checks that no data can
269// be sent if both modules are inactive.
Sebastian Jansson63470292019-02-01 10:13:43 +0100270TEST(RtpVideoSenderTest, SendSimulcastSetActiveModules) {
Niels Möller663844d2019-02-14 16:15:54 +0100271 constexpr uint8_t kPayload = 'a';
Niels Möllerd3b8c632018-08-27 15:33:42 +0200272 EncodedImage encoded_image_1;
273 encoded_image_1.SetTimestamp(1);
274 encoded_image_1.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 15:43:58 +0100275 encoded_image_1._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200276 encoded_image_1.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Niels Möller77536a22019-01-15 08:50:01 +0100277
Niels Möllerd3b8c632018-08-27 15:33:42 +0200278 EncodedImage encoded_image_2(encoded_image_1);
279 encoded_image_2.SetSpatialIndex(1);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200280
Erik Språng490d76c2019-05-07 09:29:15 -0700281 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
282 kPayloadType, {});
Niels Möllerd3b8c632018-08-27 15:33:42 +0200283 CodecSpecificInfo codec_info;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200284 codec_info.codecType = kVideoCodecVP8;
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800285
286 // Only setting one stream to active will still set the payload router to
287 // active and allow sending data on the active stream.
288 std::vector<bool> active_modules({true, false});
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200289 test.router()->SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800290 EXPECT_EQ(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200291 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800292
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200293 // Setting both streams to inactive will turn the payload router to
294 // inactive.
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800295 active_modules = {false, false};
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200296 test.router()->SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800297 // An incoming encoded image will not ask the module to send outgoing data
298 // because the payload router is inactive.
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800299 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200300 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800301 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200302 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800303}
304
Sebastian Jansson63470292019-02-01 10:13:43 +0100305TEST(RtpVideoSenderTest, CreateWithNoPreviousStates) {
Erik Språng490d76c2019-05-07 09:29:15 -0700306 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
307 kPayloadType, {});
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200308 test.router()->SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200309
310 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200311 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 10:04:04 +0200312 EXPECT_EQ(2u, initial_states.size());
313 EXPECT_NE(initial_states.find(kSsrc1), initial_states.end());
314 EXPECT_NE(initial_states.find(kSsrc2), initial_states.end());
315}
316
Sebastian Jansson63470292019-02-01 10:13:43 +0100317TEST(RtpVideoSenderTest, CreateWithPreviousStates) {
philipel25d31ec2018-08-08 16:33:01 +0200318 const int64_t kState1SharedFrameId = 123;
319 const int64_t kState2SharedFrameId = 234;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200320 RtpPayloadState state1;
321 state1.picture_id = kInitialPictureId1;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100322 state1.tl0_pic_idx = kInitialTl0PicIdx1;
philipel25d31ec2018-08-08 16:33:01 +0200323 state1.shared_frame_id = kState1SharedFrameId;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200324 RtpPayloadState state2;
325 state2.picture_id = kInitialPictureId2;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100326 state2.tl0_pic_idx = kInitialTl0PicIdx2;
philipel25d31ec2018-08-08 16:33:01 +0200327 state2.shared_frame_id = kState2SharedFrameId;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200328 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
329 {kSsrc2, state2}};
330
Erik Språng490d76c2019-05-07 09:29:15 -0700331 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
332 kPayloadType, states);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200333 test.router()->SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200334
335 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200336 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 10:04:04 +0200337 EXPECT_EQ(2u, initial_states.size());
338 EXPECT_EQ(kInitialPictureId1, initial_states[kSsrc1].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100339 EXPECT_EQ(kInitialTl0PicIdx1, initial_states[kSsrc1].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200340 EXPECT_EQ(kInitialPictureId2, initial_states[kSsrc2].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100341 EXPECT_EQ(kInitialTl0PicIdx2, initial_states[kSsrc2].tl0_pic_idx);
philipel25d31ec2018-08-08 16:33:01 +0200342 EXPECT_EQ(kState2SharedFrameId, initial_states[kSsrc1].shared_frame_id);
343 EXPECT_EQ(kState2SharedFrameId, initial_states[kSsrc2].shared_frame_id);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200344}
Niels Möller949f0fd2019-01-29 09:44:24 +0100345
Sebastian Jansson63470292019-02-01 10:13:43 +0100346TEST(RtpVideoSenderTest, FrameCountCallbacks) {
Niels Möller949f0fd2019-01-29 09:44:24 +0100347 class MockFrameCountObserver : public FrameCountObserver {
348 public:
Danil Chapovalov9a5efe92020-05-14 22:06:18 +0200349 MOCK_METHOD(void,
350 FrameCountUpdated,
351 (const FrameCounts& frame_counts, uint32_t ssrc),
352 (override));
Niels Möller949f0fd2019-01-29 09:44:24 +0100353 } callback;
354
Erik Språng490d76c2019-05-07 09:29:15 -0700355 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {},
356 &callback);
Niels Möller949f0fd2019-01-29 09:44:24 +0100357
Niels Möller663844d2019-02-14 16:15:54 +0100358 constexpr uint8_t kPayload = 'a';
Niels Möller949f0fd2019-01-29 09:44:24 +0100359 EncodedImage encoded_image;
360 encoded_image.SetTimestamp(1);
361 encoded_image.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 15:43:58 +0100362 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200363 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Niels Möller949f0fd2019-01-29 09:44:24 +0100364
Niels Möller8f7ce222019-03-21 15:43:58 +0100365 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller949f0fd2019-01-29 09:44:24 +0100366
367 // No callbacks when not active.
368 EXPECT_CALL(callback, FrameCountUpdated).Times(0);
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200369 EXPECT_NE(EncodedImageCallback::Result::OK,
370 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200371 ::testing::Mock::VerifyAndClearExpectations(&callback);
Niels Möller949f0fd2019-01-29 09:44:24 +0100372
373 test.router()->SetActive(true);
374
375 FrameCounts frame_counts;
376 EXPECT_CALL(callback, FrameCountUpdated(_, kSsrc1))
377 .WillOnce(SaveArg<0>(&frame_counts));
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200378 EXPECT_EQ(EncodedImageCallback::Result::OK,
379 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Niels Möller949f0fd2019-01-29 09:44:24 +0100380
381 EXPECT_EQ(1, frame_counts.key_frames);
382 EXPECT_EQ(0, frame_counts.delta_frames);
383
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200384 ::testing::Mock::VerifyAndClearExpectations(&callback);
Niels Möller949f0fd2019-01-29 09:44:24 +0100385
Niels Möller8f7ce222019-03-21 15:43:58 +0100386 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
Niels Möller949f0fd2019-01-29 09:44:24 +0100387 EXPECT_CALL(callback, FrameCountUpdated(_, kSsrc1))
388 .WillOnce(SaveArg<0>(&frame_counts));
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200389 EXPECT_EQ(EncodedImageCallback::Result::OK,
390 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Niels Möller949f0fd2019-01-29 09:44:24 +0100391
392 EXPECT_EQ(1, frame_counts.key_frames);
393 EXPECT_EQ(1, frame_counts.delta_frames);
394}
395
Erik Språng490d76c2019-05-07 09:29:15 -0700396// Integration test verifying that ack of packet via TransportFeedback means
Erik Språng845c6aa2019-05-29 13:02:24 +0200397// that the packet is removed from RtpPacketHistory and won't be retransmitted
Erik Språng490d76c2019-05-07 09:29:15 -0700398// again.
399TEST(RtpVideoSenderTest, DoesNotRetrasmitAckedPackets) {
Erik Språng490d76c2019-05-07 09:29:15 -0700400 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
401 kPayloadType, {});
402 test.router()->SetActive(true);
403
404 constexpr uint8_t kPayload = 'a';
405 EncodedImage encoded_image;
406 encoded_image.SetTimestamp(1);
407 encoded_image.capture_time_ms_ = 2;
408 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200409 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Erik Språng490d76c2019-05-07 09:29:15 -0700410
411 // Send two tiny images, mapping to two RTP packets. Capture sequence numbers.
Erik Språng490d76c2019-05-07 09:29:15 -0700412 std::vector<uint16_t> rtp_sequence_numbers;
413 std::vector<uint16_t> transport_sequence_numbers;
414 EXPECT_CALL(test.transport(), SendRtp)
415 .Times(2)
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100416 .WillRepeatedly([&rtp_sequence_numbers, &transport_sequence_numbers](
417 const uint8_t* packet, size_t length,
418 const PacketOptions& options) {
419 RtpPacket rtp_packet;
420 EXPECT_TRUE(rtp_packet.Parse(packet, length));
421 rtp_sequence_numbers.push_back(rtp_packet.SequenceNumber());
422 transport_sequence_numbers.push_back(options.packet_id);
423 return true;
424 });
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200425 EXPECT_EQ(EncodedImageCallback::Result::OK,
426 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Erik Språng490d76c2019-05-07 09:29:15 -0700427 encoded_image.SetTimestamp(2);
428 encoded_image.capture_time_ms_ = 3;
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200429 EXPECT_EQ(EncodedImageCallback::Result::OK,
430 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Erik Språngbd7046c2019-05-07 14:54:29 -0700431
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100432 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 09:29:15 -0700433
Erik Språng490d76c2019-05-07 09:29:15 -0700434 // Construct a NACK message for requesting retransmission of both packet.
435 rtcp::Nack nack;
436 nack.SetMediaSsrc(kSsrc1);
437 nack.SetPacketIds(rtp_sequence_numbers);
438 rtc::Buffer nack_buffer = nack.Build();
439
440 std::vector<uint16_t> retransmitted_rtp_sequence_numbers;
441 EXPECT_CALL(test.transport(), SendRtp)
442 .Times(2)
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100443 .WillRepeatedly([&retransmitted_rtp_sequence_numbers](
Erik Språng490d76c2019-05-07 09:29:15 -0700444 const uint8_t* packet, size_t length,
445 const PacketOptions& options) {
446 RtpPacket rtp_packet;
447 EXPECT_TRUE(rtp_packet.Parse(packet, length));
448 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
449 // Capture the retransmitted sequence number from the RTX header.
450 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
451 retransmitted_rtp_sequence_numbers.push_back(
452 ByteReader<uint16_t>::ReadBigEndian(payload.data()));
Erik Språng490d76c2019-05-07 09:29:15 -0700453 return true;
454 });
455 test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size());
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100456 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 09:29:15 -0700457
458 // Verify that both packets were retransmitted.
459 EXPECT_EQ(retransmitted_rtp_sequence_numbers, rtp_sequence_numbers);
460
461 // Simulate transport feedback indicating fist packet received, next packet
Erik Språng00cc8362019-11-25 12:21:46 +0100462 // lost (not other way around as that would trigger early retransmit).
Sebastian Janssonf2988552019-10-29 17:18:51 +0100463 StreamFeedbackObserver::StreamPacketInfo lost_packet_feedback;
Erik Språng00cc8362019-11-25 12:21:46 +0100464 lost_packet_feedback.rtp_sequence_number = rtp_sequence_numbers[0];
Erik Språng490d76c2019-05-07 09:29:15 -0700465 lost_packet_feedback.ssrc = kSsrc1;
Sebastian Janssonf2988552019-10-29 17:18:51 +0100466 lost_packet_feedback.received = false;
Erik Språng490d76c2019-05-07 09:29:15 -0700467
Erik Språng00cc8362019-11-25 12:21:46 +0100468 StreamFeedbackObserver::StreamPacketInfo received_packet_feedback;
469 received_packet_feedback.rtp_sequence_number = rtp_sequence_numbers[1];
470 received_packet_feedback.ssrc = kSsrc1;
471 received_packet_feedback.received = true;
472
Sebastian Janssonf2988552019-10-29 17:18:51 +0100473 test.router()->OnPacketFeedbackVector(
Erik Språng00cc8362019-11-25 12:21:46 +0100474 {lost_packet_feedback, received_packet_feedback});
Erik Språng490d76c2019-05-07 09:29:15 -0700475
476 // Advance time to make sure retransmission would be allowed and try again.
477 // This time the retransmission should not happen for the first packet since
478 // the history has been notified of the ack and removed the packet. The
479 // second packet, included in the feedback but not marked as received, should
480 // still be retransmitted.
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100481 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 09:29:15 -0700482 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100483 .WillOnce([&lost_packet_feedback](const uint8_t* packet, size_t length,
484 const PacketOptions& options) {
Erik Språng490d76c2019-05-07 09:29:15 -0700485 RtpPacket rtp_packet;
486 EXPECT_TRUE(rtp_packet.Parse(packet, length));
487 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
488 // Capture the retransmitted sequence number from the RTX header.
489 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
490 EXPECT_EQ(lost_packet_feedback.rtp_sequence_number,
491 ByteReader<uint16_t>::ReadBigEndian(payload.data()));
Erik Språng490d76c2019-05-07 09:29:15 -0700492 return true;
493 });
494 test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size());
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100495 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 09:29:15 -0700496}
Erik Språng845c6aa2019-05-29 13:02:24 +0200497
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100498// This tests that we utilize transport wide feedback to retransmit lost
499// packets. This is tested by dropping all ordirary packets from a "lossy"
500// stream send along with an secondary untouched stream. The transport wide
501// feedback packets from the secondary stream allows the sending side to
502// detect and retreansmit the lost packets from the lossy stream.
503TEST(RtpVideoSenderTest, RetransmitsOnTransportWideLossInfo) {
504 int rtx_packets;
505 test::Scenario s(test_info_);
506 test::CallClientConfig call_conf;
507 // Keeping the bitrate fixed to avoid RTX due to probing.
Danil Chapovalovcad3e0e2020-02-17 18:46:07 +0100508 call_conf.transport.rates.max_rate = DataRate::KilobitsPerSec(300);
509 call_conf.transport.rates.start_rate = DataRate::KilobitsPerSec(300);
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100510 test::NetworkSimulationConfig net_conf;
Danil Chapovalovcad3e0e2020-02-17 18:46:07 +0100511 net_conf.bandwidth = DataRate::KilobitsPerSec(300);
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100512 auto send_node = s.CreateSimulationNode(net_conf);
Tommi3c9bcc12020-04-15 16:45:47 +0200513 auto* callee = s.CreateClient("return", call_conf);
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100514 auto* route = s.CreateRoutes(s.CreateClient("send", call_conf), {send_node},
Tommi3c9bcc12020-04-15 16:45:47 +0200515 callee, {s.CreateSimulationNode(net_conf)});
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100516
517 test::VideoStreamConfig lossy_config;
518 lossy_config.source.framerate = 5;
519 auto* lossy = s.CreateVideoStream(route->forward(), lossy_config);
520 // The secondary stream acts a driver for transport feedback messages,
521 // ensuring that lost packets on the lossy stream are retransmitted.
522 s.CreateVideoStream(route->forward(), test::VideoStreamConfig());
523
524 send_node->router()->SetFilter([&](const EmulatedIpPacket& packet) {
525 RtpPacket rtp;
526 if (rtp.Parse(packet.data)) {
527 // Drops all regular packets for the lossy stream and counts all RTX
528 // packets. Since no packets are let trough, NACKs can't be triggered
529 // by the receiving side.
530 if (lossy->send()->UsingSsrc(rtp.Ssrc())) {
531 return false;
532 } else if (lossy->send()->UsingRtxSsrc(rtp.Ssrc())) {
533 ++rtx_packets;
534 }
535 }
536 return true;
537 });
538
539 // Run for a short duration and reset counters to avoid counting RTX packets
540 // from initial probing.
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100541 s.RunFor(TimeDelta::Seconds(1));
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100542 rtx_packets = 0;
Tommi3c9bcc12020-04-15 16:45:47 +0200543 int decoded_baseline = 0;
544 callee->SendTask([&decoded_baseline, &lossy]() {
545 decoded_baseline = lossy->receive()->GetStats().frames_decoded;
546 });
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100547 s.RunFor(TimeDelta::Seconds(1));
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100548 // We expect both that RTX packets were sent and that an appropriate number of
549 // frames were received. This is somewhat redundant but reduces the risk of
550 // false positives in future regressions (e.g. RTX is send due to probing).
551 EXPECT_GE(rtx_packets, 1);
Tommi3c9bcc12020-04-15 16:45:47 +0200552 int frames_decoded = 0;
553 callee->SendTask([&decoded_baseline, &frames_decoded, &lossy]() {
554 frames_decoded =
555 lossy->receive()->GetStats().frames_decoded - decoded_baseline;
556 });
Sebastian Jansson3d4d94a2020-01-14 14:25:41 +0100557 EXPECT_EQ(frames_decoded, 5);
558}
559
Erik Språng845c6aa2019-05-29 13:02:24 +0200560// Integration test verifying that retransmissions are sent for packets which
561// can be detected as lost early, using transport wide feedback.
562TEST(RtpVideoSenderTest, EarlyRetransmits) {
Erik Språng845c6aa2019-05-29 13:02:24 +0200563 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
564 kPayloadType, {});
565 test.router()->SetActive(true);
566
Niels Möllerb9bfe652019-10-03 08:43:53 +0200567 const uint8_t kPayload[1] = {'a'};
Erik Språng845c6aa2019-05-29 13:02:24 +0200568 EncodedImage encoded_image;
569 encoded_image.SetTimestamp(1);
570 encoded_image.capture_time_ms_ = 2;
571 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möllerb9bfe652019-10-03 08:43:53 +0200572 encoded_image.SetEncodedData(
573 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
Erik Språng845c6aa2019-05-29 13:02:24 +0200574 encoded_image.SetSpatialIndex(0);
575
576 CodecSpecificInfo codec_specific;
577 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
578
579 // Send two tiny images, mapping to single RTP packets. Capture sequence
580 // numbers.
Erik Språng845c6aa2019-05-29 13:02:24 +0200581 uint16_t frame1_rtp_sequence_number = 0;
582 uint16_t frame1_transport_sequence_number = 0;
583 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100584 .WillOnce(
585 [&frame1_rtp_sequence_number, &frame1_transport_sequence_number](
586 const uint8_t* packet, size_t length,
587 const PacketOptions& options) {
588 RtpPacket rtp_packet;
589 EXPECT_TRUE(rtp_packet.Parse(packet, length));
590 frame1_rtp_sequence_number = rtp_packet.SequenceNumber();
591 frame1_transport_sequence_number = options.packet_id;
592 EXPECT_EQ(rtp_packet.Ssrc(), kSsrc1);
593 return true;
594 });
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200595 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Erik Språng845c6aa2019-05-29 13:02:24 +0200596 EncodedImageCallback::Result::OK);
Erik Språng845c6aa2019-05-29 13:02:24 +0200597
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100598 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng845c6aa2019-05-29 13:02:24 +0200599
600 uint16_t frame2_rtp_sequence_number = 0;
601 uint16_t frame2_transport_sequence_number = 0;
602 encoded_image.SetSpatialIndex(1);
603 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100604 .WillOnce(
605 [&frame2_rtp_sequence_number, &frame2_transport_sequence_number](
606 const uint8_t* packet, size_t length,
607 const PacketOptions& options) {
608 RtpPacket rtp_packet;
609 EXPECT_TRUE(rtp_packet.Parse(packet, length));
610 frame2_rtp_sequence_number = rtp_packet.SequenceNumber();
611 frame2_transport_sequence_number = options.packet_id;
612 EXPECT_EQ(rtp_packet.Ssrc(), kSsrc2);
613 return true;
614 });
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200615 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Erik Språng845c6aa2019-05-29 13:02:24 +0200616 EncodedImageCallback::Result::OK);
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100617 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng845c6aa2019-05-29 13:02:24 +0200618
619 EXPECT_NE(frame1_transport_sequence_number, frame2_transport_sequence_number);
620
621 // Inject a transport feedback where the packet for the first frame is lost,
622 // expect a retransmission for it.
623 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 16:13:14 +0100624 .WillOnce([&frame1_rtp_sequence_number](const uint8_t* packet,
625 size_t length,
626 const PacketOptions& options) {
Erik Språng845c6aa2019-05-29 13:02:24 +0200627 RtpPacket rtp_packet;
628 EXPECT_TRUE(rtp_packet.Parse(packet, length));
Sebastian Janssonf2988552019-10-29 17:18:51 +0100629 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
Erik Språng845c6aa2019-05-29 13:02:24 +0200630
631 // Retransmitted sequence number from the RTX header should match
632 // the lost packet.
633 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
634 EXPECT_EQ(ByteReader<uint16_t>::ReadBigEndian(payload.data()),
635 frame1_rtp_sequence_number);
Erik Språng845c6aa2019-05-29 13:02:24 +0200636 return true;
637 });
638
Sebastian Janssonf2988552019-10-29 17:18:51 +0100639 StreamFeedbackObserver::StreamPacketInfo first_packet_feedback;
Erik Språng845c6aa2019-05-29 13:02:24 +0200640 first_packet_feedback.rtp_sequence_number = frame1_rtp_sequence_number;
641 first_packet_feedback.ssrc = kSsrc1;
Sebastian Janssonf2988552019-10-29 17:18:51 +0100642 first_packet_feedback.received = false;
Erik Språng845c6aa2019-05-29 13:02:24 +0200643
Sebastian Janssonf2988552019-10-29 17:18:51 +0100644 StreamFeedbackObserver::StreamPacketInfo second_packet_feedback;
645 second_packet_feedback.rtp_sequence_number = frame2_rtp_sequence_number;
646 second_packet_feedback.ssrc = kSsrc2;
647 second_packet_feedback.received = true;
Erik Språng845c6aa2019-05-29 13:02:24 +0200648
Sebastian Janssonf2988552019-10-29 17:18:51 +0100649 test.router()->OnPacketFeedbackVector(
650 {first_packet_feedback, second_packet_feedback});
Erik Språng845c6aa2019-05-29 13:02:24 +0200651
652 // Wait for pacer to run and send the RTX packet.
Danil Chapovalov0c626af2020-02-10 11:16:00 +0100653 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng845c6aa2019-05-29 13:02:24 +0200654}
Sebastian Janssoncf41eb12019-06-10 11:30:59 +0200655
Danil Chapovalov2272f202020-02-18 12:09:43 +0100656TEST(RtpVideoSenderTest, SupportsDependencyDescriptor) {
Danil Chapovalov2272f202020-02-18 12:09:43 +0100657 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
658 test.router()->SetActive(true);
659
660 RtpHeaderExtensionMap extensions;
661 extensions.Register<RtpDependencyDescriptorExtension>(
662 kDependencyDescriptorExtensionId);
663 std::vector<RtpPacket> sent_packets;
664 ON_CALL(test.transport(), SendRtp)
665 .WillByDefault([&](const uint8_t* packet, size_t length,
666 const PacketOptions& options) {
667 sent_packets.emplace_back(&extensions);
668 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
669 return true;
670 });
671
672 const uint8_t kPayload[1] = {'a'};
673 EncodedImage encoded_image;
674 encoded_image.SetTimestamp(1);
675 encoded_image.capture_time_ms_ = 2;
676 encoded_image.SetEncodedData(
677 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
678
679 CodecSpecificInfo codec_specific;
680 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
681 codec_specific.template_structure.emplace();
682 codec_specific.template_structure->num_decode_targets = 1;
683 codec_specific.template_structure->templates = {
Danil Chapovalov24263f42020-06-11 13:23:45 +0200684 FrameDependencyTemplate().T(0).Dtis("S"),
685 FrameDependencyTemplate().T(0).Dtis("S").FrameDiffs({2}),
686 FrameDependencyTemplate().T(1).Dtis("D").FrameDiffs({1}),
Danil Chapovalov2272f202020-02-18 12:09:43 +0100687 };
688
689 // Send two tiny images, mapping to single RTP packets.
690 // Send in key frame.
691 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
692 codec_specific.generic_frame_info =
693 GenericFrameInfo::Builder().T(0).Dtis("S").Build();
694 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200695 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 12:09:43 +0100696 EncodedImageCallback::Result::OK);
697 test.AdvanceTime(TimeDelta::Millis(33));
698 ASSERT_THAT(sent_packets, SizeIs(1));
699 EXPECT_TRUE(
700 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
701
702 // Send in delta frame.
703 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
704 codec_specific.template_structure = absl::nullopt;
705 codec_specific.generic_frame_info =
706 GenericFrameInfo::Builder().T(1).Dtis("D").Build();
707 codec_specific.generic_frame_info->encoder_buffers = {{0, true, false}};
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200708 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 12:09:43 +0100709 EncodedImageCallback::Result::OK);
710 test.AdvanceTime(TimeDelta::Millis(33));
711 ASSERT_THAT(sent_packets, SizeIs(2));
712 EXPECT_TRUE(
713 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
714}
715
Danil Chapovalov0be18462021-01-20 12:11:29 +0100716TEST(RtpVideoSenderTest, SupportsDependencyDescriptorForVp9) {
717 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
718 test.router()->SetActive(true);
719
720 RtpHeaderExtensionMap extensions;
721 extensions.Register<RtpDependencyDescriptorExtension>(
722 kDependencyDescriptorExtensionId);
723 std::vector<RtpPacket> sent_packets;
724 ON_CALL(test.transport(), SendRtp)
725 .WillByDefault([&](const uint8_t* packet, size_t length,
726 const PacketOptions& options) {
727 sent_packets.emplace_back(&extensions);
728 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
729 return true;
730 });
731
732 const uint8_t kPayload[1] = {'a'};
733 EncodedImage encoded_image;
734 encoded_image.SetTimestamp(1);
735 encoded_image.capture_time_ms_ = 2;
736 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
737 encoded_image.SetEncodedData(
738 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
739
740 CodecSpecificInfo codec_specific;
741 codec_specific.codecType = VideoCodecType::kVideoCodecVP9;
742 codec_specific.template_structure.emplace();
743 codec_specific.template_structure->num_decode_targets = 2;
744 codec_specific.template_structure->templates = {
745 FrameDependencyTemplate().S(0).Dtis("SS"),
746 FrameDependencyTemplate().S(1).Dtis("-S").FrameDiffs({1}),
747 };
748
749 // Send two tiny images, each mapping to single RTP packet.
750 // Send in key frame for the base spatial layer.
751 codec_specific.generic_frame_info =
752 GenericFrameInfo::Builder().S(0).Dtis("SS").Build();
753 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
754 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
755 EncodedImageCallback::Result::OK);
756 // Send in 2nd spatial layer.
757 codec_specific.template_structure = absl::nullopt;
758 codec_specific.generic_frame_info =
759 GenericFrameInfo::Builder().S(1).Dtis("-S").Build();
760 codec_specific.generic_frame_info->encoder_buffers = {{0, true, false},
761 {1, false, true}};
762 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
763 EncodedImageCallback::Result::OK);
764
765 test.AdvanceTime(TimeDelta::Millis(33));
766 ASSERT_THAT(sent_packets, SizeIs(2));
767 EXPECT_TRUE(sent_packets[0].HasExtension<RtpDependencyDescriptorExtension>());
768 EXPECT_TRUE(sent_packets[1].HasExtension<RtpDependencyDescriptorExtension>());
769}
770
Danil Chapovalov2272f202020-02-18 12:09:43 +0100771TEST(RtpVideoSenderTest, SupportsStoppingUsingDependencyDescriptor) {
Danil Chapovalov2272f202020-02-18 12:09:43 +0100772 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
773 test.router()->SetActive(true);
774
775 RtpHeaderExtensionMap extensions;
776 extensions.Register<RtpDependencyDescriptorExtension>(
777 kDependencyDescriptorExtensionId);
778 std::vector<RtpPacket> sent_packets;
779 ON_CALL(test.transport(), SendRtp)
780 .WillByDefault([&](const uint8_t* packet, size_t length,
781 const PacketOptions& options) {
782 sent_packets.emplace_back(&extensions);
783 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
784 return true;
785 });
786
787 const uint8_t kPayload[1] = {'a'};
788 EncodedImage encoded_image;
789 encoded_image.SetTimestamp(1);
790 encoded_image.capture_time_ms_ = 2;
791 encoded_image.SetEncodedData(
792 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
793
794 CodecSpecificInfo codec_specific;
795 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
796 codec_specific.template_structure.emplace();
797 codec_specific.template_structure->num_decode_targets = 1;
798 codec_specific.template_structure->templates = {
Danil Chapovalov24263f42020-06-11 13:23:45 +0200799 FrameDependencyTemplate().T(0).Dtis("S"),
800 FrameDependencyTemplate().T(0).Dtis("S").FrameDiffs({2}),
801 FrameDependencyTemplate().T(1).Dtis("D").FrameDiffs({1}),
Danil Chapovalov2272f202020-02-18 12:09:43 +0100802 };
803
804 // Send two tiny images, mapping to single RTP packets.
805 // Send in a key frame.
806 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
807 codec_specific.generic_frame_info =
808 GenericFrameInfo::Builder().T(0).Dtis("S").Build();
809 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200810 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 12:09:43 +0100811 EncodedImageCallback::Result::OK);
812 test.AdvanceTime(TimeDelta::Millis(33));
813 ASSERT_THAT(sent_packets, SizeIs(1));
814 EXPECT_TRUE(
815 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
816
817 // Send in a new key frame without the support for the dependency descriptor.
818 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
819 codec_specific.template_structure = absl::nullopt;
Danil Chapovalov383f2cf2020-08-12 11:06:53 +0200820 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 12:09:43 +0100821 EncodedImageCallback::Result::OK);
822 test.AdvanceTime(TimeDelta::Millis(33));
823 ASSERT_THAT(sent_packets, SizeIs(2));
824 EXPECT_FALSE(
825 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
826}
827
Danil Chapovalov37dfddd2021-01-27 19:24:23 +0100828TEST(RtpVideoSenderTest,
829 SupportsStoppingUsingDependencyDescriptorForVp8Simulcast) {
830 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {}, kPayloadType, {});
831 test.router()->SetActive(true);
832
833 RtpHeaderExtensionMap extensions;
834 extensions.Register<RtpDependencyDescriptorExtension>(
835 kDependencyDescriptorExtensionId);
836 std::vector<RtpPacket> sent_packets;
837 ON_CALL(test.transport(), SendRtp)
838 .WillByDefault([&](const uint8_t* packet, size_t length,
839 const PacketOptions& options) {
840 sent_packets.emplace_back(&extensions);
841 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
842 return true;
843 });
844
845 const uint8_t kPayload[1] = {'a'};
846 EncodedImage encoded_image;
847 encoded_image.SetTimestamp(1);
848 encoded_image.capture_time_ms_ = 2;
849 encoded_image.SetEncodedData(
850 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
851 // VP8 simulcast uses spatial index to communicate simulcast stream.
852 encoded_image.SetSpatialIndex(1);
853
854 CodecSpecificInfo codec_specific;
855 codec_specific.codecType = VideoCodecType::kVideoCodecVP8;
856 codec_specific.template_structure.emplace();
857 codec_specific.template_structure->num_decode_targets = 1;
858 codec_specific.template_structure->templates = {
859 FrameDependencyTemplate().T(0).Dtis("S")};
860
861 // Send two tiny images, mapping to single RTP packets.
862 // Send in a key frame.
863 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
864 codec_specific.generic_frame_info =
865 GenericFrameInfo::Builder().T(0).Dtis("S").Build();
866 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
867 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
868 EncodedImageCallback::Result::OK);
869 test.AdvanceTime(TimeDelta::Millis(33));
870 ASSERT_THAT(sent_packets, SizeIs(1));
871 EXPECT_TRUE(
872 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
873
874 // Send in a new key frame without the support for the dependency descriptor.
875 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
876 codec_specific.template_structure = absl::nullopt;
877 codec_specific.generic_frame_info = absl::nullopt;
878 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
879 EncodedImageCallback::Result::OK);
880 test.AdvanceTime(TimeDelta::Millis(33));
881 ASSERT_THAT(sent_packets, SizeIs(2));
882 EXPECT_FALSE(
883 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
884}
885
Jakob Ivarsson9a12ee52020-11-26 16:04:18 +0100886TEST(RtpVideoSenderTest, CanSetZeroBitrate) {
Sebastian Janssoncf41eb12019-06-10 11:30:59 +0200887 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
Jakob Ivarsson9a12ee52020-11-26 16:04:18 +0100888 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(0),
889 /*framerate*/ 0);
Sebastian Janssoncf41eb12019-06-10 11:30:59 +0200890}
Marina Cioceadc69fd22020-04-10 20:19:14 +0200891
892TEST(RtpVideoSenderTest, SimulcastSenderRegistersFrameTransformers) {
Marina Cioceadc69fd22020-04-10 20:19:14 +0200893 rtc::scoped_refptr<MockFrameTransformer> transformer =
894 new rtc::RefCountedObject<MockFrameTransformer>();
895
896 EXPECT_CALL(*transformer, RegisterTransformedFrameSinkCallback(_, kSsrc1));
897 EXPECT_CALL(*transformer, RegisterTransformedFrameSinkCallback(_, kSsrc2));
898 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
899 kPayloadType, {}, nullptr, transformer);
900
901 EXPECT_CALL(*transformer, UnregisterTransformedFrameSinkCallback(kSsrc1));
902 EXPECT_CALL(*transformer, UnregisterTransformedFrameSinkCallback(kSsrc2));
903}
Jakob Ivarsson9a12ee52020-11-26 16:04:18 +0100904
905TEST(RtpVideoSenderTest, OverheadIsSubtractedFromTargetBitrate) {
906 test::ScopedFieldTrials field_trials(
907 "WebRTC-Video-UseFrameRateForOverhead/Enabled/");
908
909 // TODO(jakobi): RTP header size should not be hard coded.
910 constexpr uint32_t kRtpHeaderSizeBytes = 20;
911 constexpr uint32_t kTransportPacketOverheadBytes = 40;
912 constexpr uint32_t kOverheadPerPacketBytes =
913 kRtpHeaderSizeBytes + kTransportPacketOverheadBytes;
914 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
915 test.router()->OnTransportOverheadChanged(kTransportPacketOverheadBytes);
916 test.router()->SetActive(true);
917
918 {
919 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(300000),
920 /*framerate*/ 15);
921 // 1 packet per frame.
922 EXPECT_EQ(test.router()->GetPayloadBitrateBps(),
923 300000 - kOverheadPerPacketBytes * 8 * 30);
924 }
925 {
926 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(150000),
927 /*framerate*/ 15);
928 // 1 packet per frame.
929 EXPECT_EQ(test.router()->GetPayloadBitrateBps(),
930 150000 - kOverheadPerPacketBytes * 8 * 15);
931 }
932 {
933 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(1000000),
934 /*framerate*/ 30);
935 // 3 packets per frame.
936 EXPECT_EQ(test.router()->GetPayloadBitrateBps(),
937 1000000 - kOverheadPerPacketBytes * 8 * 30 * 3);
938 }
939}
940
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000941} // namespace webrtc