blob: 45888a8f5033d2300e050cae7aecbdd5f40b78c5 [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
kwiberg27f982b2016-03-01 11:52:33 -080013#include <memory>
Åsa Persson4bece9a2017-10-06 10:04:04 +020014#include <string>
kwiberg27f982b2016-03-01 11:52:33 -080015
Steve Anton40d55332019-01-07 10:21:47 -080016#include "absl/memory/memory.h"
Danil Chapovalovd3ba2362019-04-10 17:01:23 +020017#include "api/task_queue/default_task_queue_factory.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020018#include "call/rtp_transport_controller_send.h"
Erik Språng490d76c2019-05-07 09:29:15 -070019#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
20#include "modules/rtp_rtcp/source/byte_io.h"
21#include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
22#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"
Erik Språng490d76c2019-05-07 09:29:15 -070025#include "rtc_base/event.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020026#include "rtc_base/rate_limiter.h"
Åsa Persson4bece9a2017-10-06 10:04:04 +020027#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "test/gmock.h"
29#include "test/gtest.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020030#include "test/mock_transport.h"
31#include "video/call_stats.h"
32#include "video/send_delay_stats.h"
33#include "video/send_statistics_proxy.h"
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000034
35using ::testing::_;
Erik Språng490d76c2019-05-07 09:29:15 -070036using ::testing::Invoke;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +000037using ::testing::NiceMock;
Niels Möller949f0fd2019-01-29 09:44:24 +010038using ::testing::SaveArg;
Åsa Persson4bece9a2017-10-06 10:04:04 +020039using ::testing::Unused;
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;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020054
55class MockRtcpIntraFrameObserver : public RtcpIntraFrameObserver {
56 public:
57 MOCK_METHOD1(OnReceivedIntraFrameRequest, void(uint32_t));
58};
59
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020060RtpSenderObservers CreateObservers(
61 RtcpRttStats* rtcp_rtt_stats,
62 RtcpIntraFrameObserver* intra_frame_callback,
63 RtcpStatisticsCallback* rtcp_stats,
Henrik Boström87e3f9d2019-05-27 10:44:24 +020064 ReportBlockDataObserver* report_block_data_observer,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020065 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 15:21:55 +020070 SendPacketObserver* send_packet_observer) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020071 RtpSenderObservers observers;
72 observers.rtcp_rtt_stats = rtcp_rtt_stats;
73 observers.intra_frame_callback = intra_frame_callback;
Erik Språng490d76c2019-05-07 09:29:15 -070074 observers.rtcp_loss_notification_observer = nullptr;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020075 observers.rtcp_stats = rtcp_stats;
Henrik Boström87e3f9d2019-05-27 10:44:24 +020076 observers.report_block_data_observer = report_block_data_observer;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020077 observers.rtp_stats = rtp_stats;
78 observers.bitrate_observer = bitrate_observer;
79 observers.frame_count_observer = frame_count_observer;
80 observers.rtcp_type_observer = rtcp_type_observer;
81 observers.send_delay_observer = send_delay_observer;
82 observers.send_packet_observer = send_packet_observer;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020083 return observers;
84}
85
Erik Språng490d76c2019-05-07 09:29:15 -070086BitrateConstraints GetBitrateConfig() {
87 BitrateConstraints bitrate_config;
88 bitrate_config.min_bitrate_bps = 30000;
89 bitrate_config.start_bitrate_bps = 300000;
90 bitrate_config.max_bitrate_bps = 3000000;
91 return bitrate_config;
92}
93
94VideoSendStream::Config CreateVideoSendStreamConfig(
95 Transport* transport,
96 const std::vector<uint32_t>& ssrcs,
97 const std::vector<uint32_t>& rtx_ssrcs,
98 int payload_type) {
99 VideoSendStream::Config config(transport);
100 config.rtp.ssrcs = ssrcs;
101 config.rtp.rtx.ssrcs = rtx_ssrcs;
102 config.rtp.payload_type = payload_type;
103 config.rtp.rtx.payload_type = payload_type + 1;
104 config.rtp.nack.rtp_history_ms = 1000;
Erik Språng845c6aa2019-05-29 13:02:24 +0200105 config.rtp.extensions.emplace_back(RtpExtension::kTransportSequenceNumberUri,
106 kTransportsSequenceExtensionId);
Erik Språng490d76c2019-05-07 09:29:15 -0700107 return config;
108}
109
Stefan Holmer9416ef82018-07-19 10:34:38 +0200110class RtpVideoSenderTestFixture {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200111 public:
Stefan Holmer9416ef82018-07-19 10:34:38 +0200112 RtpVideoSenderTestFixture(
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200113 const std::vector<uint32_t>& ssrcs,
Erik Språng490d76c2019-05-07 09:29:15 -0700114 const std::vector<uint32_t>& rtx_ssrcs,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200115 int payload_type,
Niels Möller949f0fd2019-01-29 09:44:24 +0100116 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
117 FrameCountObserver* frame_count_observer)
Sebastian Jansson572c60f2019-03-04 18:30:41 +0100118 : clock_(1000000),
Erik Språng490d76c2019-05-07 09:29:15 -0700119 config_(CreateVideoSendStreamConfig(&transport_,
120 ssrcs,
121 rtx_ssrcs,
122 payload_type)),
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200123 send_delay_stats_(&clock_),
Erik Språng490d76c2019-05-07 09:29:15 -0700124 bitrate_config_(GetBitrateConfig()),
Danil Chapovalovd3ba2362019-04-10 17:01:23 +0200125 task_queue_factory_(CreateDefaultTaskQueueFactory()),
Sebastian Janssoned50e6c2019-03-01 14:45:21 +0100126 transport_controller_(&clock_,
127 &event_log_,
128 nullptr,
Ying Wang0810a7c2019-04-10 13:48:24 +0200129 nullptr,
Sebastian Janssoned50e6c2019-03-01 14:45:21 +0100130 bitrate_config_,
131 ProcessThread::Create("PacerThread"),
Danil Chapovalovd3ba2362019-04-10 17:01:23 +0200132 task_queue_factory_.get()),
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200133 process_thread_(ProcessThread::Create("test_thread")),
134 call_stats_(&clock_, process_thread_.get()),
135 stats_proxy_(&clock_,
136 config_,
137 VideoEncoderConfig::ContentType::kRealtimeVideo),
138 retransmission_rate_limiter_(&clock_, kRetransmitWindowSizeMs) {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200139 std::map<uint32_t, RtpState> suspended_ssrcs;
Stefan Holmer9416ef82018-07-19 10:34:38 +0200140 router_ = absl::make_unique<RtpVideoSender>(
Sebastian Jansson572c60f2019-03-04 18:30:41 +0100141 &clock_, suspended_ssrcs, suspended_payload_states, config_.rtp,
Oleh Prypine8964902019-03-29 15:33:01 +0000142 config_.rtcp_report_interval_ms, &transport_,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200143 CreateObservers(&call_stats_, &encoder_feedback_, &stats_proxy_,
Henrik Boström87e3f9d2019-05-27 10:44:24 +0200144 &stats_proxy_, &stats_proxy_, &stats_proxy_,
145 frame_count_observer, &stats_proxy_, &stats_proxy_,
146 &send_delay_stats_),
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200147 &transport_controller_, &event_log_, &retransmission_rate_limiter_,
Benjamin Wright192eeec2018-10-17 17:27:25 -0700148 absl::make_unique<FecControllerDefault>(&clock_), nullptr,
149 CryptoOptions{});
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200150 }
Niels Möller949f0fd2019-01-29 09:44:24 +0100151 RtpVideoSenderTestFixture(
152 const std::vector<uint32_t>& ssrcs,
Erik Språng490d76c2019-05-07 09:29:15 -0700153 const std::vector<uint32_t>& rtx_ssrcs,
Niels Möller949f0fd2019-01-29 09:44:24 +0100154 int payload_type,
155 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states)
156 : RtpVideoSenderTestFixture(ssrcs,
Erik Språng490d76c2019-05-07 09:29:15 -0700157 rtx_ssrcs,
Niels Möller949f0fd2019-01-29 09:44:24 +0100158 payload_type,
159 suspended_payload_states,
160 /*frame_count_observer=*/nullptr) {}
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200161
Stefan Holmer9416ef82018-07-19 10:34:38 +0200162 RtpVideoSender* router() { return router_.get(); }
Erik Språng490d76c2019-05-07 09:29:15 -0700163 MockTransport& transport() { return transport_; }
164 SimulatedClock& clock() { return clock_; }
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200165
166 private:
167 NiceMock<MockTransport> transport_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200168 NiceMock<MockRtcpIntraFrameObserver> encoder_feedback_;
169 SimulatedClock clock_;
Danil Chapovalov83bbe912019-08-07 12:24:53 +0200170 RtcEventLogNull event_log_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200171 VideoSendStream::Config config_;
172 SendDelayStats send_delay_stats_;
173 BitrateConstraints bitrate_config_;
Danil Chapovalovd3ba2362019-04-10 17:01:23 +0200174 const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200175 RtpTransportControllerSend transport_controller_;
176 std::unique_ptr<ProcessThread> process_thread_;
177 CallStats call_stats_;
178 SendStatisticsProxy stats_proxy_;
179 RateLimiter retransmission_rate_limiter_;
Stefan Holmer9416ef82018-07-19 10:34:38 +0200180 std::unique_ptr<RtpVideoSender> router_;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200181};
Åsa Persson4bece9a2017-10-06 10:04:04 +0200182} // namespace
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000183
Sebastian Jansson63470292019-02-01 10:13:43 +0100184TEST(RtpVideoSenderTest, SendOnOneModule) {
Niels Möller663844d2019-02-14 16:15:54 +0100185 constexpr uint8_t kPayload = 'a';
kjellander02b3d272016-04-20 05:05:54 -0700186 EncodedImage encoded_image;
Niels Möller23775882018-08-16 10:24:12 +0200187 encoded_image.SetTimestamp(1);
kjellander02b3d272016-04-20 05:05:54 -0700188 encoded_image.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 15:43:58 +0100189 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200190 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
kjellander02b3d272016-04-20 05:05:54 -0700191
Erik Språng490d76c2019-05-07 09:29:15 -0700192 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
sergeyu2cb155a2016-11-04 11:39:29 -0700193 EXPECT_NE(
194 EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200195 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000196
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200197 test.router()->SetActive(true);
sergeyu2cb155a2016-11-04 11:39:29 -0700198 EXPECT_EQ(
199 EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200200 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000201
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200202 test.router()->SetActive(false);
sergeyu2cb155a2016-11-04 11:39:29 -0700203 EXPECT_NE(
204 EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200205 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000206
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200207 test.router()->SetActive(true);
sergeyu2cb155a2016-11-04 11:39:29 -0700208 EXPECT_EQ(
209 EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200210 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000211}
212
Sebastian Jansson63470292019-02-01 10:13:43 +0100213TEST(RtpVideoSenderTest, SendSimulcastSetActive) {
Niels Möller663844d2019-02-14 16:15:54 +0100214 constexpr uint8_t kPayload = 'a';
Niels Möllerd3b8c632018-08-27 15:33:42 +0200215 EncodedImage encoded_image_1;
216 encoded_image_1.SetTimestamp(1);
217 encoded_image_1.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 15:43:58 +0100218 encoded_image_1._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200219 encoded_image_1.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
kjellander02b3d272016-04-20 05:05:54 -0700220
Erik Språng490d76c2019-05-07 09:29:15 -0700221 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
222 kPayloadType, {});
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000223
Niels Möllerd3b8c632018-08-27 15:33:42 +0200224 CodecSpecificInfo codec_info;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200225 codec_info.codecType = kVideoCodecVP8;
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000226
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200227 test.router()->SetActive(true);
sergeyu2cb155a2016-11-04 11:39:29 -0700228 EXPECT_EQ(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200229 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200230 ->OnEncodedImage(encoded_image_1, &codec_info, nullptr)
sergeyu2cb155a2016-11-04 11:39:29 -0700231 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000232
Niels Möllerd3b8c632018-08-27 15:33:42 +0200233 EncodedImage encoded_image_2(encoded_image_1);
234 encoded_image_2.SetSpatialIndex(1);
sergeyu2cb155a2016-11-04 11:39:29 -0700235 EXPECT_EQ(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200236 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200237 ->OnEncodedImage(encoded_image_2, &codec_info, nullptr)
sergeyu2cb155a2016-11-04 11:39:29 -0700238 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000239
mflodman@webrtc.org50e28162015-02-23 07:45:11 +0000240 // Inactive.
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200241 test.router()->SetActive(false);
sergeyu2cb155a2016-11-04 11:39:29 -0700242 EXPECT_NE(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200243 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200244 ->OnEncodedImage(encoded_image_1, &codec_info, nullptr)
sergeyu2cb155a2016-11-04 11:39:29 -0700245 .error);
246 EXPECT_NE(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200247 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200248 ->OnEncodedImage(encoded_image_2, &codec_info, nullptr)
sergeyu2cb155a2016-11-04 11:39:29 -0700249 .error);
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000250}
251
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800252// Tests how setting individual rtp modules to active affects the overall
253// behavior of the payload router. First sets one module to active and checks
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200254// that outgoing data can be sent on this module, and checks that no data can
255// be sent if both modules are inactive.
Sebastian Jansson63470292019-02-01 10:13:43 +0100256TEST(RtpVideoSenderTest, SendSimulcastSetActiveModules) {
Niels Möller663844d2019-02-14 16:15:54 +0100257 constexpr uint8_t kPayload = 'a';
Niels Möllerd3b8c632018-08-27 15:33:42 +0200258 EncodedImage encoded_image_1;
259 encoded_image_1.SetTimestamp(1);
260 encoded_image_1.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 15:43:58 +0100261 encoded_image_1._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200262 encoded_image_1.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Niels Möller77536a22019-01-15 08:50:01 +0100263
Niels Möllerd3b8c632018-08-27 15:33:42 +0200264 EncodedImage encoded_image_2(encoded_image_1);
265 encoded_image_2.SetSpatialIndex(1);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200266
Erik Språng490d76c2019-05-07 09:29:15 -0700267 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
268 kPayloadType, {});
Niels Möllerd3b8c632018-08-27 15:33:42 +0200269 CodecSpecificInfo codec_info;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200270 codec_info.codecType = kVideoCodecVP8;
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800271
272 // Only setting one stream to active will still set the payload router to
273 // active and allow sending data on the active stream.
274 std::vector<bool> active_modules({true, false});
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200275 test.router()->SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800276 EXPECT_EQ(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200277 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200278 ->OnEncodedImage(encoded_image_1, &codec_info, nullptr)
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800279 .error);
280
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200281 // Setting both streams to inactive will turn the payload router to
282 // inactive.
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800283 active_modules = {false, false};
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200284 test.router()->SetActiveModules(active_modules);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800285 // An incoming encoded image will not ask the module to send outgoing data
286 // because the payload router is inactive.
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800287 EXPECT_NE(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200288 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200289 ->OnEncodedImage(encoded_image_1, &codec_info, nullptr)
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800290 .error);
291 EXPECT_NE(EncodedImageCallback::Result::OK,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200292 test.router()
Niels Möllerd3b8c632018-08-27 15:33:42 +0200293 ->OnEncodedImage(encoded_image_1, &codec_info, nullptr)
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800294 .error);
295}
296
Sebastian Jansson63470292019-02-01 10:13:43 +0100297TEST(RtpVideoSenderTest, CreateWithNoPreviousStates) {
Erik Språng490d76c2019-05-07 09:29:15 -0700298 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
299 kPayloadType, {});
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200300 test.router()->SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200301
302 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200303 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 10:04:04 +0200304 EXPECT_EQ(2u, initial_states.size());
305 EXPECT_NE(initial_states.find(kSsrc1), initial_states.end());
306 EXPECT_NE(initial_states.find(kSsrc2), initial_states.end());
307}
308
Sebastian Jansson63470292019-02-01 10:13:43 +0100309TEST(RtpVideoSenderTest, CreateWithPreviousStates) {
philipel25d31ec2018-08-08 16:33:01 +0200310 const int64_t kState1SharedFrameId = 123;
311 const int64_t kState2SharedFrameId = 234;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200312 RtpPayloadState state1;
313 state1.picture_id = kInitialPictureId1;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100314 state1.tl0_pic_idx = kInitialTl0PicIdx1;
philipel25d31ec2018-08-08 16:33:01 +0200315 state1.shared_frame_id = kState1SharedFrameId;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200316 RtpPayloadState state2;
317 state2.picture_id = kInitialPictureId2;
Niels Möllerbb894ff2018-03-15 12:28:53 +0100318 state2.tl0_pic_idx = kInitialTl0PicIdx2;
philipel25d31ec2018-08-08 16:33:01 +0200319 state2.shared_frame_id = kState2SharedFrameId;
Åsa Persson4bece9a2017-10-06 10:04:04 +0200320 std::map<uint32_t, RtpPayloadState> states = {{kSsrc1, state1},
321 {kSsrc2, state2}};
322
Erik Språng490d76c2019-05-07 09:29:15 -0700323 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
324 kPayloadType, states);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200325 test.router()->SetActive(true);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200326
327 std::map<uint32_t, RtpPayloadState> initial_states =
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200328 test.router()->GetRtpPayloadStates();
Åsa Persson4bece9a2017-10-06 10:04:04 +0200329 EXPECT_EQ(2u, initial_states.size());
330 EXPECT_EQ(kInitialPictureId1, initial_states[kSsrc1].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100331 EXPECT_EQ(kInitialTl0PicIdx1, initial_states[kSsrc1].tl0_pic_idx);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200332 EXPECT_EQ(kInitialPictureId2, initial_states[kSsrc2].picture_id);
Niels Möllerbb894ff2018-03-15 12:28:53 +0100333 EXPECT_EQ(kInitialTl0PicIdx2, initial_states[kSsrc2].tl0_pic_idx);
philipel25d31ec2018-08-08 16:33:01 +0200334 EXPECT_EQ(kState2SharedFrameId, initial_states[kSsrc1].shared_frame_id);
335 EXPECT_EQ(kState2SharedFrameId, initial_states[kSsrc2].shared_frame_id);
Åsa Persson4bece9a2017-10-06 10:04:04 +0200336}
Niels Möller949f0fd2019-01-29 09:44:24 +0100337
Sebastian Jansson63470292019-02-01 10:13:43 +0100338TEST(RtpVideoSenderTest, FrameCountCallbacks) {
Niels Möller949f0fd2019-01-29 09:44:24 +0100339 class MockFrameCountObserver : public FrameCountObserver {
340 public:
341 MOCK_METHOD2(FrameCountUpdated,
342 void(const FrameCounts& frame_counts, uint32_t ssrc));
343 } callback;
344
Erik Språng490d76c2019-05-07 09:29:15 -0700345 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {},
346 &callback);
Niels Möller949f0fd2019-01-29 09:44:24 +0100347
Niels Möller663844d2019-02-14 16:15:54 +0100348 constexpr uint8_t kPayload = 'a';
Niels Möller949f0fd2019-01-29 09:44:24 +0100349 EncodedImage encoded_image;
350 encoded_image.SetTimestamp(1);
351 encoded_image.capture_time_ms_ = 2;
Niels Möller8f7ce222019-03-21 15:43:58 +0100352 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200353 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Niels Möller949f0fd2019-01-29 09:44:24 +0100354
Niels Möller8f7ce222019-03-21 15:43:58 +0100355 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller949f0fd2019-01-29 09:44:24 +0100356
357 // No callbacks when not active.
358 EXPECT_CALL(callback, FrameCountUpdated).Times(0);
359 EXPECT_NE(
360 EncodedImageCallback::Result::OK,
361 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200362 ::testing::Mock::VerifyAndClearExpectations(&callback);
Niels Möller949f0fd2019-01-29 09:44:24 +0100363
364 test.router()->SetActive(true);
365
366 FrameCounts frame_counts;
367 EXPECT_CALL(callback, FrameCountUpdated(_, kSsrc1))
368 .WillOnce(SaveArg<0>(&frame_counts));
369 EXPECT_EQ(
370 EncodedImageCallback::Result::OK,
371 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
372
373 EXPECT_EQ(1, frame_counts.key_frames);
374 EXPECT_EQ(0, frame_counts.delta_frames);
375
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200376 ::testing::Mock::VerifyAndClearExpectations(&callback);
Niels Möller949f0fd2019-01-29 09:44:24 +0100377
Niels Möller8f7ce222019-03-21 15:43:58 +0100378 encoded_image._frameType = VideoFrameType::kVideoFrameDelta;
Niels Möller949f0fd2019-01-29 09:44:24 +0100379 EXPECT_CALL(callback, FrameCountUpdated(_, kSsrc1))
380 .WillOnce(SaveArg<0>(&frame_counts));
381 EXPECT_EQ(
382 EncodedImageCallback::Result::OK,
383 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
384
385 EXPECT_EQ(1, frame_counts.key_frames);
386 EXPECT_EQ(1, frame_counts.delta_frames);
387}
388
Erik Språng490d76c2019-05-07 09:29:15 -0700389// Integration test verifying that ack of packet via TransportFeedback means
Erik Språng845c6aa2019-05-29 13:02:24 +0200390// that the packet is removed from RtpPacketHistory and won't be retransmitted
Erik Språng490d76c2019-05-07 09:29:15 -0700391// again.
392TEST(RtpVideoSenderTest, DoesNotRetrasmitAckedPackets) {
393 const int64_t kTimeoutMs = 500;
394
395 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
396 kPayloadType, {});
397 test.router()->SetActive(true);
398
399 constexpr uint8_t kPayload = 'a';
400 EncodedImage encoded_image;
401 encoded_image.SetTimestamp(1);
402 encoded_image.capture_time_ms_ = 2;
403 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
Niels Möller4d504c72019-06-18 15:56:56 +0200404 encoded_image.SetEncodedData(EncodedImageBuffer::Create(&kPayload, 1));
Erik Språng490d76c2019-05-07 09:29:15 -0700405
406 // Send two tiny images, mapping to two RTP packets. Capture sequence numbers.
407 rtc::Event event;
408 std::vector<uint16_t> rtp_sequence_numbers;
409 std::vector<uint16_t> transport_sequence_numbers;
410 EXPECT_CALL(test.transport(), SendRtp)
411 .Times(2)
412 .WillRepeatedly(
413 [&event, &rtp_sequence_numbers, &transport_sequence_numbers](
414 const uint8_t* packet, size_t length,
415 const PacketOptions& options) {
416 RtpPacket rtp_packet;
417 EXPECT_TRUE(rtp_packet.Parse(packet, length));
418 rtp_sequence_numbers.push_back(rtp_packet.SequenceNumber());
419 transport_sequence_numbers.push_back(options.packet_id);
420 if (transport_sequence_numbers.size() == 2) {
421 event.Set();
422 }
423 return true;
424 });
425 EXPECT_EQ(
426 EncodedImageCallback::Result::OK,
427 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
428 encoded_image.SetTimestamp(2);
429 encoded_image.capture_time_ms_ = 3;
430 EXPECT_EQ(
431 EncodedImageCallback::Result::OK,
432 test.router()->OnEncodedImage(encoded_image, nullptr, nullptr).error);
Erik Språngbd7046c2019-05-07 14:54:29 -0700433 const int64_t send_time_ms = test.clock().TimeInMilliseconds();
434
Erik Språng490d76c2019-05-07 09:29:15 -0700435 test.clock().AdvanceTimeMilliseconds(33);
436
437 ASSERT_TRUE(event.Wait(kTimeoutMs));
438
439 // Construct a NACK message for requesting retransmission of both packet.
440 rtcp::Nack nack;
441 nack.SetMediaSsrc(kSsrc1);
442 nack.SetPacketIds(rtp_sequence_numbers);
443 rtc::Buffer nack_buffer = nack.Build();
444
445 std::vector<uint16_t> retransmitted_rtp_sequence_numbers;
446 EXPECT_CALL(test.transport(), SendRtp)
447 .Times(2)
448 .WillRepeatedly([&event, &retransmitted_rtp_sequence_numbers](
449 const uint8_t* packet, size_t length,
450 const PacketOptions& options) {
451 RtpPacket rtp_packet;
452 EXPECT_TRUE(rtp_packet.Parse(packet, length));
453 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
454 // Capture the retransmitted sequence number from the RTX header.
455 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
456 retransmitted_rtp_sequence_numbers.push_back(
457 ByteReader<uint16_t>::ReadBigEndian(payload.data()));
458 if (retransmitted_rtp_sequence_numbers.size() == 2) {
459 event.Set();
460 }
461 return true;
462 });
463 test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size());
464 ASSERT_TRUE(event.Wait(kTimeoutMs));
465
466 // Verify that both packets were retransmitted.
467 EXPECT_EQ(retransmitted_rtp_sequence_numbers, rtp_sequence_numbers);
468
469 // Simulate transport feedback indicating fist packet received, next packet
470 // lost.
471 PacketFeedback received_packet_feedback(test.clock().TimeInMilliseconds(),
472 transport_sequence_numbers[0]);
473 received_packet_feedback.rtp_sequence_number = rtp_sequence_numbers[0];
474 received_packet_feedback.ssrc = kSsrc1;
Erik Språngbd7046c2019-05-07 14:54:29 -0700475 received_packet_feedback.send_time_ms = send_time_ms;
Erik Språng490d76c2019-05-07 09:29:15 -0700476
477 PacketFeedback lost_packet_feedback(PacketFeedback::kNotReceived,
478 transport_sequence_numbers[1]);
479 lost_packet_feedback.rtp_sequence_number = rtp_sequence_numbers[1];
480 lost_packet_feedback.ssrc = kSsrc1;
Erik Språngbd7046c2019-05-07 14:54:29 -0700481 lost_packet_feedback.send_time_ms = send_time_ms;
Erik Språng490d76c2019-05-07 09:29:15 -0700482 std::vector<PacketFeedback> feedback_vector = {received_packet_feedback,
483 lost_packet_feedback};
484
485 test.router()->OnPacketFeedbackVector(feedback_vector);
486
487 // Advance time to make sure retransmission would be allowed and try again.
488 // This time the retransmission should not happen for the first packet since
489 // the history has been notified of the ack and removed the packet. The
490 // second packet, included in the feedback but not marked as received, should
491 // still be retransmitted.
492 test.clock().AdvanceTimeMilliseconds(33);
493 EXPECT_CALL(test.transport(), SendRtp)
494 .WillOnce([&event, &lost_packet_feedback](const uint8_t* packet,
495 size_t length,
496 const PacketOptions& options) {
497 RtpPacket rtp_packet;
498 EXPECT_TRUE(rtp_packet.Parse(packet, length));
499 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc1);
500 // Capture the retransmitted sequence number from the RTX header.
501 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
502 EXPECT_EQ(lost_packet_feedback.rtp_sequence_number,
503 ByteReader<uint16_t>::ReadBigEndian(payload.data()));
504 event.Set();
505 return true;
506 });
507 test.router()->DeliverRtcp(nack_buffer.data(), nack_buffer.size());
508 ASSERT_TRUE(event.Wait(kTimeoutMs));
509}
Erik Språng845c6aa2019-05-29 13:02:24 +0200510
511// Integration test verifying that retransmissions are sent for packets which
512// can be detected as lost early, using transport wide feedback.
513TEST(RtpVideoSenderTest, EarlyRetransmits) {
514 const int64_t kTimeoutMs = 500;
515
516 RtpVideoSenderTestFixture test({kSsrc1, kSsrc2}, {kRtxSsrc1, kRtxSsrc2},
517 kPayloadType, {});
518 test.router()->SetActive(true);
519
520 constexpr uint8_t kPayload = 'a';
521 EncodedImage encoded_image;
522 encoded_image.SetTimestamp(1);
523 encoded_image.capture_time_ms_ = 2;
524 encoded_image._frameType = VideoFrameType::kVideoFrameKey;
525 encoded_image.Allocate(1);
526 encoded_image.data()[0] = kPayload;
527 encoded_image.set_size(1);
528 encoded_image.SetSpatialIndex(0);
529
530 CodecSpecificInfo codec_specific;
531 codec_specific.codecType = VideoCodecType::kVideoCodecGeneric;
532
533 // Send two tiny images, mapping to single RTP packets. Capture sequence
534 // numbers.
535 rtc::Event event;
536 uint16_t frame1_rtp_sequence_number = 0;
537 uint16_t frame1_transport_sequence_number = 0;
538 EXPECT_CALL(test.transport(), SendRtp)
539 .WillOnce([&event, &frame1_rtp_sequence_number,
540 &frame1_transport_sequence_number](
541 const uint8_t* packet, size_t length,
542 const PacketOptions& options) {
543 RtpPacket rtp_packet;
544 EXPECT_TRUE(rtp_packet.Parse(packet, length));
545 frame1_rtp_sequence_number = rtp_packet.SequenceNumber();
546 frame1_transport_sequence_number = options.packet_id;
547 EXPECT_EQ(rtp_packet.Ssrc(), kSsrc1);
548 event.Set();
549 return true;
550 });
551 EXPECT_EQ(test.router()
552 ->OnEncodedImage(encoded_image, &codec_specific, nullptr)
553 .error,
554 EncodedImageCallback::Result::OK);
555 const int64_t send_time_ms = test.clock().TimeInMilliseconds();
556
557 test.clock().AdvanceTimeMilliseconds(33);
558 ASSERT_TRUE(event.Wait(kTimeoutMs));
559
560 uint16_t frame2_rtp_sequence_number = 0;
561 uint16_t frame2_transport_sequence_number = 0;
562 encoded_image.SetSpatialIndex(1);
563 EXPECT_CALL(test.transport(), SendRtp)
564 .WillOnce([&event, &frame2_rtp_sequence_number,
565 &frame2_transport_sequence_number](
566 const uint8_t* packet, size_t length,
567 const PacketOptions& options) {
568 RtpPacket rtp_packet;
569 EXPECT_TRUE(rtp_packet.Parse(packet, length));
570 frame2_rtp_sequence_number = rtp_packet.SequenceNumber();
571 frame2_transport_sequence_number = options.packet_id;
572 EXPECT_EQ(rtp_packet.Ssrc(), kSsrc2);
573 event.Set();
574 return true;
575 });
576 EXPECT_EQ(test.router()
577 ->OnEncodedImage(encoded_image, &codec_specific, nullptr)
578 .error,
579 EncodedImageCallback::Result::OK);
580 test.clock().AdvanceTimeMilliseconds(33);
581 ASSERT_TRUE(event.Wait(kTimeoutMs));
582
583 EXPECT_NE(frame1_transport_sequence_number, frame2_transport_sequence_number);
584
585 // Inject a transport feedback where the packet for the first frame is lost,
586 // expect a retransmission for it.
587 EXPECT_CALL(test.transport(), SendRtp)
588 .WillOnce([&event, &frame1_rtp_sequence_number](
589 const uint8_t* packet, size_t length,
590 const PacketOptions& options) {
591 RtpPacket rtp_packet;
592 EXPECT_TRUE(rtp_packet.Parse(packet, length));
593 EXPECT_EQ(rtp_packet.Ssrc(), kRtxSsrc2);
594
595 // Retransmitted sequence number from the RTX header should match
596 // the lost packet.
597 rtc::ArrayView<const uint8_t> payload = rtp_packet.payload();
598 EXPECT_EQ(ByteReader<uint16_t>::ReadBigEndian(payload.data()),
599 frame1_rtp_sequence_number);
600 event.Set();
601 return true;
602 });
603
604 PacketFeedback first_packet_feedback(PacketFeedback::kNotReceived,
605 frame1_transport_sequence_number);
606 first_packet_feedback.rtp_sequence_number = frame1_rtp_sequence_number;
607 first_packet_feedback.ssrc = kSsrc1;
608 first_packet_feedback.send_time_ms = send_time_ms;
609
610 PacketFeedback second_packet_feedback(test.clock().TimeInMilliseconds(),
611 frame2_transport_sequence_number);
612 first_packet_feedback.rtp_sequence_number = frame2_rtp_sequence_number;
613 first_packet_feedback.ssrc = kSsrc2;
614 first_packet_feedback.send_time_ms = send_time_ms + 33;
615
616 std::vector<PacketFeedback> feedback_vector = {first_packet_feedback,
617 second_packet_feedback};
618
619 test.router()->OnPacketFeedbackVector(feedback_vector);
620
621 // Wait for pacer to run and send the RTX packet.
622 test.clock().AdvanceTimeMilliseconds(33);
623 ASSERT_TRUE(event.Wait(kTimeoutMs));
624}
Sebastian Janssoncf41eb12019-06-10 11:30:59 +0200625
626TEST(RtpVideoSenderTest, CanSetZeroBitrateWithOverhead) {
627 test::ScopedFieldTrials trials("WebRTC-SendSideBwe-WithOverhead/Enabled/");
628 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
629
630 test.router()->OnBitrateUpdated(/*bitrate_bps*/ 0,
631 /*fraction_loss*/ 0,
632 /*rtt*/ 0,
633 /*framerate*/ 0);
634}
635
636TEST(RtpVideoSenderTest, CanSetZeroBitrateWithoutOverhead) {
637 RtpVideoSenderTestFixture test({kSsrc1}, {kRtxSsrc1}, kPayloadType, {});
638
639 test.router()->OnBitrateUpdated(/*bitrate_bps*/ 0,
640 /*fraction_loss*/ 0,
641 /*rtt*/ 0,
642 /*framerate*/ 0);
643}
mflodman@webrtc.org02270cd2015-02-06 13:10:19 +0000644} // namespace webrtc