blob: 0f44c6fd5224f40386e14c5b05247e3966ed311f [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
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +000011#include <vector>
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +000012
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000013#include "testing/gtest/include/gtest/gtest.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000014
Per9b3f56e2015-04-09 13:44:16 +020015#include "webrtc/base/bind.h"
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000016#include "webrtc/base/checks.h"
Peter Boströmff019b02015-04-30 14:16:07 +020017#include "webrtc/base/criticalsection.h"
Peter Boström415d2cd2015-10-26 11:35:17 +010018#include "webrtc/base/logging.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000019#include "webrtc/base/scoped_ptr.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000020#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020021#include "webrtc/call/transport_adapter.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000022#include "webrtc/frame_callback.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010023#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
24#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000025#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
pbos@webrtc.org013d9942013-08-22 09:42:17 +000026#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
philipel0f9af012015-09-01 07:01:51 -070027#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h"
philipel7fabd462015-09-03 04:42:32 -070028#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010029#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
30#include "webrtc/system_wrappers/include/event_wrapper.h"
31#include "webrtc/system_wrappers/include/ref_count.h"
32#include "webrtc/system_wrappers/include/sleep.h"
33#include "webrtc/system_wrappers/include/thread_wrapper.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000034#include "webrtc/test/call_test.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000035#include "webrtc/test/configurable_frame_size_encoder.h"
Peter Boströmeb66e802015-06-05 11:08:03 +020036#include "webrtc/test/fake_texture_frame.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000037#include "webrtc/test/null_transport.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000038#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.org273a4142014-12-01 15:23:21 +000039#include "webrtc/video/send_statistics_proxy.h"
Thiago Farina9bfe3da2015-04-10 12:52:13 +020040#include "webrtc/video_frame.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000041#include "webrtc/video_send_stream.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000042
43namespace webrtc {
44
sprang@webrtc.org346094c2014-02-18 08:40:33 +000045enum VideoFormat { kGeneric, kVP8, };
46
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070047void ExpectEqualFrames(const VideoFrame& frame1, const VideoFrame& frame2);
48void ExpectEqualTextureFrames(const VideoFrame& frame1,
49 const VideoFrame& frame2);
50void ExpectEqualBufferFrames(const VideoFrame& frame1,
51 const VideoFrame& frame2);
52void ExpectEqualFramesVector(const std::vector<VideoFrame>& frames1,
53 const std::vector<VideoFrame>& frames2);
54VideoFrame CreateVideoFrame(int width, int height, uint8_t data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000055
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000056class VideoSendStreamTest : public test::CallTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000057 protected:
stefan@webrtc.org69969e22013-11-15 12:32:15 +000058 void TestNackRetransmission(uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +000059 uint8_t retransmit_payload_type);
sprang@webrtc.org346094c2014-02-18 08:40:33 +000060 void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
pbos@webrtc.org013d9942013-08-22 09:42:17 +000061};
62
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000063TEST_F(VideoSendStreamTest, CanStartStartedStream) {
solenberg4fbae2b2015-08-28 04:07:10 -070064 Call::Config call_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000065 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000066
solenberg4fbae2b2015-08-28 04:07:10 -070067 test::NullTransport transport;
68 CreateSendConfig(1, &transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000069 CreateStreams();
70 send_stream_->Start();
71 send_stream_->Start();
72 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000073}
74
75TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
solenberg4fbae2b2015-08-28 04:07:10 -070076 Call::Config call_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000077 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000078
solenberg4fbae2b2015-08-28 04:07:10 -070079 test::NullTransport transport;
80 CreateSendConfig(1, &transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000081 CreateStreams();
82 send_stream_->Stop();
83 send_stream_->Stop();
84 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000085}
86
pbos@webrtc.org013d9942013-08-22 09:42:17 +000087TEST_F(VideoSendStreamTest, SupportsCName) {
88 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000089 class CNameObserver : public test::SendTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000090 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000091 CNameObserver() : SendTest(kDefaultTimeoutMs) {}
pbos@webrtc.org013d9942013-08-22 09:42:17 +000092
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000093 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000094 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000095 RTCPUtility::RTCPParserV2 parser(packet, length, true);
96 EXPECT_TRUE(parser.IsValid());
97
98 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +020099 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
100 if (packet_type == RTCPUtility::RTCPPacketTypes::kSdesChunk) {
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000101 EXPECT_EQ(parser.Packet().CName.CName, kCName);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000102 observation_complete_->Set();
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000103 }
104
105 packet_type = parser.Iterate();
106 }
107
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000108 return SEND_PACKET;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000109 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000110
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000111 void ModifyConfigs(VideoSendStream::Config* send_config,
112 std::vector<VideoReceiveStream::Config>* receive_configs,
113 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000114 send_config->rtp.c_name = kCName;
115 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000116
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000117 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000118 EXPECT_EQ(kEventSignaled, Wait())
119 << "Timed out while waiting for RTCP with CNAME.";
120 }
121 } test;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000122
stefanf116bd02015-10-27 08:29:42 -0700123 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000124}
125
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000126TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
127 static const uint8_t kAbsSendTimeExtensionId = 13;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000128 class AbsoluteSendTimeObserver : public test::SendTest {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000129 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000130 AbsoluteSendTimeObserver() : SendTest(kDefaultTimeoutMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000131 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000132 kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId));
133 }
134
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000135 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000136 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000137 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000138
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000139 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
140 EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
141 EXPECT_EQ(header.extension.transmissionTimeOffset, 0);
142 EXPECT_GT(header.extension.absoluteSendTime, 0u);
143 observation_complete_->Set();
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000144
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000145 return SEND_PACKET;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000146 }
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000147
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000148 void ModifyConfigs(VideoSendStream::Config* send_config,
149 std::vector<VideoReceiveStream::Config>* receive_configs,
150 VideoEncoderConfig* encoder_config) override {
Erik Språng95261872015-04-10 11:58:49 +0200151 send_config->rtp.extensions.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000152 send_config->rtp.extensions.push_back(
153 RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
154 }
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +0000155
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000156 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000157 EXPECT_EQ(kEventSignaled, Wait())
158 << "Timed out while waiting for single RTP packet.";
159 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000160 } test;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000161
stefanf116bd02015-10-27 08:29:42 -0700162 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000163}
164
pbos@webrtc.org29023282013-09-11 10:14:56 +0000165TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000166 static const int kEncodeDelayMs = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000167 class TransmissionTimeOffsetObserver : public test::SendTest {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000168 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000169 TransmissionTimeOffsetObserver()
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000170 : SendTest(kDefaultTimeoutMs),
171 encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000172 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
Stefan Holmer12952972015-10-29 15:13:24 +0100173 kRtpExtensionTransmissionTimeOffset, test::kTOffsetExtensionId));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000174 }
175
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000176 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000177 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000178 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000179 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000180
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000181 EXPECT_TRUE(header.extension.hasTransmissionTimeOffset);
182 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000183 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000184 EXPECT_EQ(header.extension.absoluteSendTime, 0u);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000185 observation_complete_->Set();
pbos@webrtc.org29023282013-09-11 10:14:56 +0000186
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000187 return SEND_PACKET;
pbos@webrtc.org29023282013-09-11 10:14:56 +0000188 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000189
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000190 void ModifyConfigs(VideoSendStream::Config* send_config,
191 std::vector<VideoReceiveStream::Config>* receive_configs,
192 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000193 send_config->encoder_settings.encoder = &encoder_;
Stefan Holmer12952972015-10-29 15:13:24 +0100194 send_config->rtp.extensions.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000195 send_config->rtp.extensions.push_back(
Stefan Holmer12952972015-10-29 15:13:24 +0100196 RtpExtension(RtpExtension::kTOffset, test::kTOffsetExtensionId));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000197 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000198
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000199 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000200 EXPECT_EQ(kEventSignaled, Wait())
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +0000201 << "Timed out while waiting for a single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000202 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000203
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000204 test::DelayedEncoder encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000205 } test;
206
stefanf116bd02015-10-27 08:29:42 -0700207 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org29023282013-09-11 10:14:56 +0000208}
209
sprang867fb522015-08-03 04:38:41 -0700210TEST_F(VideoSendStreamTest, SupportsTransportWideSequenceNumbers) {
211 static const uint8_t kExtensionId = 13;
212 class TransportWideSequenceNumberObserver : public test::SendTest {
213 public:
214 TransportWideSequenceNumberObserver()
215 : SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) {
216 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
217 kRtpExtensionTransportSequenceNumber, kExtensionId));
218 }
219
220 private:
221 Action OnSendRtp(const uint8_t* packet, size_t length) override {
222 RTPHeader header;
223 EXPECT_TRUE(parser_->Parse(packet, length, &header));
224
225 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
226 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
227 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
228
229 observation_complete_->Set();
230
231 return SEND_PACKET;
232 }
233
234 void ModifyConfigs(VideoSendStream::Config* send_config,
235 std::vector<VideoReceiveStream::Config>* receive_configs,
236 VideoEncoderConfig* encoder_config) override {
237 send_config->encoder_settings.encoder = &encoder_;
Stefan Holmer12952972015-10-29 15:13:24 +0100238 send_config->rtp.extensions.clear();
sprang867fb522015-08-03 04:38:41 -0700239 send_config->rtp.extensions.push_back(
240 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
241 }
242
243 void PerformTest() override {
244 EXPECT_EQ(kEventSignaled, Wait())
245 << "Timed out while waiting for a single RTP packet.";
246 }
247
248 test::FakeEncoder encoder_;
249 } test;
250
stefanf116bd02015-10-27 08:29:42 -0700251 RunBaseTest(&test, FakeNetworkPipe::Config());
sprang867fb522015-08-03 04:38:41 -0700252}
253
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000254class FakeReceiveStatistics : public NullReceiveStatistics {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000255 public:
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000256 FakeReceiveStatistics(uint32_t send_ssrc,
257 uint32_t last_sequence_number,
258 uint32_t cumulative_lost,
259 uint8_t fraction_lost)
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000260 : lossy_stats_(new LossyStatistician(last_sequence_number,
261 cumulative_lost,
262 fraction_lost)) {
263 stats_map_[send_ssrc] = lossy_stats_.get();
264 }
265
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000266 StatisticianMap GetActiveStatisticians() const override { return stats_map_; }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000267
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000268 StreamStatistician* GetStatistician(uint32_t ssrc) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000269 return lossy_stats_.get();
270 }
271
272 private:
273 class LossyStatistician : public StreamStatistician {
274 public:
275 LossyStatistician(uint32_t extended_max_sequence_number,
276 uint32_t cumulative_lost,
277 uint8_t fraction_lost) {
278 stats_.fraction_lost = fraction_lost;
279 stats_.cumulative_lost = cumulative_lost;
280 stats_.extended_max_sequence_number = extended_max_sequence_number;
281 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000282 bool GetStatistics(RtcpStatistics* statistics, bool reset) override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000283 *statistics = stats_;
284 return true;
285 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000286 void GetDataCounters(size_t* bytes_received,
287 uint32_t* packets_received) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000288 *bytes_received = 0;
289 *packets_received = 0;
290 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000291 void GetReceiveStreamDataCounters(
292 StreamDataCounters* data_counters) const override {}
293 uint32_t BitrateReceived() const override { return 0; }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000294 bool IsRetransmitOfOldPacket(const RTPHeader& header,
295 int64_t min_rtt) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000296 return false;
297 }
298
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000299 bool IsPacketInOrder(uint16_t sequence_number) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000300 return true;
301 }
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000302
303 RtcpStatistics stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000304 };
305
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000306 rtc::scoped_ptr<LossyStatistician> lossy_stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000307 StatisticianMap stats_map_;
308};
309
310TEST_F(VideoSendStreamTest, SupportsFec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000311 class FecObserver : public test::SendTest {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000312 public:
313 FecObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000314 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000315 send_count_(0),
316 received_media_(false),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000317 received_fec_(false) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000318 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000319
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000320 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000321 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000322 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000323 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000324
325 // Send lossy receive reports to trigger FEC enabling.
326 if (send_count_++ % 2 != 0) {
327 // Receive statistics reporting having lost 50% of the packets.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000328 FakeReceiveStatistics lossy_receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000329 kSendSsrcs[0], header.sequenceNumber, send_count_ / 2, 127);
Peter Boströmac547a62015-09-17 23:03:57 +0200330 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
sprang86fd9ed2015-09-29 04:45:43 -0700331 &lossy_receive_stats, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700332 transport_adapter_.get());
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000333
pbosda903ea2015-10-02 02:36:56 -0700334 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000335 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000336
337 RTCPSender::FeedbackState feedback_state;
338
339 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
340 }
341
Stefan Holmer01b48882015-05-05 10:21:24 +0200342 int encapsulated_payload_type = -1;
343 if (header.payloadType == kRedPayloadType) {
344 encapsulated_payload_type =
345 static_cast<int>(packet[header.headerLength]);
346 if (encapsulated_payload_type != kFakeSendPayloadType)
347 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000348 } else {
Stefan Holmer01b48882015-05-05 10:21:24 +0200349 EXPECT_EQ(kFakeSendPayloadType, header.payloadType);
350 }
351
352 if (encapsulated_payload_type != -1) {
353 if (encapsulated_payload_type == kUlpfecPayloadType) {
354 received_fec_ = true;
355 } else {
356 received_media_ = true;
357 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000358 }
359
360 if (received_media_ && received_fec_)
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000361 observation_complete_->Set();
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000362
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000363 return SEND_PACKET;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000364 }
365
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000366 void ModifyConfigs(VideoSendStream::Config* send_config,
367 std::vector<VideoReceiveStream::Config>* receive_configs,
368 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700369 transport_adapter_.reset(
370 new internal::TransportAdapter(send_config->send_transport));
371 transport_adapter_->Enable();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000372 send_config->rtp.fec.red_payload_type = kRedPayloadType;
373 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
374 }
375
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000376 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000377 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
378 }
379
stefanf116bd02015-10-27 08:29:42 -0700380 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000381 int send_count_;
382 bool received_media_;
383 bool received_fec_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000384 } test;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000385
stefanf116bd02015-10-27 08:29:42 -0700386 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000387}
388
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000389void VideoSendStreamTest::TestNackRetransmission(
390 uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000391 uint8_t retransmit_payload_type) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000392 class NackObserver : public test::SendTest {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000393 public:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000394 explicit NackObserver(uint32_t retransmit_ssrc,
395 uint8_t retransmit_payload_type)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000396 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000397 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000398 retransmit_ssrc_(retransmit_ssrc),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000399 retransmit_payload_type_(retransmit_payload_type),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000400 nacked_sequence_number_(-1) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000401 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000402
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000403 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000404 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000405 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000406 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000407
408 // Nack second packet after receiving the third one.
409 if (++send_count_ == 3) {
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000410 uint16_t nack_sequence_number = header.sequenceNumber - 1;
411 nacked_sequence_number_ = nack_sequence_number;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000412 NullReceiveStatistics null_stats;
Peter Boströmac547a62015-09-17 23:03:57 +0200413 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), &null_stats,
stefanf116bd02015-10-27 08:29:42 -0700414 nullptr, transport_adapter_.get());
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000415
pbosda903ea2015-10-02 02:36:56 -0700416 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000417 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000418
419 RTCPSender::FeedbackState feedback_state;
420
421 EXPECT_EQ(0,
422 rtcp_sender.SendRTCP(
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000423 feedback_state, kRtcpNack, 1, &nack_sequence_number));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000424 }
425
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000426 uint16_t sequence_number = header.sequenceNumber;
427
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000428 if (header.ssrc == retransmit_ssrc_ &&
429 retransmit_ssrc_ != kSendSsrcs[0]) {
430 // Not kSendSsrcs[0], assume correct RTX packet. Extract sequence
431 // number.
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000432 const uint8_t* rtx_header = packet + header.headerLength;
433 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
434 }
435
436 if (sequence_number == nacked_sequence_number_) {
437 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000438 EXPECT_EQ(retransmit_payload_type_, header.payloadType);
439 observation_complete_->Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000440 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000441
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000442 return SEND_PACKET;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000443 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000444
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000445 void ModifyConfigs(VideoSendStream::Config* send_config,
446 std::vector<VideoReceiveStream::Config>* receive_configs,
447 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700448 transport_adapter_.reset(
449 new internal::TransportAdapter(send_config->send_transport));
450 transport_adapter_->Enable();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000451 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000452 send_config->rtp.rtx.payload_type = retransmit_payload_type_;
453 if (retransmit_ssrc_ != kSendSsrcs[0])
454 send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
455 }
456
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000457 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000458 EXPECT_EQ(kEventSignaled, Wait())
459 << "Timed out while waiting for NACK retransmission.";
460 }
461
stefanf116bd02015-10-27 08:29:42 -0700462 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000463 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000464 uint32_t retransmit_ssrc_;
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000465 uint8_t retransmit_payload_type_;
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000466 int nacked_sequence_number_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000467 } test(retransmit_ssrc, retransmit_payload_type);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000468
stefanf116bd02015-10-27 08:29:42 -0700469 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000470}
471
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000472TEST_F(VideoSendStreamTest, RetransmitsNack) {
473 // Normal NACKs should use the send SSRC.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000474 TestNackRetransmission(kSendSsrcs[0], kFakeSendPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000475}
476
477TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
478 // NACKs over RTX should use a separate SSRC.
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000479 TestNackRetransmission(kSendRtxSsrcs[0], kSendRtxPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000480}
481
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000482void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
483 bool with_fec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000484 // Use a fake encoder to output a frame of every size in the range [90, 290],
485 // for each size making sure that the exact number of payload bytes received
486 // is correct and that packets are fragmented to respect max packet size.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000487 static const size_t kMaxPacketSize = 128;
488 static const size_t start = 90;
489 static const size_t stop = 290;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000490
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000491 // Observer that verifies that the expected number of packets and bytes
492 // arrive for each frame size, from start_size to stop_size.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000493 class FrameFragmentationTest : public test::SendTest,
494 public EncodedFrameObserver {
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000495 public:
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000496 FrameFragmentationTest(size_t max_packet_size,
497 size_t start_size,
498 size_t stop_size,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000499 bool test_generic_packetization,
500 bool use_fec)
501 : SendTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000502 encoder_(stop),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000503 max_packet_size_(max_packet_size),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000504 stop_size_(stop_size),
505 test_generic_packetization_(test_generic_packetization),
506 use_fec_(use_fec),
507 packet_count_(0),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000508 accumulated_size_(0),
509 accumulated_payload_(0),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000510 fec_packet_received_(false),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000511 current_size_rtp_(start_size),
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000512 current_size_frame_(static_cast<int32_t>(start_size)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000513 // Fragmentation required, this test doesn't make sense without it.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000514 encoder_.SetFrameSize(start_size);
henrikg91d6ede2015-09-17 00:24:34 -0700515 RTC_DCHECK_GT(stop_size, max_packet_size);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000516 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000517
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000518 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000519 Action OnSendRtp(const uint8_t* packet, size_t size) override {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000520 size_t length = size;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000521 RTPHeader header;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000522 EXPECT_TRUE(parser_->Parse(packet, length, &header));
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000523
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000524 EXPECT_LE(length, max_packet_size_);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000525
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000526 if (use_fec_) {
527 uint8_t payload_type = packet[header.headerLength];
528 bool is_fec = header.payloadType == kRedPayloadType &&
529 payload_type == kUlpfecPayloadType;
530 if (is_fec) {
531 fec_packet_received_ = true;
532 return SEND_PACKET;
533 }
534 }
535
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000536 accumulated_size_ += length;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000537
538 if (use_fec_)
539 TriggerLossReport(header);
540
541 if (test_generic_packetization_) {
Stefan Holmer586b19b2015-09-18 11:14:31 +0200542 size_t overhead = header.headerLength + header.paddingLength;
543 // Only remove payload header and RED header if the packet actually
544 // contains payload.
545 if (length > overhead) {
546 overhead += (1 /* Generic header */);
547 if (use_fec_)
548 overhead += 1; // RED for FEC header.
549 }
550 EXPECT_GE(length, overhead);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000551 accumulated_payload_ += length - overhead;
552 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000553
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000554 // Marker bit set indicates last packet of a frame.
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000555 if (header.markerBit) {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000556 if (use_fec_ && accumulated_payload_ == current_size_rtp_ - 1) {
557 // With FEC enabled, frame size is incremented asynchronously, so
558 // "old" frames one byte too small may arrive. Accept, but don't
559 // increase expected frame size.
560 accumulated_size_ = 0;
561 accumulated_payload_ = 0;
562 return SEND_PACKET;
563 }
564
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000565 EXPECT_GE(accumulated_size_, current_size_rtp_);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000566 if (test_generic_packetization_) {
567 EXPECT_EQ(current_size_rtp_, accumulated_payload_);
568 }
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000569
570 // Last packet of frame; reset counters.
571 accumulated_size_ = 0;
572 accumulated_payload_ = 0;
573 if (current_size_rtp_ == stop_size_) {
574 // Done! (Don't increase size again, might arrive more @ stop_size).
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000575 observation_complete_->Set();
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000576 } else {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000577 // Increase next expected frame size. If testing with FEC, make sure
578 // a FEC packet has been received for this frame size before
579 // proceeding, to make sure that redundancy packets don't exceed
580 // size limit.
581 if (!use_fec_) {
582 ++current_size_rtp_;
583 } else if (fec_packet_received_) {
584 fec_packet_received_ = false;
585 ++current_size_rtp_;
586 ++current_size_frame_;
587 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000588 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000589 }
590
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000591 return SEND_PACKET;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000592 }
593
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000594 void TriggerLossReport(const RTPHeader& header) {
595 // Send lossy receive reports to trigger FEC enabling.
596 if (packet_count_++ % 2 != 0) {
597 // Receive statistics reporting having lost 50% of the packets.
598 FakeReceiveStatistics lossy_receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000599 kSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127);
Peter Boströmac547a62015-09-17 23:03:57 +0200600 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
sprang86fd9ed2015-09-29 04:45:43 -0700601 &lossy_receive_stats, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700602 transport_adapter_.get());
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000603
pbosda903ea2015-10-02 02:36:56 -0700604 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000605 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000606
607 RTCPSender::FeedbackState feedback_state;
608
609 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
610 }
611 }
612
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000613 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
614 // Increase frame size for next encoded frame, in the context of the
615 // encoder thread.
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000616 if (!use_fec_ &&
617 current_size_frame_.Value() < static_cast<int32_t>(stop_size_)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000618 ++current_size_frame_;
619 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000620 encoder_.SetFrameSize(static_cast<size_t>(current_size_frame_.Value()));
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000621 }
622
Stefan Holmere5904162015-03-26 11:11:06 +0100623 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700624 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100625 const int kMinBitrateBps = 30000;
626 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
627 return config;
628 }
629
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000630 void ModifyConfigs(VideoSendStream::Config* send_config,
631 std::vector<VideoReceiveStream::Config>* receive_configs,
632 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700633 transport_adapter_.reset(
634 new internal::TransportAdapter(send_config->send_transport));
635 transport_adapter_->Enable();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000636 if (use_fec_) {
637 send_config->rtp.fec.red_payload_type = kRedPayloadType;
638 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
639 }
640
641 if (!test_generic_packetization_)
642 send_config->encoder_settings.payload_name = "VP8";
643
644 send_config->encoder_settings.encoder = &encoder_;
645 send_config->rtp.max_packet_size = kMaxPacketSize;
646 send_config->post_encode_callback = this;
647
Erik Språng95261872015-04-10 11:58:49 +0200648 // Make sure there is at least one extension header, to make the RTP
649 // header larger than the base length of 12 bytes.
650 EXPECT_FALSE(send_config->rtp.extensions.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000651 }
652
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000653 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000654 EXPECT_EQ(kEventSignaled, Wait())
655 << "Timed out while observing incoming RTP packets.";
656 }
657
stefanf116bd02015-10-27 08:29:42 -0700658 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000659 test::ConfigurableFrameSizeEncoder encoder_;
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000660
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000661 const size_t max_packet_size_;
662 const size_t stop_size_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000663 const bool test_generic_packetization_;
664 const bool use_fec_;
665
666 uint32_t packet_count_;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000667 size_t accumulated_size_;
668 size_t accumulated_payload_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000669 bool fec_packet_received_;
670
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000671 size_t current_size_rtp_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000672 Atomic32 current_size_frame_;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000673 };
674
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000675 // Don't auto increment if FEC is used; continue sending frame size until
676 // a FEC packet has been received.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000677 FrameFragmentationTest test(
678 kMaxPacketSize, start, stop, format == kGeneric, with_fec);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000679
stefanf116bd02015-10-27 08:29:42 -0700680 RunBaseTest(&test, FakeNetworkPipe::Config());
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000681}
682
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000683// TODO(sprang): Is there any way of speeding up these tests?
684TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSize) {
685 TestPacketFragmentationSize(kGeneric, false);
686}
687
688TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSizeWithFec) {
689 TestPacketFragmentationSize(kGeneric, true);
690}
691
692TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSize) {
693 TestPacketFragmentationSize(kVP8, false);
694}
695
696TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSizeWithFec) {
697 TestPacketFragmentationSize(kVP8, true);
698}
699
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000700// The test will go through a number of phases.
701// 1. Start sending packets.
702// 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 +0000703// suspend the stream.
704// 3. Wait until |kSuspendTimeFrames| have been captured without seeing any RTP
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000705// packets.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000706// 4. Signal a high REMB and then wait for the RTP stream to start again.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000707// When the stream is detected again, and the stats show that the stream
708// is no longer suspended, the test ends.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000709TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
710 static const int kSuspendTimeFrames = 60; // Suspend for 2 seconds @ 30 fps.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000711
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000712 class RembObserver : public test::SendTest, public I420FrameCallback {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000713 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000714 RembObserver()
715 : SendTest(kDefaultTimeoutMs),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000716 clock_(Clock::GetRealTimeClock()),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000717 test_state_(kBeforeSuspend),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000718 rtp_count_(0),
719 last_sequence_number_(0),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000720 suspended_frame_count_(0),
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000721 low_remb_bps_(0),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000722 high_remb_bps_(0) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000723 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000724
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000725 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000726 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200727 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000728 ++rtp_count_;
729 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000730 EXPECT_TRUE(parser_->Parse(packet, length, &header));
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000731 last_sequence_number_ = header.sequenceNumber;
732
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000733 if (test_state_ == kBeforeSuspend) {
734 // The stream has started. Try to suspend it.
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000735 SendRtcpFeedback(low_remb_bps_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000736 test_state_ = kDuringSuspend;
737 } else if (test_state_ == kDuringSuspend) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000738 if (header.paddingLength == 0) {
739 // Received non-padding packet during suspension period. Reset the
740 // counter.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000741 suspended_frame_count_ = 0;
742 }
stefanf116bd02015-10-27 08:29:42 -0700743 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000744 } else if (test_state_ == kWaitingForPacket) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000745 if (header.paddingLength == 0) {
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000746 // Non-padding packet observed. Test is almost complete. Will just
747 // have to wait for the stats to change.
748 test_state_ = kWaitingForStats;
749 }
stefanf116bd02015-10-27 08:29:42 -0700750 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000751 } else if (test_state_ == kWaitingForStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000752 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000753 if (stats.suspended == false) {
754 // Stats flipped to false. Test is complete.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000755 observation_complete_->Set();
756 }
stefanf116bd02015-10-27 08:29:42 -0700757 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000758 }
759
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000760 return SEND_PACKET;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000761 }
762
763 // This method implements the I420FrameCallback.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700764 void FrameCallback(VideoFrame* video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200765 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000766 if (test_state_ == kDuringSuspend &&
767 ++suspended_frame_count_ > kSuspendTimeFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000768 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000769 EXPECT_TRUE(stats.suspended);
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000770 SendRtcpFeedback(high_remb_bps_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000771 test_state_ = kWaitingForPacket;
772 }
773 }
774
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000775 void set_low_remb_bps(int value) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200776 rtc::CritScope lock(&crit_);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000777 low_remb_bps_ = value;
778 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000779
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000780 void set_high_remb_bps(int value) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200781 rtc::CritScope lock(&crit_);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000782 high_remb_bps_ = value;
783 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000784
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000785 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000786 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000787 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000788 stream_ = send_stream;
789 }
790
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000791 void ModifyConfigs(VideoSendStream::Config* send_config,
792 std::vector<VideoReceiveStream::Config>* receive_configs,
793 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700794 transport_adapter_.reset(
795 new internal::TransportAdapter(send_config->send_transport));
796 transport_adapter_->Enable();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000797 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000798 send_config->pre_encode_callback = this;
799 send_config->suspend_below_min_bitrate = true;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000800 int min_bitrate_bps = encoder_config->streams[0].min_bitrate_bps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000801 set_low_remb_bps(min_bitrate_bps - 10000);
802 int threshold_window = std::max(min_bitrate_bps / 10, 10000);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000803 ASSERT_GT(encoder_config->streams[0].max_bitrate_bps,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000804 min_bitrate_bps + threshold_window + 5000);
805 set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
806 }
807
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000808 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000809 EXPECT_EQ(kEventSignaled, Wait())
810 << "Timed out during suspend-below-min-bitrate test.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000811 }
812
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000813 enum TestState {
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000814 kBeforeSuspend,
815 kDuringSuspend,
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000816 kWaitingForPacket,
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000817 kWaitingForStats
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000818 };
819
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000820 virtual void SendRtcpFeedback(int remb_value)
821 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000822 FakeReceiveStatistics receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000823 kSendSsrcs[0], last_sequence_number_, rtp_count_, 0);
sprang86fd9ed2015-09-29 04:45:43 -0700824 RTCPSender rtcp_sender(false, clock_, &receive_stats, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700825 transport_adapter_.get());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000826
pbosda903ea2015-10-02 02:36:56 -0700827 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000828 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000829 if (remb_value > 0) {
830 rtcp_sender.SetREMBStatus(true);
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000831 rtcp_sender.SetREMBData(remb_value, std::vector<uint32_t>());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000832 }
833 RTCPSender::FeedbackState feedback_state;
834 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
835 }
836
stefanf116bd02015-10-27 08:29:42 -0700837 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000838 Clock* const clock_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000839 VideoSendStream* stream_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000840
Peter Boströmf2f82832015-05-01 13:00:41 +0200841 rtc::CriticalSection crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000842 TestState test_state_ GUARDED_BY(crit_);
843 int rtp_count_ GUARDED_BY(crit_);
844 int last_sequence_number_ GUARDED_BY(crit_);
845 int suspended_frame_count_ GUARDED_BY(crit_);
846 int low_remb_bps_ GUARDED_BY(crit_);
847 int high_remb_bps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000848 } test;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000849
stefanf116bd02015-10-27 08:29:42 -0700850 RunBaseTest(&test, FakeNetworkPipe::Config());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000851}
852
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000853TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000854 class NoPaddingWhenVideoIsMuted : public test::SendTest {
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000855 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000856 NoPaddingWhenVideoIsMuted()
857 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000858 clock_(Clock::GetRealTimeClock()),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000859 last_packet_time_ms_(-1),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000860 capturer_(nullptr) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000861 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000862
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000863 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000864 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200865 rtc::CritScope lock(&crit_);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000866 last_packet_time_ms_ = clock_->TimeInMilliseconds();
867 capturer_->Stop();
868 return SEND_PACKET;
869 }
870
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000871 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200872 rtc::CritScope lock(&crit_);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000873 const int kVideoMutedThresholdMs = 10000;
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000874 if (last_packet_time_ms_ > 0 &&
875 clock_->TimeInMilliseconds() - last_packet_time_ms_ >
876 kVideoMutedThresholdMs)
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000877 observation_complete_->Set();
878 // Receive statistics reporting having lost 50% of the packets.
879 FakeReceiveStatistics receive_stats(kSendSsrcs[0], 1, 1, 0);
Peter Boströmac547a62015-09-17 23:03:57 +0200880 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), &receive_stats,
stefanf116bd02015-10-27 08:29:42 -0700881 nullptr, transport_adapter_.get());
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000882
pbosda903ea2015-10-02 02:36:56 -0700883 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000884 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
885
886 RTCPSender::FeedbackState feedback_state;
887
888 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
889 return SEND_PACKET;
890 }
891
stefanf116bd02015-10-27 08:29:42 -0700892 void OnTransportsCreated(
893 test::PacketTransport* send_transport,
894 test::PacketTransport* receive_transport) override {
895 transport_adapter_.reset(
896 new internal::TransportAdapter(receive_transport));
897 transport_adapter_->Enable();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000898 }
899
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000900 size_t GetNumStreams() const override { return 3; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000901
902 virtual void OnFrameGeneratorCapturerCreated(
903 test::FrameGeneratorCapturer* frame_generator_capturer) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200904 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000905 capturer_ = frame_generator_capturer;
906 }
907
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000908 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000909 EXPECT_EQ(kEventSignaled, Wait())
910 << "Timed out while waiting for RTP packets to stop being sent.";
911 }
912
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000913 Clock* const clock_;
stefanf116bd02015-10-27 08:29:42 -0700914 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
Peter Boströmf2f82832015-05-01 13:00:41 +0200915 rtc::CriticalSection crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000916 int64_t last_packet_time_ms_ GUARDED_BY(crit_);
917 test::FrameGeneratorCapturer* capturer_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000918 } test;
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000919
stefanf116bd02015-10-27 08:29:42 -0700920 RunBaseTest(&test, FakeNetworkPipe::Config());
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000921}
922
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000923// This test first observes "high" bitrate use at which point it sends a REMB to
924// indicate that it should be lowered significantly. The test then observes that
925// the bitrate observed is sinking well below the min-transmit-bitrate threshold
926// to verify that the min-transmit bitrate respects incoming REMB.
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000927//
928// Note that the test starts at "high" bitrate and does not ramp up to "higher"
929// bitrate since no receiver block or remb is sent in the initial phase.
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000930TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
931 static const int kMinTransmitBitrateBps = 400000;
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000932 static const int kHighBitrateBps = 150000;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000933 static const int kRembBitrateBps = 80000;
934 static const int kRembRespectedBitrateBps = 100000;
stefanf116bd02015-10-27 08:29:42 -0700935 class BitrateObserver : public test::SendTest {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000936 public:
937 BitrateObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000938 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000939 bitrate_capped_(false) {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000940 }
941
942 private:
stefanf116bd02015-10-27 08:29:42 -0700943 virtual Action OnSendRtp(const uint8_t* packet, size_t length) {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000944 if (RtpHeaderParser::IsRtcp(packet, length))
stefanf116bd02015-10-27 08:29:42 -0700945 return DROP_PACKET;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000946
947 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000948 if (!parser_->Parse(packet, length, &header))
stefanf116bd02015-10-27 08:29:42 -0700949 return DROP_PACKET;
henrikg91d6ede2015-09-17 00:24:34 -0700950 RTC_DCHECK(stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000951 VideoSendStream::Stats stats = stream_->GetStats();
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000952 if (!stats.substreams.empty()) {
953 EXPECT_EQ(1u, stats.substreams.size());
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000954 int total_bitrate_bps =
955 stats.substreams.begin()->second.total_bitrate_bps;
956 test::PrintResult("bitrate_stats_",
957 "min_transmit_bitrate_low_remb",
958 "bitrate_bps",
959 static_cast<size_t>(total_bitrate_bps),
960 "bps",
961 false);
962 if (total_bitrate_bps > kHighBitrateBps) {
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000963 rtp_rtcp_->SetREMBData(kRembBitrateBps,
964 std::vector<uint32_t>(1, header.ssrc));
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000965 rtp_rtcp_->Process();
966 bitrate_capped_ = true;
967 } else if (bitrate_capped_ &&
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000968 total_bitrate_bps < kRembRespectedBitrateBps) {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000969 observation_complete_->Set();
970 }
971 }
stefanf116bd02015-10-27 08:29:42 -0700972 // Packets don't have to be delivered since the test is the receiver.
973 return DROP_PACKET;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000974 }
975
stefanf116bd02015-10-27 08:29:42 -0700976 void OnStreamsCreated(
977 VideoSendStream* send_stream,
978 const std::vector<VideoReceiveStream*>& receive_streams) override {
979 stream_ = send_stream;
980 RtpRtcp::Configuration config;
981 config.outgoing_transport = feedback_transport_.get();
982 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
983 rtp_rtcp_->SetREMBStatus(true);
984 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000985 }
986
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000987 void ModifyConfigs(VideoSendStream::Config* send_config,
988 std::vector<VideoReceiveStream::Config>* receive_configs,
989 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700990 feedback_transport_.reset(
991 new internal::TransportAdapter(send_config->send_transport));
992 feedback_transport_->Enable();
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +0000993 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000994 }
995
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000996 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000997 EXPECT_EQ(kEventSignaled, Wait())
998 << "Timeout while waiting for low bitrate stats after REMB.";
999 }
1000
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001001 rtc::scoped_ptr<RtpRtcp> rtp_rtcp_;
stefanf116bd02015-10-27 08:29:42 -07001002 rtc::scoped_ptr<internal::TransportAdapter> feedback_transport_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001003 VideoSendStream* stream_;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001004 bool bitrate_capped_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001005 } test;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001006
stefanf116bd02015-10-27 08:29:42 -07001007 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001008}
1009
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001010TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) {
1011 class StartBitrateObserver : public test::FakeEncoder {
1012 public:
1013 StartBitrateObserver()
1014 : FakeEncoder(Clock::GetRealTimeClock()), start_bitrate_kbps_(0) {}
1015 int32_t InitEncode(const VideoCodec* config,
1016 int32_t number_of_cores,
1017 size_t max_payload_size) override {
1018 rtc::CritScope lock(&crit_);
1019 start_bitrate_kbps_ = config->startBitrate;
1020 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1021 }
1022
1023 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
1024 rtc::CritScope lock(&crit_);
1025 start_bitrate_kbps_ = new_target_bitrate;
1026 return FakeEncoder::SetRates(new_target_bitrate, framerate);
1027 }
1028
1029 int GetStartBitrateKbps() const {
1030 rtc::CritScope lock(&crit_);
1031 return start_bitrate_kbps_;
1032 }
1033
1034 private:
1035 mutable rtc::CriticalSection crit_;
1036 int start_bitrate_kbps_ GUARDED_BY(crit_);
1037 };
1038
solenberg4fbae2b2015-08-28 04:07:10 -07001039 CreateSenderCall(Call::Config());
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001040
solenberg4fbae2b2015-08-28 04:07:10 -07001041 test::NullTransport transport;
1042 CreateSendConfig(1, &transport);
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001043
1044 Call::Config::BitrateConfig bitrate_config;
1045 bitrate_config.start_bitrate_bps =
1046 2 * encoder_config_.streams[0].max_bitrate_bps;
1047 sender_call_->SetBitrateConfig(bitrate_config);
1048
1049 StartBitrateObserver encoder;
1050 send_config_.encoder_settings.encoder = &encoder;
1051
1052 CreateStreams();
1053
1054 EXPECT_EQ(encoder_config_.streams[0].max_bitrate_bps / 1000,
1055 encoder.GetStartBitrateKbps());
1056
1057 encoder_config_.streams[0].max_bitrate_bps =
1058 2 * bitrate_config.start_bitrate_bps;
1059 send_stream_->ReconfigureVideoEncoder(encoder_config_);
1060
1061 // New bitrate should be reconfigured above the previous max. As there's no
1062 // network connection this shouldn't be flaky, as no bitrate should've been
1063 // reported in between.
1064 EXPECT_EQ(bitrate_config.start_bitrate_bps / 1000,
1065 encoder.GetStartBitrateKbps());
1066
1067 DestroyStreams();
1068}
1069
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001070TEST_F(VideoSendStreamTest, CapturesTextureAndVideoFrames) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001071 class FrameObserver : public I420FrameCallback {
1072 public:
1073 FrameObserver() : output_frame_event_(EventWrapper::Create()) {}
1074
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001075 void FrameCallback(VideoFrame* video_frame) override {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001076 output_frames_.push_back(*video_frame);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001077 output_frame_event_->Set();
1078 }
1079
1080 void WaitOutputFrame() {
1081 const unsigned long kWaitFrameTimeoutMs = 3000;
1082 EXPECT_EQ(kEventSignaled, output_frame_event_->Wait(kWaitFrameTimeoutMs))
1083 << "Timeout while waiting for output frames.";
1084 }
1085
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001086 const std::vector<VideoFrame>& output_frames() const {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001087 return output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001088 }
1089
1090 private:
1091 // Delivered output frames.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001092 std::vector<VideoFrame> output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001093
1094 // Indicate an output frame has arrived.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001095 rtc::scoped_ptr<EventWrapper> output_frame_event_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001096 };
1097
1098 // Initialize send stream.
solenberg4fbae2b2015-08-28 04:07:10 -07001099 CreateSenderCall(Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001100
solenberg4fbae2b2015-08-28 04:07:10 -07001101 test::NullTransport transport;
1102 CreateSendConfig(1, &transport);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001103 FrameObserver observer;
1104 send_config_.pre_encode_callback = &observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001105 CreateStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001106
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001107 // Prepare five input frames. Send ordinary VideoFrame and texture frames
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001108 // alternatively.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001109 std::vector<VideoFrame> input_frames;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001110 int width = static_cast<int>(encoder_config_.streams[0].width);
1111 int height = static_cast<int>(encoder_config_.streams[0].height);
Peter Boströmeb66e802015-06-05 11:08:03 +02001112 test::FakeNativeHandle* handle1 = new test::FakeNativeHandle();
1113 test::FakeNativeHandle* handle2 = new test::FakeNativeHandle();
1114 test::FakeNativeHandle* handle3 = new test::FakeNativeHandle();
1115 input_frames.push_back(test::CreateFakeNativeHandleFrame(
1116 handle1, width, height, 1, 1, kVideoRotation_0));
1117 input_frames.push_back(test::CreateFakeNativeHandleFrame(
1118 handle2, width, height, 2, 2, kVideoRotation_0));
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001119 input_frames.push_back(CreateVideoFrame(width, height, 3));
1120 input_frames.push_back(CreateVideoFrame(width, height, 4));
Peter Boströmeb66e802015-06-05 11:08:03 +02001121 input_frames.push_back(test::CreateFakeNativeHandleFrame(
1122 handle3, width, height, 5, 5, kVideoRotation_0));
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001123
1124 send_stream_->Start();
1125 for (size_t i = 0; i < input_frames.size(); i++) {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001126 send_stream_->Input()->IncomingCapturedFrame(input_frames[i]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001127 // Do not send the next frame too fast, so the frame dropper won't drop it.
1128 if (i < input_frames.size() - 1)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001129 SleepMs(1000 / encoder_config_.streams[0].max_framerate);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001130 // Wait until the output frame is received before sending the next input
1131 // frame. Or the previous input frame may be replaced without delivering.
1132 observer.WaitOutputFrame();
1133 }
1134 send_stream_->Stop();
1135
1136 // Test if the input and output frames are the same. render_time_ms and
1137 // timestamp are not compared because capturer sets those values.
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001138 ExpectEqualFramesVector(input_frames, observer.output_frames());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001139
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001140 DestroyStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001141}
1142
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001143void ExpectEqualFrames(const VideoFrame& frame1, const VideoFrame& frame2) {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001144 if (frame1.native_handle() != nullptr || frame2.native_handle() != nullptr)
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001145 ExpectEqualTextureFrames(frame1, frame2);
1146 else
1147 ExpectEqualBufferFrames(frame1, frame2);
1148}
1149
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001150void ExpectEqualTextureFrames(const VideoFrame& frame1,
1151 const VideoFrame& frame2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001152 EXPECT_EQ(frame1.native_handle(), frame2.native_handle());
1153 EXPECT_EQ(frame1.width(), frame2.width());
1154 EXPECT_EQ(frame1.height(), frame2.height());
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001155 EXPECT_EQ(frame1.render_time_ms(), frame2.render_time_ms());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001156}
1157
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001158void ExpectEqualBufferFrames(const VideoFrame& frame1,
1159 const VideoFrame& frame2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001160 EXPECT_EQ(frame1.width(), frame2.width());
1161 EXPECT_EQ(frame1.height(), frame2.height());
1162 EXPECT_EQ(frame1.stride(kYPlane), frame2.stride(kYPlane));
1163 EXPECT_EQ(frame1.stride(kUPlane), frame2.stride(kUPlane));
1164 EXPECT_EQ(frame1.stride(kVPlane), frame2.stride(kVPlane));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001165 EXPECT_EQ(frame1.render_time_ms(), frame2.render_time_ms());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001166 ASSERT_EQ(frame1.allocated_size(kYPlane), frame2.allocated_size(kYPlane));
1167 EXPECT_EQ(0,
1168 memcmp(frame1.buffer(kYPlane),
1169 frame2.buffer(kYPlane),
1170 frame1.allocated_size(kYPlane)));
1171 ASSERT_EQ(frame1.allocated_size(kUPlane), frame2.allocated_size(kUPlane));
1172 EXPECT_EQ(0,
1173 memcmp(frame1.buffer(kUPlane),
1174 frame2.buffer(kUPlane),
1175 frame1.allocated_size(kUPlane)));
1176 ASSERT_EQ(frame1.allocated_size(kVPlane), frame2.allocated_size(kVPlane));
1177 EXPECT_EQ(0,
1178 memcmp(frame1.buffer(kVPlane),
1179 frame2.buffer(kVPlane),
1180 frame1.allocated_size(kVPlane)));
1181}
1182
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001183void ExpectEqualFramesVector(const std::vector<VideoFrame>& frames1,
1184 const std::vector<VideoFrame>& frames2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001185 EXPECT_EQ(frames1.size(), frames2.size());
1186 for (size_t i = 0; i < std::min(frames1.size(), frames2.size()); ++i)
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001187 ExpectEqualFrames(frames1[i], frames2[i]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001188}
1189
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001190VideoFrame CreateVideoFrame(int width, int height, uint8_t data) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001191 const int kSizeY = width * height * 2;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001192 rtc::scoped_ptr<uint8_t[]> buffer(new uint8_t[kSizeY]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001193 memset(buffer.get(), data, kSizeY);
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001194 VideoFrame frame;
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001195 frame.CreateFrame(buffer.get(), buffer.get(), buffer.get(), width, height,
1196 width, width / 2, width / 2);
1197 frame.set_timestamp(data);
1198 frame.set_render_time_ms(data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001199 return frame;
1200}
1201
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001202TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
1203 class EncoderStateObserver : public test::SendTest, public VideoEncoder {
1204 public:
1205 EncoderStateObserver()
1206 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001207 initialized_(false),
1208 callback_registered_(false),
1209 num_releases_(0),
1210 released_(false) {}
1211
1212 bool IsReleased() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001213 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001214 return released_;
1215 }
1216
1217 bool IsReadyForEncode() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001218 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001219 return initialized_ && callback_registered_;
1220 }
1221
1222 size_t num_releases() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001223 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001224 return num_releases_;
1225 }
1226
1227 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001228 int32_t InitEncode(const VideoCodec* codecSettings,
1229 int32_t numberOfCores,
1230 size_t maxPayloadSize) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001231 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001232 EXPECT_FALSE(initialized_);
1233 initialized_ = true;
1234 released_ = false;
1235 return 0;
1236 }
1237
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001238 int32_t Encode(const VideoFrame& inputImage,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001239 const CodecSpecificInfo* codecSpecificInfo,
pbos22993e12015-10-19 02:39:06 -07001240 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001241 EXPECT_TRUE(IsReadyForEncode());
1242
1243 observation_complete_->Set();
1244 return 0;
1245 }
1246
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001247 int32_t RegisterEncodeCompleteCallback(
1248 EncodedImageCallback* callback) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001249 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001250 EXPECT_TRUE(initialized_);
1251 callback_registered_ = true;
1252 return 0;
1253 }
1254
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001255 int32_t Release() override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001256 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001257 EXPECT_TRUE(IsReadyForEncode());
1258 EXPECT_FALSE(released_);
1259 initialized_ = false;
1260 callback_registered_ = false;
1261 released_ = true;
1262 ++num_releases_;
1263 return 0;
1264 }
1265
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001266 int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001267 EXPECT_TRUE(IsReadyForEncode());
1268 return 0;
1269 }
1270
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001271 int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001272 EXPECT_TRUE(IsReadyForEncode());
1273 return 0;
1274 }
1275
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001276 void OnStreamsCreated(
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001277 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001278 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001279 // Encoder initialization should be done in stream construction before
1280 // starting.
1281 EXPECT_TRUE(IsReadyForEncode());
1282 stream_ = send_stream;
1283 }
1284
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001285 void ModifyConfigs(VideoSendStream::Config* send_config,
1286 std::vector<VideoReceiveStream::Config>* receive_configs,
1287 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001288 send_config->encoder_settings.encoder = this;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001289 encoder_config_ = *encoder_config;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001290 }
1291
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001292 void PerformTest() override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001293 EXPECT_EQ(kEventSignaled, Wait())
1294 << "Timed out while waiting for Encode.";
1295 EXPECT_EQ(0u, num_releases());
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001296 stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001297 EXPECT_EQ(0u, num_releases());
1298 stream_->Stop();
1299 // Encoder should not be released before destroying the VideoSendStream.
1300 EXPECT_FALSE(IsReleased());
1301 EXPECT_TRUE(IsReadyForEncode());
1302 stream_->Start();
1303 // Sanity check, make sure we still encode frames with this encoder.
1304 EXPECT_EQ(kEventSignaled, Wait())
1305 << "Timed out while waiting for Encode.";
1306 }
1307
Peter Boströmf2f82832015-05-01 13:00:41 +02001308 rtc::CriticalSection crit_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001309 VideoSendStream* stream_;
1310 bool initialized_ GUARDED_BY(crit_);
1311 bool callback_registered_ GUARDED_BY(crit_);
1312 size_t num_releases_ GUARDED_BY(crit_);
1313 bool released_ GUARDED_BY(crit_);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001314 VideoEncoderConfig encoder_config_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001315 } test_encoder;
1316
stefanf116bd02015-10-27 08:29:42 -07001317 RunBaseTest(&test_encoder, FakeNetworkPipe::Config());
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001318
1319 EXPECT_TRUE(test_encoder.IsReleased());
1320 EXPECT_EQ(1u, test_encoder.num_releases());
1321}
1322
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001323TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
1324 class VideoCodecConfigObserver : public test::SendTest,
1325 public test::FakeEncoder {
1326 public:
1327 VideoCodecConfigObserver()
1328 : SendTest(kDefaultTimeoutMs),
1329 FakeEncoder(Clock::GetRealTimeClock()),
1330 num_initializations_(0) {}
1331
1332 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001333 void ModifyConfigs(VideoSendStream::Config* send_config,
1334 std::vector<VideoReceiveStream::Config>* receive_configs,
1335 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001336 send_config->encoder_settings.encoder = this;
1337 encoder_config_ = *encoder_config;
1338 }
1339
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001340 void OnStreamsCreated(
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001341 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001342 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001343 stream_ = send_stream;
1344 }
1345
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001346 int32_t InitEncode(const VideoCodec* config,
1347 int32_t number_of_cores,
1348 size_t max_payload_size) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001349 if (num_initializations_ == 0) {
1350 // Verify default values.
1351 EXPECT_EQ(kRealtimeVideo, config->mode);
1352 } else {
1353 // Verify that changed values are propagated.
1354 EXPECT_EQ(kScreensharing, config->mode);
1355 }
1356 ++num_initializations_;
1357 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1358 }
1359
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001360 void PerformTest() override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001361 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1362
Erik Språng143cec12015-04-28 10:01:41 +02001363 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001364 stream_->ReconfigureVideoEncoder(encoder_config_);
1365 EXPECT_EQ(2u, num_initializations_)
1366 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1367 "new encoder settings.";
1368 }
1369
1370 size_t num_initializations_;
1371 VideoSendStream* stream_;
1372 VideoEncoderConfig encoder_config_;
1373 } test;
1374
stefanf116bd02015-10-27 08:29:42 -07001375 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001376}
1377
Peter Boström53eda3d2015-03-27 15:53:18 +01001378static const size_t kVideoCodecConfigObserverNumberOfTemporalLayers = 4;
1379template <typename T>
1380class VideoCodecConfigObserver : public test::SendTest,
1381 public test::FakeEncoder {
1382
1383 public:
1384 VideoCodecConfigObserver(VideoCodecType video_codec_type,
1385 const char* codec_name)
1386 : SendTest(VideoSendStreamTest::kDefaultTimeoutMs),
1387 FakeEncoder(Clock::GetRealTimeClock()),
1388 video_codec_type_(video_codec_type),
1389 codec_name_(codec_name),
1390 num_initializations_(0) {
1391 memset(&encoder_settings_, 0, sizeof(encoder_settings_));
1392 }
1393
1394 private:
1395 void ModifyConfigs(VideoSendStream::Config* send_config,
1396 std::vector<VideoReceiveStream::Config>* receive_configs,
1397 VideoEncoderConfig* encoder_config) override {
1398 send_config->encoder_settings.encoder = this;
1399 send_config->encoder_settings.payload_name = codec_name_;
1400
1401 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
1402 encoder_config->streams[i].temporal_layer_thresholds_bps.resize(
1403 kVideoCodecConfigObserverNumberOfTemporalLayers - 1);
1404 }
1405
1406 encoder_config->encoder_specific_settings = &encoder_settings_;
1407 encoder_config_ = *encoder_config;
1408 }
1409
1410 void OnStreamsCreated(
1411 VideoSendStream* send_stream,
1412 const std::vector<VideoReceiveStream*>& receive_streams) override {
1413 stream_ = send_stream;
1414 }
1415
1416 int32_t InitEncode(const VideoCodec* config,
1417 int32_t number_of_cores,
1418 size_t max_payload_size) override {
1419 EXPECT_EQ(video_codec_type_, config->codecType);
1420 VerifyCodecSpecifics(*config);
1421 ++num_initializations_;
1422 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1423 }
1424
1425 void VerifyCodecSpecifics(const VideoCodec& config) const;
1426
1427 void PerformTest() override {
1428 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1429
1430 encoder_settings_.frameDroppingOn = true;
1431 stream_->ReconfigureVideoEncoder(encoder_config_);
1432 EXPECT_EQ(2u, num_initializations_)
1433 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1434 "new encoder settings.";
1435 }
1436
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001437 int32_t Encode(const VideoFrame& input_image,
Peter Boström53eda3d2015-03-27 15:53:18 +01001438 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07001439 const std::vector<FrameType>* frame_types) override {
Peter Boström53eda3d2015-03-27 15:53:18 +01001440 // Silently skip the encode, FakeEncoder::Encode doesn't produce VP8.
1441 return 0;
1442 }
1443
1444 T encoder_settings_;
1445 const VideoCodecType video_codec_type_;
1446 const char* const codec_name_;
1447 size_t num_initializations_;
1448 VideoSendStream* stream_;
1449 VideoEncoderConfig encoder_config_;
1450};
1451
1452template <>
1453void VideoCodecConfigObserver<VideoCodecH264>::VerifyCodecSpecifics(
1454 const VideoCodec& config) const {
1455 EXPECT_EQ(0, memcmp(&config.codecSpecific.H264, &encoder_settings_,
1456 sizeof(encoder_settings_)));
1457}
1458template <>
1459void VideoCodecConfigObserver<VideoCodecVP8>::VerifyCodecSpecifics(
1460 const VideoCodec& config) const {
1461 // Check that the number of temporal layers has propagated properly to
1462 // VideoCodec.
1463 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1464 config.codecSpecific.VP8.numberOfTemporalLayers);
1465
1466 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1467 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1468 config.simulcastStream[i].numberOfTemporalLayers);
1469 }
1470
1471 // Set expected temporal layers as they should have been set when
1472 // reconfiguring the encoder and not match the set config.
1473 VideoCodecVP8 encoder_settings = encoder_settings_;
1474 encoder_settings.numberOfTemporalLayers =
1475 kVideoCodecConfigObserverNumberOfTemporalLayers;
1476 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP8, &encoder_settings,
1477 sizeof(encoder_settings_)));
1478}
1479template <>
1480void VideoCodecConfigObserver<VideoCodecVP9>::VerifyCodecSpecifics(
1481 const VideoCodec& config) const {
1482 // Check that the number of temporal layers has propagated properly to
1483 // VideoCodec.
1484 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1485 config.codecSpecific.VP9.numberOfTemporalLayers);
1486
1487 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1488 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1489 config.simulcastStream[i].numberOfTemporalLayers);
1490 }
1491
1492 // Set expected temporal layers as they should have been set when
1493 // reconfiguring the encoder and not match the set config.
1494 VideoCodecVP9 encoder_settings = encoder_settings_;
1495 encoder_settings.numberOfTemporalLayers =
1496 kVideoCodecConfigObserverNumberOfTemporalLayers;
1497 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP9, &encoder_settings,
1498 sizeof(encoder_settings_)));
1499}
1500
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001501TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp8Config) {
Peter Boström53eda3d2015-03-27 15:53:18 +01001502 VideoCodecConfigObserver<VideoCodecVP8> test(kVideoCodecVP8, "VP8");
stefanf116bd02015-10-27 08:29:42 -07001503 RunBaseTest(&test, FakeNetworkPipe::Config());
Peter Boström53eda3d2015-03-27 15:53:18 +01001504}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001505
Peter Boström53eda3d2015-03-27 15:53:18 +01001506TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp9Config) {
1507 VideoCodecConfigObserver<VideoCodecVP9> test(kVideoCodecVP9, "VP9");
stefanf116bd02015-10-27 08:29:42 -07001508 RunBaseTest(&test, FakeNetworkPipe::Config());
Peter Boström53eda3d2015-03-27 15:53:18 +01001509}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001510
Peter Boström53eda3d2015-03-27 15:53:18 +01001511TEST_F(VideoSendStreamTest, EncoderSetupPropagatesH264Config) {
1512 VideoCodecConfigObserver<VideoCodecH264> test(kVideoCodecH264, "H264");
stefanf116bd02015-10-27 08:29:42 -07001513 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001514}
1515
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001516TEST_F(VideoSendStreamTest, RtcpSenderReportContainsMediaBytesSent) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001517 class RtcpSenderReportTest : public test::SendTest {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001518 public:
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001519 RtcpSenderReportTest() : SendTest(kDefaultTimeoutMs),
1520 rtp_packets_sent_(0),
1521 media_bytes_sent_(0) {}
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001522
1523 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001524 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001525 RTPHeader header;
1526 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001527 ++rtp_packets_sent_;
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001528 media_bytes_sent_ += length - header.headerLength - header.paddingLength;
1529 return SEND_PACKET;
1530 }
1531
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001532 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001533 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1534 EXPECT_TRUE(parser.IsValid());
1535
1536 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001537 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1538 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001539 // Only compare sent media bytes if SenderPacketCount matches the
1540 // number of sent rtp packets (a new rtp packet could be sent before
1541 // the rtcp packet).
1542 if (parser.Packet().SR.SenderOctetCount > 0 &&
1543 parser.Packet().SR.SenderPacketCount == rtp_packets_sent_) {
1544 EXPECT_EQ(media_bytes_sent_, parser.Packet().SR.SenderOctetCount);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001545 observation_complete_->Set();
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001546 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001547 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001548 packet_type = parser.Iterate();
1549 }
1550
1551 return SEND_PACKET;
1552 }
1553
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001554 void PerformTest() override {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001555 EXPECT_EQ(kEventSignaled, Wait())
1556 << "Timed out while waiting for RTCP sender report.";
1557 }
1558
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001559 size_t rtp_packets_sent_;
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001560 size_t media_bytes_sent_;
1561 } test;
1562
stefanf116bd02015-10-27 08:29:42 -07001563 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001564}
1565
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001566TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
1567 static const int kScreencastTargetBitrateKbps = 200;
1568 class ScreencastTargetBitrateTest : public test::SendTest,
1569 public test::FakeEncoder {
1570 public:
1571 ScreencastTargetBitrateTest()
1572 : SendTest(kDefaultTimeoutMs),
1573 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1574
1575 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001576 int32_t InitEncode(const VideoCodec* config,
1577 int32_t number_of_cores,
1578 size_t max_payload_size) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001579 EXPECT_EQ(static_cast<unsigned int>(kScreencastTargetBitrateKbps),
1580 config->targetBitrate);
1581 observation_complete_->Set();
1582 return test::FakeEncoder::InitEncode(
1583 config, number_of_cores, max_payload_size);
1584 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001585 void ModifyConfigs(VideoSendStream::Config* send_config,
1586 std::vector<VideoReceiveStream::Config>* receive_configs,
1587 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001588 send_config->encoder_settings.encoder = this;
1589 EXPECT_EQ(1u, encoder_config->streams.size());
1590 EXPECT_TRUE(
1591 encoder_config->streams[0].temporal_layer_thresholds_bps.empty());
1592 encoder_config->streams[0].temporal_layer_thresholds_bps.push_back(
1593 kScreencastTargetBitrateKbps * 1000);
Erik Språng143cec12015-04-28 10:01:41 +02001594 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001595 }
1596
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001597 void PerformTest() override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001598 EXPECT_EQ(kEventSignaled, Wait())
1599 << "Timed out while waiting for the encoder to be initialized.";
1600 }
1601 } test;
1602
stefanf116bd02015-10-27 08:29:42 -07001603 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001604}
pbos@webrtc.org00873182014-11-25 14:03:34 +00001605
Stefan Holmere5904162015-03-26 11:11:06 +01001606TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001607 // These are chosen to be "kind of odd" to not be accidentally checked against
1608 // default values.
1609 static const int kMinBitrateKbps = 137;
1610 static const int kStartBitrateKbps = 345;
1611 static const int kLowerMaxBitrateKbps = 312;
1612 static const int kMaxBitrateKbps = 413;
1613 static const int kIncreasedStartBitrateKbps = 451;
1614 static const int kIncreasedMaxBitrateKbps = 597;
1615 class EncoderBitrateThresholdObserver : public test::SendTest,
1616 public test::FakeEncoder {
1617 public:
1618 EncoderBitrateThresholdObserver()
1619 : SendTest(kDefaultTimeoutMs),
1620 FakeEncoder(Clock::GetRealTimeClock()),
1621 num_initializations_(0) {}
1622
1623 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001624 int32_t InitEncode(const VideoCodec* codecSettings,
1625 int32_t numberOfCores,
1626 size_t maxPayloadSize) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001627 if (num_initializations_ == 0) {
1628 EXPECT_EQ(static_cast<unsigned int>(kMinBitrateKbps),
1629 codecSettings->minBitrate);
1630 EXPECT_EQ(static_cast<unsigned int>(kStartBitrateKbps),
1631 codecSettings->startBitrate);
1632 EXPECT_EQ(static_cast<unsigned int>(kMaxBitrateKbps),
1633 codecSettings->maxBitrate);
1634 observation_complete_->Set();
1635 } else if (num_initializations_ == 1) {
1636 EXPECT_EQ(static_cast<unsigned int>(kLowerMaxBitrateKbps),
1637 codecSettings->maxBitrate);
1638 // The start bitrate should be kept (-1) and capped to the max bitrate.
1639 // Since this is not an end-to-end call no receiver should have been
1640 // returning a REMB that could lower this estimate.
1641 EXPECT_EQ(codecSettings->startBitrate, codecSettings->maxBitrate);
1642 } else if (num_initializations_ == 2) {
1643 EXPECT_EQ(static_cast<unsigned int>(kIncreasedMaxBitrateKbps),
1644 codecSettings->maxBitrate);
1645 EXPECT_EQ(static_cast<unsigned int>(kIncreasedStartBitrateKbps),
1646 codecSettings->startBitrate);
1647 }
1648 ++num_initializations_;
1649 return FakeEncoder::InitEncode(codecSettings, numberOfCores,
1650 maxPayloadSize);
1651 }
1652
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001653 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -07001654 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +01001655 config.bitrate_config.min_bitrate_bps = kMinBitrateKbps * 1000;
1656 config.bitrate_config.start_bitrate_bps = kStartBitrateKbps * 1000;
1657 config.bitrate_config.max_bitrate_bps = kMaxBitrateKbps * 1000;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001658 return config;
1659 }
1660
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001661 void ModifyConfigs(VideoSendStream::Config* send_config,
1662 std::vector<VideoReceiveStream::Config>* receive_configs,
1663 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001664 send_config->encoder_settings.encoder = this;
1665 // Set bitrates lower/higher than min/max to make sure they are properly
1666 // capped.
Stefan Holmere5904162015-03-26 11:11:06 +01001667 encoder_config->streams.front().min_bitrate_bps = kMinBitrateKbps * 1000;
1668 encoder_config->streams.front().max_bitrate_bps = kMaxBitrateKbps * 1000;
1669 encoder_config_ = *encoder_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001670 }
1671
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001672 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001673 call_ = sender_call;
1674 }
1675
Stefan Holmere5904162015-03-26 11:11:06 +01001676 void OnStreamsCreated(
1677 VideoSendStream* send_stream,
1678 const std::vector<VideoReceiveStream*>& receive_streams) override {
1679 send_stream_ = send_stream;
1680 }
1681
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001682 void PerformTest() override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001683 Call::Config::BitrateConfig bitrate_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001684 bitrate_config.start_bitrate_bps = kIncreasedStartBitrateKbps * 1000;
1685 bitrate_config.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000;
1686 call_->SetBitrateConfig(bitrate_config);
Stefan Holmere5904162015-03-26 11:11:06 +01001687 EXPECT_EQ(kEventSignaled, Wait())
1688 << "Timed out while waiting encoder to be configured.";
1689 encoder_config_.streams[0].min_bitrate_bps = 0;
1690 encoder_config_.streams[0].max_bitrate_bps = kLowerMaxBitrateKbps * 1000;
1691 send_stream_->ReconfigureVideoEncoder(encoder_config_);
1692 EXPECT_EQ(2, num_initializations_)
1693 << "Encoder should have been reconfigured with the new value.";
1694 encoder_config_.streams[0].target_bitrate_bps =
1695 encoder_config_.streams[0].min_bitrate_bps;
1696 encoder_config_.streams[0].max_bitrate_bps =
1697 kIncreasedMaxBitrateKbps * 1000;
1698 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org00873182014-11-25 14:03:34 +00001699 EXPECT_EQ(3, num_initializations_)
1700 << "Encoder should have been reconfigured with the new value.";
1701 }
1702
1703 int num_initializations_;
1704 webrtc::Call* call_;
Stefan Holmere5904162015-03-26 11:11:06 +01001705 webrtc::VideoSendStream* send_stream_;
1706 webrtc::VideoEncoderConfig encoder_config_;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001707 } test;
1708
stefanf116bd02015-10-27 08:29:42 -07001709 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org00873182014-11-25 14:03:34 +00001710}
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001711
1712TEST_F(VideoSendStreamTest, ReportsSentResolution) {
1713 static const size_t kNumStreams = 3;
1714 // Unusual resolutions to make sure that they are the ones being reported.
1715 static const struct {
1716 int width;
1717 int height;
1718 } kEncodedResolution[kNumStreams] = {
1719 {241, 181}, {300, 121}, {121, 221}};
1720 class ScreencastTargetBitrateTest : public test::SendTest,
1721 public test::FakeEncoder {
1722 public:
1723 ScreencastTargetBitrateTest()
1724 : SendTest(kDefaultTimeoutMs),
1725 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1726
1727 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001728 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001729 const CodecSpecificInfo* codecSpecificInfo,
pbos22993e12015-10-19 02:39:06 -07001730 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001731 CodecSpecificInfo specifics;
1732 memset(&specifics, 0, sizeof(specifics));
1733 specifics.codecType = kVideoCodecGeneric;
1734
1735 uint8_t buffer[16] = {0};
1736 EncodedImage encoded(buffer, sizeof(buffer), sizeof(buffer));
1737 encoded._timeStamp = input_image.timestamp();
1738 encoded.capture_time_ms_ = input_image.render_time_ms();
1739
1740 for (size_t i = 0; i < kNumStreams; ++i) {
1741 specifics.codecSpecific.generic.simulcast_idx = static_cast<uint8_t>(i);
1742 encoded._frameType = (*frame_types)[i];
1743 encoded._encodedWidth = kEncodedResolution[i].width;
1744 encoded._encodedHeight = kEncodedResolution[i].height;
henrikg91d6ede2015-09-17 00:24:34 -07001745 RTC_DCHECK(callback_ != nullptr);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001746 if (callback_->Encoded(encoded, &specifics, nullptr) != 0)
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001747 return -1;
1748 }
1749
1750 observation_complete_->Set();
1751 return 0;
1752 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001753 void ModifyConfigs(VideoSendStream::Config* send_config,
1754 std::vector<VideoReceiveStream::Config>* receive_configs,
1755 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001756 send_config->encoder_settings.encoder = this;
1757 EXPECT_EQ(kNumStreams, encoder_config->streams.size());
1758 }
1759
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001760 size_t GetNumStreams() const override { return kNumStreams; }
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001761
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001762 void PerformTest() override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001763 EXPECT_EQ(kEventSignaled, Wait())
1764 << "Timed out while waiting for the encoder to send one frame.";
1765 VideoSendStream::Stats stats = send_stream_->GetStats();
1766
1767 for (size_t i = 0; i < kNumStreams; ++i) {
1768 ASSERT_TRUE(stats.substreams.find(kSendSsrcs[i]) !=
1769 stats.substreams.end())
1770 << "No stats for SSRC: " << kSendSsrcs[i]
1771 << ", stats should exist as soon as frames have been encoded.";
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001772 VideoSendStream::StreamStats ssrc_stats =
1773 stats.substreams[kSendSsrcs[i]];
1774 EXPECT_EQ(kEncodedResolution[i].width, ssrc_stats.width);
1775 EXPECT_EQ(kEncodedResolution[i].height, ssrc_stats.height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001776 }
1777 }
1778
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001779 void OnStreamsCreated(
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001780 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001781 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001782 send_stream_ = send_stream;
1783 }
1784
1785 VideoSendStream* send_stream_;
1786 } test;
1787
stefanf116bd02015-10-27 08:29:42 -07001788 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001789}
philipel0f9af012015-09-01 07:01:51 -07001790
1791class VP9HeaderObeserver : public test::SendTest {
1792 public:
philipel7fabd462015-09-03 04:42:32 -07001793 VP9HeaderObeserver()
1794 : SendTest(VideoSendStreamTest::kDefaultTimeoutMs),
1795 vp9_encoder_(VP9Encoder::Create()),
philipelcfc319b2015-11-10 07:17:23 -08001796 vp9_settings_(VideoEncoder::GetDefaultVp9Settings()) {
1797 vp9_settings_.numberOfTemporalLayers = 1;
1798 vp9_settings_.numberOfSpatialLayers = 2;
1799 }
philipel7fabd462015-09-03 04:42:32 -07001800
philipel0f9af012015-09-01 07:01:51 -07001801 virtual void ModifyConfigsHook(
1802 VideoSendStream::Config* send_config,
1803 std::vector<VideoReceiveStream::Config>* receive_configs,
1804 VideoEncoderConfig* encoder_config) {}
1805
1806 virtual void InspectHeader(RTPVideoHeaderVP9* vp9videoHeader) = 0;
1807
1808 private:
1809 const int kVp9PayloadType = 105;
1810
1811 void ModifyConfigs(VideoSendStream::Config* send_config,
1812 std::vector<VideoReceiveStream::Config>* receive_configs,
1813 VideoEncoderConfig* encoder_config) override {
1814 encoder_config->encoder_specific_settings = &vp9_settings_;
philipelcfc319b2015-11-10 07:17:23 -08001815 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
philipel7fabd462015-09-03 04:42:32 -07001816 send_config->encoder_settings.encoder = vp9_encoder_.get();
philipel0f9af012015-09-01 07:01:51 -07001817 send_config->encoder_settings.payload_name = "VP9";
1818 send_config->encoder_settings.payload_type = kVp9PayloadType;
1819 ModifyConfigsHook(send_config, receive_configs, encoder_config);
1820 }
1821
1822 void PerformTest() override {
1823 EXPECT_EQ(kEventSignaled, Wait())
1824 << "Test timed out waiting for VP9 packet";
1825 }
1826
1827 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1828 RTPHeader header;
1829 EXPECT_TRUE(parser_->Parse(packet, length, &header));
1830
1831 if (header.payloadType == kVp9PayloadType) {
1832 RtpDepacketizerVp9 vp9depacketizer;
1833 RtpDepacketizer::ParsedPayload vp9payload;
1834 const uint8_t* vp9_packet = packet + header.headerLength;
1835 size_t payload_length =
1836 length - header.headerLength - header.paddingLength;
1837
Stefan Holmer586b19b2015-09-18 11:14:31 +02001838 if (payload_length > 0) {
1839 bool parse_vp9header_successful =
1840 vp9depacketizer.Parse(&vp9payload, vp9_packet, payload_length);
1841 bool is_vp9_codec_type =
1842 vp9payload.type.Video.codec == RtpVideoCodecTypes::kRtpVideoVp9;
1843 EXPECT_TRUE(parse_vp9header_successful);
1844 EXPECT_TRUE(is_vp9_codec_type);
philipel0f9af012015-09-01 07:01:51 -07001845
Stefan Holmer586b19b2015-09-18 11:14:31 +02001846 RTPVideoHeaderVP9* vp9videoHeader =
1847 &vp9payload.type.Video.codecHeader.VP9;
1848 if (parse_vp9header_successful && is_vp9_codec_type) {
1849 InspectHeader(vp9videoHeader);
1850 } else {
1851 observation_complete_->Set();
1852 }
philipel0f9af012015-09-01 07:01:51 -07001853 }
1854 }
1855
1856 return SEND_PACKET;
1857 }
1858
philipel7fabd462015-09-03 04:42:32 -07001859 protected:
1860 rtc::scoped_ptr<VP9Encoder> vp9_encoder_;
philipel0f9af012015-09-01 07:01:51 -07001861 VideoCodecVP9 vp9_settings_;
1862};
1863
philipelf325d212015-09-08 12:47:02 +02001864TEST_F(VideoSendStreamTest, DISABLED_VP9FlexMode) {
philipel0f9af012015-09-01 07:01:51 -07001865 class FlexibleMode : public VP9HeaderObeserver {
1866 void ModifyConfigsHook(
1867 VideoSendStream::Config* send_config,
1868 std::vector<VideoReceiveStream::Config>* receive_configs,
1869 VideoEncoderConfig* encoder_config) override {
1870 vp9_settings_.flexibleMode = true;
philipel0f9af012015-09-01 07:01:51 -07001871 }
1872
1873 void InspectHeader(RTPVideoHeaderVP9* vp9videoHeader) override {
1874 EXPECT_TRUE(vp9videoHeader->flexible_mode);
1875 observation_complete_->Set();
1876 }
philipelcfc319b2015-11-10 07:17:23 -08001877 } test;
1878
1879 RunBaseTest(&test, FakeNetworkPipe::Config());
1880}
1881
1882TEST_F(VideoSendStreamTest, VP9FlexModeHasPictureId) {
1883 class FlexibleMode : public VP9HeaderObeserver {
1884 void ModifyConfigsHook(
1885 VideoSendStream::Config* send_config,
1886 std::vector<VideoReceiveStream::Config>* receive_configs,
1887 VideoEncoderConfig* encoder_config) override {
1888 vp9_settings_.flexibleMode = true;
1889 }
1890
1891 void InspectHeader(RTPVideoHeaderVP9* vp9videoHeader) override {
1892 EXPECT_NE(vp9videoHeader->picture_id, kNoPictureId);
1893 observation_complete_->Set();
1894 }
1895 } test;
1896
1897 RunBaseTest(&test, FakeNetworkPipe::Config());
1898}
1899
1900TEST_F(VideoSendStreamTest, VP9FlexModeRefCount) {
1901 class FlexibleMode : public VP9HeaderObeserver {
1902 void ModifyConfigsHook(
1903 VideoSendStream::Config* send_config,
1904 std::vector<VideoReceiveStream::Config>* receive_configs,
1905 VideoEncoderConfig* encoder_config) override {
1906 vp9_settings_.flexibleMode = true;
1907 }
1908
1909 void InspectHeader(RTPVideoHeaderVP9* vp9videoHeader) override {
1910 EXPECT_TRUE(vp9videoHeader->flexible_mode);
1911 if (vp9videoHeader->inter_pic_predicted) {
1912 EXPECT_GT(vp9videoHeader->num_ref_pics, 0u);
1913 observation_complete_->Set();
1914 }
1915 }
1916 } test;
1917
1918 RunBaseTest(&test, FakeNetworkPipe::Config());
1919}
1920
1921TEST_F(VideoSendStreamTest, VP9FlexModeRefs) {
1922 class FlexibleMode : public VP9HeaderObeserver {
1923 void ModifyConfigsHook(
1924 VideoSendStream::Config* send_config,
1925 std::vector<VideoReceiveStream::Config>* receive_configs,
1926 VideoEncoderConfig* encoder_config) override {
1927 vp9_settings_.flexibleMode = true;
1928 }
1929
1930 void InspectHeader(RTPVideoHeaderVP9* vp9videoHeader) override {
1931 EXPECT_TRUE(vp9videoHeader->flexible_mode);
1932 if (vp9videoHeader->inter_pic_predicted) {
1933 EXPECT_GT(vp9videoHeader->num_ref_pics, 0u);
1934 observation_complete_->Set();
1935 }
1936 }
philipel0f9af012015-09-01 07:01:51 -07001937
1938 } test;
1939
stefanf116bd02015-10-27 08:29:42 -07001940 RunBaseTest(&test, FakeNetworkPipe::Config());
philipel0f9af012015-09-01 07:01:51 -07001941}
1942
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +00001943} // namespace webrtc