blob: 45f8149bba4beae64e0af3e838ca123505ecb533 [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
Stefan Holmer9416ef82018-07-19 10:34:38 +0200140TEST(RtpVideoSenderTest, SendOnOneModule) {
kjellander02b3d272016-04-20 05:05:54 -0700141 uint8_t payload = 'a';
kjellander02b3d272016-04-20 05:05:54 -0700142 EncodedImage encoded_image;
143 encoded_image._timeStamp = 1;
144 encoded_image.capture_time_ms_ = 2;
145 encoded_image._frameType = kVideoFrameKey;
146 encoded_image._buffer = &payload;
147 encoded_image._length = 1;
148
Stefan Holmer9416ef82018-07-19 10:34:38 +0200149 RtpVideoSenderTestFixture test({kSsrc1}, kPayloadType, {});
sergeyu2cb155a2016-11-04 11:39:29 -0700150 EXPECT_NE(
151 EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200152 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000153
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200154 test.router()->SetActive(true);
sergeyu2cb155a2016-11-04 11:39:29 -0700155 EXPECT_EQ(
156 EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200157 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000158
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200159 test.router()->SetActive(false);
sergeyu2cb155a2016-11-04 11:39:29 -0700160 EXPECT_NE(
161 EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200162 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000163
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200164 test.router()->SetActive(true);
sergeyu2cb155a2016-11-04 11:39:29 -0700165 EXPECT_EQ(
166 EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200167 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000168}
169
Stefan Holmer9416ef82018-07-19 10:34:38 +0200170TEST(RtpVideoSenderTest, SendSimulcastSetActive) {
kjellander02b3d272016-04-20 05:05:54 -0700171 uint8_t payload = 'a';
172 EncodedImage encoded_image;
173 encoded_image._timeStamp = 1;
174 encoded_image.capture_time_ms_ = 2;
175 encoded_image._frameType = kVideoFrameKey;
176 encoded_image._buffer = &payload;
177 encoded_image._length = 1;
178
Stefan Holmer9416ef82018-07-19 10:34:38 +0200179 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000180
kjellander02b3d272016-04-20 05:05:54 -0700181 CodecSpecificInfo codec_info_1;
182 memset(&codec_info_1, 0, sizeof(CodecSpecificInfo));
183 codec_info_1.codecType = kVideoCodecVP8;
184 codec_info_1.codecSpecific.VP8.simulcastIdx = 0;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000185
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200186 test.router()->SetActive(true);
sergeyu2cb155a2016-11-04 11:39:29 -0700187 EXPECT_EQ(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200188 test.router()
189 ->OnEncodedImage(encoded_image, &codec_info_1, nullptr)
sergeyu2cb155a2016-11-04 11:39:29 -0700190 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000191
kjellander02b3d272016-04-20 05:05:54 -0700192 CodecSpecificInfo codec_info_2;
193 memset(&codec_info_2, 0, sizeof(CodecSpecificInfo));
194 codec_info_2.codecType = kVideoCodecVP8;
195 codec_info_2.codecSpecific.VP8.simulcastIdx = 1;
sergeyu2cb155a2016-11-04 11:39:29 -0700196 EXPECT_EQ(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200197 test.router()
198 ->OnEncodedImage(encoded_image, &codec_info_2, nullptr)
sergeyu2cb155a2016-11-04 11:39:29 -0700199 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000200
mflodman@webrtc.org50e28162015-02-23 07:45:11 +0000201 // Inactive.
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200202 test.router()->SetActive(false);
sergeyu2cb155a2016-11-04 11:39:29 -0700203 EXPECT_NE(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200204 test.router()
205 ->OnEncodedImage(encoded_image, &codec_info_1, nullptr)
sergeyu2cb155a2016-11-04 11:39:29 -0700206 .error);
207 EXPECT_NE(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200208 test.router()
209 ->OnEncodedImage(encoded_image, &codec_info_2, nullptr)
sergeyu2cb155a2016-11-04 11:39:29 -0700210 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000211}
212
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800213// Tests how setting individual rtp modules to active affects the overall
214// behavior of the payload router. First sets one module to active and checks
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200215// that outgoing data can be sent on this module, and checks that no data can
216// be sent if both modules are inactive.
Stefan Holmer9416ef82018-07-19 10:34:38 +0200217TEST(RtpVideoSenderTest, SendSimulcastSetActiveModules) {
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800218 uint8_t payload = 'a';
219 EncodedImage encoded_image;
220 encoded_image._timeStamp = 1;
221 encoded_image.capture_time_ms_ = 2;
222 encoded_image._frameType = kVideoFrameKey;
223 encoded_image._buffer = &payload;
224 encoded_image._length = 1;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200225
Stefan Holmer9416ef82018-07-19 10:34:38 +0200226 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, kPayloadType, {});
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800227 CodecSpecificInfo codec_info_1;
228 memset(&codec_info_1, 0, sizeof(CodecSpecificInfo));
229 codec_info_1.codecType = kVideoCodecVP8;
230 codec_info_1.codecSpecific.VP8.simulcastIdx = 0;
231 CodecSpecificInfo codec_info_2;
232 memset(&codec_info_2, 0, sizeof(CodecSpecificInfo));
233 codec_info_2.codecType = kVideoCodecVP8;
234 codec_info_2.codecSpecific.VP8.simulcastIdx = 1;
235
236 // Only setting one stream to active will still set the payload router to
237 // active and allow sending data on the active stream.
238 std::vector<bool> active_modules({true, false});
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200239 test.router()->SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800240 EXPECT_EQ(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200241 test.router()
242 ->OnEncodedImage(encoded_image, &codec_info_1, nullptr)
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800243 .error);
244
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200245 // Setting both streams to inactive will turn the payload router to
246 // inactive.
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800247 active_modules = {false, false};
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200248 test.router()->SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800249 // An incoming encoded image will not ask the module to send outgoing data
250 // because the payload router is inactive.
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800251 EXPECT_NE(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200252 test.router()
253 ->OnEncodedImage(encoded_image, &codec_info_1, nullptr)
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800254 .error);
255 EXPECT_NE(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200256 test.router()
257 ->OnEncodedImage(encoded_image, &codec_info_2, nullptr)
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800258 .error);
259}
260
Stefan Holmer9416ef82018-07-19 10:34:38 +0200261TEST(RtpVideoSenderTest, CreateWithNoPreviousStates) {
262 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, kPayloadType, {});
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200263 test.router()->SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200264
265 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200266 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 10:04:04 +0200267 EXPECT_EQ(2u, initial_states.size());
268 EXPECT_NE(initial_states.find(kSsrc1), initial_states.end());
269 EXPECT_NE(initial_states.find(kSsrc2), initial_states.end());
270}
271
Stefan Holmer9416ef82018-07-19 10:34:38 +0200272TEST(RtpVideoSenderTest, CreateWithPreviousStates) {
Åsa Persson4bece9a2017-10-06 10:04:04 +0200273 RtpPayloadState state1;
274 state1.picture_id = kInitialPictureId1;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100275 state1.tl0_pic_idx = kInitialTl0PicIdx1;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200276 RtpPayloadState state2;
277 state2.picture_id = kInitialPictureId2;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100278 state2.tl0_pic_idx = kInitialTl0PicIdx2;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200279 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
280 {kSsrc2, state2}};
281
Stefan Holmer9416ef82018-07-19 10:34:38 +0200282 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, kPayloadType, states);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200283 test.router()->SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200284
285 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200286 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 10:04:04 +0200287 EXPECT_EQ(2u, initial_states.size());
288 EXPECT_EQ(kInitialPictureId1, initial_states[kSsrc1].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100289 EXPECT_EQ(kInitialTl0PicIdx1, initial_states[kSsrc1].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200290 EXPECT_EQ(kInitialPictureId2, initial_states[kSsrc2].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100291 EXPECT_EQ(kInitialTl0PicIdx2, initial_states[kSsrc2].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200292}
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000293} // namespace webrtc