blob: 29fc2b602015ed69e4cc46747ab4df863a2343a7 [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
kwiberg27f982b2016-03-01 11:52:33 -080011#include <memory>
Åsa Persson4bece9a2017-10-06 10:04:04 +020012#include <string>
kwiberg27f982b2016-03-01 11:52:33 -080013
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020014#include "call/rtp_transport_controller_send.h"
Stefan Holmer9416ef82018-07-19 10:34:38 +020015#include "call/rtp_video_sender.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/video_coding/include/video_codec_interface.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020017#include "rtc_base/rate_limiter.h"
Åsa Persson4bece9a2017-10-06 10:04:04 +020018#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "test/gmock.h"
20#include "test/gtest.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020021#include "test/mock_transport.h"
22#include "video/call_stats.h"
23#include "video/send_delay_stats.h"
24#include "video/send_statistics_proxy.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000025
26using ::testing::_;
27using ::testing::AnyNumber;
Åsa Persson4bece9a2017-10-06 10:04:04 +020028using ::testing::Invoke;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000029using ::testing::NiceMock;
30using ::testing::Return;
Åsa Persson4bece9a2017-10-06 10:04:04 +020031using ::testing::Unused;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000032
33namespace webrtc {
Åsa Persson4bece9a2017-10-06 10:04:04 +020034namespace {
35const int8_t kPayloadType = 96;
36const uint32_t kSsrc1 = 12345;
37const uint32_t kSsrc2 = 23456;
Åsa Persson4bece9a2017-10-06 10:04:04 +020038const int16_t kInitialPictureId1 = 222;
39const int16_t kInitialPictureId2 = 44;
Niels Möllerbb894ff2018-03-15 12:28:53 +010040const int16_t kInitialTl0PicIdx1 = 99;
41const int16_t kInitialTl0PicIdx2 = 199;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020042const int64_t kRetransmitWindowSizeMs = 500;
43
44class MockRtcpIntraFrameObserver : public RtcpIntraFrameObserver {
45 public:
46 MOCK_METHOD1(OnReceivedIntraFrameRequest, void(uint32_t));
47};
48
49class MockOverheadObserver : public OverheadObserver {
50 public:
51 MOCK_METHOD1(OnOverheadChanged, void(size_t overhead_bytes_per_packet));
52};
53
54class MockCongestionObserver : public NetworkChangedObserver {
55 public:
56 MOCK_METHOD4(OnNetworkChanged,
57 void(uint32_t bitrate_bps,
58 uint8_t fraction_loss,
59 int64_t rtt_ms,
60 int64_t probing_interval_ms));
61};
62
63RtpSenderObservers CreateObservers(
64 RtcpRttStats* rtcp_rtt_stats,
65 RtcpIntraFrameObserver* intra_frame_callback,
66 RtcpStatisticsCallback* rtcp_stats,
67 StreamDataCountersCallback* rtp_stats,
68 BitrateStatisticsObserver* bitrate_observer,
69 FrameCountObserver* frame_count_observer,
70 RtcpPacketTypeCounterObserver* rtcp_type_observer,
71 SendSideDelayObserver* send_delay_observer,
72 SendPacketObserver* send_packet_observer,
73 OverheadObserver* overhead_observer) {
74 RtpSenderObservers observers;
75 observers.rtcp_rtt_stats = rtcp_rtt_stats;
76 observers.intra_frame_callback = intra_frame_callback;
77 observers.rtcp_stats = rtcp_stats;
78 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;
84 observers.overhead_observer = overhead_observer;
85 return observers;
86}
87
Stefan Holmer9416ef82018-07-19 10:34:38 +020088class RtpVideoSenderTestFixture {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020089 public:
Stefan Holmer9416ef82018-07-19 10:34:38 +020090 RtpVideoSenderTestFixture(
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020091 const std::vector<uint32_t>& ssrcs,
92 int payload_type,
93 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states)
94 : clock_(0),
95 config_(&transport_),
96 send_delay_stats_(&clock_),
97 transport_controller_(&clock_, &event_log_, nullptr, bitrate_config_),
98 process_thread_(ProcessThread::Create("test_thread")),
99 call_stats_(&clock_, process_thread_.get()),
100 stats_proxy_(&clock_,
101 config_,
102 VideoEncoderConfig::ContentType::kRealtimeVideo),
103 retransmission_rate_limiter_(&clock_, kRetransmitWindowSizeMs) {
104 for (uint32_t ssrc : ssrcs) {
105 config_.rtp.ssrcs.push_back(ssrc);
106 }
107 config_.rtp.payload_type = payload_type;
108 std::map<uint32_t, RtpState> suspended_ssrcs;
Stefan Holmer9416ef82018-07-19 10:34:38 +0200109 router_ = absl::make_unique<RtpVideoSender>(
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200110 config_.rtp.ssrcs, suspended_ssrcs, suspended_payload_states,
111 config_.rtp, config_.rtcp, &transport_,
112 CreateObservers(&call_stats_, &encoder_feedback_, &stats_proxy_,
113 &stats_proxy_, &stats_proxy_, &stats_proxy_,
114 &stats_proxy_, &stats_proxy_, &send_delay_stats_,
115 &overhead_observer_),
116 &transport_controller_, &event_log_, &retransmission_rate_limiter_);
117 }
118
Stefan Holmer9416ef82018-07-19 10:34:38 +0200119 RtpVideoSender* router() { return router_.get(); }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200120
121 private:
122 NiceMock<MockTransport> transport_;
123 NiceMock<MockCongestionObserver> congestion_observer_;
124 NiceMock<MockOverheadObserver> overhead_observer_;
125 NiceMock<MockRtcpIntraFrameObserver> encoder_feedback_;
126 SimulatedClock clock_;
127 RtcEventLogNullImpl event_log_;
128 VideoSendStream::Config config_;
129 SendDelayStats send_delay_stats_;
130 BitrateConstraints bitrate_config_;
131 RtpTransportControllerSend transport_controller_;
132 std::unique_ptr<ProcessThread> process_thread_;
133 CallStats call_stats_;
134 SendStatisticsProxy stats_proxy_;
135 RateLimiter retransmission_rate_limiter_;
Stefan Holmer9416ef82018-07-19 10:34:38 +0200136 std::unique_ptr<RtpVideoSender> router_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200137};
Åsa Persson4bece9a2017-10-06 10:04:04 +0200138} // namespace
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000139
Sebastian Janssondc8c9812018-09-27 17:32:00 +0200140class RtpVideoSenderTest : public ::testing::Test,
141 public ::testing::WithParamInterface<std::string> {
142 public:
143 RtpVideoSenderTest() : field_trial_(GetParam()) {}
144
145 private:
146 test::ScopedFieldTrials field_trial_;
147};
148
149INSTANTIATE_TEST_CASE_P(Default, RtpVideoSenderTest, ::testing::Values(""));
150
151INSTANTIATE_TEST_CASE_P(
152 TaskQueueTrial,
153 RtpVideoSenderTest,
154 ::testing::Values("WebRTC-TaskQueueCongestionControl/Enabled/"));
155
156TEST_P(RtpVideoSenderTest, SendOnOneModule) {
kjellander02b3d272016-04-20 05:05:54 -0700157 uint8_t payload = 'a';
kjellander02b3d272016-04-20 05:05:54 -0700158 EncodedImage encoded_image;
Niels Möller23775882018-08-16 10:24:12 +0200159 encoded_image.SetTimestamp(1);
kjellander02b3d272016-04-20 05:05:54 -0700160 encoded_image.capture_time_ms_ = 2;
161 encoded_image._frameType = kVideoFrameKey;
162 encoded_image._buffer = &payload;
163 encoded_image._length = 1;
164
Stefan Holmer9416ef82018-07-19 10:34:38 +0200165 RtpVideoSenderTestFixture test({kSsrc1}, kPayloadType, {});
sergeyu2cb155a2016-11-04 11:39:29 -0700166 EXPECT_NE(
167 EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200168 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000169
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200170 test.router()->SetActive(true);
sergeyu2cb155a2016-11-04 11:39:29 -0700171 EXPECT_EQ(
172 EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200173 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000174
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200175 test.router()->SetActive(false);
sergeyu2cb155a2016-11-04 11:39:29 -0700176 EXPECT_NE(
177 EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200178 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000179
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200180 test.router()->SetActive(true);
sergeyu2cb155a2016-11-04 11:39:29 -0700181 EXPECT_EQ(
182 EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200183 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000184}
185
Sebastian Janssondc8c9812018-09-27 17:32:00 +0200186TEST_P(RtpVideoSenderTest, SendSimulcastSetActive) {
kjellander02b3d272016-04-20 05:05:54 -0700187 uint8_t payload = 'a';
Niels Möllerd3b8c632018-08-27 15:33:42 +0200188 EncodedImage encoded_image_1;
189 encoded_image_1.SetTimestamp(1);
190 encoded_image_1.capture_time_ms_ = 2;
191 encoded_image_1._frameType = kVideoFrameKey;
192 encoded_image_1._buffer = &payload;
193 encoded_image_1._length = 1;
kjellander02b3d272016-04-20 05:05:54 -0700194
Stefan Holmer9416ef82018-07-19 10:34:38 +0200195 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000196
Niels Möllerd3b8c632018-08-27 15:33:42 +0200197 CodecSpecificInfo codec_info;
198 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
199 codec_info.codecType = kVideoCodecVP8;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000200
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200201 test.router()->SetActive(true);
sergeyu2cb155a2016-11-04 11:39:29 -0700202 EXPECT_EQ(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200203 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200204 ->OnEncodedImage(encoded_image_1, &codec_info, nullptr)
sergeyu2cb155a2016-11-04 11:39:29 -0700205 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000206
Niels Möllerd3b8c632018-08-27 15:33:42 +0200207 EncodedImage encoded_image_2(encoded_image_1);
208 encoded_image_2.SetSpatialIndex(1);
sergeyu2cb155a2016-11-04 11:39:29 -0700209 EXPECT_EQ(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200210 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200211 ->OnEncodedImage(encoded_image_2, &codec_info, nullptr)
sergeyu2cb155a2016-11-04 11:39:29 -0700212 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000213
mflodman@webrtc.org50e28162015-02-23 07:45:11 +0000214 // Inactive.
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200215 test.router()->SetActive(false);
sergeyu2cb155a2016-11-04 11:39:29 -0700216 EXPECT_NE(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200217 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200218 ->OnEncodedImage(encoded_image_1, &codec_info, nullptr)
sergeyu2cb155a2016-11-04 11:39:29 -0700219 .error);
220 EXPECT_NE(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200221 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200222 ->OnEncodedImage(encoded_image_2, &codec_info, nullptr)
sergeyu2cb155a2016-11-04 11:39:29 -0700223 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000224}
225
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800226// Tests how setting individual rtp modules to active affects the overall
227// behavior of the payload router. First sets one module to active and checks
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200228// that outgoing data can be sent on this module, and checks that no data can
229// be sent if both modules are inactive.
Sebastian Janssondc8c9812018-09-27 17:32:00 +0200230TEST_P(RtpVideoSenderTest, SendSimulcastSetActiveModules) {
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800231 uint8_t payload = 'a';
Niels Möllerd3b8c632018-08-27 15:33:42 +0200232 EncodedImage encoded_image_1;
233 encoded_image_1.SetTimestamp(1);
234 encoded_image_1.capture_time_ms_ = 2;
235 encoded_image_1._frameType = kVideoFrameKey;
236 encoded_image_1._buffer = &payload;
237 encoded_image_1._length = 1;
238 EncodedImage encoded_image_2(encoded_image_1);
239 encoded_image_2.SetSpatialIndex(1);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200240
Stefan Holmer9416ef82018-07-19 10:34:38 +0200241 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, kPayloadType, {});
Niels Möllerd3b8c632018-08-27 15:33:42 +0200242 CodecSpecificInfo codec_info;
243 memset(&codec_info, 0, sizeof(CodecSpecificInfo));
244 codec_info.codecType = kVideoCodecVP8;
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800245
246 // Only setting one stream to active will still set the payload router to
247 // active and allow sending data on the active stream.
248 std::vector<bool> active_modules({true, false});
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200249 test.router()->SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800250 EXPECT_EQ(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200251 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200252 ->OnEncodedImage(encoded_image_1, &codec_info, nullptr)
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800253 .error);
254
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200255 // Setting both streams to inactive will turn the payload router to
256 // inactive.
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800257 active_modules = {false, false};
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200258 test.router()->SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800259 // An incoming encoded image will not ask the module to send outgoing data
260 // because the payload router is inactive.
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800261 EXPECT_NE(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200262 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200263 ->OnEncodedImage(encoded_image_1, &codec_info, nullptr)
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800264 .error);
265 EXPECT_NE(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200266 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200267 ->OnEncodedImage(encoded_image_1, &codec_info, nullptr)
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800268 .error);
269}
270
Sebastian Janssondc8c9812018-09-27 17:32:00 +0200271TEST_P(RtpVideoSenderTest, CreateWithNoPreviousStates) {
Stefan Holmer9416ef82018-07-19 10:34:38 +0200272 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, kPayloadType, {});
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200273 test.router()->SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200274
275 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200276 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 10:04:04 +0200277 EXPECT_EQ(2u, initial_states.size());
278 EXPECT_NE(initial_states.find(kSsrc1), initial_states.end());
279 EXPECT_NE(initial_states.find(kSsrc2), initial_states.end());
280}
281
Sebastian Janssondc8c9812018-09-27 17:32:00 +0200282TEST_P(RtpVideoSenderTest, CreateWithPreviousStates) {
philipel25d31ec2018-08-08 16:33:01 +0200283 const int64_t kState1SharedFrameId = 123;
284 const int64_t kState2SharedFrameId = 234;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200285 RtpPayloadState state1;
286 state1.picture_id = kInitialPictureId1;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100287 state1.tl0_pic_idx = kInitialTl0PicIdx1;
philipel25d31ec2018-08-08 16:33:01 +0200288 state1.shared_frame_id = kState1SharedFrameId;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200289 RtpPayloadState state2;
290 state2.picture_id = kInitialPictureId2;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100291 state2.tl0_pic_idx = kInitialTl0PicIdx2;
philipel25d31ec2018-08-08 16:33:01 +0200292 state2.shared_frame_id = kState2SharedFrameId;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200293 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
294 {kSsrc2, state2}};
295
Stefan Holmer9416ef82018-07-19 10:34:38 +0200296 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, kPayloadType, states);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200297 test.router()->SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200298
299 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200300 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 10:04:04 +0200301 EXPECT_EQ(2u, initial_states.size());
302 EXPECT_EQ(kInitialPictureId1, initial_states[kSsrc1].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100303 EXPECT_EQ(kInitialTl0PicIdx1, initial_states[kSsrc1].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200304 EXPECT_EQ(kInitialPictureId2, initial_states[kSsrc2].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100305 EXPECT_EQ(kInitialTl0PicIdx2, initial_states[kSsrc2].tl0_pic_idx);
philipel25d31ec2018-08-08 16:33:01 +0200306 EXPECT_EQ(kState2SharedFrameId, initial_states[kSsrc1].shared_frame_id);
307 EXPECT_EQ(kState2SharedFrameId, initial_states[kSsrc2].shared_frame_id);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200308}
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000309} // namespace webrtc