blob: 57a3420e4590943ff463258ba32c0ee0cb92e3d8 [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"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000022#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020023#include "webrtc/call/transport_adapter.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000024#include "webrtc/frame_callback.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010025#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
26#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000027#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
pbos@webrtc.org013d9942013-08-22 09:42:17 +000028#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
philipel0f9af012015-09-01 07:01:51 -070029#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h"
philipel7fabd462015-09-03 04:42:32 -070030#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010031#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000032#include "webrtc/test/call_test.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000033#include "webrtc/test/configurable_frame_size_encoder.h"
Peter Boströmeb66e802015-06-05 11:08:03 +020034#include "webrtc/test/fake_texture_frame.h"
nisse26acec42016-04-15 03:43:39 -070035#include "webrtc/test/frame_utils.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000036#include "webrtc/test/null_transport.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000037#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.org273a4142014-12-01 15:23:21 +000038#include "webrtc/video/send_statistics_proxy.h"
Thiago Farina9bfe3da2015-04-10 12:52:13 +020039#include "webrtc/video_frame.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000040#include "webrtc/video_send_stream.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000041
42namespace webrtc {
43
sprang@webrtc.org346094c2014-02-18 08:40:33 +000044enum VideoFormat { kGeneric, kVP8, };
45
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070046void ExpectEqualFramesVector(const std::vector<VideoFrame>& frames1,
47 const std::vector<VideoFrame>& frames2);
48VideoFrame CreateVideoFrame(int width, int height, uint8_t data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000049
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000050class VideoSendStreamTest : public test::CallTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000051 protected:
stefan@webrtc.org69969e22013-11-15 12:32:15 +000052 void TestNackRetransmission(uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +000053 uint8_t retransmit_payload_type);
sprang@webrtc.org346094c2014-02-18 08:40:33 +000054 void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
Åsa Perssonff24c042015-12-04 10:58:08 +010055
56 void TestVp9NonFlexMode(uint8_t num_temporal_layers,
57 uint8_t num_spatial_layers);
pbos@webrtc.org013d9942013-08-22 09:42:17 +000058};
59
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000060TEST_F(VideoSendStreamTest, CanStartStartedStream) {
solenberg4fbae2b2015-08-28 04:07:10 -070061 Call::Config call_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000062 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000063
solenberg4fbae2b2015-08-28 04:07:10 -070064 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +010065 CreateSendConfig(1, 0, &transport);
66 CreateVideoStreams();
stefanff483612015-12-21 03:14:00 -080067 video_send_stream_->Start();
68 video_send_stream_->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000069 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000070}
71
72TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
solenberg4fbae2b2015-08-28 04:07:10 -070073 Call::Config call_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000074 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000075
solenberg4fbae2b2015-08-28 04:07:10 -070076 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +010077 CreateSendConfig(1, 0, &transport);
78 CreateVideoStreams();
stefanff483612015-12-21 03:14:00 -080079 video_send_stream_->Stop();
80 video_send_stream_->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000081 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000082}
83
pbos@webrtc.org013d9942013-08-22 09:42:17 +000084TEST_F(VideoSendStreamTest, SupportsCName) {
85 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000086 class CNameObserver : public test::SendTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000087 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000088 CNameObserver() : SendTest(kDefaultTimeoutMs) {}
pbos@webrtc.org013d9942013-08-22 09:42:17 +000089
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000090 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000091 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000092 RTCPUtility::RTCPParserV2 parser(packet, length, true);
93 EXPECT_TRUE(parser.IsValid());
94
95 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +020096 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
97 if (packet_type == RTCPUtility::RTCPPacketTypes::kSdesChunk) {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000098 EXPECT_EQ(parser.Packet().CName.CName, kCName);
Peter Boström5811a392015-12-10 13:02:50 +010099 observation_complete_.Set();
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000100 }
101
102 packet_type = parser.Iterate();
103 }
104
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000105 return SEND_PACKET;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000106 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000107
stefanff483612015-12-21 03:14:00 -0800108 void ModifyVideoConfigs(
109 VideoSendStream::Config* send_config,
110 std::vector<VideoReceiveStream::Config>* receive_configs,
111 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000112 send_config->rtp.c_name = kCName;
113 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000114
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000115 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100116 EXPECT_TRUE(Wait()) << "Timed out while waiting for RTCP with CNAME.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000117 }
118 } test;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000119
stefane74eef12016-01-08 06:47:13 -0800120 RunBaseTest(&test);
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000121}
122
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000123TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000124 class AbsoluteSendTimeObserver : public test::SendTest {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000125 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000126 AbsoluteSendTimeObserver() : SendTest(kDefaultTimeoutMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000127 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
Stefan Holmer4654d202015-12-08 09:10:43 +0100128 kRtpExtensionAbsoluteSendTime, test::kAbsSendTimeExtensionId));
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000129 }
130
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000131 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000132 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000133 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000134
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000135 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
136 EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
137 EXPECT_EQ(header.extension.transmissionTimeOffset, 0);
138 EXPECT_GT(header.extension.absoluteSendTime, 0u);
Peter Boström5811a392015-12-10 13:02:50 +0100139 observation_complete_.Set();
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000140
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000141 return SEND_PACKET;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000142 }
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000143
stefanff483612015-12-21 03:14:00 -0800144 void ModifyVideoConfigs(
145 VideoSendStream::Config* send_config,
146 std::vector<VideoReceiveStream::Config>* receive_configs,
147 VideoEncoderConfig* encoder_config) override {
Erik Språng95261872015-04-10 11:58:49 +0200148 send_config->rtp.extensions.clear();
Stefan Holmer4654d202015-12-08 09:10:43 +0100149 send_config->rtp.extensions.push_back(RtpExtension(
150 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000151 }
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +0000152
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000153 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100154 EXPECT_TRUE(Wait()) << "Timed out while waiting for single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000155 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000156 } test;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000157
stefane74eef12016-01-08 06:47:13 -0800158 RunBaseTest(&test);
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000159}
160
pbos@webrtc.org29023282013-09-11 10:14:56 +0000161TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000162 static const int kEncodeDelayMs = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000163 class TransmissionTimeOffsetObserver : public test::SendTest {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000164 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000165 TransmissionTimeOffsetObserver()
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000166 : SendTest(kDefaultTimeoutMs),
167 encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000168 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
Stefan Holmer12952972015-10-29 15:13:24 +0100169 kRtpExtensionTransmissionTimeOffset, test::kTOffsetExtensionId));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000170 }
171
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000172 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000173 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000174 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000175 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000176
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000177 EXPECT_TRUE(header.extension.hasTransmissionTimeOffset);
178 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000179 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000180 EXPECT_EQ(header.extension.absoluteSendTime, 0u);
Peter Boström5811a392015-12-10 13:02:50 +0100181 observation_complete_.Set();
pbos@webrtc.org29023282013-09-11 10:14:56 +0000182
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000183 return SEND_PACKET;
pbos@webrtc.org29023282013-09-11 10:14:56 +0000184 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000185
stefanff483612015-12-21 03:14:00 -0800186 void ModifyVideoConfigs(
187 VideoSendStream::Config* send_config,
188 std::vector<VideoReceiveStream::Config>* receive_configs,
189 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000190 send_config->encoder_settings.encoder = &encoder_;
Stefan Holmer12952972015-10-29 15:13:24 +0100191 send_config->rtp.extensions.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000192 send_config->rtp.extensions.push_back(
Stefan Holmer12952972015-10-29 15:13:24 +0100193 RtpExtension(RtpExtension::kTOffset, test::kTOffsetExtensionId));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000194 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000195
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000196 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100197 EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000198 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000199
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000200 test::DelayedEncoder encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000201 } test;
202
stefane74eef12016-01-08 06:47:13 -0800203 RunBaseTest(&test);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000204}
205
sprang867fb522015-08-03 04:38:41 -0700206TEST_F(VideoSendStreamTest, SupportsTransportWideSequenceNumbers) {
207 static const uint8_t kExtensionId = 13;
208 class TransportWideSequenceNumberObserver : public test::SendTest {
209 public:
210 TransportWideSequenceNumberObserver()
211 : SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) {
212 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
213 kRtpExtensionTransportSequenceNumber, kExtensionId));
214 }
215
216 private:
217 Action OnSendRtp(const uint8_t* packet, size_t length) override {
218 RTPHeader header;
219 EXPECT_TRUE(parser_->Parse(packet, length, &header));
220
221 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
222 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
223 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
224
Peter Boström5811a392015-12-10 13:02:50 +0100225 observation_complete_.Set();
sprang867fb522015-08-03 04:38:41 -0700226
227 return SEND_PACKET;
228 }
229
stefanff483612015-12-21 03:14:00 -0800230 void ModifyVideoConfigs(
231 VideoSendStream::Config* send_config,
232 std::vector<VideoReceiveStream::Config>* receive_configs,
233 VideoEncoderConfig* encoder_config) override {
sprang867fb522015-08-03 04:38:41 -0700234 send_config->encoder_settings.encoder = &encoder_;
Stefan Holmer12952972015-10-29 15:13:24 +0100235 send_config->rtp.extensions.clear();
sprang867fb522015-08-03 04:38:41 -0700236 send_config->rtp.extensions.push_back(
237 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
238 }
239
240 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100241 EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
sprang867fb522015-08-03 04:38:41 -0700242 }
243
244 test::FakeEncoder encoder_;
245 } test;
246
stefane74eef12016-01-08 06:47:13 -0800247 RunBaseTest(&test);
sprang867fb522015-08-03 04:38:41 -0700248}
249
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000250class FakeReceiveStatistics : public NullReceiveStatistics {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000251 public:
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000252 FakeReceiveStatistics(uint32_t send_ssrc,
253 uint32_t last_sequence_number,
254 uint32_t cumulative_lost,
255 uint8_t fraction_lost)
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000256 : lossy_stats_(new LossyStatistician(last_sequence_number,
257 cumulative_lost,
258 fraction_lost)) {
259 stats_map_[send_ssrc] = lossy_stats_.get();
260 }
261
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000262 StatisticianMap GetActiveStatisticians() const override { return stats_map_; }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000263
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000264 StreamStatistician* GetStatistician(uint32_t ssrc) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000265 return lossy_stats_.get();
266 }
267
268 private:
269 class LossyStatistician : public StreamStatistician {
270 public:
271 LossyStatistician(uint32_t extended_max_sequence_number,
272 uint32_t cumulative_lost,
273 uint8_t fraction_lost) {
274 stats_.fraction_lost = fraction_lost;
275 stats_.cumulative_lost = cumulative_lost;
276 stats_.extended_max_sequence_number = extended_max_sequence_number;
277 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000278 bool GetStatistics(RtcpStatistics* statistics, bool reset) override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000279 *statistics = stats_;
280 return true;
281 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000282 void GetDataCounters(size_t* bytes_received,
283 uint32_t* packets_received) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000284 *bytes_received = 0;
285 *packets_received = 0;
286 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000287 void GetReceiveStreamDataCounters(
288 StreamDataCounters* data_counters) const override {}
289 uint32_t BitrateReceived() const override { return 0; }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000290 bool IsRetransmitOfOldPacket(const RTPHeader& header,
291 int64_t min_rtt) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000292 return false;
293 }
294
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000295 bool IsPacketInOrder(uint16_t sequence_number) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000296 return true;
297 }
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000298
299 RtcpStatistics stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000300 };
301
kwiberg27f982b2016-03-01 11:52:33 -0800302 std::unique_ptr<LossyStatistician> lossy_stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000303 StatisticianMap stats_map_;
304};
305
Peter Boström39593972016-02-15 11:27:15 +0100306class FecObserver : public test::EndToEndTest {
Stefan Holmer4654d202015-12-08 09:10:43 +0100307 public:
Peter Boström39593972016-02-15 11:27:15 +0100308 FecObserver(bool header_extensions_enabled,
309 bool use_nack,
310 bool expect_red,
311 const std::string& codec)
312 : EndToEndTest(VideoSendStreamTest::kDefaultTimeoutMs),
313 payload_name_(codec),
314 use_nack_(use_nack),
315 expect_red_(expect_red),
Stefan Holmer4654d202015-12-08 09:10:43 +0100316 send_count_(0),
317 received_media_(false),
318 received_fec_(false),
Peter Boström39593972016-02-15 11:27:15 +0100319 header_extensions_enabled_(header_extensions_enabled) {
320 if (codec == "H264") {
321 encoder_.reset(new test::FakeH264Encoder(Clock::GetRealTimeClock()));
322 } else if (codec == "VP8") {
323 encoder_.reset(VideoEncoder::Create(VideoEncoder::EncoderType::kVp8));
324 } else if (codec == "VP9") {
325 encoder_.reset(VideoEncoder::Create(VideoEncoder::EncoderType::kVp9));
326 } else {
327 RTC_NOTREACHED();
328 }
329 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100330
331 private:
332 Action OnSendRtp(const uint8_t* packet, size_t length) override {
333 RTPHeader header;
334 EXPECT_TRUE(parser_->Parse(packet, length, &header));
335
Peter Boström39593972016-02-15 11:27:15 +0100336 ++send_count_;
Stefan Holmer4654d202015-12-08 09:10:43 +0100337 int encapsulated_payload_type = -1;
338 if (header.payloadType == VideoSendStreamTest::kRedPayloadType) {
Peter Boström39593972016-02-15 11:27:15 +0100339 EXPECT_TRUE(expect_red_);
Stefan Holmer4654d202015-12-08 09:10:43 +0100340 encapsulated_payload_type = static_cast<int>(packet[header.headerLength]);
341 if (encapsulated_payload_type !=
Peter Boström39593972016-02-15 11:27:15 +0100342 VideoSendStreamTest::kFakeVideoSendPayloadType) {
Stefan Holmer4654d202015-12-08 09:10:43 +0100343 EXPECT_EQ(VideoSendStreamTest::kUlpfecPayloadType,
344 encapsulated_payload_type);
Peter Boström39593972016-02-15 11:27:15 +0100345 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100346 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100347 EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType,
348 header.payloadType);
Peter Boström39593972016-02-15 11:27:15 +0100349 if (static_cast<size_t>(header.headerLength + header.paddingLength) <
350 length) {
351 // Not padding-only, media received outside of RED.
352 EXPECT_FALSE(expect_red_);
353 received_media_ = true;
354 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100355 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000356
Stefan Holmer4654d202015-12-08 09:10:43 +0100357 if (header_extensions_enabled_) {
358 EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
359 uint32_t kHalf24BitsSpace = 0xFFFFFF / 2;
360 if (header.extension.absoluteSendTime <= kHalf24BitsSpace &&
361 prev_header_.extension.absoluteSendTime > kHalf24BitsSpace) {
362 // 24 bits wrap.
363 EXPECT_GT(prev_header_.extension.absoluteSendTime,
364 header.extension.absoluteSendTime);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000365 } else {
Stefan Holmer4654d202015-12-08 09:10:43 +0100366 EXPECT_GE(header.extension.absoluteSendTime,
367 prev_header_.extension.absoluteSendTime);
Stefan Holmer01b48882015-05-05 10:21:24 +0200368 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100369 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
370 uint16_t seq_num_diff = header.extension.transportSequenceNumber -
371 prev_header_.extension.transportSequenceNumber;
372 EXPECT_EQ(1, seq_num_diff);
373 }
Stefan Holmer01b48882015-05-05 10:21:24 +0200374
Stefan Holmer4654d202015-12-08 09:10:43 +0100375 if (encapsulated_payload_type != -1) {
376 if (encapsulated_payload_type ==
377 VideoSendStreamTest::kUlpfecPayloadType) {
378 received_fec_ = true;
379 } else {
380 received_media_ = true;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000381 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000382 }
383
Peter Boström39593972016-02-15 11:27:15 +0100384 if (send_count_ > 100 && received_media_) {
385 if (received_fec_ || !expect_red_)
386 observation_complete_.Set();
387 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000388
Stefan Holmer4654d202015-12-08 09:10:43 +0100389 prev_header_ = header;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000390
Stefan Holmer4654d202015-12-08 09:10:43 +0100391 return SEND_PACKET;
392 }
393
Peter Boström39593972016-02-15 11:27:15 +0100394 test::PacketTransport* CreateSendTransport(Call* sender_call) override {
395 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
396 // Configure some network delay.
397 const int kNetworkDelayMs = 100;
398 FakeNetworkPipe::Config config;
399 config.loss_percent = 50;
400 config.queue_delay_ms = kNetworkDelayMs;
401 return new test::PacketTransport(sender_call, this,
402 test::PacketTransport::kSender, config);
403 }
404
stefanff483612015-12-21 03:14:00 -0800405 void ModifyVideoConfigs(
406 VideoSendStream::Config* send_config,
407 std::vector<VideoReceiveStream::Config>* receive_configs,
408 VideoEncoderConfig* encoder_config) override {
Stefan Holmer4654d202015-12-08 09:10:43 +0100409 transport_adapter_.reset(
410 new internal::TransportAdapter(send_config->send_transport));
411 transport_adapter_->Enable();
Peter Boström39593972016-02-15 11:27:15 +0100412 if (use_nack_) {
413 send_config->rtp.nack.rtp_history_ms =
414 (*receive_configs)[0].rtp.nack.rtp_history_ms =
415 VideoSendStreamTest::kNackRtpHistoryMs;
416 }
417 send_config->encoder_settings.encoder = encoder_.get();
418 send_config->encoder_settings.payload_name = payload_name_;
Stefan Holmer4654d202015-12-08 09:10:43 +0100419 send_config->rtp.fec.red_payload_type =
Peter Boström39593972016-02-15 11:27:15 +0100420 VideoSendStreamTest::kRedPayloadType;
Stefan Holmer4654d202015-12-08 09:10:43 +0100421 send_config->rtp.fec.ulpfec_payload_type =
Peter Boström39593972016-02-15 11:27:15 +0100422 VideoSendStreamTest::kUlpfecPayloadType;
Stefan Holmer4654d202015-12-08 09:10:43 +0100423 if (header_extensions_enabled_) {
424 send_config->rtp.extensions.push_back(RtpExtension(
425 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId));
426 send_config->rtp.extensions.push_back(
427 RtpExtension(RtpExtension::kTransportSequenceNumber,
428 test::kTransportSequenceNumberExtensionId));
429 }
Peter Boström39593972016-02-15 11:27:15 +0100430 (*receive_configs)[0].rtp.fec.red_payload_type =
431 send_config->rtp.fec.red_payload_type;
432 (*receive_configs)[0].rtp.fec.ulpfec_payload_type =
433 send_config->rtp.fec.ulpfec_payload_type;
Stefan Holmer4654d202015-12-08 09:10:43 +0100434 }
435
436 void PerformTest() override {
437 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
438 }
439
kwiberg27f982b2016-03-01 11:52:33 -0800440 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
441 std::unique_ptr<VideoEncoder> encoder_;
Peter Boström39593972016-02-15 11:27:15 +0100442 const std::string payload_name_;
443 const bool use_nack_;
444 const bool expect_red_;
Stefan Holmer4654d202015-12-08 09:10:43 +0100445 int send_count_;
446 bool received_media_;
447 bool received_fec_;
448 bool header_extensions_enabled_;
449 RTPHeader prev_header_;
450};
451
452TEST_F(VideoSendStreamTest, SupportsFecWithExtensions) {
Peter Boström39593972016-02-15 11:27:15 +0100453 FecObserver test(true, false, true, "VP8");
stefane74eef12016-01-08 06:47:13 -0800454 RunBaseTest(&test);
Stefan Holmer4654d202015-12-08 09:10:43 +0100455}
456
457TEST_F(VideoSendStreamTest, SupportsFecWithoutExtensions) {
Peter Boström39593972016-02-15 11:27:15 +0100458 FecObserver test(false, false, true, "VP8");
459 RunBaseTest(&test);
460}
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000461
Peter Boström39593972016-02-15 11:27:15 +0100462// The FEC scheme used is not efficient for H264, so we should not use RED/FEC
463// since we'll still have to re-request FEC packets, effectively wasting
464// bandwidth since the receiver has to wait for FEC retransmissions to determine
465// that the received state is actually decodable.
466TEST_F(VideoSendStreamTest, DoesNotUtilizeRedForH264WithNackEnabled) {
467 FecObserver test(false, true, false, "H264");
468 RunBaseTest(&test);
469}
470
471// Without retransmissions FEC for H264 is fine.
472TEST_F(VideoSendStreamTest, DoesUtilizeRedForH264WithoutNackEnabled) {
473 FecObserver test(false, false, true, "H264");
474 RunBaseTest(&test);
475}
476
477TEST_F(VideoSendStreamTest, DoesUtilizeRedForVp8WithNackEnabled) {
478 FecObserver test(false, true, true, "VP8");
479 RunBaseTest(&test);
480}
481
482TEST_F(VideoSendStreamTest, DoesUtilizeRedForVp9WithNackEnabled) {
483 FecObserver test(false, true, true, "VP9");
stefane74eef12016-01-08 06:47:13 -0800484 RunBaseTest(&test);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000485}
486
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000487void VideoSendStreamTest::TestNackRetransmission(
488 uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000489 uint8_t retransmit_payload_type) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000490 class NackObserver : public test::SendTest {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000491 public:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000492 explicit NackObserver(uint32_t retransmit_ssrc,
493 uint8_t retransmit_payload_type)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000494 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000495 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000496 retransmit_ssrc_(retransmit_ssrc),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000497 retransmit_payload_type_(retransmit_payload_type),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000498 nacked_sequence_number_(-1) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000499 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000500
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000501 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000502 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000503 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000504 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000505
506 // Nack second packet after receiving the third one.
507 if (++send_count_ == 3) {
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000508 uint16_t nack_sequence_number = header.sequenceNumber - 1;
509 nacked_sequence_number_ = nack_sequence_number;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000510 NullReceiveStatistics null_stats;
Peter Boströmac547a62015-09-17 23:03:57 +0200511 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), &null_stats,
terelius429c3452016-01-21 05:42:04 -0800512 nullptr, nullptr, transport_adapter_.get());
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000513
pbosda903ea2015-10-02 02:36:56 -0700514 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100515 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000516
517 RTCPSender::FeedbackState feedback_state;
518
519 EXPECT_EQ(0,
520 rtcp_sender.SendRTCP(
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000521 feedback_state, kRtcpNack, 1, &nack_sequence_number));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000522 }
523
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000524 uint16_t sequence_number = header.sequenceNumber;
525
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000526 if (header.ssrc == retransmit_ssrc_ &&
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100527 retransmit_ssrc_ != kVideoSendSsrcs[0]) {
528 // Not kVideoSendSsrcs[0], assume correct RTX packet. Extract sequence
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000529 // number.
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000530 const uint8_t* rtx_header = packet + header.headerLength;
531 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
532 }
533
534 if (sequence_number == nacked_sequence_number_) {
535 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000536 EXPECT_EQ(retransmit_payload_type_, header.payloadType);
Peter Boström5811a392015-12-10 13:02:50 +0100537 observation_complete_.Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000538 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000539
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000540 return SEND_PACKET;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000541 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000542
stefanff483612015-12-21 03:14:00 -0800543 void ModifyVideoConfigs(
544 VideoSendStream::Config* send_config,
545 std::vector<VideoReceiveStream::Config>* receive_configs,
546 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700547 transport_adapter_.reset(
548 new internal::TransportAdapter(send_config->send_transport));
549 transport_adapter_->Enable();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000550 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000551 send_config->rtp.rtx.payload_type = retransmit_payload_type_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100552 if (retransmit_ssrc_ != kVideoSendSsrcs[0])
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000553 send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
554 }
555
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000556 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100557 EXPECT_TRUE(Wait()) << "Timed out while waiting for NACK retransmission.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000558 }
559
kwiberg27f982b2016-03-01 11:52:33 -0800560 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000561 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000562 uint32_t retransmit_ssrc_;
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000563 uint8_t retransmit_payload_type_;
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000564 int nacked_sequence_number_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000565 } test(retransmit_ssrc, retransmit_payload_type);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000566
stefane74eef12016-01-08 06:47:13 -0800567 RunBaseTest(&test);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000568}
569
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000570TEST_F(VideoSendStreamTest, RetransmitsNack) {
571 // Normal NACKs should use the send SSRC.
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100572 TestNackRetransmission(kVideoSendSsrcs[0], kFakeVideoSendPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000573}
574
575TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
576 // NACKs over RTX should use a separate SSRC.
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000577 TestNackRetransmission(kSendRtxSsrcs[0], kSendRtxPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000578}
579
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000580void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
581 bool with_fec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000582 // Use a fake encoder to output a frame of every size in the range [90, 290],
583 // for each size making sure that the exact number of payload bytes received
584 // is correct and that packets are fragmented to respect max packet size.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000585 static const size_t kMaxPacketSize = 128;
586 static const size_t start = 90;
587 static const size_t stop = 290;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000588
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000589 // Observer that verifies that the expected number of packets and bytes
590 // arrive for each frame size, from start_size to stop_size.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000591 class FrameFragmentationTest : public test::SendTest,
592 public EncodedFrameObserver {
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000593 public:
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000594 FrameFragmentationTest(size_t max_packet_size,
595 size_t start_size,
596 size_t stop_size,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000597 bool test_generic_packetization,
598 bool use_fec)
599 : SendTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000600 encoder_(stop),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000601 max_packet_size_(max_packet_size),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000602 stop_size_(stop_size),
603 test_generic_packetization_(test_generic_packetization),
604 use_fec_(use_fec),
605 packet_count_(0),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000606 accumulated_size_(0),
607 accumulated_payload_(0),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000608 fec_packet_received_(false),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000609 current_size_rtp_(start_size),
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000610 current_size_frame_(static_cast<int32_t>(start_size)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000611 // Fragmentation required, this test doesn't make sense without it.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000612 encoder_.SetFrameSize(start_size);
henrikg91d6ede2015-09-17 00:24:34 -0700613 RTC_DCHECK_GT(stop_size, max_packet_size);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000614 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000615
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000616 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000617 Action OnSendRtp(const uint8_t* packet, size_t size) override {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000618 size_t length = size;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000619 RTPHeader header;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000620 EXPECT_TRUE(parser_->Parse(packet, length, &header));
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000621
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000622 EXPECT_LE(length, max_packet_size_);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000623
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000624 if (use_fec_) {
625 uint8_t payload_type = packet[header.headerLength];
626 bool is_fec = header.payloadType == kRedPayloadType &&
627 payload_type == kUlpfecPayloadType;
628 if (is_fec) {
629 fec_packet_received_ = true;
630 return SEND_PACKET;
631 }
632 }
633
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000634 accumulated_size_ += length;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000635
636 if (use_fec_)
637 TriggerLossReport(header);
638
639 if (test_generic_packetization_) {
Stefan Holmer586b19b2015-09-18 11:14:31 +0200640 size_t overhead = header.headerLength + header.paddingLength;
641 // Only remove payload header and RED header if the packet actually
642 // contains payload.
643 if (length > overhead) {
644 overhead += (1 /* Generic header */);
645 if (use_fec_)
646 overhead += 1; // RED for FEC header.
647 }
648 EXPECT_GE(length, overhead);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000649 accumulated_payload_ += length - overhead;
650 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000651
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000652 // Marker bit set indicates last packet of a frame.
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000653 if (header.markerBit) {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000654 if (use_fec_ && accumulated_payload_ == current_size_rtp_ - 1) {
655 // With FEC enabled, frame size is incremented asynchronously, so
656 // "old" frames one byte too small may arrive. Accept, but don't
657 // increase expected frame size.
658 accumulated_size_ = 0;
659 accumulated_payload_ = 0;
660 return SEND_PACKET;
661 }
662
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000663 EXPECT_GE(accumulated_size_, current_size_rtp_);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000664 if (test_generic_packetization_) {
665 EXPECT_EQ(current_size_rtp_, accumulated_payload_);
666 }
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000667
668 // Last packet of frame; reset counters.
669 accumulated_size_ = 0;
670 accumulated_payload_ = 0;
671 if (current_size_rtp_ == stop_size_) {
672 // Done! (Don't increase size again, might arrive more @ stop_size).
Peter Boström5811a392015-12-10 13:02:50 +0100673 observation_complete_.Set();
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000674 } else {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000675 // Increase next expected frame size. If testing with FEC, make sure
676 // a FEC packet has been received for this frame size before
677 // proceeding, to make sure that redundancy packets don't exceed
678 // size limit.
679 if (!use_fec_) {
680 ++current_size_rtp_;
681 } else if (fec_packet_received_) {
682 fec_packet_received_ = false;
683 ++current_size_rtp_;
684 ++current_size_frame_;
685 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000686 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000687 }
688
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000689 return SEND_PACKET;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000690 }
691
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000692 void TriggerLossReport(const RTPHeader& header) {
693 // Send lossy receive reports to trigger FEC enabling.
694 if (packet_count_++ % 2 != 0) {
695 // Receive statistics reporting having lost 50% of the packets.
696 FakeReceiveStatistics lossy_receive_stats(
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100697 kVideoSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127);
Peter Boströmac547a62015-09-17 23:03:57 +0200698 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
terelius429c3452016-01-21 05:42:04 -0800699 &lossy_receive_stats, nullptr, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700700 transport_adapter_.get());
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000701
pbosda903ea2015-10-02 02:36:56 -0700702 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100703 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000704
705 RTCPSender::FeedbackState feedback_state;
706
707 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
708 }
709 }
710
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000711 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
712 // Increase frame size for next encoded frame, in the context of the
713 // encoder thread.
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000714 if (!use_fec_ &&
715 current_size_frame_.Value() < static_cast<int32_t>(stop_size_)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000716 ++current_size_frame_;
717 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000718 encoder_.SetFrameSize(static_cast<size_t>(current_size_frame_.Value()));
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000719 }
720
Stefan Holmere5904162015-03-26 11:11:06 +0100721 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700722 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100723 const int kMinBitrateBps = 30000;
724 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
725 return config;
726 }
727
stefanff483612015-12-21 03:14:00 -0800728 void ModifyVideoConfigs(
729 VideoSendStream::Config* send_config,
730 std::vector<VideoReceiveStream::Config>* receive_configs,
731 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700732 transport_adapter_.reset(
733 new internal::TransportAdapter(send_config->send_transport));
734 transport_adapter_->Enable();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000735 if (use_fec_) {
736 send_config->rtp.fec.red_payload_type = kRedPayloadType;
737 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
738 }
739
740 if (!test_generic_packetization_)
741 send_config->encoder_settings.payload_name = "VP8";
742
743 send_config->encoder_settings.encoder = &encoder_;
744 send_config->rtp.max_packet_size = kMaxPacketSize;
745 send_config->post_encode_callback = this;
746
Erik Språng95261872015-04-10 11:58:49 +0200747 // Make sure there is at least one extension header, to make the RTP
748 // header larger than the base length of 12 bytes.
749 EXPECT_FALSE(send_config->rtp.extensions.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000750 }
751
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000752 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100753 EXPECT_TRUE(Wait()) << "Timed out while observing incoming RTP packets.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000754 }
755
kwiberg27f982b2016-03-01 11:52:33 -0800756 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000757 test::ConfigurableFrameSizeEncoder encoder_;
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000758
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000759 const size_t max_packet_size_;
760 const size_t stop_size_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000761 const bool test_generic_packetization_;
762 const bool use_fec_;
763
764 uint32_t packet_count_;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000765 size_t accumulated_size_;
766 size_t accumulated_payload_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000767 bool fec_packet_received_;
768
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000769 size_t current_size_rtp_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000770 Atomic32 current_size_frame_;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000771 };
772
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000773 // Don't auto increment if FEC is used; continue sending frame size until
774 // a FEC packet has been received.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000775 FrameFragmentationTest test(
776 kMaxPacketSize, start, stop, format == kGeneric, with_fec);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000777
stefane74eef12016-01-08 06:47:13 -0800778 RunBaseTest(&test);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000779}
780
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000781// TODO(sprang): Is there any way of speeding up these tests?
782TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSize) {
783 TestPacketFragmentationSize(kGeneric, false);
784}
785
786TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSizeWithFec) {
787 TestPacketFragmentationSize(kGeneric, true);
788}
789
790TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSize) {
791 TestPacketFragmentationSize(kVP8, false);
792}
793
794TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSizeWithFec) {
795 TestPacketFragmentationSize(kVP8, true);
796}
797
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000798// The test will go through a number of phases.
799// 1. Start sending packets.
800// 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 +0000801// suspend the stream.
802// 3. Wait until |kSuspendTimeFrames| have been captured without seeing any RTP
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000803// packets.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000804// 4. Signal a high REMB and then wait for the RTP stream to start again.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000805// When the stream is detected again, and the stats show that the stream
806// is no longer suspended, the test ends.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000807TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
808 static const int kSuspendTimeFrames = 60; // Suspend for 2 seconds @ 30 fps.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000809
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000810 class RembObserver : public test::SendTest, public I420FrameCallback {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000811 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000812 RembObserver()
813 : SendTest(kDefaultTimeoutMs),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000814 clock_(Clock::GetRealTimeClock()),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000815 test_state_(kBeforeSuspend),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000816 rtp_count_(0),
817 last_sequence_number_(0),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000818 suspended_frame_count_(0),
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000819 low_remb_bps_(0),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000820 high_remb_bps_(0) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000821 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000822
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000823 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000824 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200825 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000826 ++rtp_count_;
827 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000828 EXPECT_TRUE(parser_->Parse(packet, length, &header));
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000829 last_sequence_number_ = header.sequenceNumber;
830
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000831 if (test_state_ == kBeforeSuspend) {
832 // The stream has started. Try to suspend it.
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000833 SendRtcpFeedback(low_remb_bps_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000834 test_state_ = kDuringSuspend;
835 } else if (test_state_ == kDuringSuspend) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000836 if (header.paddingLength == 0) {
837 // Received non-padding packet during suspension period. Reset the
838 // counter.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000839 suspended_frame_count_ = 0;
840 }
stefanf116bd02015-10-27 08:29:42 -0700841 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000842 } else if (test_state_ == kWaitingForPacket) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000843 if (header.paddingLength == 0) {
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000844 // Non-padding packet observed. Test is almost complete. Will just
845 // have to wait for the stats to change.
846 test_state_ = kWaitingForStats;
847 }
stefanf116bd02015-10-27 08:29:42 -0700848 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000849 } else if (test_state_ == kWaitingForStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000850 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000851 if (stats.suspended == false) {
852 // Stats flipped to false. Test is complete.
Peter Boström5811a392015-12-10 13:02:50 +0100853 observation_complete_.Set();
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000854 }
stefanf116bd02015-10-27 08:29:42 -0700855 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000856 }
857
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000858 return SEND_PACKET;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000859 }
860
861 // This method implements the I420FrameCallback.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700862 void FrameCallback(VideoFrame* video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200863 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000864 if (test_state_ == kDuringSuspend &&
865 ++suspended_frame_count_ > kSuspendTimeFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000866 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000867 EXPECT_TRUE(stats.suspended);
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000868 SendRtcpFeedback(high_remb_bps_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000869 test_state_ = kWaitingForPacket;
870 }
871 }
872
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000873 void set_low_remb_bps(int value) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200874 rtc::CritScope lock(&crit_);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000875 low_remb_bps_ = value;
876 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000877
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000878 void set_high_remb_bps(int value) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200879 rtc::CritScope lock(&crit_);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000880 high_remb_bps_ = value;
881 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000882
stefanff483612015-12-21 03:14:00 -0800883 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000884 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000885 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000886 stream_ = send_stream;
887 }
888
stefanff483612015-12-21 03:14:00 -0800889 void ModifyVideoConfigs(
890 VideoSendStream::Config* send_config,
891 std::vector<VideoReceiveStream::Config>* receive_configs,
892 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700893 transport_adapter_.reset(
894 new internal::TransportAdapter(send_config->send_transport));
895 transport_adapter_->Enable();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000896 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000897 send_config->pre_encode_callback = this;
898 send_config->suspend_below_min_bitrate = true;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000899 int min_bitrate_bps = encoder_config->streams[0].min_bitrate_bps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000900 set_low_remb_bps(min_bitrate_bps - 10000);
901 int threshold_window = std::max(min_bitrate_bps / 10, 10000);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000902 ASSERT_GT(encoder_config->streams[0].max_bitrate_bps,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000903 min_bitrate_bps + threshold_window + 5000);
904 set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
905 }
906
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000907 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100908 EXPECT_TRUE(Wait()) << "Timed out during suspend-below-min-bitrate test.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000909 }
910
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000911 enum TestState {
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000912 kBeforeSuspend,
913 kDuringSuspend,
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000914 kWaitingForPacket,
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000915 kWaitingForStats
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000916 };
917
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000918 virtual void SendRtcpFeedback(int remb_value)
919 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100920 FakeReceiveStatistics receive_stats(kVideoSendSsrcs[0],
921 last_sequence_number_, rtp_count_, 0);
terelius429c3452016-01-21 05:42:04 -0800922 RTCPSender rtcp_sender(false, clock_, &receive_stats, nullptr, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700923 transport_adapter_.get());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000924
pbosda903ea2015-10-02 02:36:56 -0700925 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100926 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000927 if (remb_value > 0) {
928 rtcp_sender.SetREMBStatus(true);
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000929 rtcp_sender.SetREMBData(remb_value, std::vector<uint32_t>());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000930 }
931 RTCPSender::FeedbackState feedback_state;
932 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
933 }
934
kwiberg27f982b2016-03-01 11:52:33 -0800935 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000936 Clock* const clock_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000937 VideoSendStream* stream_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000938
Peter Boströmf2f82832015-05-01 13:00:41 +0200939 rtc::CriticalSection crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000940 TestState test_state_ GUARDED_BY(crit_);
941 int rtp_count_ GUARDED_BY(crit_);
942 int last_sequence_number_ GUARDED_BY(crit_);
943 int suspended_frame_count_ GUARDED_BY(crit_);
944 int low_remb_bps_ GUARDED_BY(crit_);
945 int high_remb_bps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000946 } test;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000947
stefane74eef12016-01-08 06:47:13 -0800948 RunBaseTest(&test);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000949}
950
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000951TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000952 class NoPaddingWhenVideoIsMuted : public test::SendTest {
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000953 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000954 NoPaddingWhenVideoIsMuted()
955 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000956 clock_(Clock::GetRealTimeClock()),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000957 last_packet_time_ms_(-1),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000958 capturer_(nullptr) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000959 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000960
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000961 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000962 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200963 rtc::CritScope lock(&crit_);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000964 last_packet_time_ms_ = clock_->TimeInMilliseconds();
965 capturer_->Stop();
966 return SEND_PACKET;
967 }
968
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000969 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200970 rtc::CritScope lock(&crit_);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000971 const int kVideoMutedThresholdMs = 10000;
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000972 if (last_packet_time_ms_ > 0 &&
973 clock_->TimeInMilliseconds() - last_packet_time_ms_ >
974 kVideoMutedThresholdMs)
Peter Boström5811a392015-12-10 13:02:50 +0100975 observation_complete_.Set();
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000976 // Receive statistics reporting having lost 50% of the packets.
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100977 FakeReceiveStatistics receive_stats(kVideoSendSsrcs[0], 1, 1, 0);
Peter Boströmac547a62015-09-17 23:03:57 +0200978 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), &receive_stats,
terelius429c3452016-01-21 05:42:04 -0800979 nullptr, nullptr, transport_adapter_.get());
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000980
pbosda903ea2015-10-02 02:36:56 -0700981 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100982 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000983
984 RTCPSender::FeedbackState feedback_state;
985
986 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
987 return SEND_PACKET;
988 }
989
stefane74eef12016-01-08 06:47:13 -0800990 test::PacketTransport* CreateReceiveTransport() override {
991 test::PacketTransport* transport = new test::PacketTransport(
992 nullptr, this, test::PacketTransport::kReceiver,
993 FakeNetworkPipe::Config());
994 transport_adapter_.reset(new internal::TransportAdapter(transport));
stefanf116bd02015-10-27 08:29:42 -0700995 transport_adapter_->Enable();
stefane74eef12016-01-08 06:47:13 -0800996 return transport;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000997 }
998
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100999 size_t GetNumVideoStreams() const override { return 3; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001000
1001 virtual void OnFrameGeneratorCapturerCreated(
1002 test::FrameGeneratorCapturer* frame_generator_capturer) {
Peter Boströmf2f82832015-05-01 13:00:41 +02001003 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001004 capturer_ = frame_generator_capturer;
1005 }
1006
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001007 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001008 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001009 << "Timed out while waiting for RTP packets to stop being sent.";
1010 }
1011
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +00001012 Clock* const clock_;
kwiberg27f982b2016-03-01 11:52:33 -08001013 std::unique_ptr<internal::TransportAdapter> transport_adapter_;
Peter Boströmf2f82832015-05-01 13:00:41 +02001014 rtc::CriticalSection crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +00001015 int64_t last_packet_time_ms_ GUARDED_BY(crit_);
1016 test::FrameGeneratorCapturer* capturer_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001017 } test;
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +00001018
stefane74eef12016-01-08 06:47:13 -08001019 RunBaseTest(&test);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +00001020}
1021
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001022// This test first observes "high" bitrate use at which point it sends a REMB to
1023// indicate that it should be lowered significantly. The test then observes that
1024// the bitrate observed is sinking well below the min-transmit-bitrate threshold
1025// to verify that the min-transmit bitrate respects incoming REMB.
andresp@webrtc.org44caf012014-03-26 21:00:21 +00001026//
1027// Note that the test starts at "high" bitrate and does not ramp up to "higher"
1028// bitrate since no receiver block or remb is sent in the initial phase.
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001029TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
1030 static const int kMinTransmitBitrateBps = 400000;
andresp@webrtc.org44caf012014-03-26 21:00:21 +00001031 static const int kHighBitrateBps = 150000;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001032 static const int kRembBitrateBps = 80000;
1033 static const int kRembRespectedBitrateBps = 100000;
stefanf116bd02015-10-27 08:29:42 -07001034 class BitrateObserver : public test::SendTest {
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001035 public:
1036 BitrateObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001037 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001038 bitrate_capped_(false) {
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001039 }
1040
1041 private:
stefanf116bd02015-10-27 08:29:42 -07001042 virtual Action OnSendRtp(const uint8_t* packet, size_t length) {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001043 if (RtpHeaderParser::IsRtcp(packet, length))
stefanf116bd02015-10-27 08:29:42 -07001044 return DROP_PACKET;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001045
1046 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001047 if (!parser_->Parse(packet, length, &header))
stefanf116bd02015-10-27 08:29:42 -07001048 return DROP_PACKET;
Peter Boström74f6e9e2016-04-04 17:56:10 +02001049 RTC_DCHECK(stream_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001050 VideoSendStream::Stats stats = stream_->GetStats();
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001051 if (!stats.substreams.empty()) {
1052 EXPECT_EQ(1u, stats.substreams.size());
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001053 int total_bitrate_bps =
1054 stats.substreams.begin()->second.total_bitrate_bps;
1055 test::PrintResult("bitrate_stats_",
1056 "min_transmit_bitrate_low_remb",
1057 "bitrate_bps",
1058 static_cast<size_t>(total_bitrate_bps),
1059 "bps",
1060 false);
1061 if (total_bitrate_bps > kHighBitrateBps) {
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001062 rtp_rtcp_->SetREMBData(kRembBitrateBps,
1063 std::vector<uint32_t>(1, header.ssrc));
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001064 rtp_rtcp_->Process();
1065 bitrate_capped_ = true;
1066 } else if (bitrate_capped_ &&
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001067 total_bitrate_bps < kRembRespectedBitrateBps) {
Peter Boström5811a392015-12-10 13:02:50 +01001068 observation_complete_.Set();
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001069 }
1070 }
stefanf116bd02015-10-27 08:29:42 -07001071 // Packets don't have to be delivered since the test is the receiver.
1072 return DROP_PACKET;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001073 }
1074
stefanff483612015-12-21 03:14:00 -08001075 void OnVideoStreamsCreated(
stefanf116bd02015-10-27 08:29:42 -07001076 VideoSendStream* send_stream,
1077 const std::vector<VideoReceiveStream*>& receive_streams) override {
1078 stream_ = send_stream;
1079 RtpRtcp::Configuration config;
1080 config.outgoing_transport = feedback_transport_.get();
1081 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1082 rtp_rtcp_->SetREMBStatus(true);
1083 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001084 }
1085
stefanff483612015-12-21 03:14:00 -08001086 void ModifyVideoConfigs(
1087 VideoSendStream::Config* send_config,
1088 std::vector<VideoReceiveStream::Config>* receive_configs,
1089 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -07001090 feedback_transport_.reset(
1091 new internal::TransportAdapter(send_config->send_transport));
1092 feedback_transport_->Enable();
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00001093 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001094 }
1095
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001096 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001097 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098 << "Timeout while waiting for low bitrate stats after REMB.";
1099 }
1100
kwiberg27f982b2016-03-01 11:52:33 -08001101 std::unique_ptr<RtpRtcp> rtp_rtcp_;
1102 std::unique_ptr<internal::TransportAdapter> feedback_transport_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001103 VideoSendStream* stream_;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001104 bool bitrate_capped_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001105 } test;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001106
stefane74eef12016-01-08 06:47:13 -08001107 RunBaseTest(&test);
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001108}
1109
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001110TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) {
1111 class StartBitrateObserver : public test::FakeEncoder {
1112 public:
1113 StartBitrateObserver()
Peter Boström81cbd922016-03-22 12:19:07 +01001114 : FakeEncoder(Clock::GetRealTimeClock()), start_bitrate_kbps_(0) {}
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001115 int32_t InitEncode(const VideoCodec* config,
1116 int32_t number_of_cores,
1117 size_t max_payload_size) override {
1118 rtc::CritScope lock(&crit_);
1119 start_bitrate_kbps_ = config->startBitrate;
1120 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1121 }
1122
1123 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
1124 rtc::CritScope lock(&crit_);
1125 start_bitrate_kbps_ = new_target_bitrate;
1126 return FakeEncoder::SetRates(new_target_bitrate, framerate);
1127 }
1128
1129 int GetStartBitrateKbps() const {
1130 rtc::CritScope lock(&crit_);
1131 return start_bitrate_kbps_;
1132 }
1133
1134 private:
pbos5ad935c2016-01-25 03:52:44 -08001135 rtc::CriticalSection crit_;
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001136 int start_bitrate_kbps_ GUARDED_BY(crit_);
1137 };
1138
solenberg4fbae2b2015-08-28 04:07:10 -07001139 CreateSenderCall(Call::Config());
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001140
solenberg4fbae2b2015-08-28 04:07:10 -07001141 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001142 CreateSendConfig(1, 0, &transport);
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001143
1144 Call::Config::BitrateConfig bitrate_config;
1145 bitrate_config.start_bitrate_bps =
stefanff483612015-12-21 03:14:00 -08001146 2 * video_encoder_config_.streams[0].max_bitrate_bps;
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001147 sender_call_->SetBitrateConfig(bitrate_config);
1148
1149 StartBitrateObserver encoder;
stefanff483612015-12-21 03:14:00 -08001150 video_send_config_.encoder_settings.encoder = &encoder;
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001151
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001152 CreateVideoStreams();
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001153
stefanff483612015-12-21 03:14:00 -08001154 EXPECT_EQ(video_encoder_config_.streams[0].max_bitrate_bps / 1000,
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001155 encoder.GetStartBitrateKbps());
1156
stefanff483612015-12-21 03:14:00 -08001157 video_encoder_config_.streams[0].max_bitrate_bps =
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001158 2 * bitrate_config.start_bitrate_bps;
stefanff483612015-12-21 03:14:00 -08001159 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001160
1161 // New bitrate should be reconfigured above the previous max. As there's no
1162 // network connection this shouldn't be flaky, as no bitrate should've been
1163 // reported in between.
1164 EXPECT_EQ(bitrate_config.start_bitrate_bps / 1000,
1165 encoder.GetStartBitrateKbps());
1166
1167 DestroyStreams();
1168}
1169
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001170TEST_F(VideoSendStreamTest, CapturesTextureAndVideoFrames) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001171 class FrameObserver : public I420FrameCallback {
1172 public:
Peter Boström5811a392015-12-10 13:02:50 +01001173 FrameObserver() : output_frame_event_(false, false) {}
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001174
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001175 void FrameCallback(VideoFrame* video_frame) override {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001176 output_frames_.push_back(*video_frame);
Peter Boström5811a392015-12-10 13:02:50 +01001177 output_frame_event_.Set();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001178 }
1179
1180 void WaitOutputFrame() {
Peter Boström5811a392015-12-10 13:02:50 +01001181 const int kWaitFrameTimeoutMs = 3000;
1182 EXPECT_TRUE(output_frame_event_.Wait(kWaitFrameTimeoutMs))
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001183 << "Timeout while waiting for output frames.";
1184 }
1185
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001186 const std::vector<VideoFrame>& output_frames() const {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001187 return output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001188 }
1189
1190 private:
1191 // Delivered output frames.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001192 std::vector<VideoFrame> output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001193
1194 // Indicate an output frame has arrived.
Peter Boström5811a392015-12-10 13:02:50 +01001195 rtc::Event output_frame_event_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001196 };
1197
1198 // Initialize send stream.
solenberg4fbae2b2015-08-28 04:07:10 -07001199 CreateSenderCall(Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001200
solenberg4fbae2b2015-08-28 04:07:10 -07001201 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001202 CreateSendConfig(1, 0, &transport);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001203 FrameObserver observer;
stefanff483612015-12-21 03:14:00 -08001204 video_send_config_.pre_encode_callback = &observer;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001205 CreateVideoStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001206
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001207 // Prepare five input frames. Send ordinary VideoFrame and texture frames
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001208 // alternatively.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001209 std::vector<VideoFrame> input_frames;
stefanff483612015-12-21 03:14:00 -08001210 int width = static_cast<int>(video_encoder_config_.streams[0].width);
1211 int height = static_cast<int>(video_encoder_config_.streams[0].height);
Peter Boströmeb66e802015-06-05 11:08:03 +02001212 test::FakeNativeHandle* handle1 = new test::FakeNativeHandle();
1213 test::FakeNativeHandle* handle2 = new test::FakeNativeHandle();
1214 test::FakeNativeHandle* handle3 = new test::FakeNativeHandle();
Peter Boström13f61df2016-01-04 22:36:38 +01001215 input_frames.push_back(test::FakeNativeHandle::CreateFrame(
Peter Boströmeb66e802015-06-05 11:08:03 +02001216 handle1, width, height, 1, 1, kVideoRotation_0));
Peter Boström13f61df2016-01-04 22:36:38 +01001217 input_frames.push_back(test::FakeNativeHandle::CreateFrame(
Peter Boströmeb66e802015-06-05 11:08:03 +02001218 handle2, width, height, 2, 2, kVideoRotation_0));
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001219 input_frames.push_back(CreateVideoFrame(width, height, 3));
1220 input_frames.push_back(CreateVideoFrame(width, height, 4));
Peter Boström13f61df2016-01-04 22:36:38 +01001221 input_frames.push_back(test::FakeNativeHandle::CreateFrame(
Peter Boströmeb66e802015-06-05 11:08:03 +02001222 handle3, width, height, 5, 5, kVideoRotation_0));
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001223
stefanff483612015-12-21 03:14:00 -08001224 video_send_stream_->Start();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001225 for (size_t i = 0; i < input_frames.size(); i++) {
stefanff483612015-12-21 03:14:00 -08001226 video_send_stream_->Input()->IncomingCapturedFrame(input_frames[i]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001227 // Do not send the next frame too fast, so the frame dropper won't drop it.
1228 if (i < input_frames.size() - 1)
stefanff483612015-12-21 03:14:00 -08001229 SleepMs(1000 / video_encoder_config_.streams[0].max_framerate);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001230 // Wait until the output frame is received before sending the next input
1231 // frame. Or the previous input frame may be replaced without delivering.
1232 observer.WaitOutputFrame();
1233 }
stefanff483612015-12-21 03:14:00 -08001234 video_send_stream_->Stop();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001235
1236 // Test if the input and output frames are the same. render_time_ms and
1237 // timestamp are not compared because capturer sets those values.
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001238 ExpectEqualFramesVector(input_frames, observer.output_frames());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001239
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001240 DestroyStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001241}
1242
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001243void ExpectEqualFramesVector(const std::vector<VideoFrame>& frames1,
1244 const std::vector<VideoFrame>& frames2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001245 EXPECT_EQ(frames1.size(), frames2.size());
1246 for (size_t i = 0; i < std::min(frames1.size(), frames2.size()); ++i)
nisse26acec42016-04-15 03:43:39 -07001247 // Compare frame buffers, since we don't care about differing timestamps.
1248 EXPECT_TRUE(test::FrameBufsEqual(frames1[i].video_frame_buffer(),
1249 frames2[i].video_frame_buffer()));
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001250}
1251
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001252VideoFrame CreateVideoFrame(int width, int height, uint8_t data) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001253 const int kSizeY = width * height * 2;
kwiberg27f982b2016-03-01 11:52:33 -08001254 std::unique_ptr<uint8_t[]> buffer(new uint8_t[kSizeY]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001255 memset(buffer.get(), data, kSizeY);
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001256 VideoFrame frame;
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001257 frame.CreateFrame(buffer.get(), buffer.get(), buffer.get(), width, height,
Niels Möller739fcb92016-02-29 13:11:45 +01001258 width, width / 2, width / 2, kVideoRotation_0);
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001259 frame.set_timestamp(data);
1260 frame.set_render_time_ms(data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001261 return frame;
1262}
1263
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001264TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
1265 class EncoderStateObserver : public test::SendTest, public VideoEncoder {
1266 public:
1267 EncoderStateObserver()
1268 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001269 initialized_(false),
1270 callback_registered_(false),
1271 num_releases_(0),
1272 released_(false) {}
1273
1274 bool IsReleased() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001275 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001276 return released_;
1277 }
1278
1279 bool IsReadyForEncode() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001280 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001281 return initialized_ && callback_registered_;
1282 }
1283
1284 size_t num_releases() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001285 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001286 return num_releases_;
1287 }
1288
1289 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001290 int32_t InitEncode(const VideoCodec* codecSettings,
1291 int32_t numberOfCores,
1292 size_t maxPayloadSize) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001293 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001294 EXPECT_FALSE(initialized_);
1295 initialized_ = true;
1296 released_ = false;
1297 return 0;
1298 }
1299
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001300 int32_t Encode(const VideoFrame& inputImage,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001301 const CodecSpecificInfo* codecSpecificInfo,
pbos22993e12015-10-19 02:39:06 -07001302 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001303 EXPECT_TRUE(IsReadyForEncode());
1304
Peter Boström5811a392015-12-10 13:02:50 +01001305 observation_complete_.Set();
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001306 return 0;
1307 }
1308
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001309 int32_t RegisterEncodeCompleteCallback(
1310 EncodedImageCallback* callback) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001311 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001312 EXPECT_TRUE(initialized_);
1313 callback_registered_ = true;
1314 return 0;
1315 }
1316
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001317 int32_t Release() override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001318 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001319 EXPECT_TRUE(IsReadyForEncode());
1320 EXPECT_FALSE(released_);
1321 initialized_ = false;
1322 callback_registered_ = false;
1323 released_ = true;
1324 ++num_releases_;
1325 return 0;
1326 }
1327
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001328 int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001329 EXPECT_TRUE(IsReadyForEncode());
1330 return 0;
1331 }
1332
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001333 int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001334 EXPECT_TRUE(IsReadyForEncode());
1335 return 0;
1336 }
1337
stefanff483612015-12-21 03:14:00 -08001338 void OnVideoStreamsCreated(
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001339 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001340 const std::vector<VideoReceiveStream*>& receive_streams) override {
Peter Boström81cbd922016-03-22 12:19:07 +01001341 // Encoder initialization should be done in stream construction before
1342 // starting.
1343 EXPECT_TRUE(IsReadyForEncode());
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001344 stream_ = send_stream;
1345 }
1346
stefanff483612015-12-21 03:14:00 -08001347 void ModifyVideoConfigs(
1348 VideoSendStream::Config* send_config,
1349 std::vector<VideoReceiveStream::Config>* receive_configs,
1350 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001351 send_config->encoder_settings.encoder = this;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001352 encoder_config_ = *encoder_config;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001353 }
1354
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001355 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001356 EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001357 EXPECT_EQ(0u, num_releases());
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001358 stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001359 EXPECT_EQ(0u, num_releases());
1360 stream_->Stop();
1361 // Encoder should not be released before destroying the VideoSendStream.
1362 EXPECT_FALSE(IsReleased());
1363 EXPECT_TRUE(IsReadyForEncode());
1364 stream_->Start();
1365 // Sanity check, make sure we still encode frames with this encoder.
Peter Boström5811a392015-12-10 13:02:50 +01001366 EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001367 }
1368
Peter Boströmf2f82832015-05-01 13:00:41 +02001369 rtc::CriticalSection crit_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001370 VideoSendStream* stream_;
1371 bool initialized_ GUARDED_BY(crit_);
1372 bool callback_registered_ GUARDED_BY(crit_);
1373 size_t num_releases_ GUARDED_BY(crit_);
1374 bool released_ GUARDED_BY(crit_);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001375 VideoEncoderConfig encoder_config_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001376 } test_encoder;
1377
stefane74eef12016-01-08 06:47:13 -08001378 RunBaseTest(&test_encoder);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001379
1380 EXPECT_TRUE(test_encoder.IsReleased());
1381 EXPECT_EQ(1u, test_encoder.num_releases());
1382}
1383
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001384TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
1385 class VideoCodecConfigObserver : public test::SendTest,
1386 public test::FakeEncoder {
1387 public:
1388 VideoCodecConfigObserver()
1389 : SendTest(kDefaultTimeoutMs),
1390 FakeEncoder(Clock::GetRealTimeClock()),
1391 num_initializations_(0) {}
1392
1393 private:
stefanff483612015-12-21 03:14:00 -08001394 void ModifyVideoConfigs(
1395 VideoSendStream::Config* send_config,
1396 std::vector<VideoReceiveStream::Config>* receive_configs,
1397 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001398 send_config->encoder_settings.encoder = this;
1399 encoder_config_ = *encoder_config;
1400 }
1401
stefanff483612015-12-21 03:14:00 -08001402 void OnVideoStreamsCreated(
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001403 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001404 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001405 stream_ = send_stream;
1406 }
1407
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001408 int32_t InitEncode(const VideoCodec* config,
1409 int32_t number_of_cores,
1410 size_t max_payload_size) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001411 if (num_initializations_ == 0) {
1412 // Verify default values.
1413 EXPECT_EQ(kRealtimeVideo, config->mode);
1414 } else {
1415 // Verify that changed values are propagated.
1416 EXPECT_EQ(kScreensharing, config->mode);
1417 }
1418 ++num_initializations_;
1419 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1420 }
1421
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001422 void PerformTest() override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001423 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1424
Erik Språng143cec12015-04-28 10:01:41 +02001425 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001426 stream_->ReconfigureVideoEncoder(encoder_config_);
1427 EXPECT_EQ(2u, num_initializations_)
1428 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1429 "new encoder settings.";
1430 }
1431
1432 size_t num_initializations_;
1433 VideoSendStream* stream_;
1434 VideoEncoderConfig encoder_config_;
1435 } test;
1436
stefane74eef12016-01-08 06:47:13 -08001437 RunBaseTest(&test);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001438}
1439
Peter Boström53eda3d2015-03-27 15:53:18 +01001440static const size_t kVideoCodecConfigObserverNumberOfTemporalLayers = 4;
1441template <typename T>
1442class VideoCodecConfigObserver : public test::SendTest,
1443 public test::FakeEncoder {
Peter Boström53eda3d2015-03-27 15:53:18 +01001444 public:
1445 VideoCodecConfigObserver(VideoCodecType video_codec_type,
1446 const char* codec_name)
1447 : SendTest(VideoSendStreamTest::kDefaultTimeoutMs),
1448 FakeEncoder(Clock::GetRealTimeClock()),
1449 video_codec_type_(video_codec_type),
1450 codec_name_(codec_name),
1451 num_initializations_(0) {
1452 memset(&encoder_settings_, 0, sizeof(encoder_settings_));
1453 }
1454
1455 private:
stefanff483612015-12-21 03:14:00 -08001456 void ModifyVideoConfigs(
1457 VideoSendStream::Config* send_config,
1458 std::vector<VideoReceiveStream::Config>* receive_configs,
1459 VideoEncoderConfig* encoder_config) override {
Peter Boström53eda3d2015-03-27 15:53:18 +01001460 send_config->encoder_settings.encoder = this;
1461 send_config->encoder_settings.payload_name = codec_name_;
1462
1463 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
1464 encoder_config->streams[i].temporal_layer_thresholds_bps.resize(
1465 kVideoCodecConfigObserverNumberOfTemporalLayers - 1);
1466 }
1467
1468 encoder_config->encoder_specific_settings = &encoder_settings_;
1469 encoder_config_ = *encoder_config;
1470 }
1471
stefanff483612015-12-21 03:14:00 -08001472 void OnVideoStreamsCreated(
Peter Boström53eda3d2015-03-27 15:53:18 +01001473 VideoSendStream* send_stream,
1474 const std::vector<VideoReceiveStream*>& receive_streams) override {
1475 stream_ = send_stream;
1476 }
1477
1478 int32_t InitEncode(const VideoCodec* config,
1479 int32_t number_of_cores,
1480 size_t max_payload_size) override {
1481 EXPECT_EQ(video_codec_type_, config->codecType);
1482 VerifyCodecSpecifics(*config);
1483 ++num_initializations_;
1484 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1485 }
1486
1487 void VerifyCodecSpecifics(const VideoCodec& config) const;
1488
1489 void PerformTest() override {
Peter Boström81cbd922016-03-22 12:19:07 +01001490 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
Peter Boström53eda3d2015-03-27 15:53:18 +01001491
1492 encoder_settings_.frameDroppingOn = true;
1493 stream_->ReconfigureVideoEncoder(encoder_config_);
1494 EXPECT_EQ(2u, num_initializations_)
1495 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1496 "new encoder settings.";
1497 }
1498
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001499 int32_t Encode(const VideoFrame& input_image,
Peter Boström53eda3d2015-03-27 15:53:18 +01001500 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07001501 const std::vector<FrameType>* frame_types) override {
Peter Boström53eda3d2015-03-27 15:53:18 +01001502 // Silently skip the encode, FakeEncoder::Encode doesn't produce VP8.
1503 return 0;
1504 }
1505
1506 T encoder_settings_;
1507 const VideoCodecType video_codec_type_;
1508 const char* const codec_name_;
1509 size_t num_initializations_;
1510 VideoSendStream* stream_;
1511 VideoEncoderConfig encoder_config_;
1512};
1513
1514template <>
1515void VideoCodecConfigObserver<VideoCodecH264>::VerifyCodecSpecifics(
1516 const VideoCodec& config) const {
1517 EXPECT_EQ(0, memcmp(&config.codecSpecific.H264, &encoder_settings_,
1518 sizeof(encoder_settings_)));
1519}
1520template <>
1521void VideoCodecConfigObserver<VideoCodecVP8>::VerifyCodecSpecifics(
1522 const VideoCodec& config) const {
1523 // Check that the number of temporal layers has propagated properly to
1524 // VideoCodec.
1525 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1526 config.codecSpecific.VP8.numberOfTemporalLayers);
1527
1528 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1529 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1530 config.simulcastStream[i].numberOfTemporalLayers);
1531 }
1532
1533 // Set expected temporal layers as they should have been set when
1534 // reconfiguring the encoder and not match the set config.
1535 VideoCodecVP8 encoder_settings = encoder_settings_;
1536 encoder_settings.numberOfTemporalLayers =
1537 kVideoCodecConfigObserverNumberOfTemporalLayers;
1538 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP8, &encoder_settings,
1539 sizeof(encoder_settings_)));
1540}
1541template <>
1542void VideoCodecConfigObserver<VideoCodecVP9>::VerifyCodecSpecifics(
1543 const VideoCodec& config) const {
1544 // Check that the number of temporal layers has propagated properly to
1545 // VideoCodec.
1546 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1547 config.codecSpecific.VP9.numberOfTemporalLayers);
1548
1549 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1550 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1551 config.simulcastStream[i].numberOfTemporalLayers);
1552 }
1553
1554 // Set expected temporal layers as they should have been set when
1555 // reconfiguring the encoder and not match the set config.
1556 VideoCodecVP9 encoder_settings = encoder_settings_;
1557 encoder_settings.numberOfTemporalLayers =
1558 kVideoCodecConfigObserverNumberOfTemporalLayers;
1559 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP9, &encoder_settings,
1560 sizeof(encoder_settings_)));
1561}
1562
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001563TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp8Config) {
Peter Boström53eda3d2015-03-27 15:53:18 +01001564 VideoCodecConfigObserver<VideoCodecVP8> test(kVideoCodecVP8, "VP8");
stefane74eef12016-01-08 06:47:13 -08001565 RunBaseTest(&test);
Peter Boström53eda3d2015-03-27 15:53:18 +01001566}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001567
Peter Boström53eda3d2015-03-27 15:53:18 +01001568TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp9Config) {
1569 VideoCodecConfigObserver<VideoCodecVP9> test(kVideoCodecVP9, "VP9");
stefane74eef12016-01-08 06:47:13 -08001570 RunBaseTest(&test);
Peter Boström53eda3d2015-03-27 15:53:18 +01001571}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001572
Peter Boström53eda3d2015-03-27 15:53:18 +01001573TEST_F(VideoSendStreamTest, EncoderSetupPropagatesH264Config) {
1574 VideoCodecConfigObserver<VideoCodecH264> test(kVideoCodecH264, "H264");
stefane74eef12016-01-08 06:47:13 -08001575 RunBaseTest(&test);
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001576}
1577
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001578TEST_F(VideoSendStreamTest, RtcpSenderReportContainsMediaBytesSent) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001579 class RtcpSenderReportTest : public test::SendTest {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001580 public:
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001581 RtcpSenderReportTest() : SendTest(kDefaultTimeoutMs),
1582 rtp_packets_sent_(0),
1583 media_bytes_sent_(0) {}
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001584
1585 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001586 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan4b569042015-11-11 06:39:57 -08001587 rtc::CritScope lock(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001588 RTPHeader header;
1589 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001590 ++rtp_packets_sent_;
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001591 media_bytes_sent_ += length - header.headerLength - header.paddingLength;
1592 return SEND_PACKET;
1593 }
1594
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001595 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan4b569042015-11-11 06:39:57 -08001596 rtc::CritScope lock(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001597 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1598 EXPECT_TRUE(parser.IsValid());
1599
1600 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001601 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1602 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001603 // Only compare sent media bytes if SenderPacketCount matches the
1604 // number of sent rtp packets (a new rtp packet could be sent before
1605 // the rtcp packet).
1606 if (parser.Packet().SR.SenderOctetCount > 0 &&
1607 parser.Packet().SR.SenderPacketCount == rtp_packets_sent_) {
1608 EXPECT_EQ(media_bytes_sent_, parser.Packet().SR.SenderOctetCount);
Peter Boström5811a392015-12-10 13:02:50 +01001609 observation_complete_.Set();
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001610 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001611 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001612 packet_type = parser.Iterate();
1613 }
1614
1615 return SEND_PACKET;
1616 }
1617
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001618 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001619 EXPECT_TRUE(Wait()) << "Timed out while waiting for RTCP sender report.";
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001620 }
1621
stefan4b569042015-11-11 06:39:57 -08001622 rtc::CriticalSection crit_;
1623 size_t rtp_packets_sent_ GUARDED_BY(&crit_);
1624 size_t media_bytes_sent_ GUARDED_BY(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001625 } test;
1626
stefane74eef12016-01-08 06:47:13 -08001627 RunBaseTest(&test);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001628}
1629
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001630TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
1631 static const int kScreencastTargetBitrateKbps = 200;
1632 class ScreencastTargetBitrateTest : public test::SendTest,
1633 public test::FakeEncoder {
1634 public:
1635 ScreencastTargetBitrateTest()
1636 : SendTest(kDefaultTimeoutMs),
1637 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1638
1639 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001640 int32_t InitEncode(const VideoCodec* config,
1641 int32_t number_of_cores,
1642 size_t max_payload_size) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001643 EXPECT_EQ(static_cast<unsigned int>(kScreencastTargetBitrateKbps),
1644 config->targetBitrate);
Peter Boström5811a392015-12-10 13:02:50 +01001645 observation_complete_.Set();
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001646 return test::FakeEncoder::InitEncode(
1647 config, number_of_cores, max_payload_size);
1648 }
stefanff483612015-12-21 03:14:00 -08001649 void ModifyVideoConfigs(
1650 VideoSendStream::Config* send_config,
1651 std::vector<VideoReceiveStream::Config>* receive_configs,
1652 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001653 send_config->encoder_settings.encoder = this;
1654 EXPECT_EQ(1u, encoder_config->streams.size());
1655 EXPECT_TRUE(
1656 encoder_config->streams[0].temporal_layer_thresholds_bps.empty());
1657 encoder_config->streams[0].temporal_layer_thresholds_bps.push_back(
1658 kScreencastTargetBitrateKbps * 1000);
Erik Språng143cec12015-04-28 10:01:41 +02001659 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001660 }
1661
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001662 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001663 EXPECT_TRUE(Wait())
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001664 << "Timed out while waiting for the encoder to be initialized.";
1665 }
1666 } test;
1667
stefane74eef12016-01-08 06:47:13 -08001668 RunBaseTest(&test);
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001669}
pbos@webrtc.org00873182014-11-25 14:03:34 +00001670
honghaizcfb7f01f2015-12-21 13:34:54 -08001671// Disabled on LinuxAsan:
1672// https://bugs.chromium.org/p/webrtc/issues/detail?id=5382
1673#if defined(ADDRESS_SANITIZER) && defined(WEBRTC_LINUX)
1674#define MAYBE_ReconfigureBitratesSetsEncoderBitratesCorrectly \
1675 DISABLED_ReconfigureBitratesSetsEncoderBitratesCorrectly
1676#else
1677#define MAYBE_ReconfigureBitratesSetsEncoderBitratesCorrectly \
1678 ReconfigureBitratesSetsEncoderBitratesCorrectly
1679#endif
1680
1681TEST_F(VideoSendStreamTest,
1682 MAYBE_ReconfigureBitratesSetsEncoderBitratesCorrectly) {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001683 // These are chosen to be "kind of odd" to not be accidentally checked against
1684 // default values.
1685 static const int kMinBitrateKbps = 137;
1686 static const int kStartBitrateKbps = 345;
1687 static const int kLowerMaxBitrateKbps = 312;
1688 static const int kMaxBitrateKbps = 413;
1689 static const int kIncreasedStartBitrateKbps = 451;
1690 static const int kIncreasedMaxBitrateKbps = 597;
1691 class EncoderBitrateThresholdObserver : public test::SendTest,
1692 public test::FakeEncoder {
1693 public:
1694 EncoderBitrateThresholdObserver()
1695 : SendTest(kDefaultTimeoutMs),
1696 FakeEncoder(Clock::GetRealTimeClock()),
1697 num_initializations_(0) {}
1698
1699 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001700 int32_t InitEncode(const VideoCodec* codecSettings,
1701 int32_t numberOfCores,
1702 size_t maxPayloadSize) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001703 if (num_initializations_ == 0) {
1704 EXPECT_EQ(static_cast<unsigned int>(kMinBitrateKbps),
1705 codecSettings->minBitrate);
1706 EXPECT_EQ(static_cast<unsigned int>(kStartBitrateKbps),
1707 codecSettings->startBitrate);
1708 EXPECT_EQ(static_cast<unsigned int>(kMaxBitrateKbps),
1709 codecSettings->maxBitrate);
Peter Boström5811a392015-12-10 13:02:50 +01001710 observation_complete_.Set();
pbos@webrtc.org00873182014-11-25 14:03:34 +00001711 } else if (num_initializations_ == 1) {
1712 EXPECT_EQ(static_cast<unsigned int>(kLowerMaxBitrateKbps),
1713 codecSettings->maxBitrate);
1714 // The start bitrate should be kept (-1) and capped to the max bitrate.
1715 // Since this is not an end-to-end call no receiver should have been
1716 // returning a REMB that could lower this estimate.
1717 EXPECT_EQ(codecSettings->startBitrate, codecSettings->maxBitrate);
1718 } else if (num_initializations_ == 2) {
1719 EXPECT_EQ(static_cast<unsigned int>(kIncreasedMaxBitrateKbps),
1720 codecSettings->maxBitrate);
1721 EXPECT_EQ(static_cast<unsigned int>(kIncreasedStartBitrateKbps),
1722 codecSettings->startBitrate);
1723 }
1724 ++num_initializations_;
1725 return FakeEncoder::InitEncode(codecSettings, numberOfCores,
1726 maxPayloadSize);
1727 }
1728
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001729 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -07001730 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +01001731 config.bitrate_config.min_bitrate_bps = kMinBitrateKbps * 1000;
1732 config.bitrate_config.start_bitrate_bps = kStartBitrateKbps * 1000;
1733 config.bitrate_config.max_bitrate_bps = kMaxBitrateKbps * 1000;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001734 return config;
1735 }
1736
stefanff483612015-12-21 03:14:00 -08001737 void ModifyVideoConfigs(
1738 VideoSendStream::Config* send_config,
1739 std::vector<VideoReceiveStream::Config>* receive_configs,
1740 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001741 send_config->encoder_settings.encoder = this;
1742 // Set bitrates lower/higher than min/max to make sure they are properly
1743 // capped.
Stefan Holmere5904162015-03-26 11:11:06 +01001744 encoder_config->streams.front().min_bitrate_bps = kMinBitrateKbps * 1000;
1745 encoder_config->streams.front().max_bitrate_bps = kMaxBitrateKbps * 1000;
1746 encoder_config_ = *encoder_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001747 }
1748
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001749 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001750 call_ = sender_call;
1751 }
1752
stefanff483612015-12-21 03:14:00 -08001753 void OnVideoStreamsCreated(
Stefan Holmere5904162015-03-26 11:11:06 +01001754 VideoSendStream* send_stream,
1755 const std::vector<VideoReceiveStream*>& receive_streams) override {
1756 send_stream_ = send_stream;
1757 }
1758
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001759 void PerformTest() override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001760 Call::Config::BitrateConfig bitrate_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001761 bitrate_config.start_bitrate_bps = kIncreasedStartBitrateKbps * 1000;
1762 bitrate_config.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000;
1763 call_->SetBitrateConfig(bitrate_config);
Peter Boström5811a392015-12-10 13:02:50 +01001764 EXPECT_TRUE(Wait())
Stefan Holmere5904162015-03-26 11:11:06 +01001765 << "Timed out while waiting encoder to be configured.";
1766 encoder_config_.streams[0].min_bitrate_bps = 0;
1767 encoder_config_.streams[0].max_bitrate_bps = kLowerMaxBitrateKbps * 1000;
1768 send_stream_->ReconfigureVideoEncoder(encoder_config_);
1769 EXPECT_EQ(2, num_initializations_)
1770 << "Encoder should have been reconfigured with the new value.";
1771 encoder_config_.streams[0].target_bitrate_bps =
1772 encoder_config_.streams[0].min_bitrate_bps;
1773 encoder_config_.streams[0].max_bitrate_bps =
1774 kIncreasedMaxBitrateKbps * 1000;
1775 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org00873182014-11-25 14:03:34 +00001776 EXPECT_EQ(3, num_initializations_)
1777 << "Encoder should have been reconfigured with the new value.";
1778 }
1779
1780 int num_initializations_;
1781 webrtc::Call* call_;
Stefan Holmere5904162015-03-26 11:11:06 +01001782 webrtc::VideoSendStream* send_stream_;
1783 webrtc::VideoEncoderConfig encoder_config_;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001784 } test;
1785
stefane74eef12016-01-08 06:47:13 -08001786 RunBaseTest(&test);
pbos@webrtc.org00873182014-11-25 14:03:34 +00001787}
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001788
1789TEST_F(VideoSendStreamTest, ReportsSentResolution) {
1790 static const size_t kNumStreams = 3;
1791 // Unusual resolutions to make sure that they are the ones being reported.
1792 static const struct {
1793 int width;
1794 int height;
1795 } kEncodedResolution[kNumStreams] = {
1796 {241, 181}, {300, 121}, {121, 221}};
1797 class ScreencastTargetBitrateTest : public test::SendTest,
1798 public test::FakeEncoder {
1799 public:
1800 ScreencastTargetBitrateTest()
1801 : SendTest(kDefaultTimeoutMs),
1802 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1803
1804 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001805 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001806 const CodecSpecificInfo* codecSpecificInfo,
pbos22993e12015-10-19 02:39:06 -07001807 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001808 CodecSpecificInfo specifics;
1809 memset(&specifics, 0, sizeof(specifics));
1810 specifics.codecType = kVideoCodecGeneric;
1811
1812 uint8_t buffer[16] = {0};
1813 EncodedImage encoded(buffer, sizeof(buffer), sizeof(buffer));
1814 encoded._timeStamp = input_image.timestamp();
1815 encoded.capture_time_ms_ = input_image.render_time_ms();
1816
1817 for (size_t i = 0; i < kNumStreams; ++i) {
1818 specifics.codecSpecific.generic.simulcast_idx = static_cast<uint8_t>(i);
1819 encoded._frameType = (*frame_types)[i];
1820 encoded._encodedWidth = kEncodedResolution[i].width;
1821 encoded._encodedHeight = kEncodedResolution[i].height;
Peter Boström74f6e9e2016-04-04 17:56:10 +02001822 RTC_DCHECK(callback_);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001823 if (callback_->Encoded(encoded, &specifics, nullptr) != 0)
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001824 return -1;
1825 }
1826
Peter Boström5811a392015-12-10 13:02:50 +01001827 observation_complete_.Set();
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001828 return 0;
1829 }
stefanff483612015-12-21 03:14:00 -08001830 void ModifyVideoConfigs(
1831 VideoSendStream::Config* send_config,
1832 std::vector<VideoReceiveStream::Config>* receive_configs,
1833 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001834 send_config->encoder_settings.encoder = this;
1835 EXPECT_EQ(kNumStreams, encoder_config->streams.size());
1836 }
1837
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001838 size_t GetNumVideoStreams() const override { return kNumStreams; }
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001839
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001840 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001841 EXPECT_TRUE(Wait())
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001842 << "Timed out while waiting for the encoder to send one frame.";
1843 VideoSendStream::Stats stats = send_stream_->GetStats();
1844
1845 for (size_t i = 0; i < kNumStreams; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001846 ASSERT_TRUE(stats.substreams.find(kVideoSendSsrcs[i]) !=
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001847 stats.substreams.end())
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001848 << "No stats for SSRC: " << kVideoSendSsrcs[i]
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001849 << ", stats should exist as soon as frames have been encoded.";
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001850 VideoSendStream::StreamStats ssrc_stats =
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001851 stats.substreams[kVideoSendSsrcs[i]];
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001852 EXPECT_EQ(kEncodedResolution[i].width, ssrc_stats.width);
1853 EXPECT_EQ(kEncodedResolution[i].height, ssrc_stats.height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001854 }
1855 }
1856
stefanff483612015-12-21 03:14:00 -08001857 void OnVideoStreamsCreated(
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001858 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001859 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001860 send_stream_ = send_stream;
1861 }
1862
1863 VideoSendStream* send_stream_;
1864 } test;
1865
stefane74eef12016-01-08 06:47:13 -08001866 RunBaseTest(&test);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001867}
philipel0f9af012015-09-01 07:01:51 -07001868
Åsa Perssonff24c042015-12-04 10:58:08 +01001869class Vp9HeaderObserver : public test::SendTest {
philipel0f9af012015-09-01 07:01:51 -07001870 public:
Åsa Perssonff24c042015-12-04 10:58:08 +01001871 Vp9HeaderObserver()
1872 : SendTest(VideoSendStreamTest::kLongTimeoutMs),
philipel7fabd462015-09-03 04:42:32 -07001873 vp9_encoder_(VP9Encoder::Create()),
Åsa Perssonff24c042015-12-04 10:58:08 +01001874 vp9_settings_(VideoEncoder::GetDefaultVp9Settings()),
1875 packets_sent_(0),
1876 frames_sent_(0) {}
philipel7fabd462015-09-03 04:42:32 -07001877
stefanff483612015-12-21 03:14:00 -08001878 virtual void ModifyVideoConfigsHook(
philipel0f9af012015-09-01 07:01:51 -07001879 VideoSendStream::Config* send_config,
1880 std::vector<VideoReceiveStream::Config>* receive_configs,
1881 VideoEncoderConfig* encoder_config) {}
1882
Åsa Perssonff24c042015-12-04 10:58:08 +01001883 virtual void InspectHeader(const RTPVideoHeaderVP9& vp9) = 0;
philipel0f9af012015-09-01 07:01:51 -07001884
1885 private:
1886 const int kVp9PayloadType = 105;
1887
stefanff483612015-12-21 03:14:00 -08001888 void ModifyVideoConfigs(
1889 VideoSendStream::Config* send_config,
1890 std::vector<VideoReceiveStream::Config>* receive_configs,
1891 VideoEncoderConfig* encoder_config) override {
philipel0f9af012015-09-01 07:01:51 -07001892 encoder_config->encoder_specific_settings = &vp9_settings_;
philipel7fabd462015-09-03 04:42:32 -07001893 send_config->encoder_settings.encoder = vp9_encoder_.get();
philipel0f9af012015-09-01 07:01:51 -07001894 send_config->encoder_settings.payload_name = "VP9";
1895 send_config->encoder_settings.payload_type = kVp9PayloadType;
stefanff483612015-12-21 03:14:00 -08001896 ModifyVideoConfigsHook(send_config, receive_configs, encoder_config);
Åsa Perssonff24c042015-12-04 10:58:08 +01001897 EXPECT_EQ(1u, encoder_config->streams.size());
1898 encoder_config->streams[0].temporal_layer_thresholds_bps.resize(
1899 vp9_settings_.numberOfTemporalLayers - 1);
1900 encoder_config_ = *encoder_config;
philipel0f9af012015-09-01 07:01:51 -07001901 }
1902
1903 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001904 EXPECT_TRUE(Wait()) << "Test timed out waiting for VP9 packet, num frames "
1905 << frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07001906 }
1907
1908 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1909 RTPHeader header;
1910 EXPECT_TRUE(parser_->Parse(packet, length, &header));
1911
Åsa Perssonff24c042015-12-04 10:58:08 +01001912 EXPECT_EQ(kVp9PayloadType, header.payloadType);
1913 const uint8_t* payload = packet + header.headerLength;
1914 size_t payload_length = length - header.headerLength - header.paddingLength;
philipel0f9af012015-09-01 07:01:51 -07001915
Åsa Perssonff24c042015-12-04 10:58:08 +01001916 bool new_packet = packets_sent_ == 0 ||
1917 IsNewerSequenceNumber(header.sequenceNumber,
1918 last_header_.sequenceNumber);
1919 if (payload_length > 0 && new_packet) {
1920 RtpDepacketizer::ParsedPayload parsed;
1921 RtpDepacketizerVp9 depacketizer;
1922 EXPECT_TRUE(depacketizer.Parse(&parsed, payload, payload_length));
1923 EXPECT_EQ(RtpVideoCodecTypes::kRtpVideoVp9, parsed.type.Video.codec);
1924 // Verify common fields for all configurations.
1925 VerifyCommonHeader(parsed.type.Video.codecHeader.VP9);
1926 CompareConsecutiveFrames(header, parsed.type.Video);
1927 // Verify configuration specific settings.
1928 InspectHeader(parsed.type.Video.codecHeader.VP9);
philipel0f9af012015-09-01 07:01:51 -07001929
Åsa Perssonff24c042015-12-04 10:58:08 +01001930 ++packets_sent_;
1931 if (header.markerBit) {
1932 ++frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07001933 }
Åsa Perssonff24c042015-12-04 10:58:08 +01001934 last_header_ = header;
1935 last_vp9_ = parsed.type.Video.codecHeader.VP9;
philipel0f9af012015-09-01 07:01:51 -07001936 }
philipel0f9af012015-09-01 07:01:51 -07001937 return SEND_PACKET;
1938 }
1939
philipel7fabd462015-09-03 04:42:32 -07001940 protected:
Åsa Perssonff24c042015-12-04 10:58:08 +01001941 bool ContinuousPictureId(const RTPVideoHeaderVP9& vp9) const {
1942 if (last_vp9_.picture_id > vp9.picture_id) {
1943 return vp9.picture_id == 0; // Wrap.
1944 } else {
1945 return vp9.picture_id == last_vp9_.picture_id + 1;
1946 }
1947 }
1948
1949 void VerifySpatialIdxWithinFrame(const RTPVideoHeaderVP9& vp9) const {
Åsa Perssonff24c042015-12-04 10:58:08 +01001950 bool new_layer = vp9.spatial_idx != last_vp9_.spatial_idx;
1951 EXPECT_EQ(new_layer, vp9.beginning_of_frame);
1952 EXPECT_EQ(new_layer, last_vp9_.end_of_frame);
1953 EXPECT_EQ(new_layer ? last_vp9_.spatial_idx + 1 : last_vp9_.spatial_idx,
1954 vp9.spatial_idx);
1955 }
1956
1957 void VerifyFixedTemporalLayerStructure(const RTPVideoHeaderVP9& vp9,
1958 uint8_t num_layers) const {
1959 switch (num_layers) {
1960 case 0:
1961 VerifyTemporalLayerStructure0(vp9);
1962 break;
1963 case 1:
1964 VerifyTemporalLayerStructure1(vp9);
1965 break;
1966 case 2:
1967 VerifyTemporalLayerStructure2(vp9);
1968 break;
1969 case 3:
1970 VerifyTemporalLayerStructure3(vp9);
1971 break;
1972 default:
1973 RTC_NOTREACHED();
1974 }
1975 }
1976
1977 void VerifyTemporalLayerStructure0(const RTPVideoHeaderVP9& vp9) const {
1978 EXPECT_EQ(kNoTl0PicIdx, vp9.tl0_pic_idx);
1979 EXPECT_EQ(kNoTemporalIdx, vp9.temporal_idx); // no tid
1980 EXPECT_FALSE(vp9.temporal_up_switch);
1981 }
1982
1983 void VerifyTemporalLayerStructure1(const RTPVideoHeaderVP9& vp9) const {
1984 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
1985 EXPECT_EQ(0, vp9.temporal_idx); // 0,0,0,...
1986 EXPECT_FALSE(vp9.temporal_up_switch);
1987 }
1988
1989 void VerifyTemporalLayerStructure2(const RTPVideoHeaderVP9& vp9) const {
1990 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
1991 EXPECT_GE(vp9.temporal_idx, 0); // 0,1,0,1,... (tid reset on I-frames).
1992 EXPECT_LE(vp9.temporal_idx, 1);
1993 EXPECT_EQ(vp9.temporal_idx > 0, vp9.temporal_up_switch);
1994 if (IsNewPictureId(vp9)) {
1995 uint8_t expected_tid =
1996 (!vp9.inter_pic_predicted || last_vp9_.temporal_idx == 1) ? 0 : 1;
1997 EXPECT_EQ(expected_tid, vp9.temporal_idx);
1998 }
1999 }
2000
2001 void VerifyTemporalLayerStructure3(const RTPVideoHeaderVP9& vp9) const {
2002 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
2003 EXPECT_GE(vp9.temporal_idx, 0); // 0,2,1,2,... (tid reset on I-frames).
2004 EXPECT_LE(vp9.temporal_idx, 2);
2005 if (IsNewPictureId(vp9) && vp9.inter_pic_predicted) {
2006 EXPECT_NE(vp9.temporal_idx, last_vp9_.temporal_idx);
2007 switch (vp9.temporal_idx) {
2008 case 0:
2009 EXPECT_EQ(2, last_vp9_.temporal_idx);
2010 EXPECT_FALSE(vp9.temporal_up_switch);
2011 break;
2012 case 1:
2013 EXPECT_EQ(2, last_vp9_.temporal_idx);
2014 EXPECT_TRUE(vp9.temporal_up_switch);
2015 break;
2016 case 2:
2017 EXPECT_EQ(last_vp9_.temporal_idx == 0, vp9.temporal_up_switch);
2018 break;
2019 }
2020 }
2021 }
2022
2023 void VerifyTl0Idx(const RTPVideoHeaderVP9& vp9) const {
2024 if (vp9.tl0_pic_idx == kNoTl0PicIdx)
2025 return;
2026
2027 uint8_t expected_tl0_idx = last_vp9_.tl0_pic_idx;
2028 if (vp9.temporal_idx == 0)
2029 ++expected_tl0_idx;
2030 EXPECT_EQ(expected_tl0_idx, vp9.tl0_pic_idx);
2031 }
2032
2033 bool IsNewPictureId(const RTPVideoHeaderVP9& vp9) const {
2034 return frames_sent_ > 0 && (vp9.picture_id != last_vp9_.picture_id);
2035 }
2036
2037 // Flexible mode (F=1): Non-flexible mode (F=0):
2038 //
2039 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2040 // |I|P|L|F|B|E|V|-| |I|P|L|F|B|E|V|-|
2041 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2042 // I: |M| PICTURE ID | I: |M| PICTURE ID |
2043 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2044 // M: | EXTENDED PID | M: | EXTENDED PID |
2045 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2046 // L: | T |U| S |D| L: | T |U| S |D|
2047 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2048 // P,F: | P_DIFF |X|N| | TL0PICIDX |
2049 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2050 // X: |EXTENDED P_DIFF| V: | SS .. |
2051 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2052 // V: | SS .. |
2053 // +-+-+-+-+-+-+-+-+
2054 void VerifyCommonHeader(const RTPVideoHeaderVP9& vp9) const {
2055 EXPECT_EQ(kMaxTwoBytePictureId, vp9.max_picture_id); // M:1
2056 EXPECT_NE(kNoPictureId, vp9.picture_id); // I:1
2057 EXPECT_EQ(vp9_settings_.flexibleMode, vp9.flexible_mode); // F
2058 EXPECT_GE(vp9.spatial_idx, 0); // S
2059 EXPECT_LT(vp9.spatial_idx, vp9_settings_.numberOfSpatialLayers);
2060 if (vp9.ss_data_available) // V
2061 VerifySsData(vp9);
2062
2063 if (frames_sent_ == 0)
2064 EXPECT_FALSE(vp9.inter_pic_predicted); // P
2065
2066 if (!vp9.inter_pic_predicted) {
2067 EXPECT_TRUE(vp9.temporal_idx == 0 || vp9.temporal_idx == kNoTemporalIdx);
2068 EXPECT_FALSE(vp9.temporal_up_switch);
2069 }
2070 }
2071
2072 // Scalability structure (SS).
2073 //
2074 // +-+-+-+-+-+-+-+-+
2075 // V: | N_S |Y|G|-|-|-|
2076 // +-+-+-+-+-+-+-+-+
2077 // Y: | WIDTH | N_S + 1 times
2078 // +-+-+-+-+-+-+-+-+
2079 // | HEIGHT |
2080 // +-+-+-+-+-+-+-+-+
2081 // G: | N_G |
2082 // +-+-+-+-+-+-+-+-+
2083 // N_G: | T |U| R |-|-| N_G times
2084 // +-+-+-+-+-+-+-+-+
2085 // | P_DIFF | R times
2086 // +-+-+-+-+-+-+-+-+
2087 void VerifySsData(const RTPVideoHeaderVP9& vp9) const {
2088 EXPECT_TRUE(vp9.ss_data_available); // V
2089 EXPECT_EQ(vp9_settings_.numberOfSpatialLayers, // N_S + 1
2090 vp9.num_spatial_layers);
2091 EXPECT_TRUE(vp9.spatial_layer_resolution_present); // Y:1
2092 size_t expected_width = encoder_config_.streams[0].width;
2093 size_t expected_height = encoder_config_.streams[0].height;
2094 for (int i = vp9.num_spatial_layers - 1; i >= 0; --i) {
2095 EXPECT_EQ(expected_width, vp9.width[i]); // WIDTH
2096 EXPECT_EQ(expected_height, vp9.height[i]); // HEIGHT
2097 expected_width /= 2;
2098 expected_height /= 2;
2099 }
2100 }
2101
2102 void CompareConsecutiveFrames(const RTPHeader& header,
2103 const RTPVideoHeader& video) const {
2104 const RTPVideoHeaderVP9& vp9 = video.codecHeader.VP9;
2105
2106 bool new_frame = packets_sent_ == 0 ||
2107 IsNewerTimestamp(header.timestamp, last_header_.timestamp);
2108 EXPECT_EQ(new_frame, video.isFirstPacket);
2109 if (!new_frame) {
2110 EXPECT_FALSE(last_header_.markerBit);
2111 EXPECT_EQ(last_header_.timestamp, header.timestamp);
2112 EXPECT_EQ(last_vp9_.picture_id, vp9.picture_id);
2113 EXPECT_EQ(last_vp9_.temporal_idx, vp9.temporal_idx);
2114 EXPECT_EQ(last_vp9_.tl0_pic_idx, vp9.tl0_pic_idx);
2115 VerifySpatialIdxWithinFrame(vp9);
2116 return;
2117 }
2118 // New frame.
2119 EXPECT_TRUE(vp9.beginning_of_frame);
2120
2121 // Compare with last packet in previous frame.
2122 if (frames_sent_ == 0)
2123 return;
2124 EXPECT_TRUE(last_vp9_.end_of_frame);
2125 EXPECT_TRUE(last_header_.markerBit);
2126 EXPECT_TRUE(ContinuousPictureId(vp9));
2127 VerifyTl0Idx(vp9);
2128 }
2129
kwiberg27f982b2016-03-01 11:52:33 -08002130 std::unique_ptr<VP9Encoder> vp9_encoder_;
philipel0f9af012015-09-01 07:01:51 -07002131 VideoCodecVP9 vp9_settings_;
Åsa Perssonff24c042015-12-04 10:58:08 +01002132 webrtc::VideoEncoderConfig encoder_config_;
2133 RTPHeader last_header_;
2134 RTPVideoHeaderVP9 last_vp9_;
2135 size_t packets_sent_;
2136 size_t frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07002137};
2138
Åsa Perssonff24c042015-12-04 10:58:08 +01002139TEST_F(VideoSendStreamTest, Vp9NonFlexMode_1Tl1SLayers) {
2140 const uint8_t kNumTemporalLayers = 1;
2141 const uint8_t kNumSpatialLayers = 1;
2142 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2143}
2144
2145TEST_F(VideoSendStreamTest, Vp9NonFlexMode_2Tl1SLayers) {
2146 const uint8_t kNumTemporalLayers = 2;
2147 const uint8_t kNumSpatialLayers = 1;
2148 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2149}
2150
2151TEST_F(VideoSendStreamTest, Vp9NonFlexMode_3Tl1SLayers) {
2152 const uint8_t kNumTemporalLayers = 3;
2153 const uint8_t kNumSpatialLayers = 1;
2154 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2155}
2156
2157TEST_F(VideoSendStreamTest, Vp9NonFlexMode_1Tl2SLayers) {
2158 const uint8_t kNumTemporalLayers = 1;
2159 const uint8_t kNumSpatialLayers = 2;
2160 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2161}
2162
2163TEST_F(VideoSendStreamTest, Vp9NonFlexMode_2Tl2SLayers) {
2164 const uint8_t kNumTemporalLayers = 2;
2165 const uint8_t kNumSpatialLayers = 2;
2166 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2167}
2168
2169TEST_F(VideoSendStreamTest, Vp9NonFlexMode_3Tl2SLayers) {
2170 const uint8_t kNumTemporalLayers = 3;
2171 const uint8_t kNumSpatialLayers = 2;
2172 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2173}
2174
2175void VideoSendStreamTest::TestVp9NonFlexMode(uint8_t num_temporal_layers,
2176 uint8_t num_spatial_layers) {
2177 static const size_t kNumFramesToSend = 100;
2178 // Set to < kNumFramesToSend and coprime to length of temporal layer
2179 // structures to verify temporal id reset on key frame.
2180 static const int kKeyFrameInterval = 31;
2181 class NonFlexibleMode : public Vp9HeaderObserver {
2182 public:
2183 NonFlexibleMode(uint8_t num_temporal_layers, uint8_t num_spatial_layers)
2184 : num_temporal_layers_(num_temporal_layers),
2185 num_spatial_layers_(num_spatial_layers),
2186 l_field_(num_temporal_layers > 1 || num_spatial_layers > 1) {}
stefanff483612015-12-21 03:14:00 -08002187 void ModifyVideoConfigsHook(
philipel0f9af012015-09-01 07:01:51 -07002188 VideoSendStream::Config* send_config,
2189 std::vector<VideoReceiveStream::Config>* receive_configs,
2190 VideoEncoderConfig* encoder_config) override {
Åsa Perssonff24c042015-12-04 10:58:08 +01002191 vp9_settings_.flexibleMode = false;
2192 vp9_settings_.frameDroppingOn = false;
2193 vp9_settings_.keyFrameInterval = kKeyFrameInterval;
2194 vp9_settings_.numberOfTemporalLayers = num_temporal_layers_;
2195 vp9_settings_.numberOfSpatialLayers = num_spatial_layers_;
philipel0f9af012015-09-01 07:01:51 -07002196 }
2197
Åsa Perssonff24c042015-12-04 10:58:08 +01002198 void InspectHeader(const RTPVideoHeaderVP9& vp9) override {
2199 bool ss_data_expected = !vp9.inter_pic_predicted &&
2200 vp9.beginning_of_frame && vp9.spatial_idx == 0;
2201 EXPECT_EQ(ss_data_expected, vp9.ss_data_available);
2202 EXPECT_EQ(vp9.spatial_idx > 0, vp9.inter_layer_predicted); // D
asapersson38bb8ad2015-12-14 01:41:19 -08002203 EXPECT_EQ(!vp9.inter_pic_predicted,
2204 frames_sent_ % kKeyFrameInterval == 0);
Åsa Perssonff24c042015-12-04 10:58:08 +01002205
2206 if (IsNewPictureId(vp9)) {
2207 EXPECT_EQ(0, vp9.spatial_idx);
2208 EXPECT_EQ(num_spatial_layers_ - 1, last_vp9_.spatial_idx);
2209 }
2210
2211 VerifyFixedTemporalLayerStructure(vp9,
2212 l_field_ ? num_temporal_layers_ : 0);
2213
2214 if (frames_sent_ > kNumFramesToSend)
Peter Boström5811a392015-12-10 13:02:50 +01002215 observation_complete_.Set();
philipel0f9af012015-09-01 07:01:51 -07002216 }
Åsa Perssonff24c042015-12-04 10:58:08 +01002217 const uint8_t num_temporal_layers_;
2218 const uint8_t num_spatial_layers_;
2219 const bool l_field_;
2220 } test(num_temporal_layers, num_spatial_layers);
philipelcfc319b2015-11-10 07:17:23 -08002221
stefane74eef12016-01-08 06:47:13 -08002222 RunBaseTest(&test);
philipelcfc319b2015-11-10 07:17:23 -08002223}
2224
asaperssond9f641e2016-01-21 01:11:35 -08002225TEST_F(VideoSendStreamTest, Vp9NonFlexModeSmallResolution) {
2226 static const size_t kNumFramesToSend = 50;
2227 static const int kWidth = 4;
2228 static const int kHeight = 4;
2229 class NonFlexibleModeResolution : public Vp9HeaderObserver {
2230 void ModifyVideoConfigsHook(
2231 VideoSendStream::Config* send_config,
2232 std::vector<VideoReceiveStream::Config>* receive_configs,
2233 VideoEncoderConfig* encoder_config) override {
2234 vp9_settings_.flexibleMode = false;
2235 vp9_settings_.numberOfTemporalLayers = 1;
2236 vp9_settings_.numberOfSpatialLayers = 1;
2237
2238 EXPECT_EQ(1u, encoder_config->streams.size());
2239 encoder_config->streams[0].width = kWidth;
2240 encoder_config->streams[0].height = kHeight;
2241 }
2242
2243 void InspectHeader(const RTPVideoHeaderVP9& vp9_header) override {
2244 if (frames_sent_ > kNumFramesToSend)
2245 observation_complete_.Set();
2246 }
2247 } test;
2248
2249 RunBaseTest(&test);
2250}
2251
kjellander44cc7952016-01-06 22:12:27 -08002252#if !defined(MEMORY_SANITIZER)
2253// Fails under MemorySanitizer:
2254// See https://code.google.com/p/webrtc/issues/detail?id=5402.
Åsa Perssonff24c042015-12-04 10:58:08 +01002255TEST_F(VideoSendStreamTest, Vp9FlexModeRefCount) {
2256 class FlexibleMode : public Vp9HeaderObserver {
stefanff483612015-12-21 03:14:00 -08002257 void ModifyVideoConfigsHook(
philipelcfc319b2015-11-10 07:17:23 -08002258 VideoSendStream::Config* send_config,
2259 std::vector<VideoReceiveStream::Config>* receive_configs,
2260 VideoEncoderConfig* encoder_config) override {
Åsa Perssonff24c042015-12-04 10:58:08 +01002261 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
philipelcfc319b2015-11-10 07:17:23 -08002262 vp9_settings_.flexibleMode = true;
Åsa Perssonff24c042015-12-04 10:58:08 +01002263 vp9_settings_.numberOfTemporalLayers = 1;
2264 vp9_settings_.numberOfSpatialLayers = 2;
philipelcfc319b2015-11-10 07:17:23 -08002265 }
2266
Åsa Perssonff24c042015-12-04 10:58:08 +01002267 void InspectHeader(const RTPVideoHeaderVP9& vp9_header) override {
2268 EXPECT_TRUE(vp9_header.flexible_mode);
2269 EXPECT_EQ(kNoTl0PicIdx, vp9_header.tl0_pic_idx);
2270 if (vp9_header.inter_pic_predicted) {
2271 EXPECT_GT(vp9_header.num_ref_pics, 0u);
Peter Boström5811a392015-12-10 13:02:50 +01002272 observation_complete_.Set();
philipelcfc319b2015-11-10 07:17:23 -08002273 }
2274 }
2275 } test;
2276
stefane74eef12016-01-08 06:47:13 -08002277 RunBaseTest(&test);
philipelcfc319b2015-11-10 07:17:23 -08002278}
kjellander44cc7952016-01-06 22:12:27 -08002279#endif
philipelcfc319b2015-11-10 07:17:23 -08002280
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +00002281} // namespace webrtc