blob: 0644556e2f2d4312e85dff7c23324a3fbda5a3d1 [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>
Sebastian Jansson3d4d94a2020-01-14 13:25:4116
Stefan Holmerdbdb3a02018-07-17 14:03:4617#include "call/rtp_transport_controller_send.h"
Erik Språng490d76c2019-05-07 16:29:1518#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 11:09:4321#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h"
Erik Språng490d76c2019-05-07 16:29:1522#include "modules/rtp_rtcp/source/rtp_packet.h"
Stefan Holmer64be7fa2018-10-04 13:21:5523#include "modules/video_coding/fec_controller_default.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3124#include "modules/video_coding/include/video_codec_interface.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4625#include "rtc_base/rate_limiter.h"
Åsa Persson4bece9a2017-10-06 08:04:0426#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3127#include "test/gmock.h"
28#include "test/gtest.h"
Marina Ciocea1148fd52020-04-29 20:39:1329#include "test/mock_frame_transformer.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4630#include "test/mock_transport.h"
Sebastian Jansson3d4d94a2020-01-14 13:25:4131#include "test/scenario/scenario.h"
Erik Språng00cc8362019-11-25 11:21:4632#include "test/time_controller/simulated_time_controller.h"
Stefan Holmerdbdb3a02018-07-17 14:03:4633#include "video/send_delay_stats.h"
34#include "video/send_statistics_proxy.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:1935
36using ::testing::_;
mflodman@webrtc.org02270cd2015-02-06 13:10:1937using ::testing::NiceMock;
Niels Möller949f0fd2019-01-29 08:44:2438using ::testing::SaveArg;
Danil Chapovalov2272f202020-02-18 11:09:4339using ::testing::SizeIs;
mflodman@webrtc.org02270cd2015-02-06 13:10:1940
41namespace webrtc {
Åsa Persson4bece9a2017-10-06 08:04:0442namespace {
43const int8_t kPayloadType = 96;
44const uint32_t kSsrc1 = 12345;
45const uint32_t kSsrc2 = 23456;
Erik Språng490d76c2019-05-07 16:29:1546const uint32_t kRtxSsrc1 = 34567;
47const uint32_t kRtxSsrc2 = 45678;
Åsa Persson4bece9a2017-10-06 08:04:0448const int16_t kInitialPictureId1 = 222;
49const int16_t kInitialPictureId2 = 44;
Niels Möllerbb894ff2018-03-15 11:28:5350const int16_t kInitialTl0PicIdx1 = 99;
51const int16_t kInitialTl0PicIdx2 = 199;
Stefan Holmerdbdb3a02018-07-17 14:03:4652const int64_t kRetransmitWindowSizeMs = 500;
Erik Språng845c6aa2019-05-29 11:02:2453const int kTransportsSequenceExtensionId = 7;
Danil Chapovalov2272f202020-02-18 11:09:4354const int kDependencyDescriptorExtensionId = 8;
Stefan Holmerdbdb3a02018-07-17 14:03:4655
56class MockRtcpIntraFrameObserver : public RtcpIntraFrameObserver {
57 public:
Danil Chapovalov9a5efe92020-05-14 20:06:1858 MOCK_METHOD(void, OnReceivedIntraFrameRequest, (uint32_t), (override));
Stefan Holmerdbdb3a02018-07-17 14:03:4659};
60
Stefan Holmerdbdb3a02018-07-17 14:03:4661RtpSenderObservers CreateObservers(
62 RtcpRttStats* rtcp_rtt_stats,
63 RtcpIntraFrameObserver* intra_frame_callback,
Henrik Boström87e3f9d2019-05-27 08:44:2464 ReportBlockDataObserver* report_block_data_observer,
Stefan Holmerdbdb3a02018-07-17 14:03:4665 StreamDataCountersCallback* rtp_stats,
66 BitrateStatisticsObserver* bitrate_observer,
67 FrameCountObserver* frame_count_observer,
68 RtcpPacketTypeCounterObserver* rtcp_type_observer,
69 SendSideDelayObserver* send_delay_observer,
Stefan Holmer64be7fa2018-10-04 13:21:5570 SendPacketObserver* send_packet_observer) {
Stefan Holmerdbdb3a02018-07-17 14:03:4671 RtpSenderObservers observers;
72 observers.rtcp_rtt_stats = rtcp_rtt_stats;
73 observers.intra_frame_callback = intra_frame_callback;
Erik Språng490d76c2019-05-07 16:29:1574 observers.rtcp_loss_notification_observer = nullptr;
Henrik Boström87e3f9d2019-05-27 08:44:2475 observers.report_block_data_observer = report_block_data_observer;
Stefan Holmerdbdb3a02018-07-17 14:03:4676 observers.rtp_stats = rtp_stats;
77 observers.bitrate_observer = bitrate_observer;
78 observers.frame_count_observer = frame_count_observer;
79 observers.rtcp_type_observer = rtcp_type_observer;
80 observers.send_delay_observer = send_delay_observer;
81 observers.send_packet_observer = send_packet_observer;
Stefan Holmerdbdb3a02018-07-17 14:03:4682 return observers;
83}
84
Erik Språng490d76c2019-05-07 16:29:1585BitrateConstraints GetBitrateConfig() {
86 BitrateConstraints bitrate_config;
87 bitrate_config.min_bitrate_bps = 30000;
88 bitrate_config.start_bitrate_bps = 300000;
89 bitrate_config.max_bitrate_bps = 3000000;
90 return bitrate_config;
91}
92
93VideoSendStream::Config CreateVideoSendStreamConfig(
94 Transport* transport,
95 const std::vector<uint32_t>& ssrcs,
96 const std::vector<uint32_t>& rtx_ssrcs,
97 int payload_type) {
98 VideoSendStream::Config config(transport);
99 config.rtp.ssrcs = ssrcs;
100 config.rtp.rtx.ssrcs = rtx_ssrcs;
101 config.rtp.payload_type = payload_type;
102 config.rtp.rtx.payload_type = payload_type + 1;
103 config.rtp.nack.rtp_history_ms = 1000;
Erik Språng845c6aa2019-05-29 11:02:24104 config.rtp.extensions.emplace_back(RtpExtension::kTransportSequenceNumberUri,
105 kTransportsSequenceExtensionId);
Danil Chapovalovd0321c52021-09-14 10:58:51106 config.rtp.extensions.emplace_back(RtpDependencyDescriptorExtension::Uri(),
Danil Chapovalov2272f202020-02-18 11:09:43107 kDependencyDescriptorExtensionId);
Danil Chapovalov748550d2021-04-29 09:42:54108 config.rtp.extmap_allow_mixed = true;
Erik Språng490d76c2019-05-07 16:29:15109 return config;
110}
111
Stefan Holmer9416ef82018-07-19 08:34:38112class RtpVideoSenderTestFixture {
Stefan Holmerdbdb3a02018-07-17 14:03:46113 public:
Stefan Holmer9416ef82018-07-19 08:34:38114 RtpVideoSenderTestFixture(
Stefan Holmerdbdb3a02018-07-17 14:03:46115 const std::vector<uint32_t>& ssrcs,
Erik Språng490d76c2019-05-07 16:29:15116 const std::vector<uint32_t>& rtx_ssrcs,
Stefan Holmerdbdb3a02018-07-17 14:03:46117 int payload_type,
Niels Möller949f0fd2019-01-29 08:44:24118 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
Marina Cioceadc69fd22020-04-10 18:19:14119 FrameCountObserver* frame_count_observer,
120 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer)
Danil Chapovalov0c626af2020-02-10 10:16:00121 : time_controller_(Timestamp::Millis(1000000)),
Erik Språng490d76c2019-05-07 16:29:15122 config_(CreateVideoSendStreamConfig(&transport_,
123 ssrcs,
124 rtx_ssrcs,
125 payload_type)),
Erik Språng00cc8362019-11-25 11:21:46126 send_delay_stats_(time_controller_.GetClock()),
Erik Språng490d76c2019-05-07 16:29:15127 bitrate_config_(GetBitrateConfig()),
Danil Chapovalova68eb8c2020-02-17 15:13:14128 transport_controller_(
129 time_controller_.GetClock(),
130 &event_log_,
131 nullptr,
132 nullptr,
133 bitrate_config_,
134 time_controller_.CreateProcessThread("PacerThread"),
135 time_controller_.GetTaskQueueFactory(),
136 &field_trials_),
Erik Språng00cc8362019-11-25 11:21:46137 stats_proxy_(time_controller_.GetClock(),
Stefan Holmerdbdb3a02018-07-17 14:03:46138 config_,
139 VideoEncoderConfig::ContentType::kRealtimeVideo),
Erik Språng00cc8362019-11-25 11:21:46140 retransmission_rate_limiter_(time_controller_.GetClock(),
141 kRetransmitWindowSizeMs) {
Erik Språng7703f232020-09-14 09:03:13142 transport_controller_.EnsureStarted();
Mirko Bonadeif18f9202019-12-10 13:24:56143 std::map<uint32_t, RtpState> suspended_ssrcs;
144 router_ = std::make_unique<RtpVideoSender>(
145 time_controller_.GetClock(), suspended_ssrcs, suspended_payload_states,
146 config_.rtp, config_.rtcp_report_interval_ms, &transport_,
Niels Möller98d9c302020-12-16 10:53:09147 CreateObservers(nullptr, &encoder_feedback_, &stats_proxy_,
Danil Chapovalovf01c2c92021-05-14 13:39:23148 &stats_proxy_, &stats_proxy_, frame_count_observer,
149 &stats_proxy_, &stats_proxy_, &send_delay_stats_),
Mirko Bonadeif18f9202019-12-10 13:24:56150 &transport_controller_, &event_log_, &retransmission_rate_limiter_,
151 std::make_unique<FecControllerDefault>(time_controller_.GetClock()),
Marina Cioceadc69fd22020-04-10 18:19:14152 nullptr, CryptoOptions{}, frame_transformer);
Stefan Holmerdbdb3a02018-07-17 14:03:46153 }
Marina Cioceadc69fd22020-04-10 18:19:14154
155 RtpVideoSenderTestFixture(
156 const std::vector<uint32_t>& ssrcs,
157 const std::vector<uint32_t>& rtx_ssrcs,
158 int payload_type,
159 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
160 FrameCountObserver* frame_count_observer)
161 : RtpVideoSenderTestFixture(ssrcs,
162 rtx_ssrcs,
163 payload_type,
164 suspended_payload_states,
165 frame_count_observer,
166 /*frame_transformer=*/nullptr) {}
167
Niels Möller949f0fd2019-01-29 08:44:24168 RtpVideoSenderTestFixture(
169 const std::vector<uint32_t>& ssrcs,
Erik Språng490d76c2019-05-07 16:29:15170 const std::vector<uint32_t>& rtx_ssrcs,
Niels Möller949f0fd2019-01-29 08:44:24171 int payload_type,
172 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states)
173 : RtpVideoSenderTestFixture(ssrcs,
Erik Språng490d76c2019-05-07 16:29:15174 rtx_ssrcs,
Niels Möller949f0fd2019-01-29 08:44:24175 payload_type,
176 suspended_payload_states,
Marina Cioceadc69fd22020-04-10 18:19:14177 /*frame_count_observer=*/nullptr,
178 /*frame_transformer=*/nullptr) {}
Mirko Bonadeif18f9202019-12-10 13:24:56179
Stefan Holmer9416ef82018-07-19 08:34:38180 RtpVideoSender* router() { return router_.get(); }
Erik Språng490d76c2019-05-07 16:29:15181 MockTransport& transport() { return transport_; }
Markus Handell486cc552019-12-03 13:37:28182 void AdvanceTime(TimeDelta delta) { time_controller_.AdvanceTime(delta); }
Stefan Holmerdbdb3a02018-07-17 14:03:46183
184 private:
185 NiceMock<MockTransport> transport_;
Stefan Holmerdbdb3a02018-07-17 14:03:46186 NiceMock<MockRtcpIntraFrameObserver> encoder_feedback_;
Erik Språng00cc8362019-11-25 11:21:46187 GlobalSimulatedTimeController time_controller_;
Danil Chapovalov83bbe912019-08-07 10:24:53188 RtcEventLogNull event_log_;
Stefan Holmerdbdb3a02018-07-17 14:03:46189 VideoSendStream::Config config_;
190 SendDelayStats send_delay_stats_;
191 BitrateConstraints bitrate_config_;
Erik Språng662678d2019-11-15 16:18:52192 const FieldTrialBasedConfig field_trials_;
Stefan Holmerdbdb3a02018-07-17 14:03:46193 RtpTransportControllerSend transport_controller_;
Stefan Holmerdbdb3a02018-07-17 14:03:46194 SendStatisticsProxy stats_proxy_;
195 RateLimiter retransmission_rate_limiter_;
Stefan Holmer9416ef82018-07-19 08:34:38196 std::unique_ptr<RtpVideoSender> router_;
Stefan Holmerdbdb3a02018-07-17 14:03:46197};
Jakob Ivarsson9a12ee52020-11-26 15:04:18198
199BitrateAllocationUpdate CreateBitrateAllocationUpdate(int target_bitrate_bps) {
200 BitrateAllocationUpdate update;
201 update.target_bitrate = DataRate::BitsPerSec(target_bitrate_bps);
202 update.round_trip_time = TimeDelta::Zero();
203 return update;
204}
205
Åsa Persson4bece9a2017-10-06 08:04:04206} // namespace
mflodman@webrtc.org02270cd2015-02-06 13:10:19207
Sebastian Jansson63470292019-02-01 09:13:43208TEST(RtpVideoSenderTest, SendOnOneModule) {
Niels Möller663844d2019-02-14 15:15:54209 constexpr uint8_t kPayload = 'a';
kjellander02b3d272016-04-20 12:05:54210 EncodedImage encoded_image;
Niels Möller23775882018-08-16 08:24:12211 encoded_image.SetTimestamp(1);
kjellander02b3d272016-04-20 12:05:54212 encoded_image.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 14:43:58213 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 13:56:56214 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
kjellander02b3d272016-04-20 12:05:54215
Erik Språng490d76c2019-05-07 16:29:15216 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
Danil Chapovalov383f2cf2020-08-12 09:06:53217 EXPECT_NE(EncodedImageCallback::Result::OK,
218 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19219
Stefan Holmerdbdb3a02018-07-17 14:03:46220 test.router()->SetActive(true);
Danil Chapovalov383f2cf2020-08-12 09:06:53221 EXPECT_EQ(EncodedImageCallback::Result::OK,
222 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19223
Stefan Holmerdbdb3a02018-07-17 14:03:46224 test.router()->SetActive(false);
Danil Chapovalov383f2cf2020-08-12 09:06:53225 EXPECT_NE(EncodedImageCallback::Result::OK,
226 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19227
Stefan Holmerdbdb3a02018-07-17 14:03:46228 test.router()->SetActive(true);
Danil Chapovalov383f2cf2020-08-12 09:06:53229 EXPECT_EQ(EncodedImageCallback::Result::OK,
230 test.router()->OnEncodedImage(encoded_image, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19231}
232
Sebastian Jansson63470292019-02-01 09:13:43233TEST(RtpVideoSenderTest, SendSimulcastSetActive) {
Niels Möller663844d2019-02-14 15:15:54234 constexpr uint8_t kPayload = 'a';
Niels Möllerd3b8c632018-08-27 13:33:42235 EncodedImage encoded_image_1;
236 encoded_image_1.SetTimestamp(1);
237 encoded_image_1.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 14:43:58238 encoded_image_1._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 13:56:56239 encoded_image_1.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
kjellander02b3d272016-04-20 12:05:54240
Erik Språng490d76c2019-05-07 16:29:15241 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
242 kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19243
Niels Möllerd3b8c632018-08-27 13:33:42244 CodecSpecificInfo codec_info;
Niels Möllerd3b8c632018-08-27 13:33:42245 codec_info.codecType = kVideoCodecVP8;
mflodman@webrtc.org02270cd2015-02-06 13:10:19246
Stefan Holmerdbdb3a02018-07-17 14:03:46247 test.router()->SetActive(true);
sergeyu2cb155a2016-11-04 18:39:29248 EXPECT_EQ(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53249 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19250
Niels Möllerd3b8c632018-08-27 13:33:42251 EncodedImage encoded_image_2(encoded_image_1);
252 encoded_image_2.SetSpatialIndex(1);
sergeyu2cb155a2016-11-04 18:39:29253 EXPECT_EQ(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53254 test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19255
mflodman@webrtc.org50e28162015-02-23 07:45:11256 // Inactive.
Stefan Holmerdbdb3a02018-07-17 14:03:46257 test.router()->SetActive(false);
sergeyu2cb155a2016-11-04 18:39:29258 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53259 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
sergeyu2cb155a2016-11-04 18:39:29260 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53261 test.router()->OnEncodedImage(encoded_image_2, &codec_info).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19262}
263
Seth Hampsoncc7125f2018-02-02 16:46:16264// Tests how setting individual rtp modules to active affects the overall
265// behavior of the payload router. First sets one module to active and checks
Stefan Holmerdbdb3a02018-07-17 14:03:46266// that outgoing data can be sent on this module, and checks that no data can
267// be sent if both modules are inactive.
Sebastian Jansson63470292019-02-01 09:13:43268TEST(RtpVideoSenderTest, SendSimulcastSetActiveModules) {
Niels Möller663844d2019-02-14 15:15:54269 constexpr uint8_t kPayload = 'a';
Niels Möllerd3b8c632018-08-27 13:33:42270 EncodedImage encoded_image_1;
271 encoded_image_1.SetTimestamp(1);
272 encoded_image_1.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 14:43:58273 encoded_image_1._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 13:56:56274 encoded_image_1.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Niels Möller77536a22019-01-15 07:50:01275
Niels Möllerd3b8c632018-08-27 13:33:42276 EncodedImage encoded_image_2(encoded_image_1);
277 encoded_image_2.SetSpatialIndex(1);
Stefan Holmerdbdb3a02018-07-17 14:03:46278
Erik Språng490d76c2019-05-07 16:29:15279 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
280 kPayloadType, {});
Niels Möllerd3b8c632018-08-27 13:33:42281 CodecSpecificInfo codec_info;
Niels Möllerd3b8c632018-08-27 13:33:42282 codec_info.codecType = kVideoCodecVP8;
Seth Hampsoncc7125f2018-02-02 16:46:16283
284 // Only setting one stream to active will still set the payload router to
285 // active and allow sending data on the active stream.
286 std::vector<bool> active_modules({true, false});
Stefan Holmerdbdb3a02018-07-17 14:03:46287 test.router()->SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 16:46:16288 EXPECT_EQ(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53289 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
Seth Hampsoncc7125f2018-02-02 16:46:16290
Stefan Holmerdbdb3a02018-07-17 14:03:46291 // Setting both streams to inactive will turn the payload router to
292 // inactive.
Seth Hampsoncc7125f2018-02-02 16:46:16293 active_modules = {false, false};
Stefan Holmerdbdb3a02018-07-17 14:03:46294 test.router()->SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 16:46:16295 // An incoming encoded image will not ask the module to send outgoing data
296 // because the payload router is inactive.
Seth Hampsoncc7125f2018-02-02 16:46:16297 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53298 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
Seth Hampsoncc7125f2018-02-02 16:46:16299 EXPECT_NE(EncodedImageCallback::Result::OK,
Danil Chapovalov383f2cf2020-08-12 09:06:53300 test.router()->OnEncodedImage(encoded_image_1, &codec_info).error);
Seth Hampsoncc7125f2018-02-02 16:46:16301}
302
Sebastian Jansson63470292019-02-01 09:13:43303TEST(RtpVideoSenderTest, CreateWithNoPreviousStates) {
Erik Språng490d76c2019-05-07 16:29:15304 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
305 kPayloadType, {});
Stefan Holmerdbdb3a02018-07-17 14:03:46306 test.router()->SetActive(true);
Åsa Persson4bece9a2017-10-06 08:04:04307
308 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 14:03:46309 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 08:04:04310 EXPECT_EQ(2u, initial_states.size());
311 EXPECT_NE(initial_states.find(kSsrc1), initial_states.end());
312 EXPECT_NE(initial_states.find(kSsrc2), initial_states.end());
313}
314
Sebastian Jansson63470292019-02-01 09:13:43315TEST(RtpVideoSenderTest, CreateWithPreviousStates) {
philipel25d31ec2018-08-08 14:33:01316 const int64_t kState1SharedFrameId = 123;
317 const int64_t kState2SharedFrameId = 234;
Åsa Persson4bece9a2017-10-06 08:04:04318 RtpPayloadState state1;
319 state1.picture_id = kInitialPictureId1;
Niels Möllerbb894ff2018-03-15 11:28:53320 state1.tl0_pic_idx = kInitialTl0PicIdx1;
philipel25d31ec2018-08-08 14:33:01321 state1.shared_frame_id = kState1SharedFrameId;
Åsa Persson4bece9a2017-10-06 08:04:04322 RtpPayloadState state2;
323 state2.picture_id = kInitialPictureId2;
Niels Möllerbb894ff2018-03-15 11:28:53324 state2.tl0_pic_idx = kInitialTl0PicIdx2;
philipel25d31ec2018-08-08 14:33:01325 state2.shared_frame_id = kState2SharedFrameId;
Åsa Persson4bece9a2017-10-06 08:04:04326 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
327 {kSsrc2, state2}};
328
Erik Språng490d76c2019-05-07 16:29:15329 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
330 kPayloadType, states);
Stefan Holmerdbdb3a02018-07-17 14:03:46331 test.router()->SetActive(true);
Åsa Persson4bece9a2017-10-06 08:04:04332
333 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 14:03:46334 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 08:04:04335 EXPECT_EQ(2u, initial_states.size());
336 EXPECT_EQ(kInitialPictureId1, initial_states[kSsrc1].picture_id);
Niels Möllerbb894ff2018-03-15 11:28:53337 EXPECT_EQ(kInitialTl0PicIdx1, initial_states[kSsrc1].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 08:04:04338 EXPECT_EQ(kInitialPictureId2, initial_states[kSsrc2].picture_id);
Niels Möllerbb894ff2018-03-15 11:28:53339 EXPECT_EQ(kInitialTl0PicIdx2, initial_states[kSsrc2].tl0_pic_idx);
philipel25d31ec2018-08-08 14:33:01340 EXPECT_EQ(kState2SharedFrameId, initial_states[kSsrc1].shared_frame_id);
341 EXPECT_EQ(kState2SharedFrameId, initial_states[kSsrc2].shared_frame_id);
Åsa Persson4bece9a2017-10-06 08:04:04342}
Niels Möller949f0fd2019-01-29 08:44:24343
Sebastian Jansson63470292019-02-01 09:13:43344TEST(RtpVideoSenderTest, FrameCountCallbacks) {
Niels Möller949f0fd2019-01-29 08:44:24345 class MockFrameCountObserver : public FrameCountObserver {
346 public:
Danil Chapovalov9a5efe92020-05-14 20:06:18347 MOCK_METHOD(void,
348 FrameCountUpdated,
349 (const FrameCounts& frame_counts, uint32_t ssrc),
350 (override));
Niels Möller949f0fd2019-01-29 08:44:24351 } callback;
352
Erik Språng490d76c2019-05-07 16:29:15353 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {},
354 &callback);
Niels Möller949f0fd2019-01-29 08:44:24355
Niels Möller663844d2019-02-14 15:15:54356 constexpr uint8_t kPayload = 'a';
Niels Möller949f0fd2019-01-29 08:44:24357 EncodedImage encoded_image;
358 encoded_image.SetTimestamp(1);
359 encoded_image.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 14:43:58360 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 13:56:56361 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Niels Möller949f0fd2019-01-29 08:44:24362
Niels Möller8f7ce222019-03-21 14:43:58363 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller949f0fd2019-01-29 08:44:24364
365 // No callbacks when not active.
366 EXPECT_CALL(callback, FrameCountUpdated).Times(0);
Danil Chapovalov383f2cf2020-08-12 09:06:53367 EXPECT_NE(EncodedImageCallback::Result::OK,
368 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Mirko Bonadei6a489f22019-04-09 13:11:12369 ::testing::Mock::VerifyAndClearExpectations(&callback);
Niels Möller949f0fd2019-01-29 08:44:24370
371 test.router()->SetActive(true);
372
373 FrameCounts frame_counts;
374 EXPECT_CALL(callback, FrameCountUpdated(_, kSsrc1))
375 .WillOnce(SaveArg<0>(&frame_counts));
Danil Chapovalov383f2cf2020-08-12 09:06:53376 EXPECT_EQ(EncodedImageCallback::Result::OK,
377 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Niels Möller949f0fd2019-01-29 08:44:24378
379 EXPECT_EQ(1, frame_counts.key_frames);
380 EXPECT_EQ(0, frame_counts.delta_frames);
381
Mirko Bonadei6a489f22019-04-09 13:11:12382 ::testing::Mock::VerifyAndClearExpectations(&callback);
Niels Möller949f0fd2019-01-29 08:44:24383
Niels Möller8f7ce222019-03-21 14:43:58384 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
Niels Möller949f0fd2019-01-29 08:44:24385 EXPECT_CALL(callback, FrameCountUpdated(_, kSsrc1))
386 .WillOnce(SaveArg<0>(&frame_counts));
Danil Chapovalov383f2cf2020-08-12 09:06:53387 EXPECT_EQ(EncodedImageCallback::Result::OK,
388 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Niels Möller949f0fd2019-01-29 08:44:24389
390 EXPECT_EQ(1, frame_counts.key_frames);
391 EXPECT_EQ(1, frame_counts.delta_frames);
392}
393
Erik Språng490d76c2019-05-07 16:29:15394// Integration test verifying that ack of packet via TransportFeedback means
Erik Språng845c6aa2019-05-29 11:02:24395// that the packet is removed from RtpPacketHistory and won't be retransmitted
Erik Språng490d76c2019-05-07 16:29:15396// again.
397TEST(RtpVideoSenderTest, DoesNotRetrasmitAckedPackets) {
Erik Språng490d76c2019-05-07 16:29:15398 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
399 kPayloadType, {});
400 test.router()->SetActive(true);
401
402 constexpr uint8_t kPayload = 'a';
403 EncodedImage encoded_image;
404 encoded_image.SetTimestamp(1);
405 encoded_image.capture_time_ms_ = 2;
406 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 13:56:56407 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Erik Språng490d76c2019-05-07 16:29:15408
409 // Send two tiny images, mapping to two RTP packets. Capture sequence numbers.
Erik Språng490d76c2019-05-07 16:29:15410 std::vector<uint16_t> rtp_sequence_numbers;
411 std::vector<uint16_t> transport_sequence_numbers;
412 EXPECT_CALL(test.transport(), SendRtp)
413 .Times(2)
Danil Chapovalova68eb8c2020-02-17 15:13:14414 .WillRepeatedly([&rtp_sequence_numbers, &transport_sequence_numbers](
415 const uint8_t* packet, size_t length,
416 const PacketOptions& options) {
417 RtpPacket rtp_packet;
418 EXPECT_TRUE(rtp_packet.Parse(packet, length));
419 rtp_sequence_numbers.push_back(rtp_packet.SequenceNumber());
420 transport_sequence_numbers.push_back(options.packet_id);
421 return true;
422 });
Danil Chapovalov383f2cf2020-08-12 09:06:53423 EXPECT_EQ(EncodedImageCallback::Result::OK,
424 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Erik Språng490d76c2019-05-07 16:29:15425 encoded_image.SetTimestamp(2);
426 encoded_image.capture_time_ms_ = 3;
Danil Chapovalov383f2cf2020-08-12 09:06:53427 EXPECT_EQ(EncodedImageCallback::Result::OK,
428 test.router()->OnEncodedImage(encoded_image, nullptr).error);
Erik Språngbd7046c2019-05-07 21:54:29429
Danil Chapovalov0c626af2020-02-10 10:16:00430 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 16:29:15431
Erik Språng490d76c2019-05-07 16:29:15432 // Construct a NACK message for requesting retransmission of both packet.
433 rtcp::Nack nack;
434 nack.SetMediaSsrc(kSsrc1);
435 nack.SetPacketIds(rtp_sequence_numbers);
436 rtc::Buffer nack_buffer = nack.Build();
437
438 std::vector<uint16_t> retransmitted_rtp_sequence_numbers;
439 EXPECT_CALL(test.transport(), SendRtp)
440 .Times(2)
Danil Chapovalova68eb8c2020-02-17 15:13:14441 .WillRepeatedly([&retransmitted_rtp_sequence_numbers](
Erik Språng490d76c2019-05-07 16:29:15442 const uint8_t* packet, size_t length,
443 const PacketOptions& options) {
444 RtpPacket rtp_packet;
445 EXPECT_TRUE(rtp_packet.Parse(packet, length));
446 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
447 // Capture the retransmitted sequence number from the RTX header.
448 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
449 retransmitted_rtp_sequence_numbers.push_back(
450 ByteReader<uint16_t>::ReadBigEndian(payload.data()));
Erik Språng490d76c2019-05-07 16:29:15451 return true;
452 });
453 test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size());
Danil Chapovalov0c626af2020-02-10 10:16:00454 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 16:29:15455
456 // Verify that both packets were retransmitted.
457 EXPECT_EQ(retransmitted_rtp_sequence_numbers, rtp_sequence_numbers);
458
459 // Simulate transport feedback indicating fist packet received, next packet
Erik Språng00cc8362019-11-25 11:21:46460 // lost (not other way around as that would trigger early retransmit).
Sebastian Janssonf2988552019-10-29 16:18:51461 StreamFeedbackObserver::StreamPacketInfo lost_packet_feedback;
Erik Språng00cc8362019-11-25 11:21:46462 lost_packet_feedback.rtp_sequence_number = rtp_sequence_numbers[0];
Erik Språng490d76c2019-05-07 16:29:15463 lost_packet_feedback.ssrc = kSsrc1;
Sebastian Janssonf2988552019-10-29 16:18:51464 lost_packet_feedback.received = false;
Erik Språng6a0a5592021-06-15 17:04:24465 lost_packet_feedback.is_retransmission = false;
Erik Språng490d76c2019-05-07 16:29:15466
Erik Språng00cc8362019-11-25 11:21:46467 StreamFeedbackObserver::StreamPacketInfo received_packet_feedback;
468 received_packet_feedback.rtp_sequence_number = rtp_sequence_numbers[1];
469 received_packet_feedback.ssrc = kSsrc1;
470 received_packet_feedback.received = true;
Erik Språng6a0a5592021-06-15 17:04:24471 lost_packet_feedback.is_retransmission = false;
Erik Språng00cc8362019-11-25 11:21:46472
Sebastian Janssonf2988552019-10-29 16:18:51473 test.router()->OnPacketFeedbackVector(
Erik Språng00cc8362019-11-25 11:21:46474 {lost_packet_feedback, received_packet_feedback});
Erik Språng490d76c2019-05-07 16:29:15475
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 10:16:00481 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 16:29:15482 EXPECT_CALL(test.transport(), SendRtp)
Danil Chapovalova68eb8c2020-02-17 15:13:14483 .WillOnce([&lost_packet_feedback](const uint8_t* packet, size_t length,
484 const PacketOptions& options) {
Erik Språng490d76c2019-05-07 16:29:15485 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 16:29:15492 return true;
493 });
494 test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size());
Danil Chapovalov0c626af2020-02-10 10:16:00495 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng490d76c2019-05-07 16:29:15496}
Erik Språng845c6aa2019-05-29 11:02:24497
Sebastian Jansson3d4d94a2020-01-14 13:25:41498// 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 17:46:07508 call_conf.transport.rates.max_rate = DataRate::KilobitsPerSec(300);
509 call_conf.transport.rates.start_rate = DataRate::KilobitsPerSec(300);
Sebastian Jansson3d4d94a2020-01-14 13:25:41510 test::NetworkSimulationConfig net_conf;
Danil Chapovalovcad3e0e2020-02-17 17:46:07511 net_conf.bandwidth = DataRate::KilobitsPerSec(300);
Sebastian Jansson3d4d94a2020-01-14 13:25:41512 auto send_node = s.CreateSimulationNode(net_conf);
Tommi3c9bcc12020-04-15 14:45:47513 auto* callee = s.CreateClient("return", call_conf);
Sebastian Jansson3d4d94a2020-01-14 13:25:41514 auto* route = s.CreateRoutes(s.CreateClient("send", call_conf), {send_node},
Tommi3c9bcc12020-04-15 14:45:47515 callee, {s.CreateSimulationNode(net_conf)});
Sebastian Jansson3d4d94a2020-01-14 13:25:41516
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 10:16:00541 s.RunFor(TimeDelta::Seconds(1));
Sebastian Jansson3d4d94a2020-01-14 13:25:41542 rtx_packets = 0;
Tommi3c9bcc12020-04-15 14:45:47543 int decoded_baseline = 0;
544 callee->SendTask([&decoded_baseline, &lossy]() {
545 decoded_baseline = lossy->receive()->GetStats().frames_decoded;
546 });
Danil Chapovalov0c626af2020-02-10 10:16:00547 s.RunFor(TimeDelta::Seconds(1));
Sebastian Jansson3d4d94a2020-01-14 13:25:41548 // 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 14:45:47552 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 13:25:41557 EXPECT_EQ(frames_decoded, 5);
558}
559
Erik Språng845c6aa2019-05-29 11:02:24560// 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 11:02:24563 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
564 kPayloadType, {});
565 test.router()->SetActive(true);
566
Niels Möllerb9bfe652019-10-03 06:43:53567 const uint8_t kPayload[1] = {'a'};
Erik Språng845c6aa2019-05-29 11:02:24568 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 06:43:53572 encoded_image.SetEncodedData(
573 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
Erik Språng845c6aa2019-05-29 11:02:24574 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 11:02:24581 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 15:13:14584 .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 09:06:53595 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Erik Språng845c6aa2019-05-29 11:02:24596 EncodedImageCallback::Result::OK);
Erik Språng845c6aa2019-05-29 11:02:24597
Danil Chapovalov0c626af2020-02-10 10:16:00598 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng845c6aa2019-05-29 11:02:24599
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 15:13:14604 .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 09:06:53615 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Erik Språng845c6aa2019-05-29 11:02:24616 EncodedImageCallback::Result::OK);
Danil Chapovalov0c626af2020-02-10 10:16:00617 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng845c6aa2019-05-29 11:02:24618
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 15:13:14624 .WillOnce([&frame1_rtp_sequence_number](const uint8_t* packet,
625 size_t length,
626 const PacketOptions& options) {
Erik Språng845c6aa2019-05-29 11:02:24627 RtpPacket rtp_packet;
628 EXPECT_TRUE(rtp_packet.Parse(packet, length));
Sebastian Janssonf2988552019-10-29 16:18:51629 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
Erik Språng845c6aa2019-05-29 11:02:24630
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 11:02:24636 return true;
637 });
638
Sebastian Janssonf2988552019-10-29 16:18:51639 StreamFeedbackObserver::StreamPacketInfo first_packet_feedback;
Erik Språng845c6aa2019-05-29 11:02:24640 first_packet_feedback.rtp_sequence_number = frame1_rtp_sequence_number;
641 first_packet_feedback.ssrc = kSsrc1;
Sebastian Janssonf2988552019-10-29 16:18:51642 first_packet_feedback.received = false;
Erik Språng6a0a5592021-06-15 17:04:24643 first_packet_feedback.is_retransmission = false;
Erik Språng845c6aa2019-05-29 11:02:24644
Sebastian Janssonf2988552019-10-29 16:18:51645 StreamFeedbackObserver::StreamPacketInfo second_packet_feedback;
646 second_packet_feedback.rtp_sequence_number = frame2_rtp_sequence_number;
647 second_packet_feedback.ssrc = kSsrc2;
648 second_packet_feedback.received = true;
Erik Språng6a0a5592021-06-15 17:04:24649 first_packet_feedback.is_retransmission = false;
Erik Språng845c6aa2019-05-29 11:02:24650
Sebastian Janssonf2988552019-10-29 16:18:51651 test.router()->OnPacketFeedbackVector(
652 {first_packet_feedback, second_packet_feedback});
Erik Språng845c6aa2019-05-29 11:02:24653
654 // Wait for pacer to run and send the RTX packet.
Danil Chapovalov0c626af2020-02-10 10:16:00655 test.AdvanceTime(TimeDelta::Millis(33));
Erik Språng845c6aa2019-05-29 11:02:24656}
Sebastian Janssoncf41eb12019-06-10 09:30:59657
Danil Chapovalov2272f202020-02-18 11:09:43658TEST(RtpVideoSenderTest, SupportsDependencyDescriptor) {
Danil Chapovalov2272f202020-02-18 11:09:43659 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
660 test.router()->SetActive(true);
661
662 RtpHeaderExtensionMap extensions;
663 extensions.Register<RtpDependencyDescriptorExtension>(
664 kDependencyDescriptorExtensionId);
665 std::vector<RtpPacket> sent_packets;
666 ON_CALL(test.transport(), SendRtp)
667 .WillByDefault([&](const uint8_t* packet, size_t length,
668 const PacketOptions& options) {
669 sent_packets.emplace_back(&extensions);
670 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
671 return true;
672 });
673
674 const uint8_t kPayload[1] = {'a'};
675 EncodedImage encoded_image;
676 encoded_image.SetTimestamp(1);
677 encoded_image.capture_time_ms_ = 2;
678 encoded_image.SetEncodedData(
679 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
680
681 CodecSpecificInfo codec_specific;
682 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
683 codec_specific.template_structure.emplace();
684 codec_specific.template_structure->num_decode_targets = 1;
685 codec_specific.template_structure->templates = {
Danil Chapovalov24263f42020-06-11 11:23:45686 FrameDependencyTemplate().T(0).Dtis("S"),
687 FrameDependencyTemplate().T(0).Dtis("S").FrameDiffs({2}),
688 FrameDependencyTemplate().T(1).Dtis("D").FrameDiffs({1}),
Danil Chapovalov2272f202020-02-18 11:09:43689 };
690
691 // Send two tiny images, mapping to single RTP packets.
692 // Send in key frame.
693 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
694 codec_specific.generic_frame_info =
695 GenericFrameInfo::Builder().T(0).Dtis("S").Build();
696 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
Danil Chapovalov383f2cf2020-08-12 09:06:53697 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 11:09:43698 EncodedImageCallback::Result::OK);
699 test.AdvanceTime(TimeDelta::Millis(33));
700 ASSERT_THAT(sent_packets, SizeIs(1));
701 EXPECT_TRUE(
702 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
703
704 // Send in delta frame.
705 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
706 codec_specific.template_structure = absl::nullopt;
707 codec_specific.generic_frame_info =
708 GenericFrameInfo::Builder().T(1).Dtis("D").Build();
709 codec_specific.generic_frame_info->encoder_buffers = {{0, true, false}};
Danil Chapovalov383f2cf2020-08-12 09:06:53710 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 11:09:43711 EncodedImageCallback::Result::OK);
712 test.AdvanceTime(TimeDelta::Millis(33));
713 ASSERT_THAT(sent_packets, SizeIs(2));
714 EXPECT_TRUE(
715 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
716}
717
Danil Chapovalov0be18462021-01-20 11:11:29718TEST(RtpVideoSenderTest, SupportsDependencyDescriptorForVp9) {
719 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
720 test.router()->SetActive(true);
721
722 RtpHeaderExtensionMap extensions;
723 extensions.Register<RtpDependencyDescriptorExtension>(
724 kDependencyDescriptorExtensionId);
725 std::vector<RtpPacket> sent_packets;
726 ON_CALL(test.transport(), SendRtp)
727 .WillByDefault([&](const uint8_t* packet, size_t length,
728 const PacketOptions& options) {
729 sent_packets.emplace_back(&extensions);
730 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
731 return true;
732 });
733
734 const uint8_t kPayload[1] = {'a'};
735 EncodedImage encoded_image;
736 encoded_image.SetTimestamp(1);
737 encoded_image.capture_time_ms_ = 2;
738 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
739 encoded_image.SetEncodedData(
740 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
741
742 CodecSpecificInfo codec_specific;
743 codec_specific.codecType = VideoCodecType::kVideoCodecVP9;
744 codec_specific.template_structure.emplace();
745 codec_specific.template_structure->num_decode_targets = 2;
746 codec_specific.template_structure->templates = {
747 FrameDependencyTemplate().S(0).Dtis("SS"),
748 FrameDependencyTemplate().S(1).Dtis("-S").FrameDiffs({1}),
749 };
750
751 // Send two tiny images, each mapping to single RTP packet.
752 // Send in key frame for the base spatial layer.
753 codec_specific.generic_frame_info =
754 GenericFrameInfo::Builder().S(0).Dtis("SS").Build();
755 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
756 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
757 EncodedImageCallback::Result::OK);
758 // Send in 2nd spatial layer.
759 codec_specific.template_structure = absl::nullopt;
760 codec_specific.generic_frame_info =
761 GenericFrameInfo::Builder().S(1).Dtis("-S").Build();
762 codec_specific.generic_frame_info->encoder_buffers = {{0, true, false},
763 {1, false, true}};
764 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
765 EncodedImageCallback::Result::OK);
766
767 test.AdvanceTime(TimeDelta::Millis(33));
768 ASSERT_THAT(sent_packets, SizeIs(2));
769 EXPECT_TRUE(sent_packets[0].HasExtension<RtpDependencyDescriptorExtension>());
770 EXPECT_TRUE(sent_packets[1].HasExtension<RtpDependencyDescriptorExtension>());
771}
772
Danil Chapovalov748550d2021-04-29 09:42:54773TEST(RtpVideoSenderTest,
774 SupportsDependencyDescriptorForVp9NotProvidedByEncoder) {
Danil Chapovalov748550d2021-04-29 09:42:54775 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
776 test.router()->SetActive(true);
777
778 RtpHeaderExtensionMap extensions;
779 extensions.Register<RtpDependencyDescriptorExtension>(
780 kDependencyDescriptorExtensionId);
781 std::vector<RtpPacket> sent_packets;
782 ON_CALL(test.transport(), SendRtp)
783 .WillByDefault([&](const uint8_t* packet, size_t length,
784 const PacketOptions& options) {
785 sent_packets.emplace_back(&extensions);
786 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
787 return true;
788 });
789
790 const uint8_t kPayload[1] = {'a'};
791 EncodedImage encoded_image;
792 encoded_image.SetTimestamp(1);
793 encoded_image.capture_time_ms_ = 2;
794 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
795 encoded_image._encodedWidth = 320;
796 encoded_image._encodedHeight = 180;
797 encoded_image.SetEncodedData(
798 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
799
800 CodecSpecificInfo codec_specific;
801 codec_specific.codecType = VideoCodecType::kVideoCodecVP9;
802 codec_specific.codecSpecific.VP9.num_spatial_layers = 1;
803 codec_specific.codecSpecific.VP9.temporal_idx = kNoTemporalIdx;
804 codec_specific.codecSpecific.VP9.first_frame_in_picture = true;
805 codec_specific.end_of_picture = true;
806 codec_specific.codecSpecific.VP9.inter_pic_predicted = false;
807
808 // Send two tiny images, each mapping to single RTP packet.
809 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
810 EncodedImageCallback::Result::OK);
811
812 // Send in 2nd picture.
813 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
814 encoded_image.SetTimestamp(3000);
815 codec_specific.codecSpecific.VP9.inter_pic_predicted = true;
816 codec_specific.codecSpecific.VP9.num_ref_pics = 1;
817 codec_specific.codecSpecific.VP9.p_diff[0] = 1;
818 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
819 EncodedImageCallback::Result::OK);
820
821 test.AdvanceTime(TimeDelta::Millis(33));
822 ASSERT_THAT(sent_packets, SizeIs(2));
823 EXPECT_TRUE(sent_packets[0].HasExtension<RtpDependencyDescriptorExtension>());
824 EXPECT_TRUE(sent_packets[1].HasExtension<RtpDependencyDescriptorExtension>());
825}
826
philipel5b231de2021-09-01 13:21:16827TEST(RtpVideoSenderTest, GenerateDependecyDescriptorForGenericCodecs) {
828 test::ScopedFieldTrials field_trials(
829 "WebRTC-GenericCodecDependencyDescriptor/Enabled/");
830 RtpVideoSenderTestFixture test({kSsrc1}, {}, 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._frameType = VideoFrameType::kVideoFrameKey;
850 encoded_image._encodedWidth = 320;
851 encoded_image._encodedHeight = 180;
852 encoded_image.SetEncodedData(
853 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
854
855 CodecSpecificInfo codec_specific;
856 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
857 codec_specific.end_of_picture = true;
858
859 // Send two tiny images, each mapping to single RTP packet.
860 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
861 EncodedImageCallback::Result::OK);
862
863 // Send in 2nd picture.
864 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
865 encoded_image.SetTimestamp(3000);
866 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
867 EncodedImageCallback::Result::OK);
868
869 test.AdvanceTime(TimeDelta::Millis(33));
870 ASSERT_THAT(sent_packets, SizeIs(2));
871 EXPECT_TRUE(sent_packets[0].HasExtension<RtpDependencyDescriptorExtension>());
872 EXPECT_TRUE(sent_packets[1].HasExtension<RtpDependencyDescriptorExtension>());
873}
874
Danil Chapovalov2272f202020-02-18 11:09:43875TEST(RtpVideoSenderTest, SupportsStoppingUsingDependencyDescriptor) {
Danil Chapovalov2272f202020-02-18 11:09:43876 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
877 test.router()->SetActive(true);
878
879 RtpHeaderExtensionMap extensions;
880 extensions.Register<RtpDependencyDescriptorExtension>(
881 kDependencyDescriptorExtensionId);
882 std::vector<RtpPacket> sent_packets;
883 ON_CALL(test.transport(), SendRtp)
884 .WillByDefault([&](const uint8_t* packet, size_t length,
885 const PacketOptions& options) {
886 sent_packets.emplace_back(&extensions);
887 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
888 return true;
889 });
890
891 const uint8_t kPayload[1] = {'a'};
892 EncodedImage encoded_image;
893 encoded_image.SetTimestamp(1);
894 encoded_image.capture_time_ms_ = 2;
895 encoded_image.SetEncodedData(
896 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
897
898 CodecSpecificInfo codec_specific;
899 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
900 codec_specific.template_structure.emplace();
901 codec_specific.template_structure->num_decode_targets = 1;
902 codec_specific.template_structure->templates = {
Danil Chapovalov24263f42020-06-11 11:23:45903 FrameDependencyTemplate().T(0).Dtis("S"),
904 FrameDependencyTemplate().T(0).Dtis("S").FrameDiffs({2}),
905 FrameDependencyTemplate().T(1).Dtis("D").FrameDiffs({1}),
Danil Chapovalov2272f202020-02-18 11:09:43906 };
907
908 // Send two tiny images, mapping to single RTP packets.
909 // Send in a key frame.
910 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
911 codec_specific.generic_frame_info =
912 GenericFrameInfo::Builder().T(0).Dtis("S").Build();
913 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
Danil Chapovalov383f2cf2020-08-12 09:06:53914 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 11:09:43915 EncodedImageCallback::Result::OK);
916 test.AdvanceTime(TimeDelta::Millis(33));
917 ASSERT_THAT(sent_packets, SizeIs(1));
918 EXPECT_TRUE(
919 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
920
921 // Send in a new key frame without the support for the dependency descriptor.
922 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
923 codec_specific.template_structure = absl::nullopt;
Danil Chapovalov383f2cf2020-08-12 09:06:53924 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
Danil Chapovalov2272f202020-02-18 11:09:43925 EncodedImageCallback::Result::OK);
926 test.AdvanceTime(TimeDelta::Millis(33));
927 ASSERT_THAT(sent_packets, SizeIs(2));
928 EXPECT_FALSE(
929 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
930}
931
Danil Chapovalov37dfddd2021-01-27 18:24:23932TEST(RtpVideoSenderTest,
933 SupportsStoppingUsingDependencyDescriptorForVp8Simulcast) {
934 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {}, kPayloadType, {});
935 test.router()->SetActive(true);
936
937 RtpHeaderExtensionMap extensions;
938 extensions.Register<RtpDependencyDescriptorExtension>(
939 kDependencyDescriptorExtensionId);
940 std::vector<RtpPacket> sent_packets;
941 ON_CALL(test.transport(), SendRtp)
942 .WillByDefault([&](const uint8_t* packet, size_t length,
943 const PacketOptions& options) {
944 sent_packets.emplace_back(&extensions);
945 EXPECT_TRUE(sent_packets.back().Parse(packet, length));
946 return true;
947 });
948
949 const uint8_t kPayload[1] = {'a'};
950 EncodedImage encoded_image;
951 encoded_image.SetTimestamp(1);
952 encoded_image.capture_time_ms_ = 2;
953 encoded_image.SetEncodedData(
954 EncodedImageBuffer::Create(kPayload, sizeof(kPayload)));
955 // VP8 simulcast uses spatial index to communicate simulcast stream.
956 encoded_image.SetSpatialIndex(1);
957
958 CodecSpecificInfo codec_specific;
959 codec_specific.codecType = VideoCodecType::kVideoCodecVP8;
960 codec_specific.template_structure.emplace();
961 codec_specific.template_structure->num_decode_targets = 1;
962 codec_specific.template_structure->templates = {
963 FrameDependencyTemplate().T(0).Dtis("S")};
964
965 // Send two tiny images, mapping to single RTP packets.
966 // Send in a key frame.
967 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
968 codec_specific.generic_frame_info =
969 GenericFrameInfo::Builder().T(0).Dtis("S").Build();
970 codec_specific.generic_frame_info->encoder_buffers = {{0, false, true}};
971 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
972 EncodedImageCallback::Result::OK);
973 test.AdvanceTime(TimeDelta::Millis(33));
974 ASSERT_THAT(sent_packets, SizeIs(1));
975 EXPECT_TRUE(
976 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
977
978 // Send in a new key frame without the support for the dependency descriptor.
979 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
980 codec_specific.template_structure = absl::nullopt;
981 codec_specific.generic_frame_info = absl::nullopt;
982 EXPECT_EQ(test.router()->OnEncodedImage(encoded_image, &codec_specific).error,
983 EncodedImageCallback::Result::OK);
984 test.AdvanceTime(TimeDelta::Millis(33));
985 ASSERT_THAT(sent_packets, SizeIs(2));
986 EXPECT_FALSE(
987 sent_packets.back().HasExtension<RtpDependencyDescriptorExtension>());
988}
989
Jakob Ivarsson9a12ee52020-11-26 15:04:18990TEST(RtpVideoSenderTest, CanSetZeroBitrate) {
Sebastian Janssoncf41eb12019-06-10 09:30:59991 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
Jakob Ivarsson9a12ee52020-11-26 15:04:18992 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(0),
993 /*framerate*/ 0);
Sebastian Janssoncf41eb12019-06-10 09:30:59994}
Marina Cioceadc69fd22020-04-10 18:19:14995
996TEST(RtpVideoSenderTest, SimulcastSenderRegistersFrameTransformers) {
Marina Cioceadc69fd22020-04-10 18:19:14997 rtc::scoped_refptr<MockFrameTransformer> transformer =
Tomas Gunnarssonc1d58912021-04-22 17:21:43998 rtc::make_ref_counted<MockFrameTransformer>();
Marina Cioceadc69fd22020-04-10 18:19:14999
1000 EXPECT_CALL(*transformer, RegisterTransformedFrameSinkCallback(_, kSsrc1));
1001 EXPECT_CALL(*transformer, RegisterTransformedFrameSinkCallback(_, kSsrc2));
1002 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
1003 kPayloadType, {}, nullptr, transformer);
1004
1005 EXPECT_CALL(*transformer, UnregisterTransformedFrameSinkCallback(kSsrc1));
1006 EXPECT_CALL(*transformer, UnregisterTransformedFrameSinkCallback(kSsrc2));
1007}
Jakob Ivarsson9a12ee52020-11-26 15:04:181008
1009TEST(RtpVideoSenderTest, OverheadIsSubtractedFromTargetBitrate) {
1010 test::ScopedFieldTrials field_trials(
1011 "WebRTC-Video-UseFrameRateForOverhead/Enabled/");
1012
1013 // TODO(jakobi): RTP header size should not be hard coded.
1014 constexpr uint32_t kRtpHeaderSizeBytes = 20;
1015 constexpr uint32_t kTransportPacketOverheadBytes = 40;
1016 constexpr uint32_t kOverheadPerPacketBytes =
1017 kRtpHeaderSizeBytes + kTransportPacketOverheadBytes;
Danil Chapovalov9554a7b2021-02-05 18:30:161018 RtpVideoSenderTestFixture test({kSsrc1}, {}, kPayloadType, {});
Jakob Ivarsson9a12ee52020-11-26 15:04:181019 test.router()->OnTransportOverheadChanged(kTransportPacketOverheadBytes);
1020 test.router()->SetActive(true);
1021
1022 {
1023 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(300000),
1024 /*framerate*/ 15);
1025 // 1 packet per frame.
1026 EXPECT_EQ(test.router()->GetPayloadBitrateBps(),
1027 300000 - kOverheadPerPacketBytes * 8 * 30);
1028 }
1029 {
1030 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(150000),
1031 /*framerate*/ 15);
1032 // 1 packet per frame.
1033 EXPECT_EQ(test.router()->GetPayloadBitrateBps(),
1034 150000 - kOverheadPerPacketBytes * 8 * 15);
1035 }
1036 {
1037 test.router()->OnBitrateUpdated(CreateBitrateAllocationUpdate(1000000),
1038 /*framerate*/ 30);
1039 // 3 packets per frame.
1040 EXPECT_EQ(test.router()->GetPayloadBitrateBps(),
1041 1000000 - kOverheadPerPacketBytes * 8 * 30 * 3);
1042 }
1043}
1044
mflodman@webrtc.org02270cd2015-02-06 13:10:191045} // namespace webrtc