blob: 623cd34ac5e8860f7b9e6666172f5a082134ffa7 [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"
nisse26acec42016-04-15 03:43:39 -070036#include "webrtc/test/frame_utils.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000037#include "webrtc/test/null_transport.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000038#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.org273a4142014-12-01 15:23:21 +000039#include "webrtc/video/send_statistics_proxy.h"
Thiago Farina9bfe3da2015-04-10 12:52:13 +020040#include "webrtc/video_frame.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000041#include "webrtc/video_send_stream.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000042
43namespace webrtc {
44
sprang@webrtc.org346094c2014-02-18 08:40:33 +000045enum VideoFormat { kGeneric, kVP8, };
46
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070047void ExpectEqualFramesVector(const std::vector<VideoFrame>& frames1,
48 const std::vector<VideoFrame>& frames2);
49VideoFrame CreateVideoFrame(int width, int height, uint8_t data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000050
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000051class VideoSendStreamTest : public test::CallTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000052 protected:
stefan@webrtc.org69969e22013-11-15 12:32:15 +000053 void TestNackRetransmission(uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +000054 uint8_t retransmit_payload_type);
sprang@webrtc.org346094c2014-02-18 08:40:33 +000055 void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
Åsa Perssonff24c042015-12-04 10:58:08 +010056
57 void TestVp9NonFlexMode(uint8_t num_temporal_layers,
58 uint8_t num_spatial_layers);
pbos@webrtc.org013d9942013-08-22 09:42:17 +000059};
60
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000061TEST_F(VideoSendStreamTest, CanStartStartedStream) {
solenberg4fbae2b2015-08-28 04:07:10 -070062 Call::Config call_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000063 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000064
solenberg4fbae2b2015-08-28 04:07:10 -070065 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +010066 CreateSendConfig(1, 0, &transport);
67 CreateVideoStreams();
stefanff483612015-12-21 03:14:00 -080068 video_send_stream_->Start();
69 video_send_stream_->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000070 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000071}
72
73TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
solenberg4fbae2b2015-08-28 04:07:10 -070074 Call::Config call_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000075 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000076
solenberg4fbae2b2015-08-28 04:07:10 -070077 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +010078 CreateSendConfig(1, 0, &transport);
79 CreateVideoStreams();
stefanff483612015-12-21 03:14:00 -080080 video_send_stream_->Stop();
81 video_send_stream_->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000082 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000083}
84
pbos@webrtc.org013d9942013-08-22 09:42:17 +000085TEST_F(VideoSendStreamTest, SupportsCName) {
86 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000087 class CNameObserver : public test::SendTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000088 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000089 CNameObserver() : SendTest(kDefaultTimeoutMs) {}
pbos@webrtc.org013d9942013-08-22 09:42:17 +000090
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000091 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000092 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000093 RTCPUtility::RTCPParserV2 parser(packet, length, true);
94 EXPECT_TRUE(parser.IsValid());
95
96 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +020097 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
98 if (packet_type == RTCPUtility::RTCPPacketTypes::kSdesChunk) {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000099 EXPECT_EQ(parser.Packet().CName.CName, kCName);
Peter Boström5811a392015-12-10 13:02:50 +0100100 observation_complete_.Set();
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000101 }
102
103 packet_type = parser.Iterate();
104 }
105
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000106 return SEND_PACKET;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000107 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000108
stefanff483612015-12-21 03:14:00 -0800109 void ModifyVideoConfigs(
110 VideoSendStream::Config* send_config,
111 std::vector<VideoReceiveStream::Config>* receive_configs,
112 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000113 send_config->rtp.c_name = kCName;
114 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000115
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000116 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100117 EXPECT_TRUE(Wait()) << "Timed out while waiting for RTCP with CNAME.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000118 }
119 } test;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000120
stefane74eef12016-01-08 06:47:13 -0800121 RunBaseTest(&test);
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000122}
123
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000124TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000125 class AbsoluteSendTimeObserver : public test::SendTest {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000126 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000127 AbsoluteSendTimeObserver() : SendTest(kDefaultTimeoutMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000128 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
Stefan Holmer4654d202015-12-08 09:10:43 +0100129 kRtpExtensionAbsoluteSendTime, test::kAbsSendTimeExtensionId));
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000130 }
131
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000132 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000133 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000134 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000135
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000136 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
137 EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
138 EXPECT_EQ(header.extension.transmissionTimeOffset, 0);
139 EXPECT_GT(header.extension.absoluteSendTime, 0u);
Peter Boström5811a392015-12-10 13:02:50 +0100140 observation_complete_.Set();
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000141
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000142 return SEND_PACKET;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000143 }
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000144
stefanff483612015-12-21 03:14:00 -0800145 void ModifyVideoConfigs(
146 VideoSendStream::Config* send_config,
147 std::vector<VideoReceiveStream::Config>* receive_configs,
148 VideoEncoderConfig* encoder_config) override {
Erik Språng95261872015-04-10 11:58:49 +0200149 send_config->rtp.extensions.clear();
Stefan Holmer4654d202015-12-08 09:10:43 +0100150 send_config->rtp.extensions.push_back(RtpExtension(
isheriff6f8d6862016-05-26 11:24:55 -0700151 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000152 }
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +0000153
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000154 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100155 EXPECT_TRUE(Wait()) << "Timed out while waiting for single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000156 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000157 } test;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000158
stefane74eef12016-01-08 06:47:13 -0800159 RunBaseTest(&test);
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000160}
161
pbos@webrtc.org29023282013-09-11 10:14:56 +0000162TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000163 static const int kEncodeDelayMs = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000164 class TransmissionTimeOffsetObserver : public test::SendTest {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000165 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000166 TransmissionTimeOffsetObserver()
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000167 : SendTest(kDefaultTimeoutMs),
168 encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000169 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
Stefan Holmer12952972015-10-29 15:13:24 +0100170 kRtpExtensionTransmissionTimeOffset, test::kTOffsetExtensionId));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000171 }
172
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000173 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000174 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000175 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000176 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000177
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000178 EXPECT_TRUE(header.extension.hasTransmissionTimeOffset);
179 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000180 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000181 EXPECT_EQ(header.extension.absoluteSendTime, 0u);
Peter Boström5811a392015-12-10 13:02:50 +0100182 observation_complete_.Set();
pbos@webrtc.org29023282013-09-11 10:14:56 +0000183
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000184 return SEND_PACKET;
pbos@webrtc.org29023282013-09-11 10:14:56 +0000185 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000186
stefanff483612015-12-21 03:14:00 -0800187 void ModifyVideoConfigs(
188 VideoSendStream::Config* send_config,
189 std::vector<VideoReceiveStream::Config>* receive_configs,
190 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000191 send_config->encoder_settings.encoder = &encoder_;
Stefan Holmer12952972015-10-29 15:13:24 +0100192 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -0700193 send_config->rtp.extensions.push_back(RtpExtension(
194 RtpExtension::kTimestampOffsetUri, test::kTOffsetExtensionId));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000195 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000196
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000197 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100198 EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000199 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000200
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000201 test::DelayedEncoder encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000202 } test;
203
stefane74eef12016-01-08 06:47:13 -0800204 RunBaseTest(&test);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000205}
206
sprang867fb522015-08-03 04:38:41 -0700207TEST_F(VideoSendStreamTest, SupportsTransportWideSequenceNumbers) {
208 static const uint8_t kExtensionId = 13;
209 class TransportWideSequenceNumberObserver : public test::SendTest {
210 public:
211 TransportWideSequenceNumberObserver()
212 : SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) {
213 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
214 kRtpExtensionTransportSequenceNumber, kExtensionId));
215 }
216
217 private:
218 Action OnSendRtp(const uint8_t* packet, size_t length) override {
219 RTPHeader header;
220 EXPECT_TRUE(parser_->Parse(packet, length, &header));
221
222 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
223 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
224 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
225
Peter Boström5811a392015-12-10 13:02:50 +0100226 observation_complete_.Set();
sprang867fb522015-08-03 04:38:41 -0700227
228 return SEND_PACKET;
229 }
230
stefanff483612015-12-21 03:14:00 -0800231 void ModifyVideoConfigs(
232 VideoSendStream::Config* send_config,
233 std::vector<VideoReceiveStream::Config>* receive_configs,
234 VideoEncoderConfig* encoder_config) override {
sprang867fb522015-08-03 04:38:41 -0700235 send_config->encoder_settings.encoder = &encoder_;
Stefan Holmer12952972015-10-29 15:13:24 +0100236 send_config->rtp.extensions.clear();
isheriff6f8d6862016-05-26 11:24:55 -0700237 send_config->rtp.extensions.push_back(RtpExtension(
238 RtpExtension::kTransportSequenceNumberUri, kExtensionId));
sprang867fb522015-08-03 04:38:41 -0700239 }
240
241 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100242 EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
sprang867fb522015-08-03 04:38:41 -0700243 }
244
245 test::FakeEncoder encoder_;
246 } test;
247
stefane74eef12016-01-08 06:47:13 -0800248 RunBaseTest(&test);
sprang867fb522015-08-03 04:38:41 -0700249}
250
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000251class FakeReceiveStatistics : public NullReceiveStatistics {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000252 public:
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000253 FakeReceiveStatistics(uint32_t send_ssrc,
254 uint32_t last_sequence_number,
255 uint32_t cumulative_lost,
256 uint8_t fraction_lost)
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000257 : lossy_stats_(new LossyStatistician(last_sequence_number,
258 cumulative_lost,
259 fraction_lost)) {
260 stats_map_[send_ssrc] = lossy_stats_.get();
261 }
262
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000263 StatisticianMap GetActiveStatisticians() const override { return stats_map_; }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000264
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000265 StreamStatistician* GetStatistician(uint32_t ssrc) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000266 return lossy_stats_.get();
267 }
268
269 private:
270 class LossyStatistician : public StreamStatistician {
271 public:
272 LossyStatistician(uint32_t extended_max_sequence_number,
273 uint32_t cumulative_lost,
274 uint8_t fraction_lost) {
275 stats_.fraction_lost = fraction_lost;
276 stats_.cumulative_lost = cumulative_lost;
277 stats_.extended_max_sequence_number = extended_max_sequence_number;
278 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000279 bool GetStatistics(RtcpStatistics* statistics, bool reset) override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000280 *statistics = stats_;
281 return true;
282 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000283 void GetDataCounters(size_t* bytes_received,
284 uint32_t* packets_received) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000285 *bytes_received = 0;
286 *packets_received = 0;
287 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000288 void GetReceiveStreamDataCounters(
289 StreamDataCounters* data_counters) const override {}
290 uint32_t BitrateReceived() const override { return 0; }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000291 bool IsRetransmitOfOldPacket(const RTPHeader& header,
292 int64_t min_rtt) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000293 return false;
294 }
295
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000296 bool IsPacketInOrder(uint16_t sequence_number) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000297 return true;
298 }
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000299
300 RtcpStatistics stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000301 };
302
kwiberg27f982b2016-03-01 11:52:33 -0800303 std::unique_ptr<LossyStatistician> lossy_stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000304 StatisticianMap stats_map_;
305};
306
Peter Boström39593972016-02-15 11:27:15 +0100307class FecObserver : public test::EndToEndTest {
Stefan Holmer4654d202015-12-08 09:10:43 +0100308 public:
Peter Boström39593972016-02-15 11:27:15 +0100309 FecObserver(bool header_extensions_enabled,
310 bool use_nack,
311 bool expect_red,
stefan8f4c77f2016-06-03 00:16:45 -0700312 bool expect_fec,
Peter Boström39593972016-02-15 11:27:15 +0100313 const std::string& codec)
314 : EndToEndTest(VideoSendStreamTest::kDefaultTimeoutMs),
315 payload_name_(codec),
316 use_nack_(use_nack),
317 expect_red_(expect_red),
stefan8f4c77f2016-06-03 00:16:45 -0700318 expect_fec_(expect_fec),
Stefan Holmer4654d202015-12-08 09:10:43 +0100319 send_count_(0),
320 received_media_(false),
321 received_fec_(false),
Peter Boström39593972016-02-15 11:27:15 +0100322 header_extensions_enabled_(header_extensions_enabled) {
323 if (codec == "H264") {
324 encoder_.reset(new test::FakeH264Encoder(Clock::GetRealTimeClock()));
325 } else if (codec == "VP8") {
326 encoder_.reset(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8));
327 } else if (codec == "VP9") {
328 encoder_.reset(VideoEncoder::Create(VideoEncoder::EncoderType::kVp9));
329 } else {
330 RTC_NOTREACHED();
331 }
332 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100333
334 private:
335 Action OnSendRtp(const uint8_t* packet, size_t length) override {
336 RTPHeader header;
337 EXPECT_TRUE(parser_->Parse(packet, length, &header));
338
Peter Boström39593972016-02-15 11:27:15 +0100339 ++send_count_;
Stefan Holmer4654d202015-12-08 09:10:43 +0100340 int encapsulated_payload_type = -1;
341 if (header.payloadType == VideoSendStreamTest::kRedPayloadType) {
Peter Boström39593972016-02-15 11:27:15 +0100342 EXPECT_TRUE(expect_red_);
Stefan Holmer4654d202015-12-08 09:10:43 +0100343 encapsulated_payload_type = static_cast<int>(packet[header.headerLength]);
344 if (encapsulated_payload_type !=
Peter Boström39593972016-02-15 11:27:15 +0100345 VideoSendStreamTest::kFakeVideoSendPayloadType) {
Stefan Holmer4654d202015-12-08 09:10:43 +0100346 EXPECT_EQ(VideoSendStreamTest::kUlpfecPayloadType,
347 encapsulated_payload_type);
Peter Boström39593972016-02-15 11:27:15 +0100348 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100349 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100350 EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType,
351 header.payloadType);
Peter Boström39593972016-02-15 11:27:15 +0100352 if (static_cast<size_t>(header.headerLength + header.paddingLength) <
353 length) {
354 // Not padding-only, media received outside of RED.
355 EXPECT_FALSE(expect_red_);
356 received_media_ = true;
357 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100358 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000359
Stefan Holmer4654d202015-12-08 09:10:43 +0100360 if (header_extensions_enabled_) {
361 EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
362 uint32_t kHalf24BitsSpace = 0xFFFFFF / 2;
363 if (header.extension.absoluteSendTime <= kHalf24BitsSpace &&
364 prev_header_.extension.absoluteSendTime > kHalf24BitsSpace) {
365 // 24 bits wrap.
366 EXPECT_GT(prev_header_.extension.absoluteSendTime,
367 header.extension.absoluteSendTime);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000368 } else {
Stefan Holmer4654d202015-12-08 09:10:43 +0100369 EXPECT_GE(header.extension.absoluteSendTime,
370 prev_header_.extension.absoluteSendTime);
Stefan Holmer01b48882015-05-05 10:21:24 +0200371 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100372 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
373 uint16_t seq_num_diff = header.extension.transportSequenceNumber -
374 prev_header_.extension.transportSequenceNumber;
375 EXPECT_EQ(1, seq_num_diff);
376 }
Stefan Holmer01b48882015-05-05 10:21:24 +0200377
Stefan Holmer4654d202015-12-08 09:10:43 +0100378 if (encapsulated_payload_type != -1) {
379 if (encapsulated_payload_type ==
380 VideoSendStreamTest::kUlpfecPayloadType) {
stefan8f4c77f2016-06-03 00:16:45 -0700381 EXPECT_TRUE(expect_fec_);
Stefan Holmer4654d202015-12-08 09:10:43 +0100382 received_fec_ = true;
383 } else {
384 received_media_ = true;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000385 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000386 }
387
Peter Boström39593972016-02-15 11:27:15 +0100388 if (send_count_ > 100 && received_media_) {
stefan8f4c77f2016-06-03 00:16:45 -0700389 if (received_fec_ || !expect_fec_)
Peter Boström39593972016-02-15 11:27:15 +0100390 observation_complete_.Set();
391 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000392
Stefan Holmer4654d202015-12-08 09:10:43 +0100393 prev_header_ = header;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000394
Stefan Holmer4654d202015-12-08 09:10:43 +0100395 return SEND_PACKET;
396 }
397
Peter Boström39593972016-02-15 11:27:15 +0100398 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
399 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
400 // Configure some network delay.
401 const int kNetworkDelayMs = 100;
402 FakeNetworkPipe::Config config;
403 config.loss_percent = 50;
404 config.queue_delay_ms = kNetworkDelayMs;
405 return new test::PacketTransport(sender_call, this,
406 test::PacketTransport::kSender, config);
407 }
408
stefanff483612015-12-21 03:14:00 -0800409 void ModifyVideoConfigs(
410 VideoSendStream::Config* send_config,
411 std::vector<VideoReceiveStream::Config>* receive_configs,
412 VideoEncoderConfig* encoder_config) override {
Stefan Holmer4654d202015-12-08 09:10:43 +0100413 transport_adapter_.reset(
414 new internal::TransportAdapter(send_config->send_transport));
415 transport_adapter_->Enable();
Peter Boström39593972016-02-15 11:27:15 +0100416 if (use_nack_) {
417 send_config->rtp.nack.rtp_history_ms =
418 (*receive_configs)[0].rtp.nack.rtp_history_ms =
419 VideoSendStreamTest::kNackRtpHistoryMs;
420 }
421 send_config->encoder_settings.encoder = encoder_.get();
422 send_config->encoder_settings.payload_name = payload_name_;
Stefan Holmer4654d202015-12-08 09:10:43 +0100423 send_config->rtp.fec.red_payload_type =
Peter Boström39593972016-02-15 11:27:15 +0100424 VideoSendStreamTest::kRedPayloadType;
Stefan Holmer4654d202015-12-08 09:10:43 +0100425 send_config->rtp.fec.ulpfec_payload_type =
Peter Boström39593972016-02-15 11:27:15 +0100426 VideoSendStreamTest::kUlpfecPayloadType;
Stefan Holmer4654d202015-12-08 09:10:43 +0100427 if (header_extensions_enabled_) {
428 send_config->rtp.extensions.push_back(RtpExtension(
isheriff6f8d6862016-05-26 11:24:55 -0700429 RtpExtension::kAbsSendTimeUri, test::kAbsSendTimeExtensionId));
Stefan Holmer4654d202015-12-08 09:10:43 +0100430 send_config->rtp.extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -0700431 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
Stefan Holmer4654d202015-12-08 09:10:43 +0100432 test::kTransportSequenceNumberExtensionId));
433 }
Peter Boström39593972016-02-15 11:27:15 +0100434 (*receive_configs)[0].rtp.fec.red_payload_type =
435 send_config->rtp.fec.red_payload_type;
436 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
437 send_config->rtp.fec.ulpfec_payload_type;
Stefan Holmer4654d202015-12-08 09:10:43 +0100438 }
439
440 void PerformTest() override {
441 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
442 }
443
kwiberg27f982b2016-03-01 11:52:33 -0800444 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
445 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100446 const std::string payload_name_;
447 const bool use_nack_;
448 const bool expect_red_;
stefan8f4c77f2016-06-03 00:16:45 -0700449 const bool expect_fec_;
Stefan Holmer4654d202015-12-08 09:10:43 +0100450 int send_count_;
451 bool received_media_;
452 bool received_fec_;
453 bool header_extensions_enabled_;
454 RTPHeader prev_header_;
455};
456
457TEST_F(VideoSendStreamTest, SupportsFecWithExtensions) {
stefan8f4c77f2016-06-03 00:16:45 -0700458 FecObserver test(true, false, true, true, "VP8");
stefane74eef12016-01-08 06:47:13 -0800459 RunBaseTest(&test);
Stefan Holmer4654d202015-12-08 09:10:43 +0100460}
461
462TEST_F(VideoSendStreamTest, SupportsFecWithoutExtensions) {
stefan8f4c77f2016-06-03 00:16:45 -0700463 FecObserver test(false, false, true, true, "VP8");
Peter Boström39593972016-02-15 11:27:15 +0100464 RunBaseTest(&test);
465}
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000466
Peter Boström39593972016-02-15 11:27:15 +0100467// The FEC scheme used is not efficient for H264, so we should not use RED/FEC
468// since we'll still have to re-request FEC packets, effectively wasting
469// bandwidth since the receiver has to wait for FEC retransmissions to determine
470// that the received state is actually decodable.
stefan8f4c77f2016-06-03 00:16:45 -0700471TEST_F(VideoSendStreamTest, DoesNotUtilizeFecForH264WithNackEnabled) {
472 FecObserver test(false, true, true, false, "H264");
Peter Boström39593972016-02-15 11:27:15 +0100473 RunBaseTest(&test);
474}
475
476// Without retransmissions FEC for H264 is fine.
477TEST_F(VideoSendStreamTest, DoesUtilizeRedForH264WithoutNackEnabled) {
stefan8f4c77f2016-06-03 00:16:45 -0700478 FecObserver test(false, false, true, true, "H264");
Peter Boström39593972016-02-15 11:27:15 +0100479 RunBaseTest(&test);
480}
481
482TEST_F(VideoSendStreamTest, DoesUtilizeRedForVp8WithNackEnabled) {
stefan8f4c77f2016-06-03 00:16:45 -0700483 FecObserver test(false, true, true, true, "VP8");
Peter Boström39593972016-02-15 11:27:15 +0100484 RunBaseTest(&test);
485}
486
Peter Boström12996152016-05-14 02:03:18 +0200487#if !defined(RTC_DISABLE_VP9)
Peter Boström39593972016-02-15 11:27:15 +0100488TEST_F(VideoSendStreamTest, DoesUtilizeRedForVp9WithNackEnabled) {
stefan8f4c77f2016-06-03 00:16:45 -0700489 FecObserver test(false, true, true, true, "VP9");
stefane74eef12016-01-08 06:47:13 -0800490 RunBaseTest(&test);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000491}
Peter Boström12996152016-05-14 02:03:18 +0200492#endif // !defined(RTC_DISABLE_VP9)
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000493
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000494void VideoSendStreamTest::TestNackRetransmission(
495 uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000496 uint8_t retransmit_payload_type) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000497 class NackObserver : public test::SendTest {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000498 public:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000499 explicit NackObserver(uint32_t retransmit_ssrc,
500 uint8_t retransmit_payload_type)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000501 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000502 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000503 retransmit_ssrc_(retransmit_ssrc),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000504 retransmit_payload_type_(retransmit_payload_type),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000505 nacked_sequence_number_(-1) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000506 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000507
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000508 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000509 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000510 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000511 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000512
513 // Nack second packet after receiving the third one.
514 if (++send_count_ == 3) {
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000515 uint16_t nack_sequence_number = header.sequenceNumber - 1;
516 nacked_sequence_number_ = nack_sequence_number;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000517 NullReceiveStatistics null_stats;
Peter Boströmac547a62015-09-17 23:03:57 +0200518 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), &null_stats,
terelius429c3452016-01-21 05:42:04 -0800519 nullptr, nullptr, transport_adapter_.get());
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000520
pbosda903ea2015-10-02 02:36:56 -0700521 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100522 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000523
524 RTCPSender::FeedbackState feedback_state;
525
526 EXPECT_EQ(0,
527 rtcp_sender.SendRTCP(
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000528 feedback_state, kRtcpNack, 1, &nack_sequence_number));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000529 }
530
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000531 uint16_t sequence_number = header.sequenceNumber;
532
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000533 if (header.ssrc == retransmit_ssrc_ &&
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100534 retransmit_ssrc_ != kVideoSendSsrcs[0]) {
535 // Not kVideoSendSsrcs[0], assume correct RTX packet. Extract sequence
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000536 // number.
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000537 const uint8_t* rtx_header = packet + header.headerLength;
538 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
539 }
540
541 if (sequence_number == nacked_sequence_number_) {
542 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000543 EXPECT_EQ(retransmit_payload_type_, header.payloadType);
Peter Boström5811a392015-12-10 13:02:50 +0100544 observation_complete_.Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000545 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000546
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000547 return SEND_PACKET;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000548 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000549
stefanff483612015-12-21 03:14:00 -0800550 void ModifyVideoConfigs(
551 VideoSendStream::Config* send_config,
552 std::vector<VideoReceiveStream::Config>* receive_configs,
553 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700554 transport_adapter_.reset(
555 new internal::TransportAdapter(send_config->send_transport));
556 transport_adapter_->Enable();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000557 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000558 send_config->rtp.rtx.payload_type = retransmit_payload_type_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100559 if (retransmit_ssrc_ != kVideoSendSsrcs[0])
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000560 send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
561 }
562
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000563 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100564 EXPECT_TRUE(Wait()) << "Timed out while waiting for NACK retransmission.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000565 }
566
kwiberg27f982b2016-03-01 11:52:33 -0800567 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000568 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000569 uint32_t retransmit_ssrc_;
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000570 uint8_t retransmit_payload_type_;
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000571 int nacked_sequence_number_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000572 } test(retransmit_ssrc, retransmit_payload_type);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000573
stefane74eef12016-01-08 06:47:13 -0800574 RunBaseTest(&test);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000575}
576
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000577TEST_F(VideoSendStreamTest, RetransmitsNack) {
578 // Normal NACKs should use the send SSRC.
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100579 TestNackRetransmission(kVideoSendSsrcs[0], kFakeVideoSendPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000580}
581
582TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
583 // NACKs over RTX should use a separate SSRC.
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000584 TestNackRetransmission(kSendRtxSsrcs[0], kSendRtxPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000585}
586
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000587void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
588 bool with_fec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000589 // Use a fake encoder to output a frame of every size in the range [90, 290],
590 // for each size making sure that the exact number of payload bytes received
591 // is correct and that packets are fragmented to respect max packet size.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000592 static const size_t kMaxPacketSize = 128;
593 static const size_t start = 90;
594 static const size_t stop = 290;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000595
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000596 // Observer that verifies that the expected number of packets and bytes
597 // arrive for each frame size, from start_size to stop_size.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000598 class FrameFragmentationTest : public test::SendTest,
599 public EncodedFrameObserver {
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000600 public:
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000601 FrameFragmentationTest(size_t max_packet_size,
602 size_t start_size,
603 size_t stop_size,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000604 bool test_generic_packetization,
605 bool use_fec)
606 : SendTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000607 encoder_(stop),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000608 max_packet_size_(max_packet_size),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000609 stop_size_(stop_size),
610 test_generic_packetization_(test_generic_packetization),
611 use_fec_(use_fec),
612 packet_count_(0),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000613 accumulated_size_(0),
614 accumulated_payload_(0),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000615 fec_packet_received_(false),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000616 current_size_rtp_(start_size),
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000617 current_size_frame_(static_cast<int32_t>(start_size)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000618 // Fragmentation required, this test doesn't make sense without it.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000619 encoder_.SetFrameSize(start_size);
henrikg91d6ede2015-09-17 00:24:34 -0700620 RTC_DCHECK_GT(stop_size, max_packet_size);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000621 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000622
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000623 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000624 Action OnSendRtp(const uint8_t* packet, size_t size) override {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000625 size_t length = size;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000626 RTPHeader header;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000627 EXPECT_TRUE(parser_->Parse(packet, length, &header));
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000628
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000629 EXPECT_LE(length, max_packet_size_);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000630
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000631 if (use_fec_) {
632 uint8_t payload_type = packet[header.headerLength];
633 bool is_fec = header.payloadType == kRedPayloadType &&
634 payload_type == kUlpfecPayloadType;
635 if (is_fec) {
636 fec_packet_received_ = true;
637 return SEND_PACKET;
638 }
639 }
640
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000641 accumulated_size_ += length;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000642
643 if (use_fec_)
644 TriggerLossReport(header);
645
646 if (test_generic_packetization_) {
Stefan Holmer586b19b2015-09-18 11:14:31 +0200647 size_t overhead = header.headerLength + header.paddingLength;
648 // Only remove payload header and RED header if the packet actually
649 // contains payload.
650 if (length > overhead) {
651 overhead += (1 /* Generic header */);
652 if (use_fec_)
653 overhead += 1; // RED for FEC header.
654 }
655 EXPECT_GE(length, overhead);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000656 accumulated_payload_ += length - overhead;
657 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000658
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000659 // Marker bit set indicates last packet of a frame.
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000660 if (header.markerBit) {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000661 if (use_fec_ && accumulated_payload_ == current_size_rtp_ - 1) {
662 // With FEC enabled, frame size is incremented asynchronously, so
663 // "old" frames one byte too small may arrive. Accept, but don't
664 // increase expected frame size.
665 accumulated_size_ = 0;
666 accumulated_payload_ = 0;
667 return SEND_PACKET;
668 }
669
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000670 EXPECT_GE(accumulated_size_, current_size_rtp_);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000671 if (test_generic_packetization_) {
672 EXPECT_EQ(current_size_rtp_, accumulated_payload_);
673 }
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000674
675 // Last packet of frame; reset counters.
676 accumulated_size_ = 0;
677 accumulated_payload_ = 0;
678 if (current_size_rtp_ == stop_size_) {
679 // Done! (Don't increase size again, might arrive more @ stop_size).
Peter Boström5811a392015-12-10 13:02:50 +0100680 observation_complete_.Set();
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000681 } else {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000682 // Increase next expected frame size. If testing with FEC, make sure
683 // a FEC packet has been received for this frame size before
684 // proceeding, to make sure that redundancy packets don't exceed
685 // size limit.
686 if (!use_fec_) {
687 ++current_size_rtp_;
688 } else if (fec_packet_received_) {
689 fec_packet_received_ = false;
690 ++current_size_rtp_;
691 ++current_size_frame_;
692 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000693 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000694 }
695
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000696 return SEND_PACKET;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000697 }
698
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000699 void TriggerLossReport(const RTPHeader& header) {
700 // Send lossy receive reports to trigger FEC enabling.
701 if (packet_count_++ % 2 != 0) {
702 // Receive statistics reporting having lost 50% of the packets.
703 FakeReceiveStatistics lossy_receive_stats(
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100704 kVideoSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127);
Peter Boströmac547a62015-09-17 23:03:57 +0200705 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
terelius429c3452016-01-21 05:42:04 -0800706 &lossy_receive_stats, nullptr, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700707 transport_adapter_.get());
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000708
pbosda903ea2015-10-02 02:36:56 -0700709 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100710 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000711
712 RTCPSender::FeedbackState feedback_state;
713
714 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
715 }
716 }
717
nisseef8b61e2016-04-29 06:09:15 -0700718 void EncodedFrameCallback(const EncodedFrame& encoded_frame) override {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000719 // Increase frame size for next encoded frame, in the context of the
720 // encoder thread.
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000721 if (!use_fec_ &&
722 current_size_frame_.Value() < static_cast<int32_t>(stop_size_)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000723 ++current_size_frame_;
724 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000725 encoder_.SetFrameSize(static_cast<size_t>(current_size_frame_.Value()));
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000726 }
727
Stefan Holmere5904162015-03-26 11:11:06 +0100728 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700729 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100730 const int kMinBitrateBps = 30000;
731 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
732 return config;
733 }
734
stefanff483612015-12-21 03:14:00 -0800735 void ModifyVideoConfigs(
736 VideoSendStream::Config* send_config,
737 std::vector<VideoReceiveStream::Config>* receive_configs,
738 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700739 transport_adapter_.reset(
740 new internal::TransportAdapter(send_config->send_transport));
741 transport_adapter_->Enable();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000742 if (use_fec_) {
743 send_config->rtp.fec.red_payload_type = kRedPayloadType;
744 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
745 }
746
747 if (!test_generic_packetization_)
748 send_config->encoder_settings.payload_name = "VP8";
749
750 send_config->encoder_settings.encoder = &encoder_;
751 send_config->rtp.max_packet_size = kMaxPacketSize;
752 send_config->post_encode_callback = this;
753
Erik Språng95261872015-04-10 11:58:49 +0200754 // Make sure there is at least one extension header, to make the RTP
755 // header larger than the base length of 12 bytes.
756 EXPECT_FALSE(send_config->rtp.extensions.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000757 }
758
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000759 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100760 EXPECT_TRUE(Wait()) << "Timed out while observing incoming RTP packets.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000761 }
762
kwiberg27f982b2016-03-01 11:52:33 -0800763 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000764 test::ConfigurableFrameSizeEncoder encoder_;
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000765
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000766 const size_t max_packet_size_;
767 const size_t stop_size_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000768 const bool test_generic_packetization_;
769 const bool use_fec_;
770
771 uint32_t packet_count_;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000772 size_t accumulated_size_;
773 size_t accumulated_payload_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000774 bool fec_packet_received_;
775
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000776 size_t current_size_rtp_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000777 Atomic32 current_size_frame_;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000778 };
779
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000780 // Don't auto increment if FEC is used; continue sending frame size until
781 // a FEC packet has been received.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000782 FrameFragmentationTest test(
783 kMaxPacketSize, start, stop, format == kGeneric, with_fec);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000784
stefane74eef12016-01-08 06:47:13 -0800785 RunBaseTest(&test);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000786}
787
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000788// TODO(sprang): Is there any way of speeding up these tests?
789TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSize) {
790 TestPacketFragmentationSize(kGeneric, false);
791}
792
793TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSizeWithFec) {
794 TestPacketFragmentationSize(kGeneric, true);
795}
796
797TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSize) {
798 TestPacketFragmentationSize(kVP8, false);
799}
800
801TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSizeWithFec) {
802 TestPacketFragmentationSize(kVP8, true);
803}
804
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000805// The test will go through a number of phases.
806// 1. Start sending packets.
807// 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 +0000808// suspend the stream.
809// 3. Wait until |kSuspendTimeFrames| have been captured without seeing any RTP
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000810// packets.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000811// 4. Signal a high REMB and then wait for the RTP stream to start again.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000812// When the stream is detected again, and the stats show that the stream
813// is no longer suspended, the test ends.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000814TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
815 static const int kSuspendTimeFrames = 60; // Suspend for 2 seconds @ 30 fps.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000816
nissed30a1112016-04-18 05:15:22 -0700817 class RembObserver : public test::SendTest,
818 public rtc::VideoSinkInterface<VideoFrame> {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000819 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000820 RembObserver()
821 : SendTest(kDefaultTimeoutMs),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000822 clock_(Clock::GetRealTimeClock()),
Erik Språng737336d2016-07-29 12:59:36 +0200823 stream_(nullptr),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000824 test_state_(kBeforeSuspend),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000825 rtp_count_(0),
826 last_sequence_number_(0),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000827 suspended_frame_count_(0),
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000828 low_remb_bps_(0),
Erik Språng737336d2016-07-29 12:59:36 +0200829 high_remb_bps_(0) {}
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000830
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000831 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000832 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200833 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000834 ++rtp_count_;
835 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000836 EXPECT_TRUE(parser_->Parse(packet, length, &header));
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000837 last_sequence_number_ = header.sequenceNumber;
838
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000839 if (test_state_ == kBeforeSuspend) {
840 // The stream has started. Try to suspend it.
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000841 SendRtcpFeedback(low_remb_bps_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000842 test_state_ = kDuringSuspend;
843 } else if (test_state_ == kDuringSuspend) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000844 if (header.paddingLength == 0) {
845 // Received non-padding packet during suspension period. Reset the
846 // counter.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000847 suspended_frame_count_ = 0;
848 }
stefanf116bd02015-10-27 08:29:42 -0700849 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000850 } else if (test_state_ == kWaitingForPacket) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000851 if (header.paddingLength == 0) {
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000852 // Non-padding packet observed. Test is almost complete. Will just
853 // have to wait for the stats to change.
854 test_state_ = kWaitingForStats;
855 }
stefanf116bd02015-10-27 08:29:42 -0700856 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000857 } else if (test_state_ == kWaitingForStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000858 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000859 if (stats.suspended == false) {
860 // Stats flipped to false. Test is complete.
Peter Boström5811a392015-12-10 13:02:50 +0100861 observation_complete_.Set();
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000862 }
stefanf116bd02015-10-27 08:29:42 -0700863 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000864 }
865
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000866 return SEND_PACKET;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000867 }
868
nissed30a1112016-04-18 05:15:22 -0700869 // This method implements the rtc::VideoSinkInterface
870 void OnFrame(const VideoFrame& video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200871 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000872 if (test_state_ == kDuringSuspend &&
873 ++suspended_frame_count_ > kSuspendTimeFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000874 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000875 EXPECT_TRUE(stats.suspended);
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000876 SendRtcpFeedback(high_remb_bps_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000877 test_state_ = kWaitingForPacket;
878 }
879 }
880
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000881 void set_low_remb_bps(int value) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200882 rtc::CritScope lock(&crit_);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000883 low_remb_bps_ = value;
884 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000885
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000886 void set_high_remb_bps(int value) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200887 rtc::CritScope lock(&crit_);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000888 high_remb_bps_ = value;
889 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000890
stefanff483612015-12-21 03:14:00 -0800891 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000892 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000893 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000894 stream_ = send_stream;
895 }
896
stefanff483612015-12-21 03:14:00 -0800897 void ModifyVideoConfigs(
898 VideoSendStream::Config* send_config,
899 std::vector<VideoReceiveStream::Config>* receive_configs,
900 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700901 transport_adapter_.reset(
902 new internal::TransportAdapter(send_config->send_transport));
903 transport_adapter_->Enable();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000904 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000905 send_config->pre_encode_callback = this;
906 send_config->suspend_below_min_bitrate = true;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000907 int min_bitrate_bps = encoder_config->streams[0].min_bitrate_bps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000908 set_low_remb_bps(min_bitrate_bps - 10000);
mflodman101f2502016-06-09 17:21:19 +0200909 int threshold_window = std::max(min_bitrate_bps / 10, 20000);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000910 ASSERT_GT(encoder_config->streams[0].max_bitrate_bps,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000911 min_bitrate_bps + threshold_window + 5000);
912 set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
913 }
914
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000915 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100916 EXPECT_TRUE(Wait()) << "Timed out during suspend-below-min-bitrate test.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000917 }
918
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000919 enum TestState {
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000920 kBeforeSuspend,
921 kDuringSuspend,
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000922 kWaitingForPacket,
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000923 kWaitingForStats
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000924 };
925
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000926 virtual void SendRtcpFeedback(int remb_value)
927 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100928 FakeReceiveStatistics receive_stats(kVideoSendSsrcs[0],
929 last_sequence_number_, rtp_count_, 0);
terelius429c3452016-01-21 05:42:04 -0800930 RTCPSender rtcp_sender(false, clock_, &receive_stats, nullptr, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700931 transport_adapter_.get());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000932
pbosda903ea2015-10-02 02:36:56 -0700933 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100934 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000935 if (remb_value > 0) {
936 rtcp_sender.SetREMBStatus(true);
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000937 rtcp_sender.SetREMBData(remb_value, std::vector<uint32_t>());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000938 }
939 RTCPSender::FeedbackState feedback_state;
940 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
941 }
942
kwiberg27f982b2016-03-01 11:52:33 -0800943 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000944 Clock* const clock_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000945 VideoSendStream* stream_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000946
Peter Boströmf2f82832015-05-01 13:00:41 +0200947 rtc::CriticalSection crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000948 TestState test_state_ GUARDED_BY(crit_);
949 int rtp_count_ GUARDED_BY(crit_);
950 int last_sequence_number_ GUARDED_BY(crit_);
951 int suspended_frame_count_ GUARDED_BY(crit_);
952 int low_remb_bps_ GUARDED_BY(crit_);
953 int high_remb_bps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000954 } test;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000955
stefane74eef12016-01-08 06:47:13 -0800956 RunBaseTest(&test);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000957}
958
perkj71ee44c2016-06-15 00:47:53 -0700959// This test that padding stops being send after a while if the Camera stops
960// producing video frames and that padding resumes if the camera restarts.
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000961TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000962 class NoPaddingWhenVideoIsMuted : public test::SendTest {
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000963 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000964 NoPaddingWhenVideoIsMuted()
965 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000966 clock_(Clock::GetRealTimeClock()),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000967 last_packet_time_ms_(-1),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000968 capturer_(nullptr) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000969 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000970
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000971 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000972 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200973 rtc::CritScope lock(&crit_);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000974 last_packet_time_ms_ = clock_->TimeInMilliseconds();
perkj71ee44c2016-06-15 00:47:53 -0700975
976 RTPHeader header;
977 parser_->Parse(packet, length, &header);
978 const bool only_padding =
979 header.headerLength + header.paddingLength == length;
980
981 if (test_state_ == kBeforeStopCapture) {
982 capturer_->Stop();
983 test_state_ = kWaitingForPadding;
984 } else if (test_state_ == kWaitingForPadding && only_padding) {
985 test_state_ = kWaitingForNoPackets;
986 } else if (test_state_ == kWaitingForPaddingAfterCameraRestart &&
987 only_padding) {
988 observation_complete_.Set();
989 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000990 return SEND_PACKET;
991 }
992
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000993 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200994 rtc::CritScope lock(&crit_);
perkj71ee44c2016-06-15 00:47:53 -0700995 const int kNoPacketsThresholdMs = 2000;
996 if (test_state_ == kWaitingForNoPackets &&
997 (last_packet_time_ms_ > 0 &&
998 clock_->TimeInMilliseconds() - last_packet_time_ms_ >
999 kNoPacketsThresholdMs)) {
1000 capturer_->Start();
1001 test_state_ = kWaitingForPaddingAfterCameraRestart;
1002 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +00001003 return SEND_PACKET;
1004 }
1005
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001006 size_t GetNumVideoStreams() const override { return 3; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001007
nisseef8b61e2016-04-29 06:09:15 -07001008 void OnFrameGeneratorCapturerCreated(
1009 test::FrameGeneratorCapturer* frame_generator_capturer) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001010 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001011 capturer_ = frame_generator_capturer;
1012 }
1013
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001014 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001015 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001016 << "Timed out while waiting for RTP packets to stop being sent.";
1017 }
1018
perkj71ee44c2016-06-15 00:47:53 -07001019 enum TestState {
1020 kBeforeStopCapture,
1021 kWaitingForPadding,
1022 kWaitingForNoPackets,
1023 kWaitingForPaddingAfterCameraRestart
1024 };
1025
1026 TestState test_state_ = kBeforeStopCapture;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +00001027 Clock* const clock_;
kwiberg27f982b2016-03-01 11:52:33 -08001028 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
Peter Boströmf2f82832015-05-01 13:00:41 +02001029 rtc::CriticalSection crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +00001030 int64_t last_packet_time_ms_ GUARDED_BY(crit_);
1031 test::FrameGeneratorCapturer* capturer_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001032 } test;
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +00001033
stefane74eef12016-01-08 06:47:13 -08001034 RunBaseTest(&test);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +00001035}
1036
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001037// This test first observes "high" bitrate use at which point it sends a REMB to
1038// indicate that it should be lowered significantly. The test then observes that
1039// the bitrate observed is sinking well below the min-transmit-bitrate threshold
1040// to verify that the min-transmit bitrate respects incoming REMB.
andresp@webrtc.org44caf012014-03-26 21:00:21 +00001041//
1042// Note that the test starts at "high" bitrate and does not ramp up to "higher"
1043// bitrate since no receiver block or remb is sent in the initial phase.
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001044TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
1045 static const int kMinTransmitBitrateBps = 400000;
andresp@webrtc.org44caf012014-03-26 21:00:21 +00001046 static const int kHighBitrateBps = 150000;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001047 static const int kRembBitrateBps = 80000;
1048 static const int kRembRespectedBitrateBps = 100000;
stefanf116bd02015-10-27 08:29:42 -07001049 class BitrateObserver : public test::SendTest {
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001050 public:
1051 BitrateObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001052 : SendTest(kDefaultTimeoutMs),
Erik Språng737336d2016-07-29 12:59:36 +02001053 retranmission_rate_limiter_(Clock::GetRealTimeClock(), 1000),
1054 stream_(nullptr),
1055 bitrate_capped_(false) {}
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001056
1057 private:
nisseef8b61e2016-04-29 06:09:15 -07001058 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001059 if (RtpHeaderParser::IsRtcp(packet, length))
stefanf116bd02015-10-27 08:29:42 -07001060 return DROP_PACKET;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001061
1062 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001063 if (!parser_->Parse(packet, length, &header))
stefanf116bd02015-10-27 08:29:42 -07001064 return DROP_PACKET;
Peter Boström74f6e9e2016-04-04 17:56:10 +02001065 RTC_DCHECK(stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001066 VideoSendStream::Stats stats = stream_->GetStats();
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001067 if (!stats.substreams.empty()) {
1068 EXPECT_EQ(1u, stats.substreams.size());
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001069 int total_bitrate_bps =
1070 stats.substreams.begin()->second.total_bitrate_bps;
1071 test::PrintResult("bitrate_stats_",
1072 "min_transmit_bitrate_low_remb",
1073 "bitrate_bps",
1074 static_cast<size_t>(total_bitrate_bps),
1075 "bps",
1076 false);
1077 if (total_bitrate_bps > kHighBitrateBps) {
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001078 rtp_rtcp_->SetREMBData(kRembBitrateBps,
1079 std::vector<uint32_t>(1, header.ssrc));
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001080 rtp_rtcp_->Process();
1081 bitrate_capped_ = true;
1082 } else if (bitrate_capped_ &&
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001083 total_bitrate_bps < kRembRespectedBitrateBps) {
Peter Boström5811a392015-12-10 13:02:50 +01001084 observation_complete_.Set();
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001085 }
1086 }
stefanf116bd02015-10-27 08:29:42 -07001087 // Packets don't have to be delivered since the test is the receiver.
1088 return DROP_PACKET;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001089 }
1090
stefanff483612015-12-21 03:14:00 -08001091 void OnVideoStreamsCreated(
stefanf116bd02015-10-27 08:29:42 -07001092 VideoSendStream* send_stream,
1093 const std::vector<VideoReceiveStream*>& receive_streams) override {
1094 stream_ = send_stream;
1095 RtpRtcp::Configuration config;
1096 config.outgoing_transport = feedback_transport_.get();
Erik Språng737336d2016-07-29 12:59:36 +02001097 config.retransmission_rate_limiter = &retranmission_rate_limiter_;
stefanf116bd02015-10-27 08:29:42 -07001098 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1099 rtp_rtcp_->SetREMBStatus(true);
1100 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001101 }
1102
stefanff483612015-12-21 03:14:00 -08001103 void ModifyVideoConfigs(
1104 VideoSendStream::Config* send_config,
1105 std::vector<VideoReceiveStream::Config>* receive_configs,
1106 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -07001107 feedback_transport_.reset(
1108 new internal::TransportAdapter(send_config->send_transport));
1109 feedback_transport_->Enable();
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00001110 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001111 }
1112
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001113 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001114 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001115 << "Timeout while waiting for low bitrate stats after REMB.";
1116 }
1117
kwiberg27f982b2016-03-01 11:52:33 -08001118 std::unique_ptr<RtpRtcp> rtp_rtcp_;
1119 std::unique_ptr<internal::TransportAdapter> feedback_transport_;
Erik Språng737336d2016-07-29 12:59:36 +02001120 RateLimiter retranmission_rate_limiter_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001121 VideoSendStream* stream_;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001122 bool bitrate_capped_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001123 } test;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001124
stefane74eef12016-01-08 06:47:13 -08001125 RunBaseTest(&test);
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001126}
1127
Stefan Holmerbe402962016-07-08 16:16:41 +02001128TEST_F(VideoSendStreamTest, ChangingNetworkRoute) {
1129 class ChangingNetworkRouteTest : public test::EndToEndTest {
1130 public:
1131 const int kStartBitrateBps = 300000;
1132 const int kNewMaxBitrateBps = 1234567;
1133
1134 ChangingNetworkRouteTest()
1135 : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
1136 call_(nullptr) {}
1137
1138 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1139 call_ = sender_call;
1140 }
1141
1142 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1143 if (call_->GetStats().send_bandwidth_bps > kStartBitrateBps) {
1144 observation_complete_.Set();
1145 }
1146
1147 return SEND_PACKET;
1148 }
1149
1150 void PerformTest() override {
1151 rtc::NetworkRoute new_route(true, 10, 20, -1);
1152 call_->OnNetworkRouteChanged("transport", new_route);
1153 Call::Config::BitrateConfig bitrate_config;
1154 bitrate_config.start_bitrate_bps = kStartBitrateBps;
1155 call_->SetBitrateConfig(bitrate_config);
1156 EXPECT_TRUE(Wait())
1157 << "Timed out while waiting for start bitrate to be exceeded.";
1158
1159 bitrate_config.start_bitrate_bps = -1;
1160 bitrate_config.max_bitrate_bps = kNewMaxBitrateBps;
1161 call_->SetBitrateConfig(bitrate_config);
1162 // TODO(holmer): We should set the last sent packet id here and verify
1163 // that we correctly ignore any packet loss reported prior to that id.
1164 ++new_route.local_network_id;
1165 call_->OnNetworkRouteChanged("transport", new_route);
1166 EXPECT_EQ(kStartBitrateBps, call_->GetStats().send_bandwidth_bps);
1167 }
1168
1169 private:
1170 Call* call_;
1171 } test;
1172
1173 RunBaseTest(&test);
1174}
1175
sprang9c0b5512016-07-06 00:54:28 -07001176class MaxPaddingSetTest : public test::SendTest {
1177 public:
1178 static const uint32_t kMinTransmitBitrateBps = 400000;
1179 static const uint32_t kActualEncodeBitrateBps = 40000;
1180 static const uint32_t kMinPacketsToSend = 50;
1181
1182 explicit MaxPaddingSetTest(bool test_switch_content_type)
1183 : SendTest(test::CallTest::kDefaultTimeoutMs),
1184 call_(nullptr),
1185 send_stream_(nullptr),
1186 packets_sent_(0),
1187 running_without_padding_(test_switch_content_type) {}
1188
1189 void OnVideoStreamsCreated(
1190 VideoSendStream* send_stream,
1191 const std::vector<VideoReceiveStream*>& receive_streams) override {
1192 send_stream_ = send_stream;
1193 }
1194
1195 void ModifyVideoConfigs(
1196 VideoSendStream::Config* send_config,
1197 std::vector<VideoReceiveStream::Config>* receive_configs,
1198 VideoEncoderConfig* encoder_config) override {
1199 RTC_DCHECK_EQ(1u, encoder_config->streams.size());
1200 if (running_without_padding_) {
1201 encoder_config->min_transmit_bitrate_bps = 0;
1202 encoder_config->content_type =
1203 VideoEncoderConfig::ContentType::kRealtimeVideo;
1204 } else {
1205 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
1206 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
1207 }
1208 encoder_config_ = *encoder_config;
1209 }
1210
1211 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1212 call_ = sender_call;
1213 }
1214
1215 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1216 rtc::CritScope lock(&crit_);
1217
1218 if (running_without_padding_)
1219 EXPECT_EQ(0, call_->GetStats().max_padding_bitrate_bps);
1220
1221 // Wait until at least kMinPacketsToSend frames have been encoded, so that
1222 // we have reliable data.
1223 if (++packets_sent_ < kMinPacketsToSend)
1224 return SEND_PACKET;
1225
1226 if (running_without_padding_) {
1227 // We've sent kMinPacketsToSend packets with default configuration, switch
1228 // to enabling screen content and setting min transmit bitrate.
1229 packets_sent_ = 0;
1230 encoder_config_.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
1231 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
1232 send_stream_->ReconfigureVideoEncoder(encoder_config_);
1233 running_without_padding_ = false;
1234 return SEND_PACKET;
1235 }
1236
1237 // Make sure the pacer has been configured with a min transmit bitrate.
1238 if (call_->GetStats().max_padding_bitrate_bps > 0)
1239 observation_complete_.Set();
1240
1241 return SEND_PACKET;
1242 }
1243
1244 void PerformTest() override {
1245 ASSERT_TRUE(Wait()) << "Timed out waiting for a valid padding bitrate.";
1246 }
1247
1248 private:
1249 rtc::CriticalSection crit_;
1250 Call* call_;
1251 VideoSendStream* send_stream_;
1252 VideoEncoderConfig encoder_config_;
1253 uint32_t packets_sent_ GUARDED_BY(crit_);
1254 bool running_without_padding_;
1255};
1256
1257TEST_F(VideoSendStreamTest, RespectsMinTransmitBitrate) {
1258 MaxPaddingSetTest test(false);
1259 RunBaseTest(&test);
1260}
1261
1262TEST_F(VideoSendStreamTest, RespectsMinTransmitBitrateAfterContentSwitch) {
1263 MaxPaddingSetTest test(true);
1264 RunBaseTest(&test);
1265}
1266
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001267TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) {
1268 class StartBitrateObserver : public test::FakeEncoder {
1269 public:
1270 StartBitrateObserver()
pbos14fe7082016-04-20 06:35:56 -07001271 : FakeEncoder(Clock::GetRealTimeClock()),
1272 start_bitrate_changed_(false, false),
1273 start_bitrate_kbps_(0) {}
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001274 int32_t InitEncode(const VideoCodec* config,
1275 int32_t number_of_cores,
1276 size_t max_payload_size) override {
1277 rtc::CritScope lock(&crit_);
1278 start_bitrate_kbps_ = config->startBitrate;
pbos14fe7082016-04-20 06:35:56 -07001279 start_bitrate_changed_.Set();
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001280 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1281 }
1282
1283 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
1284 rtc::CritScope lock(&crit_);
1285 start_bitrate_kbps_ = new_target_bitrate;
pbos14fe7082016-04-20 06:35:56 -07001286 start_bitrate_changed_.Set();
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001287 return FakeEncoder::SetRates(new_target_bitrate, framerate);
1288 }
1289
1290 int GetStartBitrateKbps() const {
1291 rtc::CritScope lock(&crit_);
1292 return start_bitrate_kbps_;
1293 }
1294
pbos14fe7082016-04-20 06:35:56 -07001295 bool WaitForStartBitrate() {
1296 return start_bitrate_changed_.Wait(
1297 VideoSendStreamTest::kDefaultTimeoutMs);
1298 }
1299
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001300 private:
pbos5ad935c2016-01-25 03:52:44 -08001301 rtc::CriticalSection crit_;
pbos14fe7082016-04-20 06:35:56 -07001302 rtc::Event start_bitrate_changed_;
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001303 int start_bitrate_kbps_ GUARDED_BY(crit_);
1304 };
1305
solenberg4fbae2b2015-08-28 04:07:10 -07001306 CreateSenderCall(Call::Config());
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001307
solenberg4fbae2b2015-08-28 04:07:10 -07001308 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001309 CreateSendConfig(1, 0, &transport);
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001310
1311 Call::Config::BitrateConfig bitrate_config;
1312 bitrate_config.start_bitrate_bps =
stefanff483612015-12-21 03:14:00 -08001313 2 * video_encoder_config_.streams[0].max_bitrate_bps;
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001314 sender_call_->SetBitrateConfig(bitrate_config);
1315
1316 StartBitrateObserver encoder;
stefanff483612015-12-21 03:14:00 -08001317 video_send_config_.encoder_settings.encoder = &encoder;
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001318
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001319 CreateVideoStreams();
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001320
pbos14fe7082016-04-20 06:35:56 -07001321 EXPECT_TRUE(encoder.WaitForStartBitrate());
stefanff483612015-12-21 03:14:00 -08001322 EXPECT_EQ(video_encoder_config_.streams[0].max_bitrate_bps / 1000,
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001323 encoder.GetStartBitrateKbps());
1324
stefanff483612015-12-21 03:14:00 -08001325 video_encoder_config_.streams[0].max_bitrate_bps =
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001326 2 * bitrate_config.start_bitrate_bps;
stefanff483612015-12-21 03:14:00 -08001327 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001328
1329 // New bitrate should be reconfigured above the previous max. As there's no
1330 // network connection this shouldn't be flaky, as no bitrate should've been
1331 // reported in between.
pbos14fe7082016-04-20 06:35:56 -07001332 EXPECT_TRUE(encoder.WaitForStartBitrate());
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001333 EXPECT_EQ(bitrate_config.start_bitrate_bps / 1000,
1334 encoder.GetStartBitrateKbps());
1335
1336 DestroyStreams();
1337}
1338
perkj57c21f92016-06-17 07:27:16 -07001339// This test that if the encoder use an internal source, VideoEncoder::SetRates
1340// will be called with zero bitrate during initialization and that
1341// VideoSendStream::Stop also triggers VideoEncoder::SetRates Start to be called
1342// with zero bitrate.
1343TEST_F(VideoSendStreamTest, VideoSendStreamStopSetEncoderRateToZero) {
1344 class StartStopBitrateObserver : public test::FakeEncoder {
1345 public:
1346 StartStopBitrateObserver()
1347 : FakeEncoder(Clock::GetRealTimeClock()),
1348 encoder_init_(false, false),
1349 bitrate_changed_(false, false),
1350 bitrate_kbps_(0) {}
1351 int32_t InitEncode(const VideoCodec* config,
1352 int32_t number_of_cores,
1353 size_t max_payload_size) override {
1354 rtc::CritScope lock(&crit_);
1355 bitrate_kbps_ = config->startBitrate;
1356 encoder_init_.Set();
1357 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1358 }
1359
1360 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
1361 rtc::CritScope lock(&crit_);
1362 bitrate_kbps_ = new_target_bitrate;
1363 bitrate_changed_.Set();
1364 return FakeEncoder::SetRates(new_target_bitrate, framerate);
1365 }
1366
1367 int GetBitrateKbps() const {
1368 rtc::CritScope lock(&crit_);
1369 return bitrate_kbps_;
1370 }
1371
1372 bool WaitForEncoderInit() {
1373 return encoder_init_.Wait(VideoSendStreamTest::kDefaultTimeoutMs);
1374 }
1375 bool WaitBitrateChanged() {
1376 return bitrate_changed_.Wait(VideoSendStreamTest::kDefaultTimeoutMs);
1377 }
1378
1379 private:
1380 rtc::CriticalSection crit_;
1381 rtc::Event encoder_init_;
1382 rtc::Event bitrate_changed_;
1383 int bitrate_kbps_ GUARDED_BY(crit_);
1384 };
1385
1386 CreateSenderCall(Call::Config());
1387
1388 test::NullTransport transport;
1389 CreateSendConfig(1, 0, &transport);
1390
1391 StartStopBitrateObserver encoder;
1392 video_send_config_.encoder_settings.encoder = &encoder;
1393 video_send_config_.encoder_settings.internal_source = true;
1394
1395 CreateVideoStreams();
1396
1397 EXPECT_TRUE(encoder.WaitForEncoderInit());
1398 EXPECT_GT(encoder.GetBitrateKbps(), 0);
1399 video_send_stream_->Start();
1400 EXPECT_TRUE(encoder.WaitBitrateChanged());
1401 EXPECT_GT(encoder.GetBitrateKbps(), 0);
1402 video_send_stream_->Stop();
1403 EXPECT_TRUE(encoder.WaitBitrateChanged());
1404 EXPECT_EQ(0, encoder.GetBitrateKbps());
1405 video_send_stream_->Start();
1406 EXPECT_TRUE(encoder.WaitBitrateChanged());
1407 EXPECT_GT(encoder.GetBitrateKbps(), 0);
1408
1409 DestroyStreams();
1410}
1411
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001412TEST_F(VideoSendStreamTest, CapturesTextureAndVideoFrames) {
nissed30a1112016-04-18 05:15:22 -07001413 class FrameObserver : public rtc::VideoSinkInterface<VideoFrame> {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001414 public:
Peter Boström5811a392015-12-10 13:02:50 +01001415 FrameObserver() : output_frame_event_(false, false) {}
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001416
nissed30a1112016-04-18 05:15:22 -07001417 void OnFrame(const VideoFrame& video_frame) override {
1418 output_frames_.push_back(video_frame);
Peter Boström5811a392015-12-10 13:02:50 +01001419 output_frame_event_.Set();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001420 }
1421
1422 void WaitOutputFrame() {
Peter Boström5811a392015-12-10 13:02:50 +01001423 const int kWaitFrameTimeoutMs = 3000;
1424 EXPECT_TRUE(output_frame_event_.Wait(kWaitFrameTimeoutMs))
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001425 << "Timeout while waiting for output frames.";
1426 }
1427
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001428 const std::vector<VideoFrame>& output_frames() const {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001429 return output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001430 }
1431
1432 private:
1433 // Delivered output frames.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001434 std::vector<VideoFrame> output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001435
1436 // Indicate an output frame has arrived.
Peter Boström5811a392015-12-10 13:02:50 +01001437 rtc::Event output_frame_event_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001438 };
1439
1440 // Initialize send stream.
solenberg4fbae2b2015-08-28 04:07:10 -07001441 CreateSenderCall(Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001442
solenberg4fbae2b2015-08-28 04:07:10 -07001443 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001444 CreateSendConfig(1, 0, &transport);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001445 FrameObserver observer;
stefanff483612015-12-21 03:14:00 -08001446 video_send_config_.pre_encode_callback = &observer;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001447 CreateVideoStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001448
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001449 // Prepare five input frames. Send ordinary VideoFrame and texture frames
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001450 // alternatively.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001451 std::vector<VideoFrame> input_frames;
stefanff483612015-12-21 03:14:00 -08001452 int width = static_cast<int>(video_encoder_config_.streams[0].width);
1453 int height = static_cast<int>(video_encoder_config_.streams[0].height);
Peter Boströmeb66e802015-06-05 11:08:03 +02001454 test::FakeNativeHandle* handle1 = new test::FakeNativeHandle();
1455 test::FakeNativeHandle* handle2 = new test::FakeNativeHandle();
1456 test::FakeNativeHandle* handle3 = new test::FakeNativeHandle();
Peter Boström13f61df2016-01-04 22:36:38 +01001457 input_frames.push_back(test::FakeNativeHandle::CreateFrame(
Peter Boströmeb66e802015-06-05 11:08:03 +02001458 handle1, width, height, 1, 1, kVideoRotation_0));
Peter Boström13f61df2016-01-04 22:36:38 +01001459 input_frames.push_back(test::FakeNativeHandle::CreateFrame(
Peter Boströmeb66e802015-06-05 11:08:03 +02001460 handle2, width, height, 2, 2, kVideoRotation_0));
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001461 input_frames.push_back(CreateVideoFrame(width, height, 3));
1462 input_frames.push_back(CreateVideoFrame(width, height, 4));
Peter Boström13f61df2016-01-04 22:36:38 +01001463 input_frames.push_back(test::FakeNativeHandle::CreateFrame(
Peter Boströmeb66e802015-06-05 11:08:03 +02001464 handle3, width, height, 5, 5, kVideoRotation_0));
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001465
stefanff483612015-12-21 03:14:00 -08001466 video_send_stream_->Start();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001467 for (size_t i = 0; i < input_frames.size(); i++) {
stefanff483612015-12-21 03:14:00 -08001468 video_send_stream_->Input()->IncomingCapturedFrame(input_frames[i]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001469 // Do not send the next frame too fast, so the frame dropper won't drop it.
1470 if (i < input_frames.size() - 1)
stefanff483612015-12-21 03:14:00 -08001471 SleepMs(1000 / video_encoder_config_.streams[0].max_framerate);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001472 // Wait until the output frame is received before sending the next input
1473 // frame. Or the previous input frame may be replaced without delivering.
1474 observer.WaitOutputFrame();
1475 }
stefanff483612015-12-21 03:14:00 -08001476 video_send_stream_->Stop();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001477
1478 // Test if the input and output frames are the same. render_time_ms and
1479 // timestamp are not compared because capturer sets those values.
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001480 ExpectEqualFramesVector(input_frames, observer.output_frames());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001481
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001482 DestroyStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001483}
1484
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001485void ExpectEqualFramesVector(const std::vector<VideoFrame>& frames1,
1486 const std::vector<VideoFrame>& frames2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001487 EXPECT_EQ(frames1.size(), frames2.size());
1488 for (size_t i = 0; i < std::min(frames1.size(), frames2.size()); ++i)
nisse26acec42016-04-15 03:43:39 -07001489 // Compare frame buffers, since we don't care about differing timestamps.
1490 EXPECT_TRUE(test::FrameBufsEqual(frames1[i].video_frame_buffer(),
1491 frames2[i].video_frame_buffer()));
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001492}
1493
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001494VideoFrame CreateVideoFrame(int width, int height, uint8_t data) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001495 const int kSizeY = width * height * 2;
kwiberg27f982b2016-03-01 11:52:33 -08001496 std::unique_ptr<uint8_t[]> buffer(new uint8_t[kSizeY]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001497 memset(buffer.get(), data, kSizeY);
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001498 VideoFrame frame;
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001499 frame.CreateFrame(buffer.get(), buffer.get(), buffer.get(), width, height,
Niels Möller739fcb92016-02-29 13:11:45 +01001500 width, width / 2, width / 2, kVideoRotation_0);
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001501 frame.set_timestamp(data);
1502 frame.set_render_time_ms(data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001503 return frame;
1504}
1505
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001506TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
1507 class EncoderStateObserver : public test::SendTest, public VideoEncoder {
1508 public:
1509 EncoderStateObserver()
1510 : SendTest(kDefaultTimeoutMs),
Erik Språng737336d2016-07-29 12:59:36 +02001511 stream_(nullptr),
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001512 initialized_(false),
1513 callback_registered_(false),
1514 num_releases_(0),
1515 released_(false) {}
1516
1517 bool IsReleased() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001518 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001519 return released_;
1520 }
1521
1522 bool IsReadyForEncode() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001523 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001524 return initialized_ && callback_registered_;
1525 }
1526
1527 size_t num_releases() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001528 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001529 return num_releases_;
1530 }
1531
1532 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001533 int32_t InitEncode(const VideoCodec* codecSettings,
1534 int32_t numberOfCores,
1535 size_t maxPayloadSize) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001536 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001537 EXPECT_FALSE(initialized_);
1538 initialized_ = true;
1539 released_ = false;
1540 return 0;
1541 }
1542
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001543 int32_t Encode(const VideoFrame& inputImage,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001544 const CodecSpecificInfo* codecSpecificInfo,
pbos22993e12015-10-19 02:39:06 -07001545 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001546 EXPECT_TRUE(IsReadyForEncode());
1547
Peter Boström5811a392015-12-10 13:02:50 +01001548 observation_complete_.Set();
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001549 return 0;
1550 }
1551
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001552 int32_t RegisterEncodeCompleteCallback(
1553 EncodedImageCallback* callback) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001554 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001555 EXPECT_TRUE(initialized_);
1556 callback_registered_ = true;
1557 return 0;
1558 }
1559
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001560 int32_t Release() override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001561 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001562 EXPECT_TRUE(IsReadyForEncode());
1563 EXPECT_FALSE(released_);
1564 initialized_ = false;
1565 callback_registered_ = false;
1566 released_ = true;
1567 ++num_releases_;
1568 return 0;
1569 }
1570
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001571 int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001572 EXPECT_TRUE(IsReadyForEncode());
1573 return 0;
1574 }
1575
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001576 int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001577 EXPECT_TRUE(IsReadyForEncode());
1578 return 0;
1579 }
1580
stefanff483612015-12-21 03:14:00 -08001581 void OnVideoStreamsCreated(
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001582 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001583 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001584 stream_ = send_stream;
1585 }
1586
stefanff483612015-12-21 03:14:00 -08001587 void ModifyVideoConfigs(
1588 VideoSendStream::Config* send_config,
1589 std::vector<VideoReceiveStream::Config>* receive_configs,
1590 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001591 send_config->encoder_settings.encoder = this;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001592 encoder_config_ = *encoder_config;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001593 }
1594
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001595 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001596 EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001597 EXPECT_EQ(0u, num_releases());
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001598 stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001599 EXPECT_EQ(0u, num_releases());
1600 stream_->Stop();
1601 // Encoder should not be released before destroying the VideoSendStream.
1602 EXPECT_FALSE(IsReleased());
1603 EXPECT_TRUE(IsReadyForEncode());
1604 stream_->Start();
1605 // Sanity check, make sure we still encode frames with this encoder.
Peter Boström5811a392015-12-10 13:02:50 +01001606 EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001607 }
1608
Peter Boströmf2f82832015-05-01 13:00:41 +02001609 rtc::CriticalSection crit_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001610 VideoSendStream* stream_;
1611 bool initialized_ GUARDED_BY(crit_);
1612 bool callback_registered_ GUARDED_BY(crit_);
1613 size_t num_releases_ GUARDED_BY(crit_);
1614 bool released_ GUARDED_BY(crit_);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001615 VideoEncoderConfig encoder_config_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001616 } test_encoder;
1617
stefane74eef12016-01-08 06:47:13 -08001618 RunBaseTest(&test_encoder);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001619
1620 EXPECT_TRUE(test_encoder.IsReleased());
1621 EXPECT_EQ(1u, test_encoder.num_releases());
1622}
1623
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001624TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
1625 class VideoCodecConfigObserver : public test::SendTest,
1626 public test::FakeEncoder {
1627 public:
1628 VideoCodecConfigObserver()
1629 : SendTest(kDefaultTimeoutMs),
1630 FakeEncoder(Clock::GetRealTimeClock()),
pbos14fe7082016-04-20 06:35:56 -07001631 init_encode_event_(false, false),
Erik Språng737336d2016-07-29 12:59:36 +02001632 num_initializations_(0),
1633 stream_(nullptr) {}
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001634
1635 private:
stefanff483612015-12-21 03:14:00 -08001636 void ModifyVideoConfigs(
1637 VideoSendStream::Config* send_config,
1638 std::vector<VideoReceiveStream::Config>* receive_configs,
1639 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001640 send_config->encoder_settings.encoder = this;
1641 encoder_config_ = *encoder_config;
1642 }
1643
stefanff483612015-12-21 03:14:00 -08001644 void OnVideoStreamsCreated(
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001645 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001646 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001647 stream_ = send_stream;
1648 }
1649
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001650 int32_t InitEncode(const VideoCodec* config,
1651 int32_t number_of_cores,
1652 size_t max_payload_size) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001653 if (num_initializations_ == 0) {
1654 // Verify default values.
1655 EXPECT_EQ(kRealtimeVideo, config->mode);
1656 } else {
1657 // Verify that changed values are propagated.
1658 EXPECT_EQ(kScreensharing, config->mode);
1659 }
1660 ++num_initializations_;
pbos14fe7082016-04-20 06:35:56 -07001661 init_encode_event_.Set();
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001662 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1663 }
1664
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001665 void PerformTest() override {
pbos14fe7082016-04-20 06:35:56 -07001666 EXPECT_TRUE(init_encode_event_.Wait(kDefaultTimeoutMs));
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001667 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1668
Erik Språng143cec12015-04-28 10:01:41 +02001669 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001670 stream_->ReconfigureVideoEncoder(encoder_config_);
pbos14fe7082016-04-20 06:35:56 -07001671 EXPECT_TRUE(init_encode_event_.Wait(kDefaultTimeoutMs));
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001672 EXPECT_EQ(2u, num_initializations_)
1673 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1674 "new encoder settings.";
1675 }
1676
pbos14fe7082016-04-20 06:35:56 -07001677 rtc::Event init_encode_event_;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001678 size_t num_initializations_;
1679 VideoSendStream* stream_;
1680 VideoEncoderConfig encoder_config_;
1681 } test;
1682
stefane74eef12016-01-08 06:47:13 -08001683 RunBaseTest(&test);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001684}
1685
Peter Boström53eda3d2015-03-27 15:53:18 +01001686static const size_t kVideoCodecConfigObserverNumberOfTemporalLayers = 4;
1687template <typename T>
1688class VideoCodecConfigObserver : public test::SendTest,
1689 public test::FakeEncoder {
Peter Boström53eda3d2015-03-27 15:53:18 +01001690 public:
1691 VideoCodecConfigObserver(VideoCodecType video_codec_type,
1692 const char* codec_name)
1693 : SendTest(VideoSendStreamTest::kDefaultTimeoutMs),
1694 FakeEncoder(Clock::GetRealTimeClock()),
1695 video_codec_type_(video_codec_type),
1696 codec_name_(codec_name),
pbos14fe7082016-04-20 06:35:56 -07001697 init_encode_event_(false, false),
Erik Språng737336d2016-07-29 12:59:36 +02001698 num_initializations_(0),
1699 stream_(nullptr) {
Peter Boström53eda3d2015-03-27 15:53:18 +01001700 memset(&encoder_settings_, 0, sizeof(encoder_settings_));
1701 }
1702
1703 private:
stefanff483612015-12-21 03:14:00 -08001704 void ModifyVideoConfigs(
1705 VideoSendStream::Config* send_config,
1706 std::vector<VideoReceiveStream::Config>* receive_configs,
1707 VideoEncoderConfig* encoder_config) override {
Peter Boström53eda3d2015-03-27 15:53:18 +01001708 send_config->encoder_settings.encoder = this;
1709 send_config->encoder_settings.payload_name = codec_name_;
1710
1711 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
1712 encoder_config->streams[i].temporal_layer_thresholds_bps.resize(
1713 kVideoCodecConfigObserverNumberOfTemporalLayers - 1);
1714 }
1715
1716 encoder_config->encoder_specific_settings = &encoder_settings_;
1717 encoder_config_ = *encoder_config;
1718 }
1719
stefanff483612015-12-21 03:14:00 -08001720 void OnVideoStreamsCreated(
Peter Boström53eda3d2015-03-27 15:53:18 +01001721 VideoSendStream* send_stream,
1722 const std::vector<VideoReceiveStream*>& receive_streams) override {
1723 stream_ = send_stream;
1724 }
1725
1726 int32_t InitEncode(const VideoCodec* config,
1727 int32_t number_of_cores,
1728 size_t max_payload_size) override {
1729 EXPECT_EQ(video_codec_type_, config->codecType);
1730 VerifyCodecSpecifics(*config);
1731 ++num_initializations_;
pbos14fe7082016-04-20 06:35:56 -07001732 init_encode_event_.Set();
Peter Boström53eda3d2015-03-27 15:53:18 +01001733 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1734 }
1735
1736 void VerifyCodecSpecifics(const VideoCodec& config) const;
1737
1738 void PerformTest() override {
pbos14fe7082016-04-20 06:35:56 -07001739 EXPECT_TRUE(
1740 init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
1741 ASSERT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
Peter Boström53eda3d2015-03-27 15:53:18 +01001742
1743 encoder_settings_.frameDroppingOn = true;
1744 stream_->ReconfigureVideoEncoder(encoder_config_);
pbos14fe7082016-04-20 06:35:56 -07001745 ASSERT_TRUE(
1746 init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
Peter Boström53eda3d2015-03-27 15:53:18 +01001747 EXPECT_EQ(2u, num_initializations_)
1748 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1749 "new encoder settings.";
1750 }
1751
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001752 int32_t Encode(const VideoFrame& input_image,
Peter Boström53eda3d2015-03-27 15:53:18 +01001753 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07001754 const std::vector<FrameType>* frame_types) override {
Peter Boström53eda3d2015-03-27 15:53:18 +01001755 // Silently skip the encode, FakeEncoder::Encode doesn't produce VP8.
1756 return 0;
1757 }
1758
1759 T encoder_settings_;
1760 const VideoCodecType video_codec_type_;
1761 const char* const codec_name_;
pbos14fe7082016-04-20 06:35:56 -07001762 rtc::Event init_encode_event_;
Peter Boström53eda3d2015-03-27 15:53:18 +01001763 size_t num_initializations_;
1764 VideoSendStream* stream_;
1765 VideoEncoderConfig encoder_config_;
1766};
1767
1768template <>
1769void VideoCodecConfigObserver<VideoCodecH264>::VerifyCodecSpecifics(
1770 const VideoCodec& config) const {
1771 EXPECT_EQ(0, memcmp(&config.codecSpecific.H264, &encoder_settings_,
1772 sizeof(encoder_settings_)));
1773}
1774template <>
1775void VideoCodecConfigObserver<VideoCodecVP8>::VerifyCodecSpecifics(
1776 const VideoCodec& config) const {
1777 // Check that the number of temporal layers has propagated properly to
1778 // VideoCodec.
1779 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1780 config.codecSpecific.VP8.numberOfTemporalLayers);
1781
1782 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1783 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1784 config.simulcastStream[i].numberOfTemporalLayers);
1785 }
1786
1787 // Set expected temporal layers as they should have been set when
1788 // reconfiguring the encoder and not match the set config.
1789 VideoCodecVP8 encoder_settings = encoder_settings_;
1790 encoder_settings.numberOfTemporalLayers =
1791 kVideoCodecConfigObserverNumberOfTemporalLayers;
1792 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP8, &encoder_settings,
1793 sizeof(encoder_settings_)));
1794}
1795template <>
1796void VideoCodecConfigObserver<VideoCodecVP9>::VerifyCodecSpecifics(
1797 const VideoCodec& config) const {
1798 // Check that the number of temporal layers has propagated properly to
1799 // VideoCodec.
1800 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1801 config.codecSpecific.VP9.numberOfTemporalLayers);
1802
1803 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1804 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1805 config.simulcastStream[i].numberOfTemporalLayers);
1806 }
1807
1808 // Set expected temporal layers as they should have been set when
1809 // reconfiguring the encoder and not match the set config.
1810 VideoCodecVP9 encoder_settings = encoder_settings_;
1811 encoder_settings.numberOfTemporalLayers =
1812 kVideoCodecConfigObserverNumberOfTemporalLayers;
1813 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP9, &encoder_settings,
1814 sizeof(encoder_settings_)));
1815}
1816
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001817TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp8Config) {
Peter Boström53eda3d2015-03-27 15:53:18 +01001818 VideoCodecConfigObserver<VideoCodecVP8> test(kVideoCodecVP8, "VP8");
stefane74eef12016-01-08 06:47:13 -08001819 RunBaseTest(&test);
Peter Boström53eda3d2015-03-27 15:53:18 +01001820}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001821
Peter Boström53eda3d2015-03-27 15:53:18 +01001822TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp9Config) {
1823 VideoCodecConfigObserver<VideoCodecVP9> test(kVideoCodecVP9, "VP9");
stefane74eef12016-01-08 06:47:13 -08001824 RunBaseTest(&test);
Peter Boström53eda3d2015-03-27 15:53:18 +01001825}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001826
Peter Boström53eda3d2015-03-27 15:53:18 +01001827TEST_F(VideoSendStreamTest, EncoderSetupPropagatesH264Config) {
1828 VideoCodecConfigObserver<VideoCodecH264> test(kVideoCodecH264, "H264");
stefane74eef12016-01-08 06:47:13 -08001829 RunBaseTest(&test);
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001830}
1831
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001832TEST_F(VideoSendStreamTest, RtcpSenderReportContainsMediaBytesSent) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001833 class RtcpSenderReportTest : public test::SendTest {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001834 public:
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001835 RtcpSenderReportTest() : SendTest(kDefaultTimeoutMs),
1836 rtp_packets_sent_(0),
1837 media_bytes_sent_(0) {}
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001838
1839 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001840 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan4b569042015-11-11 06:39:57 -08001841 rtc::CritScope lock(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001842 RTPHeader header;
1843 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001844 ++rtp_packets_sent_;
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001845 media_bytes_sent_ += length - header.headerLength - header.paddingLength;
1846 return SEND_PACKET;
1847 }
1848
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001849 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan4b569042015-11-11 06:39:57 -08001850 rtc::CritScope lock(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001851 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1852 EXPECT_TRUE(parser.IsValid());
1853
1854 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001855 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1856 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001857 // Only compare sent media bytes if SenderPacketCount matches the
1858 // number of sent rtp packets (a new rtp packet could be sent before
1859 // the rtcp packet).
1860 if (parser.Packet().SR.SenderOctetCount > 0 &&
1861 parser.Packet().SR.SenderPacketCount == rtp_packets_sent_) {
1862 EXPECT_EQ(media_bytes_sent_, parser.Packet().SR.SenderOctetCount);
Peter Boström5811a392015-12-10 13:02:50 +01001863 observation_complete_.Set();
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001864 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001865 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001866 packet_type = parser.Iterate();
1867 }
1868
1869 return SEND_PACKET;
1870 }
1871
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001872 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001873 EXPECT_TRUE(Wait()) << "Timed out while waiting for RTCP sender report.";
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001874 }
1875
stefan4b569042015-11-11 06:39:57 -08001876 rtc::CriticalSection crit_;
1877 size_t rtp_packets_sent_ GUARDED_BY(&crit_);
1878 size_t media_bytes_sent_ GUARDED_BY(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001879 } test;
1880
stefane74eef12016-01-08 06:47:13 -08001881 RunBaseTest(&test);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001882}
1883
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001884TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
1885 static const int kScreencastTargetBitrateKbps = 200;
1886 class ScreencastTargetBitrateTest : public test::SendTest,
1887 public test::FakeEncoder {
1888 public:
1889 ScreencastTargetBitrateTest()
1890 : SendTest(kDefaultTimeoutMs),
1891 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1892
1893 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001894 int32_t InitEncode(const VideoCodec* config,
1895 int32_t number_of_cores,
1896 size_t max_payload_size) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001897 EXPECT_EQ(static_cast<unsigned int>(kScreencastTargetBitrateKbps),
1898 config->targetBitrate);
Peter Boström5811a392015-12-10 13:02:50 +01001899 observation_complete_.Set();
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001900 return test::FakeEncoder::InitEncode(
1901 config, number_of_cores, max_payload_size);
1902 }
stefanff483612015-12-21 03:14:00 -08001903 void ModifyVideoConfigs(
1904 VideoSendStream::Config* send_config,
1905 std::vector<VideoReceiveStream::Config>* receive_configs,
1906 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001907 send_config->encoder_settings.encoder = this;
1908 EXPECT_EQ(1u, encoder_config->streams.size());
1909 EXPECT_TRUE(
1910 encoder_config->streams[0].temporal_layer_thresholds_bps.empty());
1911 encoder_config->streams[0].temporal_layer_thresholds_bps.push_back(
1912 kScreencastTargetBitrateKbps * 1000);
Erik Språng143cec12015-04-28 10:01:41 +02001913 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001914 }
1915
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001916 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001917 EXPECT_TRUE(Wait())
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001918 << "Timed out while waiting for the encoder to be initialized.";
1919 }
1920 } test;
1921
stefane74eef12016-01-08 06:47:13 -08001922 RunBaseTest(&test);
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001923}
pbos@webrtc.org00873182014-11-25 14:03:34 +00001924
philipelc6957c72016-04-28 15:52:49 +02001925TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001926 // These are chosen to be "kind of odd" to not be accidentally checked against
1927 // default values.
1928 static const int kMinBitrateKbps = 137;
1929 static const int kStartBitrateKbps = 345;
1930 static const int kLowerMaxBitrateKbps = 312;
1931 static const int kMaxBitrateKbps = 413;
1932 static const int kIncreasedStartBitrateKbps = 451;
1933 static const int kIncreasedMaxBitrateKbps = 597;
1934 class EncoderBitrateThresholdObserver : public test::SendTest,
1935 public test::FakeEncoder {
1936 public:
1937 EncoderBitrateThresholdObserver()
1938 : SendTest(kDefaultTimeoutMs),
1939 FakeEncoder(Clock::GetRealTimeClock()),
pbos14fe7082016-04-20 06:35:56 -07001940 init_encode_event_(false, false),
Erik Språng737336d2016-07-29 12:59:36 +02001941 num_initializations_(0),
1942 call_(nullptr),
1943 send_stream_(nullptr) {}
pbos@webrtc.org00873182014-11-25 14:03:34 +00001944
1945 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001946 int32_t InitEncode(const VideoCodec* codecSettings,
1947 int32_t numberOfCores,
1948 size_t maxPayloadSize) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001949 if (num_initializations_ == 0) {
1950 EXPECT_EQ(static_cast<unsigned int>(kMinBitrateKbps),
1951 codecSettings->minBitrate);
1952 EXPECT_EQ(static_cast<unsigned int>(kStartBitrateKbps),
1953 codecSettings->startBitrate);
1954 EXPECT_EQ(static_cast<unsigned int>(kMaxBitrateKbps),
1955 codecSettings->maxBitrate);
Peter Boström5811a392015-12-10 13:02:50 +01001956 observation_complete_.Set();
pbos@webrtc.org00873182014-11-25 14:03:34 +00001957 } else if (num_initializations_ == 1) {
1958 EXPECT_EQ(static_cast<unsigned int>(kLowerMaxBitrateKbps),
1959 codecSettings->maxBitrate);
1960 // The start bitrate should be kept (-1) and capped to the max bitrate.
1961 // Since this is not an end-to-end call no receiver should have been
1962 // returning a REMB that could lower this estimate.
1963 EXPECT_EQ(codecSettings->startBitrate, codecSettings->maxBitrate);
1964 } else if (num_initializations_ == 2) {
1965 EXPECT_EQ(static_cast<unsigned int>(kIncreasedMaxBitrateKbps),
1966 codecSettings->maxBitrate);
1967 EXPECT_EQ(static_cast<unsigned int>(kIncreasedStartBitrateKbps),
1968 codecSettings->startBitrate);
1969 }
1970 ++num_initializations_;
pbos14fe7082016-04-20 06:35:56 -07001971 init_encode_event_.Set();
pbos@webrtc.org00873182014-11-25 14:03:34 +00001972 return FakeEncoder::InitEncode(codecSettings, numberOfCores,
1973 maxPayloadSize);
1974 }
1975
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001976 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -07001977 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +01001978 config.bitrate_config.min_bitrate_bps = kMinBitrateKbps * 1000;
1979 config.bitrate_config.start_bitrate_bps = kStartBitrateKbps * 1000;
1980 config.bitrate_config.max_bitrate_bps = kMaxBitrateKbps * 1000;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001981 return config;
1982 }
1983
stefanff483612015-12-21 03:14:00 -08001984 void ModifyVideoConfigs(
1985 VideoSendStream::Config* send_config,
1986 std::vector<VideoReceiveStream::Config>* receive_configs,
1987 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001988 send_config->encoder_settings.encoder = this;
1989 // Set bitrates lower/higher than min/max to make sure they are properly
1990 // capped.
Stefan Holmere5904162015-03-26 11:11:06 +01001991 encoder_config->streams.front().min_bitrate_bps = kMinBitrateKbps * 1000;
1992 encoder_config->streams.front().max_bitrate_bps = kMaxBitrateKbps * 1000;
1993 encoder_config_ = *encoder_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001994 }
1995
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001996 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001997 call_ = sender_call;
1998 }
1999
stefanff483612015-12-21 03:14:00 -08002000 void OnVideoStreamsCreated(
Stefan Holmere5904162015-03-26 11:11:06 +01002001 VideoSendStream* send_stream,
2002 const std::vector<VideoReceiveStream*>& receive_streams) override {
2003 send_stream_ = send_stream;
2004 }
2005
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002006 void PerformTest() override {
pbos14fe7082016-04-20 06:35:56 -07002007 ASSERT_TRUE(
2008 init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs))
2009 << "Timed out while waiting encoder to be configured.";
pbos@webrtc.org00873182014-11-25 14:03:34 +00002010 Call::Config::BitrateConfig bitrate_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00002011 bitrate_config.start_bitrate_bps = kIncreasedStartBitrateKbps * 1000;
2012 bitrate_config.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000;
2013 call_->SetBitrateConfig(bitrate_config);
Peter Boström5811a392015-12-10 13:02:50 +01002014 EXPECT_TRUE(Wait())
Stefan Holmere5904162015-03-26 11:11:06 +01002015 << "Timed out while waiting encoder to be configured.";
2016 encoder_config_.streams[0].min_bitrate_bps = 0;
2017 encoder_config_.streams[0].max_bitrate_bps = kLowerMaxBitrateKbps * 1000;
2018 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos14fe7082016-04-20 06:35:56 -07002019 ASSERT_TRUE(
2020 init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
Stefan Holmere5904162015-03-26 11:11:06 +01002021 EXPECT_EQ(2, num_initializations_)
2022 << "Encoder should have been reconfigured with the new value.";
2023 encoder_config_.streams[0].target_bitrate_bps =
2024 encoder_config_.streams[0].min_bitrate_bps;
2025 encoder_config_.streams[0].max_bitrate_bps =
2026 kIncreasedMaxBitrateKbps * 1000;
2027 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos14fe7082016-04-20 06:35:56 -07002028 ASSERT_TRUE(
2029 init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
pbos@webrtc.org00873182014-11-25 14:03:34 +00002030 EXPECT_EQ(3, num_initializations_)
2031 << "Encoder should have been reconfigured with the new value.";
2032 }
2033
pbos14fe7082016-04-20 06:35:56 -07002034 rtc::Event init_encode_event_;
pbos@webrtc.org00873182014-11-25 14:03:34 +00002035 int num_initializations_;
2036 webrtc::Call* call_;
Stefan Holmere5904162015-03-26 11:11:06 +01002037 webrtc::VideoSendStream* send_stream_;
2038 webrtc::VideoEncoderConfig encoder_config_;
pbos@webrtc.org00873182014-11-25 14:03:34 +00002039 } test;
2040
stefane74eef12016-01-08 06:47:13 -08002041 RunBaseTest(&test);
pbos@webrtc.org00873182014-11-25 14:03:34 +00002042}
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002043
2044TEST_F(VideoSendStreamTest, ReportsSentResolution) {
2045 static const size_t kNumStreams = 3;
2046 // Unusual resolutions to make sure that they are the ones being reported.
2047 static const struct {
2048 int width;
2049 int height;
2050 } kEncodedResolution[kNumStreams] = {
2051 {241, 181}, {300, 121}, {121, 221}};
2052 class ScreencastTargetBitrateTest : public test::SendTest,
2053 public test::FakeEncoder {
2054 public:
2055 ScreencastTargetBitrateTest()
2056 : SendTest(kDefaultTimeoutMs),
Erik Språng737336d2016-07-29 12:59:36 +02002057 test::FakeEncoder(Clock::GetRealTimeClock()),
2058 send_stream_(nullptr) {}
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002059
2060 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07002061 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002062 const CodecSpecificInfo* codecSpecificInfo,
pbos22993e12015-10-19 02:39:06 -07002063 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002064 CodecSpecificInfo specifics;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002065 specifics.codecType = kVideoCodecGeneric;
2066
2067 uint8_t buffer[16] = {0};
2068 EncodedImage encoded(buffer, sizeof(buffer), sizeof(buffer));
2069 encoded._timeStamp = input_image.timestamp();
2070 encoded.capture_time_ms_ = input_image.render_time_ms();
2071
2072 for (size_t i = 0; i < kNumStreams; ++i) {
2073 specifics.codecSpecific.generic.simulcast_idx = static_cast<uint8_t>(i);
2074 encoded._frameType = (*frame_types)[i];
2075 encoded._encodedWidth = kEncodedResolution[i].width;
2076 encoded._encodedHeight = kEncodedResolution[i].height;
Peter Boström74f6e9e2016-04-04 17:56:10 +02002077 RTC_DCHECK(callback_);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002078 if (callback_->Encoded(encoded, &specifics, nullptr) != 0)
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002079 return -1;
2080 }
2081
Peter Boström5811a392015-12-10 13:02:50 +01002082 observation_complete_.Set();
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002083 return 0;
2084 }
stefanff483612015-12-21 03:14:00 -08002085 void ModifyVideoConfigs(
2086 VideoSendStream::Config* send_config,
2087 std::vector<VideoReceiveStream::Config>* receive_configs,
2088 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002089 send_config->encoder_settings.encoder = this;
2090 EXPECT_EQ(kNumStreams, encoder_config->streams.size());
2091 }
2092
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002093 size_t GetNumVideoStreams() const override { return kNumStreams; }
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002094
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002095 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002096 EXPECT_TRUE(Wait())
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002097 << "Timed out while waiting for the encoder to send one frame.";
2098 VideoSendStream::Stats stats = send_stream_->GetStats();
2099
2100 for (size_t i = 0; i < kNumStreams; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002101 ASSERT_TRUE(stats.substreams.find(kVideoSendSsrcs[i]) !=
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002102 stats.substreams.end())
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002103 << "No stats for SSRC: " << kVideoSendSsrcs[i]
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002104 << ", stats should exist as soon as frames have been encoded.";
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002105 VideoSendStream::StreamStats ssrc_stats =
Stefan Holmer9fea80f2016-01-07 17:43:18 +01002106 stats.substreams[kVideoSendSsrcs[i]];
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002107 EXPECT_EQ(kEncodedResolution[i].width, ssrc_stats.width);
2108 EXPECT_EQ(kEncodedResolution[i].height, ssrc_stats.height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002109 }
2110 }
2111
stefanff483612015-12-21 03:14:00 -08002112 void OnVideoStreamsCreated(
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002113 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002114 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002115 send_stream_ = send_stream;
2116 }
2117
2118 VideoSendStream* send_stream_;
2119 } test;
2120
stefane74eef12016-01-08 06:47:13 -08002121 RunBaseTest(&test);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00002122}
philipel0f9af012015-09-01 07:01:51 -07002123
Peter Boström12996152016-05-14 02:03:18 +02002124#if !defined(RTC_DISABLE_VP9)
Åsa Perssonff24c042015-12-04 10:58:08 +01002125class Vp9HeaderObserver : public test::SendTest {
philipel0f9af012015-09-01 07:01:51 -07002126 public:
Åsa Perssonff24c042015-12-04 10:58:08 +01002127 Vp9HeaderObserver()
2128 : SendTest(VideoSendStreamTest::kLongTimeoutMs),
philipel7fabd462015-09-03 04:42:32 -07002129 vp9_encoder_(VP9Encoder::Create()),
Åsa Perssonff24c042015-12-04 10:58:08 +01002130 vp9_settings_(VideoEncoder::GetDefaultVp9Settings()),
2131 packets_sent_(0),
2132 frames_sent_(0) {}
philipel7fabd462015-09-03 04:42:32 -07002133
stefanff483612015-12-21 03:14:00 -08002134 virtual void ModifyVideoConfigsHook(
philipel0f9af012015-09-01 07:01:51 -07002135 VideoSendStream::Config* send_config,
2136 std::vector<VideoReceiveStream::Config>* receive_configs,
2137 VideoEncoderConfig* encoder_config) {}
2138
Åsa Perssonff24c042015-12-04 10:58:08 +01002139 virtual void InspectHeader(const RTPVideoHeaderVP9& vp9) = 0;
philipel0f9af012015-09-01 07:01:51 -07002140
2141 private:
2142 const int kVp9PayloadType = 105;
2143
stefanff483612015-12-21 03:14:00 -08002144 void ModifyVideoConfigs(
2145 VideoSendStream::Config* send_config,
2146 std::vector<VideoReceiveStream::Config>* receive_configs,
2147 VideoEncoderConfig* encoder_config) override {
philipel0f9af012015-09-01 07:01:51 -07002148 encoder_config->encoder_specific_settings = &vp9_settings_;
philipel7fabd462015-09-03 04:42:32 -07002149 send_config->encoder_settings.encoder = vp9_encoder_.get();
philipel0f9af012015-09-01 07:01:51 -07002150 send_config->encoder_settings.payload_name = "VP9";
2151 send_config->encoder_settings.payload_type = kVp9PayloadType;
stefanff483612015-12-21 03:14:00 -08002152 ModifyVideoConfigsHook(send_config, receive_configs, encoder_config);
Åsa Perssonff24c042015-12-04 10:58:08 +01002153 EXPECT_EQ(1u, encoder_config->streams.size());
2154 encoder_config->streams[0].temporal_layer_thresholds_bps.resize(
2155 vp9_settings_.numberOfTemporalLayers - 1);
2156 encoder_config_ = *encoder_config;
philipel0f9af012015-09-01 07:01:51 -07002157 }
2158
2159 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01002160 EXPECT_TRUE(Wait()) << "Test timed out waiting for VP9 packet, num frames "
2161 << frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07002162 }
2163
2164 Action OnSendRtp(const uint8_t* packet, size_t length) override {
2165 RTPHeader header;
2166 EXPECT_TRUE(parser_->Parse(packet, length, &header));
2167
Åsa Perssonff24c042015-12-04 10:58:08 +01002168 EXPECT_EQ(kVp9PayloadType, header.payloadType);
2169 const uint8_t* payload = packet + header.headerLength;
2170 size_t payload_length = length - header.headerLength - header.paddingLength;
philipel0f9af012015-09-01 07:01:51 -07002171
Åsa Perssonff24c042015-12-04 10:58:08 +01002172 bool new_packet = packets_sent_ == 0 ||
2173 IsNewerSequenceNumber(header.sequenceNumber,
2174 last_header_.sequenceNumber);
2175 if (payload_length > 0 && new_packet) {
2176 RtpDepacketizer::ParsedPayload parsed;
2177 RtpDepacketizerVp9 depacketizer;
2178 EXPECT_TRUE(depacketizer.Parse(&parsed, payload, payload_length));
2179 EXPECT_EQ(RtpVideoCodecTypes::kRtpVideoVp9, parsed.type.Video.codec);
2180 // Verify common fields for all configurations.
2181 VerifyCommonHeader(parsed.type.Video.codecHeader.VP9);
2182 CompareConsecutiveFrames(header, parsed.type.Video);
2183 // Verify configuration specific settings.
2184 InspectHeader(parsed.type.Video.codecHeader.VP9);
philipel0f9af012015-09-01 07:01:51 -07002185
Åsa Perssonff24c042015-12-04 10:58:08 +01002186 ++packets_sent_;
2187 if (header.markerBit) {
2188 ++frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07002189 }
Åsa Perssonff24c042015-12-04 10:58:08 +01002190 last_header_ = header;
2191 last_vp9_ = parsed.type.Video.codecHeader.VP9;
philipel0f9af012015-09-01 07:01:51 -07002192 }
philipel0f9af012015-09-01 07:01:51 -07002193 return SEND_PACKET;
2194 }
2195
philipel7fabd462015-09-03 04:42:32 -07002196 protected:
Åsa Perssonff24c042015-12-04 10:58:08 +01002197 bool ContinuousPictureId(const RTPVideoHeaderVP9& vp9) const {
2198 if (last_vp9_.picture_id > vp9.picture_id) {
2199 return vp9.picture_id == 0; // Wrap.
2200 } else {
2201 return vp9.picture_id == last_vp9_.picture_id + 1;
2202 }
2203 }
2204
2205 void VerifySpatialIdxWithinFrame(const RTPVideoHeaderVP9& vp9) const {
Åsa Perssonff24c042015-12-04 10:58:08 +01002206 bool new_layer = vp9.spatial_idx != last_vp9_.spatial_idx;
2207 EXPECT_EQ(new_layer, vp9.beginning_of_frame);
2208 EXPECT_EQ(new_layer, last_vp9_.end_of_frame);
2209 EXPECT_EQ(new_layer ? last_vp9_.spatial_idx + 1 : last_vp9_.spatial_idx,
2210 vp9.spatial_idx);
2211 }
2212
2213 void VerifyFixedTemporalLayerStructure(const RTPVideoHeaderVP9& vp9,
2214 uint8_t num_layers) const {
2215 switch (num_layers) {
2216 case 0:
2217 VerifyTemporalLayerStructure0(vp9);
2218 break;
2219 case 1:
2220 VerifyTemporalLayerStructure1(vp9);
2221 break;
2222 case 2:
2223 VerifyTemporalLayerStructure2(vp9);
2224 break;
2225 case 3:
2226 VerifyTemporalLayerStructure3(vp9);
2227 break;
2228 default:
2229 RTC_NOTREACHED();
2230 }
2231 }
2232
2233 void VerifyTemporalLayerStructure0(const RTPVideoHeaderVP9& vp9) const {
2234 EXPECT_EQ(kNoTl0PicIdx, vp9.tl0_pic_idx);
2235 EXPECT_EQ(kNoTemporalIdx, vp9.temporal_idx); // no tid
2236 EXPECT_FALSE(vp9.temporal_up_switch);
2237 }
2238
2239 void VerifyTemporalLayerStructure1(const RTPVideoHeaderVP9& vp9) const {
2240 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
2241 EXPECT_EQ(0, vp9.temporal_idx); // 0,0,0,...
2242 EXPECT_FALSE(vp9.temporal_up_switch);
2243 }
2244
2245 void VerifyTemporalLayerStructure2(const RTPVideoHeaderVP9& vp9) const {
2246 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
2247 EXPECT_GE(vp9.temporal_idx, 0); // 0,1,0,1,... (tid reset on I-frames).
2248 EXPECT_LE(vp9.temporal_idx, 1);
2249 EXPECT_EQ(vp9.temporal_idx > 0, vp9.temporal_up_switch);
2250 if (IsNewPictureId(vp9)) {
2251 uint8_t expected_tid =
2252 (!vp9.inter_pic_predicted || last_vp9_.temporal_idx == 1) ? 0 : 1;
2253 EXPECT_EQ(expected_tid, vp9.temporal_idx);
2254 }
2255 }
2256
2257 void VerifyTemporalLayerStructure3(const RTPVideoHeaderVP9& vp9) const {
2258 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
2259 EXPECT_GE(vp9.temporal_idx, 0); // 0,2,1,2,... (tid reset on I-frames).
2260 EXPECT_LE(vp9.temporal_idx, 2);
2261 if (IsNewPictureId(vp9) && vp9.inter_pic_predicted) {
2262 EXPECT_NE(vp9.temporal_idx, last_vp9_.temporal_idx);
2263 switch (vp9.temporal_idx) {
2264 case 0:
2265 EXPECT_EQ(2, last_vp9_.temporal_idx);
2266 EXPECT_FALSE(vp9.temporal_up_switch);
2267 break;
2268 case 1:
2269 EXPECT_EQ(2, last_vp9_.temporal_idx);
2270 EXPECT_TRUE(vp9.temporal_up_switch);
2271 break;
2272 case 2:
2273 EXPECT_EQ(last_vp9_.temporal_idx == 0, vp9.temporal_up_switch);
2274 break;
2275 }
2276 }
2277 }
2278
2279 void VerifyTl0Idx(const RTPVideoHeaderVP9& vp9) const {
2280 if (vp9.tl0_pic_idx == kNoTl0PicIdx)
2281 return;
2282
2283 uint8_t expected_tl0_idx = last_vp9_.tl0_pic_idx;
2284 if (vp9.temporal_idx == 0)
2285 ++expected_tl0_idx;
2286 EXPECT_EQ(expected_tl0_idx, vp9.tl0_pic_idx);
2287 }
2288
2289 bool IsNewPictureId(const RTPVideoHeaderVP9& vp9) const {
2290 return frames_sent_ > 0 && (vp9.picture_id != last_vp9_.picture_id);
2291 }
2292
2293 // Flexible mode (F=1): Non-flexible mode (F=0):
2294 //
2295 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2296 // |I|P|L|F|B|E|V|-| |I|P|L|F|B|E|V|-|
2297 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2298 // I: |M| PICTURE ID | I: |M| PICTURE ID |
2299 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2300 // M: | EXTENDED PID | M: | EXTENDED PID |
2301 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2302 // L: | T |U| S |D| L: | T |U| S |D|
2303 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2304 // P,F: | P_DIFF |X|N| | TL0PICIDX |
2305 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2306 // X: |EXTENDED P_DIFF| V: | SS .. |
2307 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2308 // V: | SS .. |
2309 // +-+-+-+-+-+-+-+-+
2310 void VerifyCommonHeader(const RTPVideoHeaderVP9& vp9) const {
2311 EXPECT_EQ(kMaxTwoBytePictureId, vp9.max_picture_id); // M:1
2312 EXPECT_NE(kNoPictureId, vp9.picture_id); // I:1
2313 EXPECT_EQ(vp9_settings_.flexibleMode, vp9.flexible_mode); // F
2314 EXPECT_GE(vp9.spatial_idx, 0); // S
2315 EXPECT_LT(vp9.spatial_idx, vp9_settings_.numberOfSpatialLayers);
2316 if (vp9.ss_data_available) // V
2317 VerifySsData(vp9);
2318
2319 if (frames_sent_ == 0)
2320 EXPECT_FALSE(vp9.inter_pic_predicted); // P
2321
2322 if (!vp9.inter_pic_predicted) {
2323 EXPECT_TRUE(vp9.temporal_idx == 0 || vp9.temporal_idx == kNoTemporalIdx);
2324 EXPECT_FALSE(vp9.temporal_up_switch);
2325 }
2326 }
2327
2328 // Scalability structure (SS).
2329 //
2330 // +-+-+-+-+-+-+-+-+
2331 // V: | N_S |Y|G|-|-|-|
2332 // +-+-+-+-+-+-+-+-+
2333 // Y: | WIDTH | N_S + 1 times
2334 // +-+-+-+-+-+-+-+-+
2335 // | HEIGHT |
2336 // +-+-+-+-+-+-+-+-+
2337 // G: | N_G |
2338 // +-+-+-+-+-+-+-+-+
2339 // N_G: | T |U| R |-|-| N_G times
2340 // +-+-+-+-+-+-+-+-+
2341 // | P_DIFF | R times
2342 // +-+-+-+-+-+-+-+-+
2343 void VerifySsData(const RTPVideoHeaderVP9& vp9) const {
2344 EXPECT_TRUE(vp9.ss_data_available); // V
2345 EXPECT_EQ(vp9_settings_.numberOfSpatialLayers, // N_S + 1
2346 vp9.num_spatial_layers);
2347 EXPECT_TRUE(vp9.spatial_layer_resolution_present); // Y:1
2348 size_t expected_width = encoder_config_.streams[0].width;
2349 size_t expected_height = encoder_config_.streams[0].height;
Peter Boström02083222016-06-14 12:52:54 +02002350 for (int i = static_cast<int>(vp9.num_spatial_layers) - 1; i >= 0; --i) {
Åsa Perssonff24c042015-12-04 10:58:08 +01002351 EXPECT_EQ(expected_width, vp9.width[i]); // WIDTH
2352 EXPECT_EQ(expected_height, vp9.height[i]); // HEIGHT
2353 expected_width /= 2;
2354 expected_height /= 2;
2355 }
2356 }
2357
2358 void CompareConsecutiveFrames(const RTPHeader& header,
2359 const RTPVideoHeader& video) const {
2360 const RTPVideoHeaderVP9& vp9 = video.codecHeader.VP9;
2361
2362 bool new_frame = packets_sent_ == 0 ||
2363 IsNewerTimestamp(header.timestamp, last_header_.timestamp);
2364 EXPECT_EQ(new_frame, video.isFirstPacket);
2365 if (!new_frame) {
2366 EXPECT_FALSE(last_header_.markerBit);
2367 EXPECT_EQ(last_header_.timestamp, header.timestamp);
2368 EXPECT_EQ(last_vp9_.picture_id, vp9.picture_id);
2369 EXPECT_EQ(last_vp9_.temporal_idx, vp9.temporal_idx);
2370 EXPECT_EQ(last_vp9_.tl0_pic_idx, vp9.tl0_pic_idx);
2371 VerifySpatialIdxWithinFrame(vp9);
2372 return;
2373 }
2374 // New frame.
2375 EXPECT_TRUE(vp9.beginning_of_frame);
2376
2377 // Compare with last packet in previous frame.
2378 if (frames_sent_ == 0)
2379 return;
2380 EXPECT_TRUE(last_vp9_.end_of_frame);
2381 EXPECT_TRUE(last_header_.markerBit);
2382 EXPECT_TRUE(ContinuousPictureId(vp9));
2383 VerifyTl0Idx(vp9);
2384 }
2385
kwiberg27f982b2016-03-01 11:52:33 -08002386 std::unique_ptr<VP9Encoder> vp9_encoder_;
philipel0f9af012015-09-01 07:01:51 -07002387 VideoCodecVP9 vp9_settings_;
Åsa Perssonff24c042015-12-04 10:58:08 +01002388 webrtc::VideoEncoderConfig encoder_config_;
2389 RTPHeader last_header_;
2390 RTPVideoHeaderVP9 last_vp9_;
2391 size_t packets_sent_;
2392 size_t frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07002393};
2394
Åsa Perssonff24c042015-12-04 10:58:08 +01002395TEST_F(VideoSendStreamTest, Vp9NonFlexMode_1Tl1SLayers) {
2396 const uint8_t kNumTemporalLayers = 1;
2397 const uint8_t kNumSpatialLayers = 1;
2398 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2399}
2400
2401TEST_F(VideoSendStreamTest, Vp9NonFlexMode_2Tl1SLayers) {
2402 const uint8_t kNumTemporalLayers = 2;
2403 const uint8_t kNumSpatialLayers = 1;
2404 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2405}
2406
2407TEST_F(VideoSendStreamTest, Vp9NonFlexMode_3Tl1SLayers) {
2408 const uint8_t kNumTemporalLayers = 3;
2409 const uint8_t kNumSpatialLayers = 1;
2410 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2411}
2412
2413TEST_F(VideoSendStreamTest, Vp9NonFlexMode_1Tl2SLayers) {
2414 const uint8_t kNumTemporalLayers = 1;
2415 const uint8_t kNumSpatialLayers = 2;
2416 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2417}
2418
2419TEST_F(VideoSendStreamTest, Vp9NonFlexMode_2Tl2SLayers) {
2420 const uint8_t kNumTemporalLayers = 2;
2421 const uint8_t kNumSpatialLayers = 2;
2422 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2423}
2424
2425TEST_F(VideoSendStreamTest, Vp9NonFlexMode_3Tl2SLayers) {
2426 const uint8_t kNumTemporalLayers = 3;
2427 const uint8_t kNumSpatialLayers = 2;
2428 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2429}
2430
2431void VideoSendStreamTest::TestVp9NonFlexMode(uint8_t num_temporal_layers,
2432 uint8_t num_spatial_layers) {
2433 static const size_t kNumFramesToSend = 100;
2434 // Set to < kNumFramesToSend and coprime to length of temporal layer
2435 // structures to verify temporal id reset on key frame.
2436 static const int kKeyFrameInterval = 31;
2437 class NonFlexibleMode : public Vp9HeaderObserver {
2438 public:
2439 NonFlexibleMode(uint8_t num_temporal_layers, uint8_t num_spatial_layers)
2440 : num_temporal_layers_(num_temporal_layers),
2441 num_spatial_layers_(num_spatial_layers),
2442 l_field_(num_temporal_layers > 1 || num_spatial_layers > 1) {}
stefanff483612015-12-21 03:14:00 -08002443 void ModifyVideoConfigsHook(
philipel0f9af012015-09-01 07:01:51 -07002444 VideoSendStream::Config* send_config,
2445 std::vector<VideoReceiveStream::Config>* receive_configs,
2446 VideoEncoderConfig* encoder_config) override {
Åsa Perssonff24c042015-12-04 10:58:08 +01002447 vp9_settings_.flexibleMode = false;
2448 vp9_settings_.frameDroppingOn = false;
2449 vp9_settings_.keyFrameInterval = kKeyFrameInterval;
2450 vp9_settings_.numberOfTemporalLayers = num_temporal_layers_;
2451 vp9_settings_.numberOfSpatialLayers = num_spatial_layers_;
philipel0f9af012015-09-01 07:01:51 -07002452 }
2453
Åsa Perssonff24c042015-12-04 10:58:08 +01002454 void InspectHeader(const RTPVideoHeaderVP9& vp9) override {
2455 bool ss_data_expected = !vp9.inter_pic_predicted &&
2456 vp9.beginning_of_frame && vp9.spatial_idx == 0;
2457 EXPECT_EQ(ss_data_expected, vp9.ss_data_available);
2458 EXPECT_EQ(vp9.spatial_idx > 0, vp9.inter_layer_predicted); // D
asapersson38bb8ad2015-12-14 01:41:19 -08002459 EXPECT_EQ(!vp9.inter_pic_predicted,
2460 frames_sent_ % kKeyFrameInterval == 0);
Åsa Perssonff24c042015-12-04 10:58:08 +01002461
2462 if (IsNewPictureId(vp9)) {
2463 EXPECT_EQ(0, vp9.spatial_idx);
2464 EXPECT_EQ(num_spatial_layers_ - 1, last_vp9_.spatial_idx);
2465 }
2466
2467 VerifyFixedTemporalLayerStructure(vp9,
2468 l_field_ ? num_temporal_layers_ : 0);
2469
2470 if (frames_sent_ > kNumFramesToSend)
Peter Boström5811a392015-12-10 13:02:50 +01002471 observation_complete_.Set();
philipel0f9af012015-09-01 07:01:51 -07002472 }
Åsa Perssonff24c042015-12-04 10:58:08 +01002473 const uint8_t num_temporal_layers_;
2474 const uint8_t num_spatial_layers_;
2475 const bool l_field_;
2476 } test(num_temporal_layers, num_spatial_layers);
philipelcfc319b2015-11-10 07:17:23 -08002477
stefane74eef12016-01-08 06:47:13 -08002478 RunBaseTest(&test);
philipelcfc319b2015-11-10 07:17:23 -08002479}
2480
asaperssond9f641e2016-01-21 01:11:35 -08002481TEST_F(VideoSendStreamTest, Vp9NonFlexModeSmallResolution) {
2482 static const size_t kNumFramesToSend = 50;
2483 static const int kWidth = 4;
2484 static const int kHeight = 4;
2485 class NonFlexibleModeResolution : public Vp9HeaderObserver {
2486 void ModifyVideoConfigsHook(
2487 VideoSendStream::Config* send_config,
2488 std::vector<VideoReceiveStream::Config>* receive_configs,
2489 VideoEncoderConfig* encoder_config) override {
2490 vp9_settings_.flexibleMode = false;
2491 vp9_settings_.numberOfTemporalLayers = 1;
2492 vp9_settings_.numberOfSpatialLayers = 1;
2493
2494 EXPECT_EQ(1u, encoder_config->streams.size());
2495 encoder_config->streams[0].width = kWidth;
2496 encoder_config->streams[0].height = kHeight;
2497 }
2498
2499 void InspectHeader(const RTPVideoHeaderVP9& vp9_header) override {
2500 if (frames_sent_ > kNumFramesToSend)
2501 observation_complete_.Set();
2502 }
2503 } test;
2504
2505 RunBaseTest(&test);
2506}
2507
Åsa Perssonff24c042015-12-04 10:58:08 +01002508TEST_F(VideoSendStreamTest, Vp9FlexModeRefCount) {
2509 class FlexibleMode : public Vp9HeaderObserver {
stefanff483612015-12-21 03:14:00 -08002510 void ModifyVideoConfigsHook(
philipelcfc319b2015-11-10 07:17:23 -08002511 VideoSendStream::Config* send_config,
2512 std::vector<VideoReceiveStream::Config>* receive_configs,
2513 VideoEncoderConfig* encoder_config) override {
Åsa Perssonff24c042015-12-04 10:58:08 +01002514 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
philipelcfc319b2015-11-10 07:17:23 -08002515 vp9_settings_.flexibleMode = true;
Åsa Perssonff24c042015-12-04 10:58:08 +01002516 vp9_settings_.numberOfTemporalLayers = 1;
2517 vp9_settings_.numberOfSpatialLayers = 2;
philipelcfc319b2015-11-10 07:17:23 -08002518 }
2519
Åsa Perssonff24c042015-12-04 10:58:08 +01002520 void InspectHeader(const RTPVideoHeaderVP9& vp9_header) override {
2521 EXPECT_TRUE(vp9_header.flexible_mode);
2522 EXPECT_EQ(kNoTl0PicIdx, vp9_header.tl0_pic_idx);
2523 if (vp9_header.inter_pic_predicted) {
2524 EXPECT_GT(vp9_header.num_ref_pics, 0u);
Peter Boström5811a392015-12-10 13:02:50 +01002525 observation_complete_.Set();
philipelcfc319b2015-11-10 07:17:23 -08002526 }
2527 }
2528 } test;
2529
stefane74eef12016-01-08 06:47:13 -08002530 RunBaseTest(&test);
philipelcfc319b2015-11-10 07:17:23 -08002531}
Peter Boström12996152016-05-14 02:03:18 +02002532#endif // !defined(RTC_DISABLE_VP9)
philipelcfc319b2015-11-10 07:17:23 -08002533
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +00002534} // namespace webrtc