blob: a36be32d32834679aa9c12bb58327a6c4b8dae02 [file] [log] [blame]
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +00001/*
2 * Copyright (c) 2013 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 */
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +000010#include <algorithm> // max
kwiberg27f982b2016-03-01 11:52:33 -080011#include <memory>
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +000012#include <vector>
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +000013
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000014#include "testing/gtest/include/gtest/gtest.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000015
Per9b3f56e2015-04-09 13:44:16 +020016#include "webrtc/base/bind.h"
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000017#include "webrtc/base/checks.h"
Peter Boströmff019b02015-04-30 14:16:07 +020018#include "webrtc/base/criticalsection.h"
Peter Boström5811a392015-12-10 13:02:50 +010019#include "webrtc/base/event.h"
Peter Boström415d2cd2015-10-26 11:35:17 +010020#include "webrtc/base/logging.h"
pbos12411ef2015-11-23 14:47:56 -080021#include "webrtc/base/platform_thread.h"
Erik Språng737336d2016-07-29 12:59:36 +020022#include "webrtc/base/rate_limiter.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000023#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020024#include "webrtc/call/transport_adapter.h"
pbosa96b60b2016-04-18 21:12:48 -070025#include "webrtc/common_video/include/frame_callback.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010026#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
27#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000028#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
pbos@webrtc.org013d9942013-08-22 09:42:17 +000029#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
philipel0f9af012015-09-01 07:01:51 -070030#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h"
philipel7fabd462015-09-03 04:42:32 -070031#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010032#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000033#include "webrtc/test/call_test.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000034#include "webrtc/test/configurable_frame_size_encoder.h"
Peter Boströmeb66e802015-06-05 11:08:03 +020035#include "webrtc/test/fake_texture_frame.h"
perkja49cbd32016-09-16 07:53:41 -070036#include "webrtc/test/frame_generator.h"
nisse26acec42016-04-15 03:43:39 -070037#include "webrtc/test/frame_utils.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000038#include "webrtc/test/null_transport.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000039#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.org273a4142014-12-01 15:23:21 +000040#include "webrtc/video/send_statistics_proxy.h"
Thiago Farina9bfe3da2015-04-10 12:52:13 +020041#include "webrtc/video_frame.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000042#include "webrtc/video_send_stream.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000043
44namespace webrtc {
45
sprang@webrtc.org346094c2014-02-18 08:40:33 +000046enum VideoFormat { kGeneric, kVP8, };
47
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070048void ExpectEqualFramesVector(const std::vector<VideoFrame>& frames1,
49 const std::vector<VideoFrame>& frames2);
50VideoFrame CreateVideoFrame(int width, int height, uint8_t data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000051
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000052class VideoSendStreamTest : public test::CallTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000053 protected:
stefan@webrtc.org69969e22013-11-15 12:32:15 +000054 void TestNackRetransmission(uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +000055 uint8_t retransmit_payload_type);
sprang@webrtc.org346094c2014-02-18 08:40:33 +000056 void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
Åsa Perssonff24c042015-12-04 10:58:08 +010057
58 void TestVp9NonFlexMode(uint8_t num_temporal_layers,
59 uint8_t num_spatial_layers);
pbos@webrtc.org013d9942013-08-22 09:42:17 +000060};
61
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000062TEST_F(VideoSendStreamTest, CanStartStartedStream) {
solenberg4fbae2b2015-08-28 04:07:10 -070063 Call::Config call_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000064 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000065
solenberg4fbae2b2015-08-28 04:07:10 -070066 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +010067 CreateSendConfig(1, 0, &transport);
68 CreateVideoStreams();
stefanff483612015-12-21 03:14:00 -080069 video_send_stream_->Start();
70 video_send_stream_->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000071 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000072}
73
74TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
solenberg4fbae2b2015-08-28 04:07:10 -070075 Call::Config call_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000076 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000077
solenberg4fbae2b2015-08-28 04:07:10 -070078 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +010079 CreateSendConfig(1, 0, &transport);
80 CreateVideoStreams();
stefanff483612015-12-21 03:14:00 -080081 video_send_stream_->Stop();
82 video_send_stream_->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000083 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000084}
85
pbos@webrtc.org013d9942013-08-22 09:42:17 +000086TEST_F(VideoSendStreamTest, SupportsCName) {
87 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000088 class CNameObserver : public test::SendTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000089 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000090 CNameObserver() : SendTest(kDefaultTimeoutMs) {}
pbos@webrtc.org013d9942013-08-22 09:42:17 +000091
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000092 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000093 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000094 RTCPUtility::RTCPParserV2 parser(packet, length, true);
95 EXPECT_TRUE(parser.IsValid());
96
97 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +020098 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
99 if (packet_type == RTCPUtility::RTCPPacketTypes::kSdesChunk) {
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000100 EXPECT_EQ(parser.Packet().CName.CName, kCName);
Peter Boström5811a392015-12-10 13:02:50 +0100101 observation_complete_.Set();
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000102 }
103
104 packet_type = parser.Iterate();
105 }
106
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000107 return SEND_PACKET;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000108 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000109
stefanff483612015-12-21 03:14:00 -0800110 void ModifyVideoConfigs(
111 VideoSendStream::Config* send_config,
112 std::vector<VideoReceiveStream::Config>* receive_configs,
113 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000114 send_config->rtp.c_name = kCName;
115 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000116
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000117 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100118 EXPECT_TRUE(Wait()) << "Timed out while waiting for RTCP with CNAME.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000119 }
120 } test;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000121
stefane74eef12016-01-08 06:47:13 -0800122 RunBaseTest(&test);
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000123}
124
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000125TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000126 class AbsoluteSendTimeObserver : public test::SendTest {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000127 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000128 AbsoluteSendTimeObserver() : SendTest(kDefaultTimeoutMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000129 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
Stefan Holmer4654d202015-12-08 09:10:43 +0100130 kRtpExtensionAbsoluteSendTime, test::kAbsSendTimeExtensionId));
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000131 }
132
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000133 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000134 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000135 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000136
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000137 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
138 EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
139 EXPECT_EQ(header.extension.transmissionTimeOffset, 0);
skvladc3f35152016-09-02 13:23:46 -0700140 if (header.extension.absoluteSendTime != 0) {
141 // Wait for at least one packet with a non-zero send time. The send time
142 // is a 16-bit value derived from the system clock, and it is valid
143 // for a packet to have a zero send time. To tell that from an
144 // unpopulated value we'll wait for a packet with non-zero send time.
145 observation_complete_.Set();
146 } else {
147 LOG(LS_WARNING) << "Got a packet with zero absoluteSendTime, waiting"
148 " for another packet...";
149 }
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000150
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000151 return SEND_PACKET;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000152 }
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000153
stefanff483612015-12-21 03:14:00 -0800154 void ModifyVideoConfigs(
155 VideoSendStream::Config* send_config,
156 std::vector<VideoReceiveStream::Config>* receive_configs,
157 VideoEncoderConfig* encoder_config) override {
Erik Språng95261872015-04-10 11:58:49 +0200158 send_config->rtp.extensions.clear();
Stefan Holmer4654d202015-12-08 09:10:43 +0100159 send_config->rtp.extensions.push_back(RtpExtension(
isheriff6f8d6862016-05-26 11:24:55 -0700160 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000161 }
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +0000162
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000163 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100164 EXPECT_TRUE(Wait()) << "Timed out while waiting for single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000165 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000166 } test;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000167
stefane74eef12016-01-08 06:47:13 -0800168 RunBaseTest(&test);
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000169}
170
pbos@webrtc.org29023282013-09-11 10:14:56 +0000171TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000172 static const int kEncodeDelayMs = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000173 class TransmissionTimeOffsetObserver : public test::SendTest {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000174 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000175 TransmissionTimeOffsetObserver()
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000176 : SendTest(kDefaultTimeoutMs),
177 encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000178 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
Stefan Holmer12952972015-10-29 15:13:24 +0100179 kRtpExtensionTransmissionTimeOffset, test::kTOffsetExtensionId));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000180 }
181
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000182 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000183 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000184 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000185 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000186
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000187 EXPECT_TRUE(header.extension.hasTransmissionTimeOffset);
188 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000189 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000190 EXPECT_EQ(header.extension.absoluteSendTime, 0u);
Peter Boström5811a392015-12-10 13:02:50 +0100191 observation_complete_.Set();
pbos@webrtc.org29023282013-09-11 10:14:56 +0000192
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000193 return SEND_PACKET;
pbos@webrtc.org29023282013-09-11 10:14:56 +0000194 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000195
stefanff483612015-12-21 03:14:00 -0800196 void ModifyVideoConfigs(
197 VideoSendStream::Config* send_config,
198 std::vector<VideoReceiveStream::Config>* receive_configs,
199 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000200 send_config->encoder_settings.encoder = &encoder_;
Stefan Holmer12952972015-10-29 15:13:24 +0100201 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -0700202 send_config->rtp.extensions.push_back(RtpExtension(
203 RtpExtension::kTimestampOffsetUri, test::kTOffsetExtensionId));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000204 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000205
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000206 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100207 EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000208 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000209
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000210 test::DelayedEncoder encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000211 } test;
212
stefane74eef12016-01-08 06:47:13 -0800213 RunBaseTest(&test);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000214}
215
sprang867fb522015-08-03 04:38:41 -0700216TEST_F(VideoSendStreamTest, SupportsTransportWideSequenceNumbers) {
217 static const uint8_t kExtensionId = 13;
218 class TransportWideSequenceNumberObserver : public test::SendTest {
219 public:
220 TransportWideSequenceNumberObserver()
221 : SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) {
222 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
223 kRtpExtensionTransportSequenceNumber, kExtensionId));
224 }
225
226 private:
227 Action OnSendRtp(const uint8_t* packet, size_t length) override {
228 RTPHeader header;
229 EXPECT_TRUE(parser_->Parse(packet, length, &header));
230
231 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
232 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
233 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
234
Peter Boström5811a392015-12-10 13:02:50 +0100235 observation_complete_.Set();
sprang867fb522015-08-03 04:38:41 -0700236
237 return SEND_PACKET;
238 }
239
stefanff483612015-12-21 03:14:00 -0800240 void ModifyVideoConfigs(
241 VideoSendStream::Config* send_config,
242 std::vector<VideoReceiveStream::Config>* receive_configs,
243 VideoEncoderConfig* encoder_config) override {
sprang867fb522015-08-03 04:38:41 -0700244 send_config->encoder_settings.encoder = &encoder_;
Stefan Holmer12952972015-10-29 15:13:24 +0100245 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -0700246 send_config->rtp.extensions.push_back(RtpExtension(
247 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -0700248 }
249
250 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100251 EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
sprang867fb522015-08-03 04:38:41 -0700252 }
253
254 test::FakeEncoder encoder_;
255 } test;
256
stefane74eef12016-01-08 06:47:13 -0800257 RunBaseTest(&test);
sprang867fb522015-08-03 04:38:41 -0700258}
259
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000260class FakeReceiveStatistics : public NullReceiveStatistics {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000261 public:
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000262 FakeReceiveStatistics(uint32_t send_ssrc,
263 uint32_t last_sequence_number,
264 uint32_t cumulative_lost,
265 uint8_t fraction_lost)
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000266 : lossy_stats_(new LossyStatistician(last_sequence_number,
267 cumulative_lost,
268 fraction_lost)) {
269 stats_map_[send_ssrc] = lossy_stats_.get();
270 }
271
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000272 StatisticianMap GetActiveStatisticians() const override { return stats_map_; }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000273
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000274 StreamStatistician* GetStatistician(uint32_t ssrc) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000275 return lossy_stats_.get();
276 }
277
278 private:
279 class LossyStatistician : public StreamStatistician {
280 public:
281 LossyStatistician(uint32_t extended_max_sequence_number,
282 uint32_t cumulative_lost,
283 uint8_t fraction_lost) {
284 stats_.fraction_lost = fraction_lost;
285 stats_.cumulative_lost = cumulative_lost;
286 stats_.extended_max_sequence_number = extended_max_sequence_number;
287 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000288 bool GetStatistics(RtcpStatistics* statistics, bool reset) override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000289 *statistics = stats_;
290 return true;
291 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000292 void GetDataCounters(size_t* bytes_received,
293 uint32_t* packets_received) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000294 *bytes_received = 0;
295 *packets_received = 0;
296 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000297 void GetReceiveStreamDataCounters(
298 StreamDataCounters* data_counters) const override {}
299 uint32_t BitrateReceived() const override { return 0; }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000300 bool IsRetransmitOfOldPacket(const RTPHeader& header,
301 int64_t min_rtt) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000302 return false;
303 }
304
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000305 bool IsPacketInOrder(uint16_t sequence_number) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000306 return true;
307 }
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000308
309 RtcpStatistics stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000310 };
311
kwiberg27f982b2016-03-01 11:52:33 -0800312 std::unique_ptr<LossyStatistician> lossy_stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000313 StatisticianMap stats_map_;
314};
315
Peter Boström39593972016-02-15 11:27:15 +0100316class FecObserver : public test::EndToEndTest {
Stefan Holmer4654d202015-12-08 09:10:43 +0100317 public:
Peter Boström39593972016-02-15 11:27:15 +0100318 FecObserver(bool header_extensions_enabled,
319 bool use_nack,
320 bool expect_red,
stefan8f4c77f2016-06-03 00:16:45 -0700321 bool expect_fec,
Peter Boström39593972016-02-15 11:27:15 +0100322 const std::string& codec)
323 : EndToEndTest(VideoSendStreamTest::kDefaultTimeoutMs),
324 payload_name_(codec),
325 use_nack_(use_nack),
326 expect_red_(expect_red),
stefan8f4c77f2016-06-03 00:16:45 -0700327 expect_fec_(expect_fec),
Stefan Holmer4654d202015-12-08 09:10:43 +0100328 send_count_(0),
329 received_media_(false),
330 received_fec_(false),
Peter Boström39593972016-02-15 11:27:15 +0100331 header_extensions_enabled_(header_extensions_enabled) {
332 if (codec == "H264") {
333 encoder_.reset(new test::FakeH264Encoder(Clock::GetRealTimeClock()));
334 } else if (codec == "VP8") {
335 encoder_.reset(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8));
336 } else if (codec == "VP9") {
337 encoder_.reset(VideoEncoder::Create(VideoEncoder::EncoderType::kVp9));
338 } else {
339 RTC_NOTREACHED();
340 }
341 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100342
343 private:
344 Action OnSendRtp(const uint8_t* packet, size_t length) override {
345 RTPHeader header;
346 EXPECT_TRUE(parser_->Parse(packet, length, &header));
347
Peter Boström39593972016-02-15 11:27:15 +0100348 ++send_count_;
Stefan Holmer4654d202015-12-08 09:10:43 +0100349 int encapsulated_payload_type = -1;
350 if (header.payloadType == VideoSendStreamTest::kRedPayloadType) {
Peter Boström39593972016-02-15 11:27:15 +0100351 EXPECT_TRUE(expect_red_);
Stefan Holmer4654d202015-12-08 09:10:43 +0100352 encapsulated_payload_type = static_cast<int>(packet[header.headerLength]);
353 if (encapsulated_payload_type !=
Peter Boström39593972016-02-15 11:27:15 +0100354 VideoSendStreamTest::kFakeVideoSendPayloadType) {
Stefan Holmer4654d202015-12-08 09:10:43 +0100355 EXPECT_EQ(VideoSendStreamTest::kUlpfecPayloadType,
356 encapsulated_payload_type);
Peter Boström39593972016-02-15 11:27:15 +0100357 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100358 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100359 EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType,
360 header.payloadType);
Peter Boström39593972016-02-15 11:27:15 +0100361 if (static_cast<size_t>(header.headerLength + header.paddingLength) <
362 length) {
363 // Not padding-only, media received outside of RED.
364 EXPECT_FALSE(expect_red_);
365 received_media_ = true;
366 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100367 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000368
Stefan Holmer4654d202015-12-08 09:10:43 +0100369 if (header_extensions_enabled_) {
370 EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
371 uint32_t kHalf24BitsSpace = 0xFFFFFF / 2;
372 if (header.extension.absoluteSendTime <= kHalf24BitsSpace &&
373 prev_header_.extension.absoluteSendTime > kHalf24BitsSpace) {
374 // 24 bits wrap.
375 EXPECT_GT(prev_header_.extension.absoluteSendTime,
376 header.extension.absoluteSendTime);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000377 } else {
Stefan Holmer4654d202015-12-08 09:10:43 +0100378 EXPECT_GE(header.extension.absoluteSendTime,
379 prev_header_.extension.absoluteSendTime);
Stefan Holmer01b48882015-05-05 10:21:24 +0200380 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100381 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
382 uint16_t seq_num_diff = header.extension.transportSequenceNumber -
383 prev_header_.extension.transportSequenceNumber;
384 EXPECT_EQ(1, seq_num_diff);
385 }
Stefan Holmer01b48882015-05-05 10:21:24 +0200386
Stefan Holmer4654d202015-12-08 09:10:43 +0100387 if (encapsulated_payload_type != -1) {
388 if (encapsulated_payload_type ==
389 VideoSendStreamTest::kUlpfecPayloadType) {
stefan8f4c77f2016-06-03 00:16:45 -0700390 EXPECT_TRUE(expect_fec_);
Stefan Holmer4654d202015-12-08 09:10:43 +0100391 received_fec_ = true;
392 } else {
393 received_media_ = true;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000394 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000395 }
396
Peter Boström39593972016-02-15 11:27:15 +0100397 if (send_count_ > 100 && received_media_) {
stefan8f4c77f2016-06-03 00:16:45 -0700398 if (received_fec_ || !expect_fec_)
Peter Boström39593972016-02-15 11:27:15 +0100399 observation_complete_.Set();
400 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000401
Stefan Holmer4654d202015-12-08 09:10:43 +0100402 prev_header_ = header;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000403
Stefan Holmer4654d202015-12-08 09:10:43 +0100404 return SEND_PACKET;
405 }
406
Peter Boström39593972016-02-15 11:27:15 +0100407 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
408 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
409 // Configure some network delay.
410 const int kNetworkDelayMs = 100;
411 FakeNetworkPipe::Config config;
412 config.loss_percent = 50;
413 config.queue_delay_ms = kNetworkDelayMs;
414 return new test::PacketTransport(sender_call, this,
415 test::PacketTransport::kSender, config);
416 }
417
stefanff483612015-12-21 03:14:00 -0800418 void ModifyVideoConfigs(
419 VideoSendStream::Config* send_config,
420 std::vector<VideoReceiveStream::Config>* receive_configs,
421 VideoEncoderConfig* encoder_config) override {
Stefan Holmer4654d202015-12-08 09:10:43 +0100422 transport_adapter_.reset(
423 new internal::TransportAdapter(send_config->send_transport));
424 transport_adapter_->Enable();
Peter Boström39593972016-02-15 11:27:15 +0100425 if (use_nack_) {
426 send_config->rtp.nack.rtp_history_ms =
427 (*receive_configs)[0].rtp.nack.rtp_history_ms =
428 VideoSendStreamTest::kNackRtpHistoryMs;
429 }
430 send_config->encoder_settings.encoder = encoder_.get();
431 send_config->encoder_settings.payload_name = payload_name_;
Stefan Holmer4654d202015-12-08 09:10:43 +0100432 send_config->rtp.fec.red_payload_type =
Peter Boström39593972016-02-15 11:27:15 +0100433 VideoSendStreamTest::kRedPayloadType;
Stefan Holmer4654d202015-12-08 09:10:43 +0100434 send_config->rtp.fec.ulpfec_payload_type =
Peter Boström39593972016-02-15 11:27:15 +0100435 VideoSendStreamTest::kUlpfecPayloadType;
Stefan Holmer4654d202015-12-08 09:10:43 +0100436 if (header_extensions_enabled_) {
437 send_config->rtp.extensions.push_back(RtpExtension(
isheriff6f8d6862016-05-26 11:24:55 -0700438 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
Stefan Holmer4654d202015-12-08 09:10:43 +0100439 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -0700440 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
Stefan Holmer4654d202015-12-08 09:10:43 +0100441 test::kTransportSequenceNumberExtensionId));
442 }
Peter Boström39593972016-02-15 11:27:15 +0100443 (*receive_configs)[0].rtp.fec.red_payload_type =
444 send_config->rtp.fec.red_payload_type;
445 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
446 send_config->rtp.fec.ulpfec_payload_type;
Stefan Holmer4654d202015-12-08 09:10:43 +0100447 }
448
449 void PerformTest() override {
450 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
451 }
452
kwiberg27f982b2016-03-01 11:52:33 -0800453 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
454 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100455 const std::string payload_name_;
456 const bool use_nack_;
457 const bool expect_red_;
stefan8f4c77f2016-06-03 00:16:45 -0700458 const bool expect_fec_;
Stefan Holmer4654d202015-12-08 09:10:43 +0100459 int send_count_;
460 bool received_media_;
461 bool received_fec_;
462 bool header_extensions_enabled_;
463 RTPHeader prev_header_;
464};
465
466TEST_F(VideoSendStreamTest, SupportsFecWithExtensions) {
stefan8f4c77f2016-06-03 00:16:45 -0700467 FecObserver test(true, false, true, true, "VP8");
stefane74eef12016-01-08 06:47:13 -0800468 RunBaseTest(&test);
Stefan Holmer4654d202015-12-08 09:10:43 +0100469}
470
471TEST_F(VideoSendStreamTest, SupportsFecWithoutExtensions) {
stefan8f4c77f2016-06-03 00:16:45 -0700472 FecObserver test(false, false, true, true, "VP8");
Peter Boström39593972016-02-15 11:27:15 +0100473 RunBaseTest(&test);
474}
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000475
Peter Boström39593972016-02-15 11:27:15 +0100476// The FEC scheme used is not efficient for H264, so we should not use RED/FEC
477// since we'll still have to re-request FEC packets, effectively wasting
478// bandwidth since the receiver has to wait for FEC retransmissions to determine
479// that the received state is actually decodable.
stefan8f4c77f2016-06-03 00:16:45 -0700480TEST_F(VideoSendStreamTest, DoesNotUtilizeFecForH264WithNackEnabled) {
481 FecObserver test(false, true, true, false, "H264");
Peter Boström39593972016-02-15 11:27:15 +0100482 RunBaseTest(&test);
483}
484
485// Without retransmissions FEC for H264 is fine.
486TEST_F(VideoSendStreamTest, DoesUtilizeRedForH264WithoutNackEnabled) {
stefan8f4c77f2016-06-03 00:16:45 -0700487 FecObserver test(false, false, true, true, "H264");
Peter Boström39593972016-02-15 11:27:15 +0100488 RunBaseTest(&test);
489}
490
491TEST_F(VideoSendStreamTest, DoesUtilizeRedForVp8WithNackEnabled) {
stefan8f4c77f2016-06-03 00:16:45 -0700492 FecObserver test(false, true, true, true, "VP8");
Peter Boström39593972016-02-15 11:27:15 +0100493 RunBaseTest(&test);
494}
495
Peter Boström12996152016-05-14 02:03:18 +0200496#if !defined(RTC_DISABLE_VP9)
Peter Boström39593972016-02-15 11:27:15 +0100497TEST_F(VideoSendStreamTest, DoesUtilizeRedForVp9WithNackEnabled) {
stefan8f4c77f2016-06-03 00:16:45 -0700498 FecObserver test(false, true, true, true, "VP9");
stefane74eef12016-01-08 06:47:13 -0800499 RunBaseTest(&test);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000500}
Peter Boström12996152016-05-14 02:03:18 +0200501#endif // !defined(RTC_DISABLE_VP9)
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000502
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000503void VideoSendStreamTest::TestNackRetransmission(
504 uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000505 uint8_t retransmit_payload_type) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000506 class NackObserver : public test::SendTest {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000507 public:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000508 explicit NackObserver(uint32_t retransmit_ssrc,
509 uint8_t retransmit_payload_type)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000510 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000511 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000512 retransmit_ssrc_(retransmit_ssrc),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000513 retransmit_payload_type_(retransmit_payload_type),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000514 nacked_sequence_number_(-1) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000515 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000516
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000517 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000518 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000519 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000520 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000521
522 // Nack second packet after receiving the third one.
523 if (++send_count_ == 3) {
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000524 uint16_t nack_sequence_number = header.sequenceNumber - 1;
525 nacked_sequence_number_ = nack_sequence_number;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000526 NullReceiveStatistics null_stats;
Peter Boströmac547a62015-09-17 23:03:57 +0200527 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), &null_stats,
terelius429c3452016-01-21 05:42:04 -0800528 nullptr, nullptr, transport_adapter_.get());
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000529
pbosda903ea2015-10-02 02:36:56 -0700530 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100531 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000532
533 RTCPSender::FeedbackState feedback_state;
534
535 EXPECT_EQ(0,
536 rtcp_sender.SendRTCP(
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000537 feedback_state, kRtcpNack, 1, &nack_sequence_number));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000538 }
539
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000540 uint16_t sequence_number = header.sequenceNumber;
541
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000542 if (header.ssrc == retransmit_ssrc_ &&
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100543 retransmit_ssrc_ != kVideoSendSsrcs[0]) {
544 // Not kVideoSendSsrcs[0], assume correct RTX packet. Extract sequence
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000545 // number.
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000546 const uint8_t* rtx_header = packet + header.headerLength;
547 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
548 }
549
550 if (sequence_number == nacked_sequence_number_) {
551 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000552 EXPECT_EQ(retransmit_payload_type_, header.payloadType);
Peter Boström5811a392015-12-10 13:02:50 +0100553 observation_complete_.Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000554 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000555
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000556 return SEND_PACKET;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000557 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000558
stefanff483612015-12-21 03:14:00 -0800559 void ModifyVideoConfigs(
560 VideoSendStream::Config* send_config,
561 std::vector<VideoReceiveStream::Config>* receive_configs,
562 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700563 transport_adapter_.reset(
564 new internal::TransportAdapter(send_config->send_transport));
565 transport_adapter_->Enable();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000566 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000567 send_config->rtp.rtx.payload_type = retransmit_payload_type_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100568 if (retransmit_ssrc_ != kVideoSendSsrcs[0])
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000569 send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
570 }
571
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000572 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100573 EXPECT_TRUE(Wait()) << "Timed out while waiting for NACK retransmission.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000574 }
575
kwiberg27f982b2016-03-01 11:52:33 -0800576 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000577 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000578 uint32_t retransmit_ssrc_;
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000579 uint8_t retransmit_payload_type_;
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000580 int nacked_sequence_number_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000581 } test(retransmit_ssrc, retransmit_payload_type);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000582
stefane74eef12016-01-08 06:47:13 -0800583 RunBaseTest(&test);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000584}
585
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000586TEST_F(VideoSendStreamTest, RetransmitsNack) {
587 // Normal NACKs should use the send SSRC.
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100588 TestNackRetransmission(kVideoSendSsrcs[0], kFakeVideoSendPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000589}
590
591TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
592 // NACKs over RTX should use a separate SSRC.
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000593 TestNackRetransmission(kSendRtxSsrcs[0], kSendRtxPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000594}
595
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000596void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
597 bool with_fec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000598 // Use a fake encoder to output a frame of every size in the range [90, 290],
599 // for each size making sure that the exact number of payload bytes received
600 // is correct and that packets are fragmented to respect max packet size.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000601 static const size_t kMaxPacketSize = 128;
602 static const size_t start = 90;
603 static const size_t stop = 290;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000604
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000605 // Observer that verifies that the expected number of packets and bytes
606 // arrive for each frame size, from start_size to stop_size.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000607 class FrameFragmentationTest : public test::SendTest,
608 public EncodedFrameObserver {
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000609 public:
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000610 FrameFragmentationTest(size_t max_packet_size,
611 size_t start_size,
612 size_t stop_size,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000613 bool test_generic_packetization,
614 bool use_fec)
615 : SendTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000616 encoder_(stop),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000617 max_packet_size_(max_packet_size),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000618 stop_size_(stop_size),
619 test_generic_packetization_(test_generic_packetization),
620 use_fec_(use_fec),
621 packet_count_(0),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000622 accumulated_size_(0),
623 accumulated_payload_(0),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000624 fec_packet_received_(false),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000625 current_size_rtp_(start_size),
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000626 current_size_frame_(static_cast<int32_t>(start_size)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000627 // Fragmentation required, this test doesn't make sense without it.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000628 encoder_.SetFrameSize(start_size);
henrikg91d6ede2015-09-17 00:24:34 -0700629 RTC_DCHECK_GT(stop_size, max_packet_size);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000630 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000631
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000632 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000633 Action OnSendRtp(const uint8_t* packet, size_t size) override {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000634 size_t length = size;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000635 RTPHeader header;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000636 EXPECT_TRUE(parser_->Parse(packet, length, &header));
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000637
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000638 EXPECT_LE(length, max_packet_size_);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000639
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000640 if (use_fec_) {
641 uint8_t payload_type = packet[header.headerLength];
642 bool is_fec = header.payloadType == kRedPayloadType &&
643 payload_type == kUlpfecPayloadType;
644 if (is_fec) {
645 fec_packet_received_ = true;
646 return SEND_PACKET;
647 }
648 }
649
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000650 accumulated_size_ += length;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000651
652 if (use_fec_)
653 TriggerLossReport(header);
654
655 if (test_generic_packetization_) {
Stefan Holmer586b19b2015-09-18 11:14:31 +0200656 size_t overhead = header.headerLength + header.paddingLength;
657 // Only remove payload header and RED header if the packet actually
658 // contains payload.
659 if (length > overhead) {
660 overhead += (1 /* Generic header */);
661 if (use_fec_)
662 overhead += 1; // RED for FEC header.
663 }
664 EXPECT_GE(length, overhead);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000665 accumulated_payload_ += length - overhead;
666 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000667
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000668 // Marker bit set indicates last packet of a frame.
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000669 if (header.markerBit) {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000670 if (use_fec_ && accumulated_payload_ == current_size_rtp_ - 1) {
671 // With FEC enabled, frame size is incremented asynchronously, so
672 // "old" frames one byte too small may arrive. Accept, but don't
673 // increase expected frame size.
674 accumulated_size_ = 0;
675 accumulated_payload_ = 0;
676 return SEND_PACKET;
677 }
678
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000679 EXPECT_GE(accumulated_size_, current_size_rtp_);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000680 if (test_generic_packetization_) {
681 EXPECT_EQ(current_size_rtp_, accumulated_payload_);
682 }
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000683
684 // Last packet of frame; reset counters.
685 accumulated_size_ = 0;
686 accumulated_payload_ = 0;
687 if (current_size_rtp_ == stop_size_) {
688 // Done! (Don't increase size again, might arrive more @ stop_size).
Peter Boström5811a392015-12-10 13:02:50 +0100689 observation_complete_.Set();
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000690 } else {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000691 // Increase next expected frame size. If testing with FEC, make sure
692 // a FEC packet has been received for this frame size before
693 // proceeding, to make sure that redundancy packets don't exceed
694 // size limit.
695 if (!use_fec_) {
696 ++current_size_rtp_;
697 } else if (fec_packet_received_) {
698 fec_packet_received_ = false;
699 ++current_size_rtp_;
700 ++current_size_frame_;
701 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000702 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000703 }
704
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000705 return SEND_PACKET;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000706 }
707
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000708 void TriggerLossReport(const RTPHeader& header) {
709 // Send lossy receive reports to trigger FEC enabling.
710 if (packet_count_++ % 2 != 0) {
711 // Receive statistics reporting having lost 50% of the packets.
712 FakeReceiveStatistics lossy_receive_stats(
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100713 kVideoSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127);
Peter Boströmac547a62015-09-17 23:03:57 +0200714 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
terelius429c3452016-01-21 05:42:04 -0800715 &lossy_receive_stats, nullptr, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700716 transport_adapter_.get());
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000717
pbosda903ea2015-10-02 02:36:56 -0700718 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100719 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000720
721 RTCPSender::FeedbackState feedback_state;
722
723 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
724 }
725 }
726
nisseef8b61e2016-04-29 06:09:15 -0700727 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000728 // Increase frame size for next encoded frame, in the context of the
729 // encoder thread.
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000730 if (!use_fec_ &&
731 current_size_frame_.Value() < static_cast<int32_t>(stop_size_)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000732 ++current_size_frame_;
733 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000734 encoder_.SetFrameSize(static_cast<size_t>(current_size_frame_.Value()));
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000735 }
736
Stefan Holmere5904162015-03-26 11:11:06 +0100737 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700738 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100739 const int kMinBitrateBps = 30000;
740 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
741 return config;
742 }
743
stefanff483612015-12-21 03:14:00 -0800744 void ModifyVideoConfigs(
745 VideoSendStream::Config* send_config,
746 std::vector<VideoReceiveStream::Config>* receive_configs,
747 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700748 transport_adapter_.reset(
749 new internal::TransportAdapter(send_config->send_transport));
750 transport_adapter_->Enable();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000751 if (use_fec_) {
752 send_config->rtp.fec.red_payload_type = kRedPayloadType;
753 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
754 }
755
756 if (!test_generic_packetization_)
757 send_config->encoder_settings.payload_name = "VP8";
758
759 send_config->encoder_settings.encoder = &encoder_;
760 send_config->rtp.max_packet_size = kMaxPacketSize;
761 send_config->post_encode_callback = this;
762
Erik Språng95261872015-04-10 11:58:49 +0200763 // Make sure there is at least one extension header, to make the RTP
764 // header larger than the base length of 12 bytes.
765 EXPECT_FALSE(send_config->rtp.extensions.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000766 }
767
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000768 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100769 EXPECT_TRUE(Wait()) << "Timed out while observing incoming RTP packets.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000770 }
771
kwiberg27f982b2016-03-01 11:52:33 -0800772 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000773 test::ConfigurableFrameSizeEncoder encoder_;
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000774
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000775 const size_t max_packet_size_;
776 const size_t stop_size_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000777 const bool test_generic_packetization_;
778 const bool use_fec_;
779
780 uint32_t packet_count_;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000781 size_t accumulated_size_;
782 size_t accumulated_payload_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000783 bool fec_packet_received_;
784
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000785 size_t current_size_rtp_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000786 Atomic32 current_size_frame_;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000787 };
788
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000789 // Don't auto increment if FEC is used; continue sending frame size until
790 // a FEC packet has been received.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000791 FrameFragmentationTest test(
792 kMaxPacketSize, start, stop, format == kGeneric, with_fec);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000793
stefane74eef12016-01-08 06:47:13 -0800794 RunBaseTest(&test);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000795}
796
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000797// TODO(sprang): Is there any way of speeding up these tests?
798TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSize) {
799 TestPacketFragmentationSize(kGeneric, false);
800}
801
802TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSizeWithFec) {
803 TestPacketFragmentationSize(kGeneric, true);
804}
805
806TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSize) {
807 TestPacketFragmentationSize(kVP8, false);
808}
809
810TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSizeWithFec) {
811 TestPacketFragmentationSize(kVP8, true);
812}
813
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000814// The test will go through a number of phases.
815// 1. Start sending packets.
816// 2. As soon as the RTP stream has been detected, signal a low REMB value to
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000817// suspend the stream.
818// 3. Wait until |kSuspendTimeFrames| have been captured without seeing any RTP
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000819// packets.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000820// 4. Signal a high REMB and then wait for the RTP stream to start again.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000821// When the stream is detected again, and the stats show that the stream
822// is no longer suspended, the test ends.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000823TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
824 static const int kSuspendTimeFrames = 60; // Suspend for 2 seconds @ 30 fps.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000825
nissed30a1112016-04-18 05:15:22 -0700826 class RembObserver : public test::SendTest,
827 public rtc::VideoSinkInterface<VideoFrame> {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000828 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000829 RembObserver()
830 : SendTest(kDefaultTimeoutMs),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000831 clock_(Clock::GetRealTimeClock()),
Erik Språng737336d2016-07-29 12:59:36 +0200832 stream_(nullptr),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000833 test_state_(kBeforeSuspend),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000834 rtp_count_(0),
835 last_sequence_number_(0),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000836 suspended_frame_count_(0),
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000837 low_remb_bps_(0),
Erik Språng737336d2016-07-29 12:59:36 +0200838 high_remb_bps_(0) {}
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000839
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000840 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000841 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200842 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000843 ++rtp_count_;
844 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000845 EXPECT_TRUE(parser_->Parse(packet, length, &header));
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000846 last_sequence_number_ = header.sequenceNumber;
847
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000848 if (test_state_ == kBeforeSuspend) {
849 // The stream has started. Try to suspend it.
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000850 SendRtcpFeedback(low_remb_bps_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000851 test_state_ = kDuringSuspend;
852 } else if (test_state_ == kDuringSuspend) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000853 if (header.paddingLength == 0) {
854 // Received non-padding packet during suspension period. Reset the
855 // counter.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000856 suspended_frame_count_ = 0;
857 }
stefanf116bd02015-10-27 08:29:42 -0700858 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000859 } else if (test_state_ == kWaitingForPacket) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000860 if (header.paddingLength == 0) {
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000861 // Non-padding packet observed. Test is almost complete. Will just
862 // have to wait for the stats to change.
863 test_state_ = kWaitingForStats;
864 }
stefanf116bd02015-10-27 08:29:42 -0700865 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000866 } else if (test_state_ == kWaitingForStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000867 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000868 if (stats.suspended == false) {
869 // Stats flipped to false. Test is complete.
Peter Boström5811a392015-12-10 13:02:50 +0100870 observation_complete_.Set();
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000871 }
stefanf116bd02015-10-27 08:29:42 -0700872 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000873 }
874
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000875 return SEND_PACKET;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000876 }
877
perkj26091b12016-09-01 01:17:40 -0700878 // This method implements the rtc::VideoSinkInterface. This is called when
879 // a frame is provided to the VideoSendStream.
nissed30a1112016-04-18 05:15:22 -0700880 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200881 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000882 if (test_state_ == kDuringSuspend &&
883 ++suspended_frame_count_ > kSuspendTimeFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000884 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000885 EXPECT_TRUE(stats.suspended);
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000886 SendRtcpFeedback(high_remb_bps_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000887 test_state_ = kWaitingForPacket;
888 }
889 }
890
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000891 void set_low_remb_bps(int value) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200892 rtc::CritScope lock(&crit_);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000893 low_remb_bps_ = value;
894 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000895
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000896 void set_high_remb_bps(int value) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200897 rtc::CritScope lock(&crit_);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000898 high_remb_bps_ = value;
899 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000900
stefanff483612015-12-21 03:14:00 -0800901 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000902 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000903 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000904 stream_ = send_stream;
905 }
906
stefanff483612015-12-21 03:14:00 -0800907 void ModifyVideoConfigs(
908 VideoSendStream::Config* send_config,
909 std::vector<VideoReceiveStream::Config>* receive_configs,
910 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700911 transport_adapter_.reset(
912 new internal::TransportAdapter(send_config->send_transport));
913 transport_adapter_->Enable();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000914 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000915 send_config->pre_encode_callback = this;
916 send_config->suspend_below_min_bitrate = true;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000917 int min_bitrate_bps = encoder_config->streams[0].min_bitrate_bps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000918 set_low_remb_bps(min_bitrate_bps - 10000);
mflodman101f2502016-06-09 17:21:19 +0200919 int threshold_window = std::max(min_bitrate_bps / 10, 20000);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000920 ASSERT_GT(encoder_config->streams[0].max_bitrate_bps,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000921 min_bitrate_bps + threshold_window + 5000);
922 set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
923 }
924
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000925 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100926 EXPECT_TRUE(Wait()) << "Timed out during suspend-below-min-bitrate test.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000927 }
928
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000929 enum TestState {
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000930 kBeforeSuspend,
931 kDuringSuspend,
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000932 kWaitingForPacket,
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000933 kWaitingForStats
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000934 };
935
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000936 virtual void SendRtcpFeedback(int remb_value)
937 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100938 FakeReceiveStatistics receive_stats(kVideoSendSsrcs[0],
939 last_sequence_number_, rtp_count_, 0);
terelius429c3452016-01-21 05:42:04 -0800940 RTCPSender rtcp_sender(false, clock_, &receive_stats, nullptr, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700941 transport_adapter_.get());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000942
pbosda903ea2015-10-02 02:36:56 -0700943 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100944 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000945 if (remb_value > 0) {
946 rtcp_sender.SetREMBStatus(true);
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000947 rtcp_sender.SetREMBData(remb_value, std::vector<uint32_t>());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000948 }
949 RTCPSender::FeedbackState feedback_state;
950 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
951 }
952
kwiberg27f982b2016-03-01 11:52:33 -0800953 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000954 Clock* const clock_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000955 VideoSendStream* stream_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000956
Peter Boströmf2f82832015-05-01 13:00:41 +0200957 rtc::CriticalSection crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000958 TestState test_state_ GUARDED_BY(crit_);
959 int rtp_count_ GUARDED_BY(crit_);
960 int last_sequence_number_ GUARDED_BY(crit_);
961 int suspended_frame_count_ GUARDED_BY(crit_);
962 int low_remb_bps_ GUARDED_BY(crit_);
963 int high_remb_bps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000964 } test;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000965
stefane74eef12016-01-08 06:47:13 -0800966 RunBaseTest(&test);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000967}
968
perkj71ee44c2016-06-15 00:47:53 -0700969// This test that padding stops being send after a while if the Camera stops
970// producing video frames and that padding resumes if the camera restarts.
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000971TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000972 class NoPaddingWhenVideoIsMuted : public test::SendTest {
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000973 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000974 NoPaddingWhenVideoIsMuted()
975 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000976 clock_(Clock::GetRealTimeClock()),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000977 last_packet_time_ms_(-1),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000978 capturer_(nullptr) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000979 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000980
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000981 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000982 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200983 rtc::CritScope lock(&crit_);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000984 last_packet_time_ms_ = clock_->TimeInMilliseconds();
perkj71ee44c2016-06-15 00:47:53 -0700985
986 RTPHeader header;
987 parser_->Parse(packet, length, &header);
988 const bool only_padding =
989 header.headerLength + header.paddingLength == length;
990
991 if (test_state_ == kBeforeStopCapture) {
992 capturer_->Stop();
993 test_state_ = kWaitingForPadding;
994 } else if (test_state_ == kWaitingForPadding && only_padding) {
995 test_state_ = kWaitingForNoPackets;
996 } else if (test_state_ == kWaitingForPaddingAfterCameraRestart &&
997 only_padding) {
998 observation_complete_.Set();
999 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +00001000 return SEND_PACKET;
1001 }
1002
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001003 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001004 rtc::CritScope lock(&crit_);
perkj71ee44c2016-06-15 00:47:53 -07001005 const int kNoPacketsThresholdMs = 2000;
1006 if (test_state_ == kWaitingForNoPackets &&
1007 (last_packet_time_ms_ > 0 &&
1008 clock_->TimeInMilliseconds() - last_packet_time_ms_ >
1009 kNoPacketsThresholdMs)) {
1010 capturer_->Start();
1011 test_state_ = kWaitingForPaddingAfterCameraRestart;
1012 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +00001013 return SEND_PACKET;
1014 }
1015
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001016 size_t GetNumVideoStreams() const override { return 3; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001017
nisseef8b61e2016-04-29 06:09:15 -07001018 void OnFrameGeneratorCapturerCreated(
1019 test::FrameGeneratorCapturer* frame_generator_capturer) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001020 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001021 capturer_ = frame_generator_capturer;
1022 }
1023
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001024 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001025 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001026 << "Timed out while waiting for RTP packets to stop being sent.";
1027 }
1028
perkj71ee44c2016-06-15 00:47:53 -07001029 enum TestState {
1030 kBeforeStopCapture,
1031 kWaitingForPadding,
1032 kWaitingForNoPackets,
1033 kWaitingForPaddingAfterCameraRestart
1034 };
1035
1036 TestState test_state_ = kBeforeStopCapture;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +00001037 Clock* const clock_;
kwiberg27f982b2016-03-01 11:52:33 -08001038 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
Peter Boströmf2f82832015-05-01 13:00:41 +02001039 rtc::CriticalSection crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +00001040 int64_t last_packet_time_ms_ GUARDED_BY(crit_);
1041 test::FrameGeneratorCapturer* capturer_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001042 } test;
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +00001043
stefane74eef12016-01-08 06:47:13 -08001044 RunBaseTest(&test);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +00001045}
1046
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001047// This test first observes "high" bitrate use at which point it sends a REMB to
1048// indicate that it should be lowered significantly. The test then observes that
1049// the bitrate observed is sinking well below the min-transmit-bitrate threshold
1050// to verify that the min-transmit bitrate respects incoming REMB.
andresp@webrtc.org44caf012014-03-26 21:00:21 +00001051//
1052// Note that the test starts at "high" bitrate and does not ramp up to "higher"
1053// bitrate since no receiver block or remb is sent in the initial phase.
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001054TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
1055 static const int kMinTransmitBitrateBps = 400000;
andresp@webrtc.org44caf012014-03-26 21:00:21 +00001056 static const int kHighBitrateBps = 150000;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001057 static const int kRembBitrateBps = 80000;
1058 static const int kRembRespectedBitrateBps = 100000;
stefanf116bd02015-10-27 08:29:42 -07001059 class BitrateObserver : public test::SendTest {
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001060 public:
1061 BitrateObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001062 : SendTest(kDefaultTimeoutMs),
Erik Språng737336d2016-07-29 12:59:36 +02001063 retranmission_rate_limiter_(Clock::GetRealTimeClock(), 1000),
1064 stream_(nullptr),
1065 bitrate_capped_(false) {}
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001066
1067 private:
nisseef8b61e2016-04-29 06:09:15 -07001068 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001069 if (RtpHeaderParser::IsRtcp(packet, length))
stefanf116bd02015-10-27 08:29:42 -07001070 return DROP_PACKET;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001071
1072 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001073 if (!parser_->Parse(packet, length, &header))
stefanf116bd02015-10-27 08:29:42 -07001074 return DROP_PACKET;
Peter Boström74f6e9e2016-04-04 17:56:10 +02001075 RTC_DCHECK(stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001076 VideoSendStream::Stats stats = stream_->GetStats();
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001077 if (!stats.substreams.empty()) {
1078 EXPECT_EQ(1u, stats.substreams.size());
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001079 int total_bitrate_bps =
1080 stats.substreams.begin()->second.total_bitrate_bps;
1081 test::PrintResult("bitrate_stats_",
1082 "min_transmit_bitrate_low_remb",
1083 "bitrate_bps",
1084 static_cast<size_t>(total_bitrate_bps),
1085 "bps",
1086 false);
1087 if (total_bitrate_bps > kHighBitrateBps) {
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001088 rtp_rtcp_->SetREMBData(kRembBitrateBps,
1089 std::vector<uint32_t>(1, header.ssrc));
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001090 rtp_rtcp_->Process();
1091 bitrate_capped_ = true;
1092 } else if (bitrate_capped_ &&
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001093 total_bitrate_bps < kRembRespectedBitrateBps) {
Peter Boström5811a392015-12-10 13:02:50 +01001094 observation_complete_.Set();
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001095 }
1096 }
stefanf116bd02015-10-27 08:29:42 -07001097 // Packets don't have to be delivered since the test is the receiver.
1098 return DROP_PACKET;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001099 }
1100
stefanff483612015-12-21 03:14:00 -08001101 void OnVideoStreamsCreated(
stefanf116bd02015-10-27 08:29:42 -07001102 VideoSendStream* send_stream,
1103 const std::vector<VideoReceiveStream*>& receive_streams) override {
1104 stream_ = send_stream;
1105 RtpRtcp::Configuration config;
1106 config.outgoing_transport = feedback_transport_.get();
Erik Språng737336d2016-07-29 12:59:36 +02001107 config.retransmission_rate_limiter = &retranmission_rate_limiter_;
stefanf116bd02015-10-27 08:29:42 -07001108 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1109 rtp_rtcp_->SetREMBStatus(true);
1110 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001111 }
1112
stefanff483612015-12-21 03:14:00 -08001113 void ModifyVideoConfigs(
1114 VideoSendStream::Config* send_config,
1115 std::vector<VideoReceiveStream::Config>* receive_configs,
1116 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -07001117 feedback_transport_.reset(
1118 new internal::TransportAdapter(send_config->send_transport));
1119 feedback_transport_->Enable();
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00001120 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001121 }
1122
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001123 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001124 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001125 << "Timeout while waiting for low bitrate stats after REMB.";
1126 }
1127
kwiberg27f982b2016-03-01 11:52:33 -08001128 std::unique_ptr<RtpRtcp> rtp_rtcp_;
1129 std::unique_ptr<internal::TransportAdapter> feedback_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02001130 RateLimiter retranmission_rate_limiter_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001131 VideoSendStream* stream_;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001132 bool bitrate_capped_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001133 } test;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001134
stefane74eef12016-01-08 06:47:13 -08001135 RunBaseTest(&test);
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001136}
1137
hbos8af4fd02016-09-26 11:45:37 -07001138TEST_F(VideoSendStreamTest, DISABLED_ChangingNetworkRoute) {
Stefan Holmerbe402962016-07-08 16:16:41 +02001139 class ChangingNetworkRouteTest : public test::EndToEndTest {
1140 public:
1141 const int kStartBitrateBps = 300000;
1142 const int kNewMaxBitrateBps = 1234567;
1143
1144 ChangingNetworkRouteTest()
1145 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
1146 call_(nullptr) {}
1147
1148 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1149 call_ = sender_call;
1150 }
1151
1152 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1153 if (call_->GetStats().send_bandwidth_bps > kStartBitrateBps) {
1154 observation_complete_.Set();
1155 }
1156
1157 return SEND_PACKET;
1158 }
1159
1160 void PerformTest() override {
1161 rtc::NetworkRoute new_route(true, 10, 20, -1);
1162 call_->OnNetworkRouteChanged("transport", new_route);
1163 Call::Config::BitrateConfig bitrate_config;
1164 bitrate_config.start_bitrate_bps = kStartBitrateBps;
1165 call_->SetBitrateConfig(bitrate_config);
1166 EXPECT_TRUE(Wait())
1167 << "Timed out while waiting for start bitrate to be exceeded.";
1168
1169 bitrate_config.start_bitrate_bps = -1;
1170 bitrate_config.max_bitrate_bps = kNewMaxBitrateBps;
1171 call_->SetBitrateConfig(bitrate_config);
1172 // TODO(holmer): We should set the last sent packet id here and verify
1173 // that we correctly ignore any packet loss reported prior to that id.
1174 ++new_route.local_network_id;
1175 call_->OnNetworkRouteChanged("transport", new_route);
1176 EXPECT_EQ(kStartBitrateBps, call_->GetStats().send_bandwidth_bps);
1177 }
1178
1179 private:
1180 Call* call_;
1181 } test;
1182
1183 RunBaseTest(&test);
1184}
1185
sprang9c0b5512016-07-06 00:54:28 -07001186class MaxPaddingSetTest : public test::SendTest {
1187 public:
1188 static const uint32_t kMinTransmitBitrateBps = 400000;
1189 static const uint32_t kActualEncodeBitrateBps = 40000;
1190 static const uint32_t kMinPacketsToSend = 50;
1191
1192 explicit MaxPaddingSetTest(bool test_switch_content_type)
1193 : SendTest(test::CallTest::kDefaultTimeoutMs),
1194 call_(nullptr),
1195 send_stream_(nullptr),
1196 packets_sent_(0),
1197 running_without_padding_(test_switch_content_type) {}
1198
1199 void OnVideoStreamsCreated(
1200 VideoSendStream* send_stream,
1201 const std::vector<VideoReceiveStream*>& receive_streams) override {
1202 send_stream_ = send_stream;
1203 }
1204
1205 void ModifyVideoConfigs(
1206 VideoSendStream::Config* send_config,
1207 std::vector<VideoReceiveStream::Config>* receive_configs,
1208 VideoEncoderConfig* encoder_config) override {
1209 RTC_DCHECK_EQ(1u, encoder_config->streams.size());
1210 if (running_without_padding_) {
1211 encoder_config->min_transmit_bitrate_bps = 0;
1212 encoder_config->content_type =
1213 VideoEncoderConfig::ContentType::kRealtimeVideo;
1214 } else {
1215 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
1216 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
1217 }
perkj26091b12016-09-01 01:17:40 -07001218 encoder_config_ = encoder_config->Copy();
sprang9c0b5512016-07-06 00:54:28 -07001219 }
1220
1221 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1222 call_ = sender_call;
1223 }
1224
1225 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1226 rtc::CritScope lock(&crit_);
1227
1228 if (running_without_padding_)
1229 EXPECT_EQ(0, call_->GetStats().max_padding_bitrate_bps);
1230
1231 // Wait until at least kMinPacketsToSend frames have been encoded, so that
1232 // we have reliable data.
1233 if (++packets_sent_ < kMinPacketsToSend)
1234 return SEND_PACKET;
1235
1236 if (running_without_padding_) {
1237 // We've sent kMinPacketsToSend packets with default configuration, switch
1238 // to enabling screen content and setting min transmit bitrate.
1239 packets_sent_ = 0;
1240 encoder_config_.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
1241 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
perkj26091b12016-09-01 01:17:40 -07001242 send_stream_->ReconfigureVideoEncoder(encoder_config_.Copy());
sprang9c0b5512016-07-06 00:54:28 -07001243 running_without_padding_ = false;
1244 return SEND_PACKET;
1245 }
1246
1247 // Make sure the pacer has been configured with a min transmit bitrate.
1248 if (call_->GetStats().max_padding_bitrate_bps > 0)
1249 observation_complete_.Set();
1250
1251 return SEND_PACKET;
1252 }
1253
1254 void PerformTest() override {
1255 ASSERT_TRUE(Wait()) << "Timed out waiting for a valid padding bitrate.";
1256 }
1257
1258 private:
1259 rtc::CriticalSection crit_;
1260 Call* call_;
1261 VideoSendStream* send_stream_;
1262 VideoEncoderConfig encoder_config_;
1263 uint32_t packets_sent_ GUARDED_BY(crit_);
1264 bool running_without_padding_;
1265};
1266
1267TEST_F(VideoSendStreamTest, RespectsMinTransmitBitrate) {
1268 MaxPaddingSetTest test(false);
1269 RunBaseTest(&test);
1270}
1271
1272TEST_F(VideoSendStreamTest, RespectsMinTransmitBitrateAfterContentSwitch) {
1273 MaxPaddingSetTest test(true);
1274 RunBaseTest(&test);
1275}
1276
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001277TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) {
1278 class StartBitrateObserver : public test::FakeEncoder {
1279 public:
1280 StartBitrateObserver()
pbos14fe7082016-04-20 06:35:56 -07001281 : FakeEncoder(Clock::GetRealTimeClock()),
1282 start_bitrate_changed_(false, false),
1283 start_bitrate_kbps_(0) {}
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001284 int32_t InitEncode(const VideoCodec* config,
1285 int32_t number_of_cores,
1286 size_t max_payload_size) override {
1287 rtc::CritScope lock(&crit_);
1288 start_bitrate_kbps_ = config->startBitrate;
pbos14fe7082016-04-20 06:35:56 -07001289 start_bitrate_changed_.Set();
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001290 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1291 }
1292
1293 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
1294 rtc::CritScope lock(&crit_);
1295 start_bitrate_kbps_ = new_target_bitrate;
pbos14fe7082016-04-20 06:35:56 -07001296 start_bitrate_changed_.Set();
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001297 return FakeEncoder::SetRates(new_target_bitrate, framerate);
1298 }
1299
1300 int GetStartBitrateKbps() const {
1301 rtc::CritScope lock(&crit_);
1302 return start_bitrate_kbps_;
1303 }
1304
pbos14fe7082016-04-20 06:35:56 -07001305 bool WaitForStartBitrate() {
1306 return start_bitrate_changed_.Wait(
1307 VideoSendStreamTest::kDefaultTimeoutMs);
1308 }
1309
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001310 private:
pbos5ad935c2016-01-25 03:52:44 -08001311 rtc::CriticalSection crit_;
pbos14fe7082016-04-20 06:35:56 -07001312 rtc::Event start_bitrate_changed_;
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001313 int start_bitrate_kbps_ GUARDED_BY(crit_);
1314 };
1315
solenberg4fbae2b2015-08-28 04:07:10 -07001316 CreateSenderCall(Call::Config());
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001317
solenberg4fbae2b2015-08-28 04:07:10 -07001318 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001319 CreateSendConfig(1, 0, &transport);
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001320
1321 Call::Config::BitrateConfig bitrate_config;
1322 bitrate_config.start_bitrate_bps =
stefanff483612015-12-21 03:14:00 -08001323 2 * video_encoder_config_.streams[0].max_bitrate_bps;
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001324 sender_call_->SetBitrateConfig(bitrate_config);
1325
1326 StartBitrateObserver encoder;
stefanff483612015-12-21 03:14:00 -08001327 video_send_config_.encoder_settings.encoder = &encoder;
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001328
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001329 CreateVideoStreams();
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001330
pbos14fe7082016-04-20 06:35:56 -07001331 EXPECT_TRUE(encoder.WaitForStartBitrate());
stefanff483612015-12-21 03:14:00 -08001332 EXPECT_EQ(video_encoder_config_.streams[0].max_bitrate_bps / 1000,
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001333 encoder.GetStartBitrateKbps());
1334
stefanff483612015-12-21 03:14:00 -08001335 video_encoder_config_.streams[0].max_bitrate_bps =
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001336 2 * bitrate_config.start_bitrate_bps;
perkj26091b12016-09-01 01:17:40 -07001337 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_.Copy());
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001338
1339 // New bitrate should be reconfigured above the previous max. As there's no
1340 // network connection this shouldn't be flaky, as no bitrate should've been
1341 // reported in between.
pbos14fe7082016-04-20 06:35:56 -07001342 EXPECT_TRUE(encoder.WaitForStartBitrate());
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001343 EXPECT_EQ(bitrate_config.start_bitrate_bps / 1000,
1344 encoder.GetStartBitrateKbps());
1345
1346 DestroyStreams();
1347}
1348
perkj57c21f92016-06-17 07:27:16 -07001349// This test that if the encoder use an internal source, VideoEncoder::SetRates
1350// will be called with zero bitrate during initialization and that
1351// VideoSendStream::Stop also triggers VideoEncoder::SetRates Start to be called
1352// with zero bitrate.
1353TEST_F(VideoSendStreamTest, VideoSendStreamStopSetEncoderRateToZero) {
1354 class StartStopBitrateObserver : public test::FakeEncoder {
1355 public:
1356 StartStopBitrateObserver()
1357 : FakeEncoder(Clock::GetRealTimeClock()),
1358 encoder_init_(false, false),
1359 bitrate_changed_(false, false),
1360 bitrate_kbps_(0) {}
1361 int32_t InitEncode(const VideoCodec* config,
1362 int32_t number_of_cores,
1363 size_t max_payload_size) override {
1364 rtc::CritScope lock(&crit_);
1365 bitrate_kbps_ = config->startBitrate;
1366 encoder_init_.Set();
1367 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1368 }
1369
1370 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
1371 rtc::CritScope lock(&crit_);
1372 bitrate_kbps_ = new_target_bitrate;
1373 bitrate_changed_.Set();
1374 return FakeEncoder::SetRates(new_target_bitrate, framerate);
1375 }
1376
1377 int GetBitrateKbps() const {
1378 rtc::CritScope lock(&crit_);
1379 return bitrate_kbps_;
1380 }
1381
1382 bool WaitForEncoderInit() {
1383 return encoder_init_.Wait(VideoSendStreamTest::kDefaultTimeoutMs);
1384 }
1385 bool WaitBitrateChanged() {
1386 return bitrate_changed_.Wait(VideoSendStreamTest::kDefaultTimeoutMs);
1387 }
1388
1389 private:
1390 rtc::CriticalSection crit_;
1391 rtc::Event encoder_init_;
1392 rtc::Event bitrate_changed_;
1393 int bitrate_kbps_ GUARDED_BY(crit_);
1394 };
1395
1396 CreateSenderCall(Call::Config());
1397
1398 test::NullTransport transport;
1399 CreateSendConfig(1, 0, &transport);
1400
1401 StartStopBitrateObserver encoder;
1402 video_send_config_.encoder_settings.encoder = &encoder;
1403 video_send_config_.encoder_settings.internal_source = true;
1404
1405 CreateVideoStreams();
1406
1407 EXPECT_TRUE(encoder.WaitForEncoderInit());
1408 EXPECT_GT(encoder.GetBitrateKbps(), 0);
1409 video_send_stream_->Start();
1410 EXPECT_TRUE(encoder.WaitBitrateChanged());
1411 EXPECT_GT(encoder.GetBitrateKbps(), 0);
1412 video_send_stream_->Stop();
1413 EXPECT_TRUE(encoder.WaitBitrateChanged());
1414 EXPECT_EQ(0, encoder.GetBitrateKbps());
1415 video_send_stream_->Start();
1416 EXPECT_TRUE(encoder.WaitBitrateChanged());
1417 EXPECT_GT(encoder.GetBitrateKbps(), 0);
1418
1419 DestroyStreams();
1420}
1421
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001422TEST_F(VideoSendStreamTest, CapturesTextureAndVideoFrames) {
nissed30a1112016-04-18 05:15:22 -07001423 class FrameObserver : public rtc::VideoSinkInterface<VideoFrame> {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001424 public:
Peter Boström5811a392015-12-10 13:02:50 +01001425 FrameObserver() : output_frame_event_(false, false) {}
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001426
nissed30a1112016-04-18 05:15:22 -07001427 void OnFrame(const VideoFrame& video_frame) override {
1428 output_frames_.push_back(video_frame);
Peter Boström5811a392015-12-10 13:02:50 +01001429 output_frame_event_.Set();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001430 }
1431
1432 void WaitOutputFrame() {
Peter Boström5811a392015-12-10 13:02:50 +01001433 const int kWaitFrameTimeoutMs = 3000;
1434 EXPECT_TRUE(output_frame_event_.Wait(kWaitFrameTimeoutMs))
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001435 << "Timeout while waiting for output frames.";
1436 }
1437
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001438 const std::vector<VideoFrame>& output_frames() const {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001439 return output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001440 }
1441
1442 private:
1443 // Delivered output frames.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001444 std::vector<VideoFrame> output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001445
1446 // Indicate an output frame has arrived.
Peter Boström5811a392015-12-10 13:02:50 +01001447 rtc::Event output_frame_event_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001448 };
1449
1450 // Initialize send stream.
solenberg4fbae2b2015-08-28 04:07:10 -07001451 CreateSenderCall(Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001452
solenberg4fbae2b2015-08-28 04:07:10 -07001453 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001454 CreateSendConfig(1, 0, &transport);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001455 FrameObserver observer;
stefanff483612015-12-21 03:14:00 -08001456 video_send_config_.pre_encode_callback = &observer;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001457 CreateVideoStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001458
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001459 // Prepare five input frames. Send ordinary VideoFrame and texture frames
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001460 // alternatively.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001461 std::vector<VideoFrame> input_frames;
stefanff483612015-12-21 03:14:00 -08001462 int width = static_cast<int>(video_encoder_config_.streams[0].width);
1463 int height = static_cast<int>(video_encoder_config_.streams[0].height);
Peter Boströmeb66e802015-06-05 11:08:03 +02001464 test::FakeNativeHandle* handle1 = new test::FakeNativeHandle();
1465 test::FakeNativeHandle* handle2 = new test::FakeNativeHandle();
1466 test::FakeNativeHandle* handle3 = new test::FakeNativeHandle();
Peter Boström13f61df2016-01-04 22:36:38 +01001467 input_frames.push_back(test::FakeNativeHandle::CreateFrame(
Peter Boströmeb66e802015-06-05 11:08:03 +02001468 handle1, width, height, 1, 1, kVideoRotation_0));
Peter Boström13f61df2016-01-04 22:36:38 +01001469 input_frames.push_back(test::FakeNativeHandle::CreateFrame(
Peter Boströmeb66e802015-06-05 11:08:03 +02001470 handle2, width, height, 2, 2, kVideoRotation_0));
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001471 input_frames.push_back(CreateVideoFrame(width, height, 3));
1472 input_frames.push_back(CreateVideoFrame(width, height, 4));
Peter Boström13f61df2016-01-04 22:36:38 +01001473 input_frames.push_back(test::FakeNativeHandle::CreateFrame(
Peter Boströmeb66e802015-06-05 11:08:03 +02001474 handle3, width, height, 5, 5, kVideoRotation_0));
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001475
stefanff483612015-12-21 03:14:00 -08001476 video_send_stream_->Start();
perkja49cbd32016-09-16 07:53:41 -07001477 test::FrameForwarder forwarder;
1478 video_send_stream_->SetSource(&forwarder);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001479 for (size_t i = 0; i < input_frames.size(); i++) {
perkja49cbd32016-09-16 07:53:41 -07001480 forwarder.IncomingCapturedFrame(input_frames[i]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001481 // Do not send the next frame too fast, so the frame dropper won't drop it.
1482 if (i < input_frames.size() - 1)
stefanff483612015-12-21 03:14:00 -08001483 SleepMs(1000 / video_encoder_config_.streams[0].max_framerate);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001484 // Wait until the output frame is received before sending the next input
1485 // frame. Or the previous input frame may be replaced without delivering.
1486 observer.WaitOutputFrame();
1487 }
stefanff483612015-12-21 03:14:00 -08001488 video_send_stream_->Stop();
perkja49cbd32016-09-16 07:53:41 -07001489 video_send_stream_->SetSource(nullptr);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001490
1491 // Test if the input and output frames are the same. render_time_ms and
1492 // timestamp are not compared because capturer sets those values.
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001493 ExpectEqualFramesVector(input_frames, observer.output_frames());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001494
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001495 DestroyStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001496}
1497
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001498void ExpectEqualFramesVector(const std::vector<VideoFrame>& frames1,
1499 const std::vector<VideoFrame>& frames2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001500 EXPECT_EQ(frames1.size(), frames2.size());
1501 for (size_t i = 0; i < std::min(frames1.size(), frames2.size()); ++i)
nisse26acec42016-04-15 03:43:39 -07001502 // Compare frame buffers, since we don't care about differing timestamps.
1503 EXPECT_TRUE(test::FrameBufsEqual(frames1[i].video_frame_buffer(),
1504 frames2[i].video_frame_buffer()));
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001505}
1506
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001507VideoFrame CreateVideoFrame(int width, int height, uint8_t data) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001508 const int kSizeY = width * height * 2;
kwiberg27f982b2016-03-01 11:52:33 -08001509 std::unique_ptr<uint8_t[]> buffer(new uint8_t[kSizeY]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001510 memset(buffer.get(), data, kSizeY);
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001511 VideoFrame frame;
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001512 frame.CreateFrame(buffer.get(), buffer.get(), buffer.get(), width, height,
Niels Möller739fcb92016-02-29 13:11:45 +01001513 width, width / 2, width / 2, kVideoRotation_0);
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001514 frame.set_timestamp(data);
1515 frame.set_render_time_ms(data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001516 return frame;
1517}
1518
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001519TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
1520 class EncoderStateObserver : public test::SendTest, public VideoEncoder {
1521 public:
1522 EncoderStateObserver()
1523 : SendTest(kDefaultTimeoutMs),
Erik Språng737336d2016-07-29 12:59:36 +02001524 stream_(nullptr),
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001525 initialized_(false),
1526 callback_registered_(false),
1527 num_releases_(0),
1528 released_(false) {}
1529
1530 bool IsReleased() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001531 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001532 return released_;
1533 }
1534
1535 bool IsReadyForEncode() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001536 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001537 return initialized_ && callback_registered_;
1538 }
1539
1540 size_t num_releases() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001541 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001542 return num_releases_;
1543 }
1544
1545 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001546 int32_t InitEncode(const VideoCodec* codecSettings,
1547 int32_t numberOfCores,
1548 size_t maxPayloadSize) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001549 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001550 EXPECT_FALSE(initialized_);
1551 initialized_ = true;
1552 released_ = false;
1553 return 0;
1554 }
1555
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001556 int32_t Encode(const VideoFrame& inputImage,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001557 const CodecSpecificInfo* codecSpecificInfo,
pbos22993e12015-10-19 02:39:06 -07001558 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001559 EXPECT_TRUE(IsReadyForEncode());
1560
Peter Boström5811a392015-12-10 13:02:50 +01001561 observation_complete_.Set();
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001562 return 0;
1563 }
1564
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001565 int32_t RegisterEncodeCompleteCallback(
1566 EncodedImageCallback* callback) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001567 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001568 EXPECT_TRUE(initialized_);
1569 callback_registered_ = true;
1570 return 0;
1571 }
1572
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001573 int32_t Release() override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001574 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001575 EXPECT_TRUE(IsReadyForEncode());
1576 EXPECT_FALSE(released_);
1577 initialized_ = false;
1578 callback_registered_ = false;
1579 released_ = true;
1580 ++num_releases_;
1581 return 0;
1582 }
1583
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001584 int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001585 EXPECT_TRUE(IsReadyForEncode());
1586 return 0;
1587 }
1588
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001589 int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001590 EXPECT_TRUE(IsReadyForEncode());
1591 return 0;
1592 }
1593
stefanff483612015-12-21 03:14:00 -08001594 void OnVideoStreamsCreated(
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001595 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001596 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001597 stream_ = send_stream;
1598 }
1599
stefanff483612015-12-21 03:14:00 -08001600 void ModifyVideoConfigs(
1601 VideoSendStream::Config* send_config,
1602 std::vector<VideoReceiveStream::Config>* receive_configs,
1603 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001604 send_config->encoder_settings.encoder = this;
perkj26091b12016-09-01 01:17:40 -07001605 encoder_config_ = encoder_config->Copy();
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001606 }
1607
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001608 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001609 EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001610 EXPECT_EQ(0u, num_releases());
perkj26091b12016-09-01 01:17:40 -07001611 stream_->ReconfigureVideoEncoder(std::move(encoder_config_));
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001612 EXPECT_EQ(0u, num_releases());
1613 stream_->Stop();
1614 // Encoder should not be released before destroying the VideoSendStream.
1615 EXPECT_FALSE(IsReleased());
1616 EXPECT_TRUE(IsReadyForEncode());
1617 stream_->Start();
1618 // Sanity check, make sure we still encode frames with this encoder.
Peter Boström5811a392015-12-10 13:02:50 +01001619 EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001620 }
1621
Peter Boströmf2f82832015-05-01 13:00:41 +02001622 rtc::CriticalSection crit_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001623 VideoSendStream* stream_;
1624 bool initialized_ GUARDED_BY(crit_);
1625 bool callback_registered_ GUARDED_BY(crit_);
1626 size_t num_releases_ GUARDED_BY(crit_);
1627 bool released_ GUARDED_BY(crit_);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001628 VideoEncoderConfig encoder_config_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001629 } test_encoder;
1630
stefane74eef12016-01-08 06:47:13 -08001631 RunBaseTest(&test_encoder);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001632
1633 EXPECT_TRUE(test_encoder.IsReleased());
1634 EXPECT_EQ(1u, test_encoder.num_releases());
1635}
1636
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001637TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
1638 class VideoCodecConfigObserver : public test::SendTest,
1639 public test::FakeEncoder {
1640 public:
1641 VideoCodecConfigObserver()
1642 : SendTest(kDefaultTimeoutMs),
1643 FakeEncoder(Clock::GetRealTimeClock()),
pbos14fe7082016-04-20 06:35:56 -07001644 init_encode_event_(false, false),
Erik Språng737336d2016-07-29 12:59:36 +02001645 num_initializations_(0),
1646 stream_(nullptr) {}
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001647
1648 private:
stefanff483612015-12-21 03:14:00 -08001649 void ModifyVideoConfigs(
1650 VideoSendStream::Config* send_config,
1651 std::vector<VideoReceiveStream::Config>* receive_configs,
1652 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001653 send_config->encoder_settings.encoder = this;
perkj26091b12016-09-01 01:17:40 -07001654 encoder_config_ = encoder_config->Copy();
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001655 }
1656
stefanff483612015-12-21 03:14:00 -08001657 void OnVideoStreamsCreated(
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001658 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001659 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001660 stream_ = send_stream;
1661 }
1662
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001663 int32_t InitEncode(const VideoCodec* config,
1664 int32_t number_of_cores,
1665 size_t max_payload_size) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001666 if (num_initializations_ == 0) {
1667 // Verify default values.
1668 EXPECT_EQ(kRealtimeVideo, config->mode);
1669 } else {
1670 // Verify that changed values are propagated.
1671 EXPECT_EQ(kScreensharing, config->mode);
1672 }
1673 ++num_initializations_;
pbos14fe7082016-04-20 06:35:56 -07001674 init_encode_event_.Set();
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001675 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1676 }
1677
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001678 void PerformTest() override {
pbos14fe7082016-04-20 06:35:56 -07001679 EXPECT_TRUE(init_encode_event_.Wait(kDefaultTimeoutMs));
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001680 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1681
Erik Språng143cec12015-04-28 10:01:41 +02001682 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
perkj26091b12016-09-01 01:17:40 -07001683 stream_->ReconfigureVideoEncoder(std::move(encoder_config_));
pbos14fe7082016-04-20 06:35:56 -07001684 EXPECT_TRUE(init_encode_event_.Wait(kDefaultTimeoutMs));
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001685 EXPECT_EQ(2u, num_initializations_)
1686 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1687 "new encoder settings.";
1688 }
1689
pbos14fe7082016-04-20 06:35:56 -07001690 rtc::Event init_encode_event_;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001691 size_t num_initializations_;
1692 VideoSendStream* stream_;
1693 VideoEncoderConfig encoder_config_;
1694 } test;
1695
stefane74eef12016-01-08 06:47:13 -08001696 RunBaseTest(&test);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001697}
1698
Peter Boström53eda3d2015-03-27 15:53:18 +01001699static const size_t kVideoCodecConfigObserverNumberOfTemporalLayers = 4;
1700template <typename T>
1701class VideoCodecConfigObserver : public test::SendTest,
1702 public test::FakeEncoder {
Peter Boström53eda3d2015-03-27 15:53:18 +01001703 public:
1704 VideoCodecConfigObserver(VideoCodecType video_codec_type,
1705 const char* codec_name)
1706 : SendTest(VideoSendStreamTest::kDefaultTimeoutMs),
1707 FakeEncoder(Clock::GetRealTimeClock()),
1708 video_codec_type_(video_codec_type),
1709 codec_name_(codec_name),
pbos14fe7082016-04-20 06:35:56 -07001710 init_encode_event_(false, false),
Erik Språng737336d2016-07-29 12:59:36 +02001711 num_initializations_(0),
1712 stream_(nullptr) {
Peter Boström53eda3d2015-03-27 15:53:18 +01001713 memset(&encoder_settings_, 0, sizeof(encoder_settings_));
1714 }
1715
1716 private:
stefanff483612015-12-21 03:14:00 -08001717 void ModifyVideoConfigs(
1718 VideoSendStream::Config* send_config,
1719 std::vector<VideoReceiveStream::Config>* receive_configs,
1720 VideoEncoderConfig* encoder_config) override {
Peter Boström53eda3d2015-03-27 15:53:18 +01001721 send_config->encoder_settings.encoder = this;
1722 send_config->encoder_settings.payload_name = codec_name_;
1723
1724 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
1725 encoder_config->streams[i].temporal_layer_thresholds_bps.resize(
1726 kVideoCodecConfigObserverNumberOfTemporalLayers - 1);
1727 }
1728
kthelgason29a44e32016-09-27 03:52:02 -07001729 encoder_config->encoder_specific_settings = GetEncoderSpecificSettings();
perkj26091b12016-09-01 01:17:40 -07001730 encoder_config_ = encoder_config->Copy();
Peter Boström53eda3d2015-03-27 15:53:18 +01001731 }
1732
stefanff483612015-12-21 03:14:00 -08001733 void OnVideoStreamsCreated(
Peter Boström53eda3d2015-03-27 15:53:18 +01001734 VideoSendStream* send_stream,
1735 const std::vector<VideoReceiveStream*>& receive_streams) override {
1736 stream_ = send_stream;
1737 }
1738
1739 int32_t InitEncode(const VideoCodec* config,
1740 int32_t number_of_cores,
1741 size_t max_payload_size) override {
1742 EXPECT_EQ(video_codec_type_, config->codecType);
1743 VerifyCodecSpecifics(*config);
1744 ++num_initializations_;
pbos14fe7082016-04-20 06:35:56 -07001745 init_encode_event_.Set();
Peter Boström53eda3d2015-03-27 15:53:18 +01001746 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1747 }
1748
1749 void VerifyCodecSpecifics(const VideoCodec& config) const;
kthelgason29a44e32016-09-27 03:52:02 -07001750 rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
1751 GetEncoderSpecificSettings() const;
Peter Boström53eda3d2015-03-27 15:53:18 +01001752
1753 void PerformTest() override {
pbos14fe7082016-04-20 06:35:56 -07001754 EXPECT_TRUE(
1755 init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
1756 ASSERT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
Peter Boström53eda3d2015-03-27 15:53:18 +01001757
1758 encoder_settings_.frameDroppingOn = true;
kthelgason29a44e32016-09-27 03:52:02 -07001759 encoder_config_.encoder_specific_settings = GetEncoderSpecificSettings();
perkj26091b12016-09-01 01:17:40 -07001760 stream_->ReconfigureVideoEncoder(std::move(encoder_config_));
pbos14fe7082016-04-20 06:35:56 -07001761 ASSERT_TRUE(
1762 init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
Peter Boström53eda3d2015-03-27 15:53:18 +01001763 EXPECT_EQ(2u, num_initializations_)
1764 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1765 "new encoder settings.";
1766 }
1767
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001768 int32_t Encode(const VideoFrame& input_image,
Peter Boström53eda3d2015-03-27 15:53:18 +01001769 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07001770 const std::vector<FrameType>* frame_types) override {
Peter Boström53eda3d2015-03-27 15:53:18 +01001771 // Silently skip the encode, FakeEncoder::Encode doesn't produce VP8.
1772 return 0;
1773 }
1774
1775 T encoder_settings_;
1776 const VideoCodecType video_codec_type_;
1777 const char* const codec_name_;
pbos14fe7082016-04-20 06:35:56 -07001778 rtc::Event init_encode_event_;
Peter Boström53eda3d2015-03-27 15:53:18 +01001779 size_t num_initializations_;
1780 VideoSendStream* stream_;
1781 VideoEncoderConfig encoder_config_;
1782};
1783
1784template <>
1785void VideoCodecConfigObserver<VideoCodecH264>::VerifyCodecSpecifics(
1786 const VideoCodec& config) const {
1787 EXPECT_EQ(0, memcmp(&config.codecSpecific.H264, &encoder_settings_,
1788 sizeof(encoder_settings_)));
1789}
kthelgason29a44e32016-09-27 03:52:02 -07001790
1791template <>
1792rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
1793VideoCodecConfigObserver<VideoCodecH264>::GetEncoderSpecificSettings() const {
1794 return new rtc::RefCountedObject<
1795 VideoEncoderConfig::H264EncoderSpecificSettings>(encoder_settings_);
1796}
1797
Peter Boström53eda3d2015-03-27 15:53:18 +01001798template <>
1799void VideoCodecConfigObserver<VideoCodecVP8>::VerifyCodecSpecifics(
1800 const VideoCodec& config) const {
1801 // Check that the number of temporal layers has propagated properly to
1802 // VideoCodec.
1803 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1804 config.codecSpecific.VP8.numberOfTemporalLayers);
1805
1806 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1807 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1808 config.simulcastStream[i].numberOfTemporalLayers);
1809 }
1810
1811 // Set expected temporal layers as they should have been set when
1812 // reconfiguring the encoder and not match the set config.
1813 VideoCodecVP8 encoder_settings = encoder_settings_;
1814 encoder_settings.numberOfTemporalLayers =
1815 kVideoCodecConfigObserverNumberOfTemporalLayers;
1816 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP8, &encoder_settings,
1817 sizeof(encoder_settings_)));
1818}
kthelgason29a44e32016-09-27 03:52:02 -07001819
1820template <>
1821rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
1822VideoCodecConfigObserver<VideoCodecVP8>::GetEncoderSpecificSettings() const {
1823 return new rtc::RefCountedObject<
1824 VideoEncoderConfig::Vp8EncoderSpecificSettings>(encoder_settings_);
1825}
1826
Peter Boström53eda3d2015-03-27 15:53:18 +01001827template <>
1828void VideoCodecConfigObserver<VideoCodecVP9>::VerifyCodecSpecifics(
1829 const VideoCodec& config) const {
1830 // Check that the number of temporal layers has propagated properly to
1831 // VideoCodec.
1832 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1833 config.codecSpecific.VP9.numberOfTemporalLayers);
1834
1835 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1836 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1837 config.simulcastStream[i].numberOfTemporalLayers);
1838 }
1839
1840 // Set expected temporal layers as they should have been set when
1841 // reconfiguring the encoder and not match the set config.
1842 VideoCodecVP9 encoder_settings = encoder_settings_;
1843 encoder_settings.numberOfTemporalLayers =
1844 kVideoCodecConfigObserverNumberOfTemporalLayers;
1845 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP9, &encoder_settings,
1846 sizeof(encoder_settings_)));
1847}
1848
kthelgason29a44e32016-09-27 03:52:02 -07001849template <>
1850rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
1851VideoCodecConfigObserver<VideoCodecVP9>::GetEncoderSpecificSettings() const {
1852 return new rtc::RefCountedObject<
1853 VideoEncoderConfig::Vp9EncoderSpecificSettings>(encoder_settings_);
1854}
1855
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001856TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp8Config) {
Peter Boström53eda3d2015-03-27 15:53:18 +01001857 VideoCodecConfigObserver<VideoCodecVP8> test(kVideoCodecVP8, "VP8");
stefane74eef12016-01-08 06:47:13 -08001858 RunBaseTest(&test);
Peter Boström53eda3d2015-03-27 15:53:18 +01001859}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001860
Peter Boström53eda3d2015-03-27 15:53:18 +01001861TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp9Config) {
1862 VideoCodecConfigObserver<VideoCodecVP9> test(kVideoCodecVP9, "VP9");
stefane74eef12016-01-08 06:47:13 -08001863 RunBaseTest(&test);
Peter Boström53eda3d2015-03-27 15:53:18 +01001864}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001865
Peter Boström53eda3d2015-03-27 15:53:18 +01001866TEST_F(VideoSendStreamTest, EncoderSetupPropagatesH264Config) {
1867 VideoCodecConfigObserver<VideoCodecH264> test(kVideoCodecH264, "H264");
stefane74eef12016-01-08 06:47:13 -08001868 RunBaseTest(&test);
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001869}
1870
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001871TEST_F(VideoSendStreamTest, RtcpSenderReportContainsMediaBytesSent) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001872 class RtcpSenderReportTest : public test::SendTest {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001873 public:
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001874 RtcpSenderReportTest() : SendTest(kDefaultTimeoutMs),
1875 rtp_packets_sent_(0),
1876 media_bytes_sent_(0) {}
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001877
1878 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001879 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan4b569042015-11-11 06:39:57 -08001880 rtc::CritScope lock(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001881 RTPHeader header;
1882 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001883 ++rtp_packets_sent_;
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001884 media_bytes_sent_ += length - header.headerLength - header.paddingLength;
1885 return SEND_PACKET;
1886 }
1887
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001888 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan4b569042015-11-11 06:39:57 -08001889 rtc::CritScope lock(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001890 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1891 EXPECT_TRUE(parser.IsValid());
1892
1893 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001894 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1895 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001896 // Only compare sent media bytes if SenderPacketCount matches the
1897 // number of sent rtp packets (a new rtp packet could be sent before
1898 // the rtcp packet).
1899 if (parser.Packet().SR.SenderOctetCount > 0 &&
1900 parser.Packet().SR.SenderPacketCount == rtp_packets_sent_) {
1901 EXPECT_EQ(media_bytes_sent_, parser.Packet().SR.SenderOctetCount);
Peter Boström5811a392015-12-10 13:02:50 +01001902 observation_complete_.Set();
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001903 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001904 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001905 packet_type = parser.Iterate();
1906 }
1907
1908 return SEND_PACKET;
1909 }
1910
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001911 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001912 EXPECT_TRUE(Wait()) << "Timed out while waiting for RTCP sender report.";
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001913 }
1914
stefan4b569042015-11-11 06:39:57 -08001915 rtc::CriticalSection crit_;
1916 size_t rtp_packets_sent_ GUARDED_BY(&crit_);
1917 size_t media_bytes_sent_ GUARDED_BY(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001918 } test;
1919
stefane74eef12016-01-08 06:47:13 -08001920 RunBaseTest(&test);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001921}
1922
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001923TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
1924 static const int kScreencastTargetBitrateKbps = 200;
1925 class ScreencastTargetBitrateTest : public test::SendTest,
1926 public test::FakeEncoder {
1927 public:
1928 ScreencastTargetBitrateTest()
1929 : SendTest(kDefaultTimeoutMs),
1930 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1931
1932 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001933 int32_t InitEncode(const VideoCodec* config,
1934 int32_t number_of_cores,
1935 size_t max_payload_size) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001936 EXPECT_EQ(static_cast<unsigned int>(kScreencastTargetBitrateKbps),
1937 config->targetBitrate);
Peter Boström5811a392015-12-10 13:02:50 +01001938 observation_complete_.Set();
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001939 return test::FakeEncoder::InitEncode(
1940 config, number_of_cores, max_payload_size);
1941 }
stefanff483612015-12-21 03:14:00 -08001942 void ModifyVideoConfigs(
1943 VideoSendStream::Config* send_config,
1944 std::vector<VideoReceiveStream::Config>* receive_configs,
1945 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001946 send_config->encoder_settings.encoder = this;
1947 EXPECT_EQ(1u, encoder_config->streams.size());
1948 EXPECT_TRUE(
1949 encoder_config->streams[0].temporal_layer_thresholds_bps.empty());
1950 encoder_config->streams[0].temporal_layer_thresholds_bps.push_back(
1951 kScreencastTargetBitrateKbps * 1000);
Erik Språng143cec12015-04-28 10:01:41 +02001952 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001953 }
1954
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001955 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001956 EXPECT_TRUE(Wait())
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001957 << "Timed out while waiting for the encoder to be initialized.";
1958 }
1959 } test;
1960
stefane74eef12016-01-08 06:47:13 -08001961 RunBaseTest(&test);
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001962}
pbos@webrtc.org00873182014-11-25 14:03:34 +00001963
philipelc6957c72016-04-28 15:52:49 +02001964TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001965 // These are chosen to be "kind of odd" to not be accidentally checked against
1966 // default values.
1967 static const int kMinBitrateKbps = 137;
1968 static const int kStartBitrateKbps = 345;
1969 static const int kLowerMaxBitrateKbps = 312;
1970 static const int kMaxBitrateKbps = 413;
1971 static const int kIncreasedStartBitrateKbps = 451;
1972 static const int kIncreasedMaxBitrateKbps = 597;
1973 class EncoderBitrateThresholdObserver : public test::SendTest,
1974 public test::FakeEncoder {
1975 public:
1976 EncoderBitrateThresholdObserver()
1977 : SendTest(kDefaultTimeoutMs),
1978 FakeEncoder(Clock::GetRealTimeClock()),
pbos14fe7082016-04-20 06:35:56 -07001979 init_encode_event_(false, false),
perkj26091b12016-09-01 01:17:40 -07001980 bitrate_changed_event_(false, false),
1981 target_bitrate_(0),
Erik Språng737336d2016-07-29 12:59:36 +02001982 num_initializations_(0),
1983 call_(nullptr),
1984 send_stream_(nullptr) {}
pbos@webrtc.org00873182014-11-25 14:03:34 +00001985
1986 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001987 int32_t InitEncode(const VideoCodec* codecSettings,
1988 int32_t numberOfCores,
1989 size_t maxPayloadSize) override {
perkj26091b12016-09-01 01:17:40 -07001990 EXPECT_GE(codecSettings->startBitrate, codecSettings->minBitrate);
1991 EXPECT_LE(codecSettings->startBitrate, codecSettings->maxBitrate);
pbos@webrtc.org00873182014-11-25 14:03:34 +00001992 if (num_initializations_ == 0) {
1993 EXPECT_EQ(static_cast<unsigned int>(kMinBitrateKbps),
1994 codecSettings->minBitrate);
1995 EXPECT_EQ(static_cast<unsigned int>(kStartBitrateKbps),
1996 codecSettings->startBitrate);
1997 EXPECT_EQ(static_cast<unsigned int>(kMaxBitrateKbps),
1998 codecSettings->maxBitrate);
Peter Boström5811a392015-12-10 13:02:50 +01001999 observation_complete_.Set();
pbos@webrtc.org00873182014-11-25 14:03:34 +00002000 } else if (num_initializations_ == 1) {
2001 EXPECT_EQ(static_cast<unsigned int>(kLowerMaxBitrateKbps),
2002 codecSettings->maxBitrate);
2003 // The start bitrate should be kept (-1) and capped to the max bitrate.
2004 // Since this is not an end-to-end call no receiver should have been
2005 // returning a REMB that could lower this estimate.
2006 EXPECT_EQ(codecSettings->startBitrate, codecSettings->maxBitrate);
2007 } else if (num_initializations_ == 2) {
2008 EXPECT_EQ(static_cast<unsigned int>(kIncreasedMaxBitrateKbps),
2009 codecSettings->maxBitrate);
perkj26091b12016-09-01 01:17:40 -07002010 // The start bitrate will be whatever the rate BitRateController
2011 // has currently configured but in the span of the set max and min
2012 // bitrate.
pbos@webrtc.org00873182014-11-25 14:03:34 +00002013 }
2014 ++num_initializations_;
pbos14fe7082016-04-20 06:35:56 -07002015 init_encode_event_.Set();
pbos@webrtc.org00873182014-11-25 14:03:34 +00002016 return FakeEncoder::InitEncode(codecSettings, numberOfCores,
2017 maxPayloadSize);
2018 }
2019
perkj26091b12016-09-01 01:17:40 -07002020 int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override {
2021 {
2022 rtc::CritScope lock(&crit_);
2023 target_bitrate_ = newBitRate;
2024 }
2025 bitrate_changed_event_.Set();
2026 return FakeEncoder::SetRates(newBitRate, frameRate);
2027 }
2028
2029 void WaitForSetRates(uint32_t expected_bitrate) {
2030 EXPECT_TRUE(
2031 bitrate_changed_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs))
2032 << "Timed out while waiting encoder rate to be set.";
2033 rtc::CritScope lock(&crit_);
2034 EXPECT_EQ(expected_bitrate, target_bitrate_);
2035 }
2036
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002037 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -07002038 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +01002039 config.bitrate_config.min_bitrate_bps = kMinBitrateKbps * 1000;
2040 config.bitrate_config.start_bitrate_bps = kStartBitrateKbps * 1000;
2041 config.bitrate_config.max_bitrate_bps = kMaxBitrateKbps * 1000;
pbos@webrtc.org00873182014-11-25 14:03:34 +00002042 return config;
2043 }
2044
stefanff483612015-12-21 03:14:00 -08002045 void ModifyVideoConfigs(
2046 VideoSendStream::Config* send_config,
2047 std::vector<VideoReceiveStream::Config>* receive_configs,
2048 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00002049 send_config->encoder_settings.encoder = this;
2050 // Set bitrates lower/higher than min/max to make sure they are properly
2051 // capped.
Stefan Holmere5904162015-03-26 11:11:06 +01002052 encoder_config->streams.front().min_bitrate_bps = kMinBitrateKbps * 1000;
2053 encoder_config->streams.front().max_bitrate_bps = kMaxBitrateKbps * 1000;
perkj26091b12016-09-01 01:17:40 -07002054 encoder_config_ = encoder_config->Copy();
pbos@webrtc.org00873182014-11-25 14:03:34 +00002055 }
2056
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002057 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00002058 call_ = sender_call;
2059 }
2060
stefanff483612015-12-21 03:14:00 -08002061 void OnVideoStreamsCreated(
Stefan Holmere5904162015-03-26 11:11:06 +01002062 VideoSendStream* send_stream,
2063 const std::vector<VideoReceiveStream*>& receive_streams) override {
2064 send_stream_ = send_stream;
2065 }
2066
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002067 void PerformTest() override {
pbos14fe7082016-04-20 06:35:56 -07002068 ASSERT_TRUE(
2069 init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs))
perkj26091b12016-09-01 01:17:40 -07002070 << "Timed out while waiting for encoder to be configured.";
2071 WaitForSetRates(kStartBitrateKbps);
pbos@webrtc.org00873182014-11-25 14:03:34 +00002072 Call::Config::BitrateConfig bitrate_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00002073 bitrate_config.start_bitrate_bps = kIncreasedStartBitrateKbps * 1000;
2074 bitrate_config.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000;
2075 call_->SetBitrateConfig(bitrate_config);
perkj26091b12016-09-01 01:17:40 -07002076 // Encoder rate is capped by EncoderConfig max_bitrate_bps.
2077 WaitForSetRates(kMaxBitrateKbps);
2078
Stefan Holmere5904162015-03-26 11:11:06 +01002079 encoder_config_.streams[0].min_bitrate_bps = 0;
2080 encoder_config_.streams[0].max_bitrate_bps = kLowerMaxBitrateKbps * 1000;
perkj26091b12016-09-01 01:17:40 -07002081 send_stream_->ReconfigureVideoEncoder(encoder_config_.Copy());
pbos14fe7082016-04-20 06:35:56 -07002082 ASSERT_TRUE(
2083 init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
Stefan Holmere5904162015-03-26 11:11:06 +01002084 EXPECT_EQ(2, num_initializations_)
2085 << "Encoder should have been reconfigured with the new value.";
perkj26091b12016-09-01 01:17:40 -07002086 WaitForSetRates(kLowerMaxBitrateKbps);
2087
Stefan Holmere5904162015-03-26 11:11:06 +01002088 encoder_config_.streams[0].target_bitrate_bps =
2089 encoder_config_.streams[0].min_bitrate_bps;
2090 encoder_config_.streams[0].max_bitrate_bps =
2091 kIncreasedMaxBitrateKbps * 1000;
perkj26091b12016-09-01 01:17:40 -07002092 send_stream_->ReconfigureVideoEncoder(encoder_config_.Copy());
pbos14fe7082016-04-20 06:35:56 -07002093 ASSERT_TRUE(
2094 init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
pbos@webrtc.org00873182014-11-25 14:03:34 +00002095 EXPECT_EQ(3, num_initializations_)
2096 << "Encoder should have been reconfigured with the new value.";
perkj26091b12016-09-01 01:17:40 -07002097 // Expected target bitrate is the start bitrate set in the call to
2098 // call_->SetBitrateConfig.
2099 WaitForSetRates(kIncreasedStartBitrateKbps);
pbos@webrtc.org00873182014-11-25 14:03:34 +00002100 }
2101
pbos14fe7082016-04-20 06:35:56 -07002102 rtc::Event init_encode_event_;
perkj26091b12016-09-01 01:17:40 -07002103 rtc::Event bitrate_changed_event_;
2104 rtc::CriticalSection crit_;
2105 uint32_t target_bitrate_ GUARDED_BY(&crit_);
pbos@webrtc.org00873182014-11-25 14:03:34 +00002106 int num_initializations_;
2107 webrtc::Call* call_;
Stefan Holmere5904162015-03-26 11:11:06 +01002108 webrtc::VideoSendStream* send_stream_;
2109 webrtc::VideoEncoderConfig encoder_config_;
pbos@webrtc.org00873182014-11-25 14:03:34 +00002110 } test;
2111
stefane74eef12016-01-08 06:47:13 -08002112 RunBaseTest(&test);
pbos@webrtc.org00873182014-11-25 14:03:34 +00002113}
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002114
2115TEST_F(VideoSendStreamTest, ReportsSentResolution) {
2116 static const size_t kNumStreams = 3;
2117 // Unusual resolutions to make sure that they are the ones being reported.
2118 static const struct {
2119 int width;
2120 int height;
2121 } kEncodedResolution[kNumStreams] = {
2122 {241, 181}, {300, 121}, {121, 221}};
2123 class ScreencastTargetBitrateTest : public test::SendTest,
2124 public test::FakeEncoder {
2125 public:
2126 ScreencastTargetBitrateTest()
2127 : SendTest(kDefaultTimeoutMs),
Erik Språng737336d2016-07-29 12:59:36 +02002128 test::FakeEncoder(Clock::GetRealTimeClock()),
2129 send_stream_(nullptr) {}
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002130
2131 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07002132 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002133 const CodecSpecificInfo* codecSpecificInfo,
pbos22993e12015-10-19 02:39:06 -07002134 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002135 CodecSpecificInfo specifics;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002136 specifics.codecType = kVideoCodecGeneric;
2137
2138 uint8_t buffer[16] = {0};
2139 EncodedImage encoded(buffer, sizeof(buffer), sizeof(buffer));
2140 encoded._timeStamp = input_image.timestamp();
2141 encoded.capture_time_ms_ = input_image.render_time_ms();
2142
2143 for (size_t i = 0; i < kNumStreams; ++i) {
2144 specifics.codecSpecific.generic.simulcast_idx = static_cast<uint8_t>(i);
2145 encoded._frameType = (*frame_types)[i];
2146 encoded._encodedWidth = kEncodedResolution[i].width;
2147 encoded._encodedHeight = kEncodedResolution[i].height;
Peter Boström74f6e9e2016-04-04 17:56:10 +02002148 RTC_DCHECK(callback_);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002149 if (callback_->Encoded(encoded, &specifics, nullptr) != 0)
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002150 return -1;
2151 }
2152
Peter Boström5811a392015-12-10 13:02:50 +01002153 observation_complete_.Set();
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002154 return 0;
2155 }
stefanff483612015-12-21 03:14:00 -08002156 void ModifyVideoConfigs(
2157 VideoSendStream::Config* send_config,
2158 std::vector<VideoReceiveStream::Config>* receive_configs,
2159 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002160 send_config->encoder_settings.encoder = this;
2161 EXPECT_EQ(kNumStreams, encoder_config->streams.size());
2162 }
2163
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002164 size_t GetNumVideoStreams() const override { return kNumStreams; }
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002165
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002166 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002167 EXPECT_TRUE(Wait())
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002168 << "Timed out while waiting for the encoder to send one frame.";
2169 VideoSendStream::Stats stats = send_stream_->GetStats();
2170
2171 for (size_t i = 0; i < kNumStreams; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002172 ASSERT_TRUE(stats.substreams.find(kVideoSendSsrcs[i]) !=
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002173 stats.substreams.end())
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002174 << "No stats for SSRC: " << kVideoSendSsrcs[i]
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002175 << ", stats should exist as soon as frames have been encoded.";
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002176 VideoSendStream::StreamStats ssrc_stats =
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002177 stats.substreams[kVideoSendSsrcs[i]];
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002178 EXPECT_EQ(kEncodedResolution[i].width, ssrc_stats.width);
2179 EXPECT_EQ(kEncodedResolution[i].height, ssrc_stats.height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002180 }
2181 }
2182
stefanff483612015-12-21 03:14:00 -08002183 void OnVideoStreamsCreated(
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002184 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002185 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002186 send_stream_ = send_stream;
2187 }
2188
2189 VideoSendStream* send_stream_;
2190 } test;
2191
stefane74eef12016-01-08 06:47:13 -08002192 RunBaseTest(&test);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002193}
philipel0f9af012015-09-01 07:01:51 -07002194
Peter Boström12996152016-05-14 02:03:18 +02002195#if !defined(RTC_DISABLE_VP9)
Åsa Perssonff24c042015-12-04 10:58:08 +01002196class Vp9HeaderObserver : public test::SendTest {
philipel0f9af012015-09-01 07:01:51 -07002197 public:
Åsa Perssonff24c042015-12-04 10:58:08 +01002198 Vp9HeaderObserver()
2199 : SendTest(VideoSendStreamTest::kLongTimeoutMs),
philipel7fabd462015-09-03 04:42:32 -07002200 vp9_encoder_(VP9Encoder::Create()),
Åsa Perssonff24c042015-12-04 10:58:08 +01002201 vp9_settings_(VideoEncoder::GetDefaultVp9Settings()),
2202 packets_sent_(0),
2203 frames_sent_(0) {}
philipel7fabd462015-09-03 04:42:32 -07002204
stefanff483612015-12-21 03:14:00 -08002205 virtual void ModifyVideoConfigsHook(
philipel0f9af012015-09-01 07:01:51 -07002206 VideoSendStream::Config* send_config,
2207 std::vector<VideoReceiveStream::Config>* receive_configs,
2208 VideoEncoderConfig* encoder_config) {}
2209
Åsa Perssonff24c042015-12-04 10:58:08 +01002210 virtual void InspectHeader(const RTPVideoHeaderVP9& vp9) = 0;
philipel0f9af012015-09-01 07:01:51 -07002211
2212 private:
2213 const int kVp9PayloadType = 105;
2214
stefanff483612015-12-21 03:14:00 -08002215 void ModifyVideoConfigs(
2216 VideoSendStream::Config* send_config,
2217 std::vector<VideoReceiveStream::Config>* receive_configs,
2218 VideoEncoderConfig* encoder_config) override {
philipel7fabd462015-09-03 04:42:32 -07002219 send_config->encoder_settings.encoder = vp9_encoder_.get();
philipel0f9af012015-09-01 07:01:51 -07002220 send_config->encoder_settings.payload_name = "VP9";
2221 send_config->encoder_settings.payload_type = kVp9PayloadType;
stefanff483612015-12-21 03:14:00 -08002222 ModifyVideoConfigsHook(send_config, receive_configs, encoder_config);
kthelgason29a44e32016-09-27 03:52:02 -07002223 encoder_config->encoder_specific_settings = new rtc::RefCountedObject<
2224 VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings_);
Åsa Perssonff24c042015-12-04 10:58:08 +01002225 EXPECT_EQ(1u, encoder_config->streams.size());
2226 encoder_config->streams[0].temporal_layer_thresholds_bps.resize(
2227 vp9_settings_.numberOfTemporalLayers - 1);
perkj26091b12016-09-01 01:17:40 -07002228 encoder_config_ = encoder_config->Copy();
philipel0f9af012015-09-01 07:01:51 -07002229 }
2230
2231 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002232 EXPECT_TRUE(Wait()) << "Test timed out waiting for VP9 packet, num frames "
2233 << frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07002234 }
2235
2236 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2237 RTPHeader header;
2238 EXPECT_TRUE(parser_->Parse(packet, length, &header));
2239
Åsa Perssonff24c042015-12-04 10:58:08 +01002240 EXPECT_EQ(kVp9PayloadType, header.payloadType);
2241 const uint8_t* payload = packet + header.headerLength;
2242 size_t payload_length = length - header.headerLength - header.paddingLength;
philipel0f9af012015-09-01 07:01:51 -07002243
Åsa Perssonff24c042015-12-04 10:58:08 +01002244 bool new_packet = packets_sent_ == 0 ||
2245 IsNewerSequenceNumber(header.sequenceNumber,
2246 last_header_.sequenceNumber);
2247 if (payload_length > 0 && new_packet) {
2248 RtpDepacketizer::ParsedPayload parsed;
2249 RtpDepacketizerVp9 depacketizer;
2250 EXPECT_TRUE(depacketizer.Parse(&parsed, payload, payload_length));
2251 EXPECT_EQ(RtpVideoCodecTypes::kRtpVideoVp9, parsed.type.Video.codec);
2252 // Verify common fields for all configurations.
2253 VerifyCommonHeader(parsed.type.Video.codecHeader.VP9);
2254 CompareConsecutiveFrames(header, parsed.type.Video);
2255 // Verify configuration specific settings.
2256 InspectHeader(parsed.type.Video.codecHeader.VP9);
philipel0f9af012015-09-01 07:01:51 -07002257
Åsa Perssonff24c042015-12-04 10:58:08 +01002258 ++packets_sent_;
2259 if (header.markerBit) {
2260 ++frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07002261 }
Åsa Perssonff24c042015-12-04 10:58:08 +01002262 last_header_ = header;
2263 last_vp9_ = parsed.type.Video.codecHeader.VP9;
philipel0f9af012015-09-01 07:01:51 -07002264 }
philipel0f9af012015-09-01 07:01:51 -07002265 return SEND_PACKET;
2266 }
2267
philipel7fabd462015-09-03 04:42:32 -07002268 protected:
Åsa Perssonff24c042015-12-04 10:58:08 +01002269 bool ContinuousPictureId(const RTPVideoHeaderVP9& vp9) const {
2270 if (last_vp9_.picture_id > vp9.picture_id) {
2271 return vp9.picture_id == 0; // Wrap.
2272 } else {
2273 return vp9.picture_id == last_vp9_.picture_id + 1;
2274 }
2275 }
2276
2277 void VerifySpatialIdxWithinFrame(const RTPVideoHeaderVP9& vp9) const {
Åsa Perssonff24c042015-12-04 10:58:08 +01002278 bool new_layer = vp9.spatial_idx != last_vp9_.spatial_idx;
2279 EXPECT_EQ(new_layer, vp9.beginning_of_frame);
2280 EXPECT_EQ(new_layer, last_vp9_.end_of_frame);
2281 EXPECT_EQ(new_layer ? last_vp9_.spatial_idx + 1 : last_vp9_.spatial_idx,
2282 vp9.spatial_idx);
2283 }
2284
2285 void VerifyFixedTemporalLayerStructure(const RTPVideoHeaderVP9& vp9,
2286 uint8_t num_layers) const {
2287 switch (num_layers) {
2288 case 0:
2289 VerifyTemporalLayerStructure0(vp9);
2290 break;
2291 case 1:
2292 VerifyTemporalLayerStructure1(vp9);
2293 break;
2294 case 2:
2295 VerifyTemporalLayerStructure2(vp9);
2296 break;
2297 case 3:
2298 VerifyTemporalLayerStructure3(vp9);
2299 break;
2300 default:
2301 RTC_NOTREACHED();
2302 }
2303 }
2304
2305 void VerifyTemporalLayerStructure0(const RTPVideoHeaderVP9& vp9) const {
2306 EXPECT_EQ(kNoTl0PicIdx, vp9.tl0_pic_idx);
2307 EXPECT_EQ(kNoTemporalIdx, vp9.temporal_idx); // no tid
2308 EXPECT_FALSE(vp9.temporal_up_switch);
2309 }
2310
2311 void VerifyTemporalLayerStructure1(const RTPVideoHeaderVP9& vp9) const {
2312 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
2313 EXPECT_EQ(0, vp9.temporal_idx); // 0,0,0,...
2314 EXPECT_FALSE(vp9.temporal_up_switch);
2315 }
2316
2317 void VerifyTemporalLayerStructure2(const RTPVideoHeaderVP9& vp9) const {
2318 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
2319 EXPECT_GE(vp9.temporal_idx, 0); // 0,1,0,1,... (tid reset on I-frames).
2320 EXPECT_LE(vp9.temporal_idx, 1);
2321 EXPECT_EQ(vp9.temporal_idx > 0, vp9.temporal_up_switch);
2322 if (IsNewPictureId(vp9)) {
2323 uint8_t expected_tid =
2324 (!vp9.inter_pic_predicted || last_vp9_.temporal_idx == 1) ? 0 : 1;
2325 EXPECT_EQ(expected_tid, vp9.temporal_idx);
2326 }
2327 }
2328
2329 void VerifyTemporalLayerStructure3(const RTPVideoHeaderVP9& vp9) const {
2330 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
2331 EXPECT_GE(vp9.temporal_idx, 0); // 0,2,1,2,... (tid reset on I-frames).
2332 EXPECT_LE(vp9.temporal_idx, 2);
2333 if (IsNewPictureId(vp9) && vp9.inter_pic_predicted) {
2334 EXPECT_NE(vp9.temporal_idx, last_vp9_.temporal_idx);
2335 switch (vp9.temporal_idx) {
2336 case 0:
2337 EXPECT_EQ(2, last_vp9_.temporal_idx);
2338 EXPECT_FALSE(vp9.temporal_up_switch);
2339 break;
2340 case 1:
2341 EXPECT_EQ(2, last_vp9_.temporal_idx);
2342 EXPECT_TRUE(vp9.temporal_up_switch);
2343 break;
2344 case 2:
2345 EXPECT_EQ(last_vp9_.temporal_idx == 0, vp9.temporal_up_switch);
2346 break;
2347 }
2348 }
2349 }
2350
2351 void VerifyTl0Idx(const RTPVideoHeaderVP9& vp9) const {
2352 if (vp9.tl0_pic_idx == kNoTl0PicIdx)
2353 return;
2354
2355 uint8_t expected_tl0_idx = last_vp9_.tl0_pic_idx;
2356 if (vp9.temporal_idx == 0)
2357 ++expected_tl0_idx;
2358 EXPECT_EQ(expected_tl0_idx, vp9.tl0_pic_idx);
2359 }
2360
2361 bool IsNewPictureId(const RTPVideoHeaderVP9& vp9) const {
2362 return frames_sent_ > 0 && (vp9.picture_id != last_vp9_.picture_id);
2363 }
2364
2365 // Flexible mode (F=1): Non-flexible mode (F=0):
2366 //
2367 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2368 // |I|P|L|F|B|E|V|-| |I|P|L|F|B|E|V|-|
2369 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2370 // I: |M| PICTURE ID | I: |M| PICTURE ID |
2371 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2372 // M: | EXTENDED PID | M: | EXTENDED PID |
2373 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2374 // L: | T |U| S |D| L: | T |U| S |D|
2375 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2376 // P,F: | P_DIFF |X|N| | TL0PICIDX |
2377 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2378 // X: |EXTENDED P_DIFF| V: | SS .. |
2379 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2380 // V: | SS .. |
2381 // +-+-+-+-+-+-+-+-+
2382 void VerifyCommonHeader(const RTPVideoHeaderVP9& vp9) const {
2383 EXPECT_EQ(kMaxTwoBytePictureId, vp9.max_picture_id); // M:1
2384 EXPECT_NE(kNoPictureId, vp9.picture_id); // I:1
2385 EXPECT_EQ(vp9_settings_.flexibleMode, vp9.flexible_mode); // F
2386 EXPECT_GE(vp9.spatial_idx, 0); // S
2387 EXPECT_LT(vp9.spatial_idx, vp9_settings_.numberOfSpatialLayers);
2388 if (vp9.ss_data_available) // V
2389 VerifySsData(vp9);
2390
2391 if (frames_sent_ == 0)
2392 EXPECT_FALSE(vp9.inter_pic_predicted); // P
2393
2394 if (!vp9.inter_pic_predicted) {
2395 EXPECT_TRUE(vp9.temporal_idx == 0 || vp9.temporal_idx == kNoTemporalIdx);
2396 EXPECT_FALSE(vp9.temporal_up_switch);
2397 }
2398 }
2399
2400 // Scalability structure (SS).
2401 //
2402 // +-+-+-+-+-+-+-+-+
2403 // V: | N_S |Y|G|-|-|-|
2404 // +-+-+-+-+-+-+-+-+
2405 // Y: | WIDTH | N_S + 1 times
2406 // +-+-+-+-+-+-+-+-+
2407 // | HEIGHT |
2408 // +-+-+-+-+-+-+-+-+
2409 // G: | N_G |
2410 // +-+-+-+-+-+-+-+-+
2411 // N_G: | T |U| R |-|-| N_G times
2412 // +-+-+-+-+-+-+-+-+
2413 // | P_DIFF | R times
2414 // +-+-+-+-+-+-+-+-+
2415 void VerifySsData(const RTPVideoHeaderVP9& vp9) const {
2416 EXPECT_TRUE(vp9.ss_data_available); // V
2417 EXPECT_EQ(vp9_settings_.numberOfSpatialLayers, // N_S + 1
2418 vp9.num_spatial_layers);
2419 EXPECT_TRUE(vp9.spatial_layer_resolution_present); // Y:1
2420 size_t expected_width = encoder_config_.streams[0].width;
2421 size_t expected_height = encoder_config_.streams[0].height;
Peter Boström02083222016-06-14 12:52:54 +02002422 for (int i = static_cast<int>(vp9.num_spatial_layers) - 1; i >= 0; --i) {
Åsa Perssonff24c042015-12-04 10:58:08 +01002423 EXPECT_EQ(expected_width, vp9.width[i]); // WIDTH
2424 EXPECT_EQ(expected_height, vp9.height[i]); // HEIGHT
2425 expected_width /= 2;
2426 expected_height /= 2;
2427 }
2428 }
2429
2430 void CompareConsecutiveFrames(const RTPHeader& header,
2431 const RTPVideoHeader& video) const {
2432 const RTPVideoHeaderVP9& vp9 = video.codecHeader.VP9;
2433
2434 bool new_frame = packets_sent_ == 0 ||
2435 IsNewerTimestamp(header.timestamp, last_header_.timestamp);
2436 EXPECT_EQ(new_frame, video.isFirstPacket);
2437 if (!new_frame) {
2438 EXPECT_FALSE(last_header_.markerBit);
2439 EXPECT_EQ(last_header_.timestamp, header.timestamp);
2440 EXPECT_EQ(last_vp9_.picture_id, vp9.picture_id);
2441 EXPECT_EQ(last_vp9_.temporal_idx, vp9.temporal_idx);
2442 EXPECT_EQ(last_vp9_.tl0_pic_idx, vp9.tl0_pic_idx);
2443 VerifySpatialIdxWithinFrame(vp9);
2444 return;
2445 }
2446 // New frame.
2447 EXPECT_TRUE(vp9.beginning_of_frame);
2448
2449 // Compare with last packet in previous frame.
2450 if (frames_sent_ == 0)
2451 return;
2452 EXPECT_TRUE(last_vp9_.end_of_frame);
2453 EXPECT_TRUE(last_header_.markerBit);
2454 EXPECT_TRUE(ContinuousPictureId(vp9));
2455 VerifyTl0Idx(vp9);
2456 }
2457
kwiberg27f982b2016-03-01 11:52:33 -08002458 std::unique_ptr<VP9Encoder> vp9_encoder_;
philipel0f9af012015-09-01 07:01:51 -07002459 VideoCodecVP9 vp9_settings_;
Åsa Perssonff24c042015-12-04 10:58:08 +01002460 webrtc::VideoEncoderConfig encoder_config_;
2461 RTPHeader last_header_;
2462 RTPVideoHeaderVP9 last_vp9_;
2463 size_t packets_sent_;
2464 size_t frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07002465};
2466
Åsa Perssonff24c042015-12-04 10:58:08 +01002467TEST_F(VideoSendStreamTest, Vp9NonFlexMode_1Tl1SLayers) {
2468 const uint8_t kNumTemporalLayers = 1;
2469 const uint8_t kNumSpatialLayers = 1;
2470 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2471}
2472
2473TEST_F(VideoSendStreamTest, Vp9NonFlexMode_2Tl1SLayers) {
2474 const uint8_t kNumTemporalLayers = 2;
2475 const uint8_t kNumSpatialLayers = 1;
2476 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2477}
2478
2479TEST_F(VideoSendStreamTest, Vp9NonFlexMode_3Tl1SLayers) {
2480 const uint8_t kNumTemporalLayers = 3;
2481 const uint8_t kNumSpatialLayers = 1;
2482 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2483}
2484
2485TEST_F(VideoSendStreamTest, Vp9NonFlexMode_1Tl2SLayers) {
2486 const uint8_t kNumTemporalLayers = 1;
2487 const uint8_t kNumSpatialLayers = 2;
2488 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2489}
2490
2491TEST_F(VideoSendStreamTest, Vp9NonFlexMode_2Tl2SLayers) {
2492 const uint8_t kNumTemporalLayers = 2;
2493 const uint8_t kNumSpatialLayers = 2;
2494 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2495}
2496
2497TEST_F(VideoSendStreamTest, Vp9NonFlexMode_3Tl2SLayers) {
2498 const uint8_t kNumTemporalLayers = 3;
2499 const uint8_t kNumSpatialLayers = 2;
2500 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2501}
2502
2503void VideoSendStreamTest::TestVp9NonFlexMode(uint8_t num_temporal_layers,
2504 uint8_t num_spatial_layers) {
2505 static const size_t kNumFramesToSend = 100;
2506 // Set to < kNumFramesToSend and coprime to length of temporal layer
2507 // structures to verify temporal id reset on key frame.
2508 static const int kKeyFrameInterval = 31;
2509 class NonFlexibleMode : public Vp9HeaderObserver {
2510 public:
2511 NonFlexibleMode(uint8_t num_temporal_layers, uint8_t num_spatial_layers)
2512 : num_temporal_layers_(num_temporal_layers),
2513 num_spatial_layers_(num_spatial_layers),
2514 l_field_(num_temporal_layers > 1 || num_spatial_layers > 1) {}
stefanff483612015-12-21 03:14:00 -08002515 void ModifyVideoConfigsHook(
philipel0f9af012015-09-01 07:01:51 -07002516 VideoSendStream::Config* send_config,
2517 std::vector<VideoReceiveStream::Config>* receive_configs,
2518 VideoEncoderConfig* encoder_config) override {
Åsa Perssonff24c042015-12-04 10:58:08 +01002519 vp9_settings_.flexibleMode = false;
2520 vp9_settings_.frameDroppingOn = false;
2521 vp9_settings_.keyFrameInterval = kKeyFrameInterval;
2522 vp9_settings_.numberOfTemporalLayers = num_temporal_layers_;
2523 vp9_settings_.numberOfSpatialLayers = num_spatial_layers_;
philipel0f9af012015-09-01 07:01:51 -07002524 }
2525
Åsa Perssonff24c042015-12-04 10:58:08 +01002526 void InspectHeader(const RTPVideoHeaderVP9& vp9) override {
2527 bool ss_data_expected = !vp9.inter_pic_predicted &&
2528 vp9.beginning_of_frame && vp9.spatial_idx == 0;
2529 EXPECT_EQ(ss_data_expected, vp9.ss_data_available);
2530 EXPECT_EQ(vp9.spatial_idx > 0, vp9.inter_layer_predicted); // D
asapersson38bb8ad2015-12-14 01:41:19 -08002531 EXPECT_EQ(!vp9.inter_pic_predicted,
2532 frames_sent_ % kKeyFrameInterval == 0);
Åsa Perssonff24c042015-12-04 10:58:08 +01002533
2534 if (IsNewPictureId(vp9)) {
2535 EXPECT_EQ(0, vp9.spatial_idx);
2536 EXPECT_EQ(num_spatial_layers_ - 1, last_vp9_.spatial_idx);
2537 }
2538
2539 VerifyFixedTemporalLayerStructure(vp9,
2540 l_field_ ? num_temporal_layers_ : 0);
2541
2542 if (frames_sent_ > kNumFramesToSend)
Peter Boström5811a392015-12-10 13:02:50 +01002543 observation_complete_.Set();
philipel0f9af012015-09-01 07:01:51 -07002544 }
Åsa Perssonff24c042015-12-04 10:58:08 +01002545 const uint8_t num_temporal_layers_;
2546 const uint8_t num_spatial_layers_;
2547 const bool l_field_;
2548 } test(num_temporal_layers, num_spatial_layers);
philipelcfc319b2015-11-10 07:17:23 -08002549
stefane74eef12016-01-08 06:47:13 -08002550 RunBaseTest(&test);
philipelcfc319b2015-11-10 07:17:23 -08002551}
2552
asaperssond9f641e2016-01-21 01:11:35 -08002553TEST_F(VideoSendStreamTest, Vp9NonFlexModeSmallResolution) {
2554 static const size_t kNumFramesToSend = 50;
2555 static const int kWidth = 4;
2556 static const int kHeight = 4;
2557 class NonFlexibleModeResolution : public Vp9HeaderObserver {
2558 void ModifyVideoConfigsHook(
2559 VideoSendStream::Config* send_config,
2560 std::vector<VideoReceiveStream::Config>* receive_configs,
2561 VideoEncoderConfig* encoder_config) override {
2562 vp9_settings_.flexibleMode = false;
2563 vp9_settings_.numberOfTemporalLayers = 1;
2564 vp9_settings_.numberOfSpatialLayers = 1;
2565
2566 EXPECT_EQ(1u, encoder_config->streams.size());
2567 encoder_config->streams[0].width = kWidth;
2568 encoder_config->streams[0].height = kHeight;
2569 }
2570
2571 void InspectHeader(const RTPVideoHeaderVP9& vp9_header) override {
2572 if (frames_sent_ > kNumFramesToSend)
2573 observation_complete_.Set();
2574 }
2575 } test;
2576
2577 RunBaseTest(&test);
2578}
2579
Åsa Perssonff24c042015-12-04 10:58:08 +01002580TEST_F(VideoSendStreamTest, Vp9FlexModeRefCount) {
2581 class FlexibleMode : public Vp9HeaderObserver {
stefanff483612015-12-21 03:14:00 -08002582 void ModifyVideoConfigsHook(
philipelcfc319b2015-11-10 07:17:23 -08002583 VideoSendStream::Config* send_config,
2584 std::vector<VideoReceiveStream::Config>* receive_configs,
2585 VideoEncoderConfig* encoder_config) override {
Åsa Perssonff24c042015-12-04 10:58:08 +01002586 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
philipelcfc319b2015-11-10 07:17:23 -08002587 vp9_settings_.flexibleMode = true;
Åsa Perssonff24c042015-12-04 10:58:08 +01002588 vp9_settings_.numberOfTemporalLayers = 1;
2589 vp9_settings_.numberOfSpatialLayers = 2;
philipelcfc319b2015-11-10 07:17:23 -08002590 }
2591
Åsa Perssonff24c042015-12-04 10:58:08 +01002592 void InspectHeader(const RTPVideoHeaderVP9& vp9_header) override {
2593 EXPECT_TRUE(vp9_header.flexible_mode);
2594 EXPECT_EQ(kNoTl0PicIdx, vp9_header.tl0_pic_idx);
2595 if (vp9_header.inter_pic_predicted) {
2596 EXPECT_GT(vp9_header.num_ref_pics, 0u);
Peter Boström5811a392015-12-10 13:02:50 +01002597 observation_complete_.Set();
philipelcfc319b2015-11-10 07:17:23 -08002598 }
2599 }
2600 } test;
2601
stefane74eef12016-01-08 06:47:13 -08002602 RunBaseTest(&test);
philipelcfc319b2015-11-10 07:17:23 -08002603}
Peter Boström12996152016-05-14 02:03:18 +02002604#endif // !defined(RTC_DISABLE_VP9)
philipelcfc319b2015-11-10 07:17:23 -08002605
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +00002606} // namespace webrtc