blob: 00aa2a901815cb4b0be6296e55e7ade6dae09364 [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öm5811a392015-12-10 13:02:50 +010018#include "webrtc/base/event.h"
Peter Boström415d2cd2015-10-26 11:35:17 +010019#include "webrtc/base/logging.h"
pbos12411ef2015-11-23 14:47:56 -080020#include "webrtc/base/platform_thread.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000021#include "webrtc/base/scoped_ptr.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000022#include "webrtc/call.h"
Peter Boström5c389d32015-09-25 13:58:30 +020023#include "webrtc/call/transport_adapter.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000024#include "webrtc/frame_callback.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010025#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
26#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000027#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
pbos@webrtc.org013d9942013-08-22 09:42:17 +000028#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
philipel0f9af012015-09-01 07:01:51 -070029#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h"
philipel7fabd462015-09-03 04:42:32 -070030#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010031#include "webrtc/system_wrappers/include/ref_count.h"
32#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000033#include "webrtc/test/call_test.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000034#include "webrtc/test/configurable_frame_size_encoder.h"
Peter Boströmeb66e802015-06-05 11:08:03 +020035#include "webrtc/test/fake_texture_frame.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000036#include "webrtc/test/null_transport.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000037#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.org273a4142014-12-01 15:23:21 +000038#include "webrtc/video/send_statistics_proxy.h"
Thiago Farina9bfe3da2015-04-10 12:52:13 +020039#include "webrtc/video_frame.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000040#include "webrtc/video_send_stream.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000041
42namespace webrtc {
43
sprang@webrtc.org346094c2014-02-18 08:40:33 +000044enum VideoFormat { kGeneric, kVP8, };
45
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070046void ExpectEqualFrames(const VideoFrame& frame1, const VideoFrame& frame2);
47void ExpectEqualTextureFrames(const VideoFrame& frame1,
48 const VideoFrame& frame2);
49void ExpectEqualBufferFrames(const VideoFrame& frame1,
50 const VideoFrame& frame2);
51void ExpectEqualFramesVector(const std::vector<VideoFrame>& frames1,
52 const std::vector<VideoFrame>& frames2);
53VideoFrame CreateVideoFrame(int width, int height, uint8_t data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000054
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000055class VideoSendStreamTest : public test::CallTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000056 protected:
stefan@webrtc.org69969e22013-11-15 12:32:15 +000057 void TestNackRetransmission(uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +000058 uint8_t retransmit_payload_type);
sprang@webrtc.org346094c2014-02-18 08:40:33 +000059 void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
Åsa Perssonff24c042015-12-04 10:58:08 +010060
61 void TestVp9NonFlexMode(uint8_t num_temporal_layers,
62 uint8_t num_spatial_layers);
pbos@webrtc.org013d9942013-08-22 09:42:17 +000063};
64
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000065TEST_F(VideoSendStreamTest, CanStartStartedStream) {
solenberg4fbae2b2015-08-28 04:07:10 -070066 Call::Config call_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000067 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000068
solenberg4fbae2b2015-08-28 04:07:10 -070069 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +010070 CreateSendConfig(1, 0, &transport);
71 CreateVideoStreams();
stefanff483612015-12-21 03:14:00 -080072 video_send_stream_->Start();
73 video_send_stream_->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000074 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000075}
76
77TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
solenberg4fbae2b2015-08-28 04:07:10 -070078 Call::Config call_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000079 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000080
solenberg4fbae2b2015-08-28 04:07:10 -070081 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +010082 CreateSendConfig(1, 0, &transport);
83 CreateVideoStreams();
stefanff483612015-12-21 03:14:00 -080084 video_send_stream_->Stop();
85 video_send_stream_->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000086 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000087}
88
pbos@webrtc.org013d9942013-08-22 09:42:17 +000089TEST_F(VideoSendStreamTest, SupportsCName) {
90 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000091 class CNameObserver : public test::SendTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000092 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000093 CNameObserver() : SendTest(kDefaultTimeoutMs) {}
pbos@webrtc.org013d9942013-08-22 09:42:17 +000094
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000095 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000096 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000097 RTCPUtility::RTCPParserV2 parser(packet, length, true);
98 EXPECT_TRUE(parser.IsValid());
99
100 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200101 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
102 if (packet_type == RTCPUtility::RTCPPacketTypes::kSdesChunk) {
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000103 EXPECT_EQ(parser.Packet().CName.CName, kCName);
Peter Boström5811a392015-12-10 13:02:50 +0100104 observation_complete_.Set();
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000105 }
106
107 packet_type = parser.Iterate();
108 }
109
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000110 return SEND_PACKET;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000111 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000112
stefanff483612015-12-21 03:14:00 -0800113 void ModifyVideoConfigs(
114 VideoSendStream::Config* send_config,
115 std::vector<VideoReceiveStream::Config>* receive_configs,
116 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000117 send_config->rtp.c_name = kCName;
118 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000119
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000120 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100121 EXPECT_TRUE(Wait()) << "Timed out while waiting for RTCP with CNAME.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000122 }
123 } test;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000124
stefane74eef12016-01-08 06:47:13 -0800125 RunBaseTest(&test);
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000126}
127
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000128TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000129 class AbsoluteSendTimeObserver : public test::SendTest {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000130 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000131 AbsoluteSendTimeObserver() : SendTest(kDefaultTimeoutMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000132 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
Stefan Holmer4654d202015-12-08 09:10:43 +0100133 kRtpExtensionAbsoluteSendTime, test::kAbsSendTimeExtensionId));
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000134 }
135
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000136 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000137 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000138 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000139
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000140 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
141 EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
142 EXPECT_EQ(header.extension.transmissionTimeOffset, 0);
143 EXPECT_GT(header.extension.absoluteSendTime, 0u);
Peter Boström5811a392015-12-10 13:02:50 +0100144 observation_complete_.Set();
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000145
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000146 return SEND_PACKET;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000147 }
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000148
stefanff483612015-12-21 03:14:00 -0800149 void ModifyVideoConfigs(
150 VideoSendStream::Config* send_config,
151 std::vector<VideoReceiveStream::Config>* receive_configs,
152 VideoEncoderConfig* encoder_config) override {
Erik Språng95261872015-04-10 11:58:49 +0200153 send_config->rtp.extensions.clear();
Stefan Holmer4654d202015-12-08 09:10:43 +0100154 send_config->rtp.extensions.push_back(RtpExtension(
155 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000156 }
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +0000157
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000158 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100159 EXPECT_TRUE(Wait()) << "Timed out while waiting for single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000160 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000161 } test;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000162
stefane74eef12016-01-08 06:47:13 -0800163 RunBaseTest(&test);
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000164}
165
pbos@webrtc.org29023282013-09-11 10:14:56 +0000166TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000167 static const int kEncodeDelayMs = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000168 class TransmissionTimeOffsetObserver : public test::SendTest {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000169 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000170 TransmissionTimeOffsetObserver()
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000171 : SendTest(kDefaultTimeoutMs),
172 encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000173 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
Stefan Holmer12952972015-10-29 15:13:24 +0100174 kRtpExtensionTransmissionTimeOffset, test::kTOffsetExtensionId));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000175 }
176
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000177 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000178 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000179 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000180 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000181
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000182 EXPECT_TRUE(header.extension.hasTransmissionTimeOffset);
183 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000184 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000185 EXPECT_EQ(header.extension.absoluteSendTime, 0u);
Peter Boström5811a392015-12-10 13:02:50 +0100186 observation_complete_.Set();
pbos@webrtc.org29023282013-09-11 10:14:56 +0000187
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000188 return SEND_PACKET;
pbos@webrtc.org29023282013-09-11 10:14:56 +0000189 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000190
stefanff483612015-12-21 03:14:00 -0800191 void ModifyVideoConfigs(
192 VideoSendStream::Config* send_config,
193 std::vector<VideoReceiveStream::Config>* receive_configs,
194 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000195 send_config->encoder_settings.encoder = &encoder_;
Stefan Holmer12952972015-10-29 15:13:24 +0100196 send_config->rtp.extensions.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000197 send_config->rtp.extensions.push_back(
Stefan Holmer12952972015-10-29 15:13:24 +0100198 RtpExtension(RtpExtension::kTOffset, test::kTOffsetExtensionId));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000199 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000200
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000201 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100202 EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000203 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000204
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000205 test::DelayedEncoder encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000206 } test;
207
stefane74eef12016-01-08 06:47:13 -0800208 RunBaseTest(&test);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000209}
210
sprang867fb522015-08-03 04:38:41 -0700211TEST_F(VideoSendStreamTest, SupportsTransportWideSequenceNumbers) {
212 static const uint8_t kExtensionId = 13;
213 class TransportWideSequenceNumberObserver : public test::SendTest {
214 public:
215 TransportWideSequenceNumberObserver()
216 : SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) {
217 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
218 kRtpExtensionTransportSequenceNumber, kExtensionId));
219 }
220
221 private:
222 Action OnSendRtp(const uint8_t* packet, size_t length) override {
223 RTPHeader header;
224 EXPECT_TRUE(parser_->Parse(packet, length, &header));
225
226 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
227 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
228 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
229
Peter Boström5811a392015-12-10 13:02:50 +0100230 observation_complete_.Set();
sprang867fb522015-08-03 04:38:41 -0700231
232 return SEND_PACKET;
233 }
234
stefanff483612015-12-21 03:14:00 -0800235 void ModifyVideoConfigs(
236 VideoSendStream::Config* send_config,
237 std::vector<VideoReceiveStream::Config>* receive_configs,
238 VideoEncoderConfig* encoder_config) override {
sprang867fb522015-08-03 04:38:41 -0700239 send_config->encoder_settings.encoder = &encoder_;
Stefan Holmer12952972015-10-29 15:13:24 +0100240 send_config->rtp.extensions.clear();
sprang867fb522015-08-03 04:38:41 -0700241 send_config->rtp.extensions.push_back(
242 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
243 }
244
245 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100246 EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
sprang867fb522015-08-03 04:38:41 -0700247 }
248
249 test::FakeEncoder encoder_;
250 } test;
251
stefane74eef12016-01-08 06:47:13 -0800252 RunBaseTest(&test);
sprang867fb522015-08-03 04:38:41 -0700253}
254
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000255class FakeReceiveStatistics : public NullReceiveStatistics {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000256 public:
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000257 FakeReceiveStatistics(uint32_t send_ssrc,
258 uint32_t last_sequence_number,
259 uint32_t cumulative_lost,
260 uint8_t fraction_lost)
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000261 : lossy_stats_(new LossyStatistician(last_sequence_number,
262 cumulative_lost,
263 fraction_lost)) {
264 stats_map_[send_ssrc] = lossy_stats_.get();
265 }
266
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000267 StatisticianMap GetActiveStatisticians() const override { return stats_map_; }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000268
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000269 StreamStatistician* GetStatistician(uint32_t ssrc) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000270 return lossy_stats_.get();
271 }
272
273 private:
274 class LossyStatistician : public StreamStatistician {
275 public:
276 LossyStatistician(uint32_t extended_max_sequence_number,
277 uint32_t cumulative_lost,
278 uint8_t fraction_lost) {
279 stats_.fraction_lost = fraction_lost;
280 stats_.cumulative_lost = cumulative_lost;
281 stats_.extended_max_sequence_number = extended_max_sequence_number;
282 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000283 bool GetStatistics(RtcpStatistics* statistics, bool reset) override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000284 *statistics = stats_;
285 return true;
286 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000287 void GetDataCounters(size_t* bytes_received,
288 uint32_t* packets_received) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000289 *bytes_received = 0;
290 *packets_received = 0;
291 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000292 void GetReceiveStreamDataCounters(
293 StreamDataCounters* data_counters) const override {}
294 uint32_t BitrateReceived() const override { return 0; }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000295 bool IsRetransmitOfOldPacket(const RTPHeader& header,
296 int64_t min_rtt) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000297 return false;
298 }
299
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000300 bool IsPacketInOrder(uint16_t sequence_number) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000301 return true;
302 }
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000303
304 RtcpStatistics stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000305 };
306
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000307 rtc::scoped_ptr<LossyStatistician> lossy_stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000308 StatisticianMap stats_map_;
309};
310
Stefan Holmer4654d202015-12-08 09:10:43 +0100311class FecObserver : public test::SendTest {
312 public:
313 explicit FecObserver(bool header_extensions_enabled)
314 : SendTest(VideoSendStreamTest::kDefaultTimeoutMs),
315 send_count_(0),
316 received_media_(false),
317 received_fec_(false),
318 header_extensions_enabled_(header_extensions_enabled) {}
319
320 private:
321 Action OnSendRtp(const uint8_t* packet, size_t length) override {
322 RTPHeader header;
323 EXPECT_TRUE(parser_->Parse(packet, length, &header));
324
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.
328 FakeReceiveStatistics lossy_receive_stats(
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100329 VideoSendStreamTest::kVideoSendSsrcs[0], header.sequenceNumber,
Stefan Holmer4654d202015-12-08 09:10:43 +0100330 send_count_ / 2, 127);
331 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
terelius429c3452016-01-21 05:42:04 -0800332 &lossy_receive_stats, nullptr, nullptr,
Stefan Holmer4654d202015-12-08 09:10:43 +0100333 transport_adapter_.get());
334
335 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100336 rtcp_sender.SetRemoteSSRC(VideoSendStreamTest::kVideoSendSsrcs[0]);
Stefan Holmer4654d202015-12-08 09:10:43 +0100337
338 RTCPSender::FeedbackState feedback_state;
339
340 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000341 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000342
Stefan Holmer4654d202015-12-08 09:10:43 +0100343 int encapsulated_payload_type = -1;
344 if (header.payloadType == VideoSendStreamTest::kRedPayloadType) {
345 encapsulated_payload_type = static_cast<int>(packet[header.headerLength]);
346 if (encapsulated_payload_type !=
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100347 VideoSendStreamTest::kFakeVideoSendPayloadType)
Stefan Holmer4654d202015-12-08 09:10:43 +0100348 EXPECT_EQ(VideoSendStreamTest::kUlpfecPayloadType,
349 encapsulated_payload_type);
350 } else {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100351 EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType,
352 header.payloadType);
Stefan Holmer4654d202015-12-08 09:10:43 +0100353 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000354
Stefan Holmer4654d202015-12-08 09:10:43 +0100355 if (header_extensions_enabled_) {
356 EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
357 uint32_t kHalf24BitsSpace = 0xFFFFFF / 2;
358 if (header.extension.absoluteSendTime <= kHalf24BitsSpace &&
359 prev_header_.extension.absoluteSendTime > kHalf24BitsSpace) {
360 // 24 bits wrap.
361 EXPECT_GT(prev_header_.extension.absoluteSendTime,
362 header.extension.absoluteSendTime);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000363 } else {
Stefan Holmer4654d202015-12-08 09:10:43 +0100364 EXPECT_GE(header.extension.absoluteSendTime,
365 prev_header_.extension.absoluteSendTime);
Stefan Holmer01b48882015-05-05 10:21:24 +0200366 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100367 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
368 uint16_t seq_num_diff = header.extension.transportSequenceNumber -
369 prev_header_.extension.transportSequenceNumber;
370 EXPECT_EQ(1, seq_num_diff);
371 }
Stefan Holmer01b48882015-05-05 10:21:24 +0200372
Stefan Holmer4654d202015-12-08 09:10:43 +0100373 if (encapsulated_payload_type != -1) {
374 if (encapsulated_payload_type ==
375 VideoSendStreamTest::kUlpfecPayloadType) {
376 received_fec_ = true;
377 } else {
378 received_media_ = true;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000379 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000380 }
381
Stefan Holmer4654d202015-12-08 09:10:43 +0100382 if (received_media_ && received_fec_ && send_count_ > 100)
Peter Boström5811a392015-12-10 13:02:50 +0100383 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000384
Stefan Holmer4654d202015-12-08 09:10:43 +0100385 prev_header_ = header;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000386
Stefan Holmer4654d202015-12-08 09:10:43 +0100387 return SEND_PACKET;
388 }
389
stefanff483612015-12-21 03:14:00 -0800390 void ModifyVideoConfigs(
391 VideoSendStream::Config* send_config,
392 std::vector<VideoReceiveStream::Config>* receive_configs,
393 VideoEncoderConfig* encoder_config) override {
Stefan Holmer4654d202015-12-08 09:10:43 +0100394 transport_adapter_.reset(
395 new internal::TransportAdapter(send_config->send_transport));
396 transport_adapter_->Enable();
397 send_config->rtp.fec.red_payload_type =
398 VideoSendStreamTest::kRedPayloadType;
399 send_config->rtp.fec.ulpfec_payload_type =
400 VideoSendStreamTest::kUlpfecPayloadType;
401 if (header_extensions_enabled_) {
402 send_config->rtp.extensions.push_back(RtpExtension(
403 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId));
404 send_config->rtp.extensions.push_back(
405 RtpExtension(RtpExtension::kTransportSequenceNumber,
406 test::kTransportSequenceNumberExtensionId));
407 }
408 }
409
410 void PerformTest() override {
411 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
412 }
413
414 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
415 int send_count_;
416 bool received_media_;
417 bool received_fec_;
418 bool header_extensions_enabled_;
419 RTPHeader prev_header_;
420};
421
422TEST_F(VideoSendStreamTest, SupportsFecWithExtensions) {
423 FecObserver test(true);
424
stefane74eef12016-01-08 06:47:13 -0800425 RunBaseTest(&test);
Stefan Holmer4654d202015-12-08 09:10:43 +0100426}
427
428TEST_F(VideoSendStreamTest, SupportsFecWithoutExtensions) {
429 FecObserver test(false);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000430
stefane74eef12016-01-08 06:47:13 -0800431 RunBaseTest(&test);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000432}
433
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000434void VideoSendStreamTest::TestNackRetransmission(
435 uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000436 uint8_t retransmit_payload_type) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000437 class NackObserver : public test::SendTest {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000438 public:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000439 explicit NackObserver(uint32_t retransmit_ssrc,
440 uint8_t retransmit_payload_type)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000441 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000442 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000443 retransmit_ssrc_(retransmit_ssrc),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000444 retransmit_payload_type_(retransmit_payload_type),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000445 nacked_sequence_number_(-1) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000446 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000447
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000448 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000449 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000450 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000451 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000452
453 // Nack second packet after receiving the third one.
454 if (++send_count_ == 3) {
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000455 uint16_t nack_sequence_number = header.sequenceNumber - 1;
456 nacked_sequence_number_ = nack_sequence_number;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000457 NullReceiveStatistics null_stats;
Peter Boströmac547a62015-09-17 23:03:57 +0200458 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), &null_stats,
terelius429c3452016-01-21 05:42:04 -0800459 nullptr, nullptr, transport_adapter_.get());
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000460
pbosda903ea2015-10-02 02:36:56 -0700461 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100462 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000463
464 RTCPSender::FeedbackState feedback_state;
465
466 EXPECT_EQ(0,
467 rtcp_sender.SendRTCP(
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000468 feedback_state, kRtcpNack, 1, &nack_sequence_number));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000469 }
470
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000471 uint16_t sequence_number = header.sequenceNumber;
472
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000473 if (header.ssrc == retransmit_ssrc_ &&
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100474 retransmit_ssrc_ != kVideoSendSsrcs[0]) {
475 // Not kVideoSendSsrcs[0], assume correct RTX packet. Extract sequence
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000476 // number.
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000477 const uint8_t* rtx_header = packet + header.headerLength;
478 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
479 }
480
481 if (sequence_number == nacked_sequence_number_) {
482 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000483 EXPECT_EQ(retransmit_payload_type_, header.payloadType);
Peter Boström5811a392015-12-10 13:02:50 +0100484 observation_complete_.Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000485 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000486
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000487 return SEND_PACKET;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000488 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000489
stefanff483612015-12-21 03:14:00 -0800490 void ModifyVideoConfigs(
491 VideoSendStream::Config* send_config,
492 std::vector<VideoReceiveStream::Config>* receive_configs,
493 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700494 transport_adapter_.reset(
495 new internal::TransportAdapter(send_config->send_transport));
496 transport_adapter_->Enable();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000497 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000498 send_config->rtp.rtx.payload_type = retransmit_payload_type_;
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100499 if (retransmit_ssrc_ != kVideoSendSsrcs[0])
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000500 send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
501 }
502
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000503 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100504 EXPECT_TRUE(Wait()) << "Timed out while waiting for NACK retransmission.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000505 }
506
stefanf116bd02015-10-27 08:29:42 -0700507 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000508 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000509 uint32_t retransmit_ssrc_;
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000510 uint8_t retransmit_payload_type_;
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000511 int nacked_sequence_number_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000512 } test(retransmit_ssrc, retransmit_payload_type);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000513
stefane74eef12016-01-08 06:47:13 -0800514 RunBaseTest(&test);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000515}
516
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000517TEST_F(VideoSendStreamTest, RetransmitsNack) {
518 // Normal NACKs should use the send SSRC.
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100519 TestNackRetransmission(kVideoSendSsrcs[0], kFakeVideoSendPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000520}
521
522TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
523 // NACKs over RTX should use a separate SSRC.
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000524 TestNackRetransmission(kSendRtxSsrcs[0], kSendRtxPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000525}
526
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000527void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
528 bool with_fec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000529 // Use a fake encoder to output a frame of every size in the range [90, 290],
530 // for each size making sure that the exact number of payload bytes received
531 // is correct and that packets are fragmented to respect max packet size.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000532 static const size_t kMaxPacketSize = 128;
533 static const size_t start = 90;
534 static const size_t stop = 290;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000535
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000536 // Observer that verifies that the expected number of packets and bytes
537 // arrive for each frame size, from start_size to stop_size.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000538 class FrameFragmentationTest : public test::SendTest,
539 public EncodedFrameObserver {
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000540 public:
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000541 FrameFragmentationTest(size_t max_packet_size,
542 size_t start_size,
543 size_t stop_size,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000544 bool test_generic_packetization,
545 bool use_fec)
546 : SendTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000547 encoder_(stop),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000548 max_packet_size_(max_packet_size),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000549 stop_size_(stop_size),
550 test_generic_packetization_(test_generic_packetization),
551 use_fec_(use_fec),
552 packet_count_(0),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000553 accumulated_size_(0),
554 accumulated_payload_(0),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000555 fec_packet_received_(false),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000556 current_size_rtp_(start_size),
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000557 current_size_frame_(static_cast<int32_t>(start_size)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000558 // Fragmentation required, this test doesn't make sense without it.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000559 encoder_.SetFrameSize(start_size);
henrikg91d6ede2015-09-17 00:24:34 -0700560 RTC_DCHECK_GT(stop_size, max_packet_size);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000561 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000562
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000563 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000564 Action OnSendRtp(const uint8_t* packet, size_t size) override {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000565 size_t length = size;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000566 RTPHeader header;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000567 EXPECT_TRUE(parser_->Parse(packet, length, &header));
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000568
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000569 EXPECT_LE(length, max_packet_size_);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000570
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000571 if (use_fec_) {
572 uint8_t payload_type = packet[header.headerLength];
573 bool is_fec = header.payloadType == kRedPayloadType &&
574 payload_type == kUlpfecPayloadType;
575 if (is_fec) {
576 fec_packet_received_ = true;
577 return SEND_PACKET;
578 }
579 }
580
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000581 accumulated_size_ += length;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000582
583 if (use_fec_)
584 TriggerLossReport(header);
585
586 if (test_generic_packetization_) {
Stefan Holmer586b19b2015-09-18 11:14:31 +0200587 size_t overhead = header.headerLength + header.paddingLength;
588 // Only remove payload header and RED header if the packet actually
589 // contains payload.
590 if (length > overhead) {
591 overhead += (1 /* Generic header */);
592 if (use_fec_)
593 overhead += 1; // RED for FEC header.
594 }
595 EXPECT_GE(length, overhead);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000596 accumulated_payload_ += length - overhead;
597 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000598
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000599 // Marker bit set indicates last packet of a frame.
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000600 if (header.markerBit) {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000601 if (use_fec_ && accumulated_payload_ == current_size_rtp_ - 1) {
602 // With FEC enabled, frame size is incremented asynchronously, so
603 // "old" frames one byte too small may arrive. Accept, but don't
604 // increase expected frame size.
605 accumulated_size_ = 0;
606 accumulated_payload_ = 0;
607 return SEND_PACKET;
608 }
609
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000610 EXPECT_GE(accumulated_size_, current_size_rtp_);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000611 if (test_generic_packetization_) {
612 EXPECT_EQ(current_size_rtp_, accumulated_payload_);
613 }
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000614
615 // Last packet of frame; reset counters.
616 accumulated_size_ = 0;
617 accumulated_payload_ = 0;
618 if (current_size_rtp_ == stop_size_) {
619 // Done! (Don't increase size again, might arrive more @ stop_size).
Peter Boström5811a392015-12-10 13:02:50 +0100620 observation_complete_.Set();
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000621 } else {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000622 // Increase next expected frame size. If testing with FEC, make sure
623 // a FEC packet has been received for this frame size before
624 // proceeding, to make sure that redundancy packets don't exceed
625 // size limit.
626 if (!use_fec_) {
627 ++current_size_rtp_;
628 } else if (fec_packet_received_) {
629 fec_packet_received_ = false;
630 ++current_size_rtp_;
631 ++current_size_frame_;
632 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000633 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000634 }
635
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000636 return SEND_PACKET;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000637 }
638
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000639 void TriggerLossReport(const RTPHeader& header) {
640 // Send lossy receive reports to trigger FEC enabling.
641 if (packet_count_++ % 2 != 0) {
642 // Receive statistics reporting having lost 50% of the packets.
643 FakeReceiveStatistics lossy_receive_stats(
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100644 kVideoSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127);
Peter Boströmac547a62015-09-17 23:03:57 +0200645 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
terelius429c3452016-01-21 05:42:04 -0800646 &lossy_receive_stats, nullptr, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700647 transport_adapter_.get());
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000648
pbosda903ea2015-10-02 02:36:56 -0700649 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100650 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000651
652 RTCPSender::FeedbackState feedback_state;
653
654 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
655 }
656 }
657
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000658 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
659 // Increase frame size for next encoded frame, in the context of the
660 // encoder thread.
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000661 if (!use_fec_ &&
662 current_size_frame_.Value() < static_cast<int32_t>(stop_size_)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000663 ++current_size_frame_;
664 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000665 encoder_.SetFrameSize(static_cast<size_t>(current_size_frame_.Value()));
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000666 }
667
Stefan Holmere5904162015-03-26 11:11:06 +0100668 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700669 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100670 const int kMinBitrateBps = 30000;
671 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
672 return config;
673 }
674
stefanff483612015-12-21 03:14:00 -0800675 void ModifyVideoConfigs(
676 VideoSendStream::Config* send_config,
677 std::vector<VideoReceiveStream::Config>* receive_configs,
678 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700679 transport_adapter_.reset(
680 new internal::TransportAdapter(send_config->send_transport));
681 transport_adapter_->Enable();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000682 if (use_fec_) {
683 send_config->rtp.fec.red_payload_type = kRedPayloadType;
684 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
685 }
686
687 if (!test_generic_packetization_)
688 send_config->encoder_settings.payload_name = "VP8";
689
690 send_config->encoder_settings.encoder = &encoder_;
691 send_config->rtp.max_packet_size = kMaxPacketSize;
692 send_config->post_encode_callback = this;
693
Erik Språng95261872015-04-10 11:58:49 +0200694 // Make sure there is at least one extension header, to make the RTP
695 // header larger than the base length of 12 bytes.
696 EXPECT_FALSE(send_config->rtp.extensions.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000697 }
698
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000699 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100700 EXPECT_TRUE(Wait()) << "Timed out while observing incoming RTP packets.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000701 }
702
stefanf116bd02015-10-27 08:29:42 -0700703 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000704 test::ConfigurableFrameSizeEncoder encoder_;
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000705
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000706 const size_t max_packet_size_;
707 const size_t stop_size_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000708 const bool test_generic_packetization_;
709 const bool use_fec_;
710
711 uint32_t packet_count_;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000712 size_t accumulated_size_;
713 size_t accumulated_payload_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000714 bool fec_packet_received_;
715
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000716 size_t current_size_rtp_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000717 Atomic32 current_size_frame_;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000718 };
719
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000720 // Don't auto increment if FEC is used; continue sending frame size until
721 // a FEC packet has been received.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000722 FrameFragmentationTest test(
723 kMaxPacketSize, start, stop, format == kGeneric, with_fec);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000724
stefane74eef12016-01-08 06:47:13 -0800725 RunBaseTest(&test);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000726}
727
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000728// TODO(sprang): Is there any way of speeding up these tests?
729TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSize) {
730 TestPacketFragmentationSize(kGeneric, false);
731}
732
733TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSizeWithFec) {
734 TestPacketFragmentationSize(kGeneric, true);
735}
736
737TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSize) {
738 TestPacketFragmentationSize(kVP8, false);
739}
740
741TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSizeWithFec) {
742 TestPacketFragmentationSize(kVP8, true);
743}
744
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000745// The test will go through a number of phases.
746// 1. Start sending packets.
747// 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 +0000748// suspend the stream.
749// 3. Wait until |kSuspendTimeFrames| have been captured without seeing any RTP
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000750// packets.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000751// 4. Signal a high REMB and then wait for the RTP stream to start again.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000752// When the stream is detected again, and the stats show that the stream
753// is no longer suspended, the test ends.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000754TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
755 static const int kSuspendTimeFrames = 60; // Suspend for 2 seconds @ 30 fps.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000756
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000757 class RembObserver : public test::SendTest, public I420FrameCallback {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000758 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000759 RembObserver()
760 : SendTest(kDefaultTimeoutMs),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000761 clock_(Clock::GetRealTimeClock()),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000762 test_state_(kBeforeSuspend),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000763 rtp_count_(0),
764 last_sequence_number_(0),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000765 suspended_frame_count_(0),
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000766 low_remb_bps_(0),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000767 high_remb_bps_(0) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000768 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000769
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000770 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000771 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200772 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000773 ++rtp_count_;
774 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000775 EXPECT_TRUE(parser_->Parse(packet, length, &header));
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000776 last_sequence_number_ = header.sequenceNumber;
777
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000778 if (test_state_ == kBeforeSuspend) {
779 // The stream has started. Try to suspend it.
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000780 SendRtcpFeedback(low_remb_bps_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000781 test_state_ = kDuringSuspend;
782 } else if (test_state_ == kDuringSuspend) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000783 if (header.paddingLength == 0) {
784 // Received non-padding packet during suspension period. Reset the
785 // counter.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000786 suspended_frame_count_ = 0;
787 }
stefanf116bd02015-10-27 08:29:42 -0700788 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000789 } else if (test_state_ == kWaitingForPacket) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000790 if (header.paddingLength == 0) {
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000791 // Non-padding packet observed. Test is almost complete. Will just
792 // have to wait for the stats to change.
793 test_state_ = kWaitingForStats;
794 }
stefanf116bd02015-10-27 08:29:42 -0700795 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000796 } else if (test_state_ == kWaitingForStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000797 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000798 if (stats.suspended == false) {
799 // Stats flipped to false. Test is complete.
Peter Boström5811a392015-12-10 13:02:50 +0100800 observation_complete_.Set();
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000801 }
stefanf116bd02015-10-27 08:29:42 -0700802 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000803 }
804
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000805 return SEND_PACKET;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000806 }
807
808 // This method implements the I420FrameCallback.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700809 void FrameCallback(VideoFrame* video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200810 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000811 if (test_state_ == kDuringSuspend &&
812 ++suspended_frame_count_ > kSuspendTimeFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000813 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000814 EXPECT_TRUE(stats.suspended);
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000815 SendRtcpFeedback(high_remb_bps_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000816 test_state_ = kWaitingForPacket;
817 }
818 }
819
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000820 void set_low_remb_bps(int value) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200821 rtc::CritScope lock(&crit_);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000822 low_remb_bps_ = value;
823 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000824
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000825 void set_high_remb_bps(int value) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200826 rtc::CritScope lock(&crit_);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000827 high_remb_bps_ = value;
828 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000829
stefanff483612015-12-21 03:14:00 -0800830 void OnVideoStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000831 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000832 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000833 stream_ = send_stream;
834 }
835
stefanff483612015-12-21 03:14:00 -0800836 void ModifyVideoConfigs(
837 VideoSendStream::Config* send_config,
838 std::vector<VideoReceiveStream::Config>* receive_configs,
839 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700840 transport_adapter_.reset(
841 new internal::TransportAdapter(send_config->send_transport));
842 transport_adapter_->Enable();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000843 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000844 send_config->pre_encode_callback = this;
845 send_config->suspend_below_min_bitrate = true;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000846 int min_bitrate_bps = encoder_config->streams[0].min_bitrate_bps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000847 set_low_remb_bps(min_bitrate_bps - 10000);
848 int threshold_window = std::max(min_bitrate_bps / 10, 10000);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000849 ASSERT_GT(encoder_config->streams[0].max_bitrate_bps,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000850 min_bitrate_bps + threshold_window + 5000);
851 set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
852 }
853
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000854 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100855 EXPECT_TRUE(Wait()) << "Timed out during suspend-below-min-bitrate test.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000856 }
857
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000858 enum TestState {
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000859 kBeforeSuspend,
860 kDuringSuspend,
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000861 kWaitingForPacket,
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000862 kWaitingForStats
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000863 };
864
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000865 virtual void SendRtcpFeedback(int remb_value)
866 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100867 FakeReceiveStatistics receive_stats(kVideoSendSsrcs[0],
868 last_sequence_number_, rtp_count_, 0);
terelius429c3452016-01-21 05:42:04 -0800869 RTCPSender rtcp_sender(false, clock_, &receive_stats, nullptr, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700870 transport_adapter_.get());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000871
pbosda903ea2015-10-02 02:36:56 -0700872 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100873 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000874 if (remb_value > 0) {
875 rtcp_sender.SetREMBStatus(true);
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000876 rtcp_sender.SetREMBData(remb_value, std::vector<uint32_t>());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000877 }
878 RTCPSender::FeedbackState feedback_state;
879 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
880 }
881
stefanf116bd02015-10-27 08:29:42 -0700882 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000883 Clock* const clock_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000884 VideoSendStream* stream_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000885
Peter Boströmf2f82832015-05-01 13:00:41 +0200886 rtc::CriticalSection crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000887 TestState test_state_ GUARDED_BY(crit_);
888 int rtp_count_ GUARDED_BY(crit_);
889 int last_sequence_number_ GUARDED_BY(crit_);
890 int suspended_frame_count_ GUARDED_BY(crit_);
891 int low_remb_bps_ GUARDED_BY(crit_);
892 int high_remb_bps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000893 } test;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000894
stefane74eef12016-01-08 06:47:13 -0800895 RunBaseTest(&test);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000896}
897
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000898TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000899 class NoPaddingWhenVideoIsMuted : public test::SendTest {
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000900 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000901 NoPaddingWhenVideoIsMuted()
902 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000903 clock_(Clock::GetRealTimeClock()),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000904 last_packet_time_ms_(-1),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000905 capturer_(nullptr) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000906 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000907
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000908 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000909 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200910 rtc::CritScope lock(&crit_);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000911 last_packet_time_ms_ = clock_->TimeInMilliseconds();
912 capturer_->Stop();
913 return SEND_PACKET;
914 }
915
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000916 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200917 rtc::CritScope lock(&crit_);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000918 const int kVideoMutedThresholdMs = 10000;
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000919 if (last_packet_time_ms_ > 0 &&
920 clock_->TimeInMilliseconds() - last_packet_time_ms_ >
921 kVideoMutedThresholdMs)
Peter Boström5811a392015-12-10 13:02:50 +0100922 observation_complete_.Set();
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000923 // Receive statistics reporting having lost 50% of the packets.
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100924 FakeReceiveStatistics receive_stats(kVideoSendSsrcs[0], 1, 1, 0);
Peter Boströmac547a62015-09-17 23:03:57 +0200925 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), &receive_stats,
terelius429c3452016-01-21 05:42:04 -0800926 nullptr, nullptr, transport_adapter_.get());
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000927
pbosda903ea2015-10-02 02:36:56 -0700928 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100929 rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000930
931 RTCPSender::FeedbackState feedback_state;
932
933 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
934 return SEND_PACKET;
935 }
936
stefane74eef12016-01-08 06:47:13 -0800937 test::PacketTransport* CreateReceiveTransport() override {
938 test::PacketTransport* transport = new test::PacketTransport(
939 nullptr, this, test::PacketTransport::kReceiver,
940 FakeNetworkPipe::Config());
941 transport_adapter_.reset(new internal::TransportAdapter(transport));
stefanf116bd02015-10-27 08:29:42 -0700942 transport_adapter_->Enable();
stefane74eef12016-01-08 06:47:13 -0800943 return transport;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000944 }
945
Stefan Holmer9fea80f2016-01-07 17:43:18 +0100946 size_t GetNumVideoStreams() const override { return 3; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000947
948 virtual void OnFrameGeneratorCapturerCreated(
949 test::FrameGeneratorCapturer* frame_generator_capturer) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200950 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000951 capturer_ = frame_generator_capturer;
952 }
953
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000954 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100955 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000956 << "Timed out while waiting for RTP packets to stop being sent.";
957 }
958
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000959 Clock* const clock_;
stefanf116bd02015-10-27 08:29:42 -0700960 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
Peter Boströmf2f82832015-05-01 13:00:41 +0200961 rtc::CriticalSection crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000962 int64_t last_packet_time_ms_ GUARDED_BY(crit_);
963 test::FrameGeneratorCapturer* capturer_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000964 } test;
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000965
stefane74eef12016-01-08 06:47:13 -0800966 RunBaseTest(&test);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000967}
968
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000969// This test first observes "high" bitrate use at which point it sends a REMB to
970// indicate that it should be lowered significantly. The test then observes that
971// the bitrate observed is sinking well below the min-transmit-bitrate threshold
972// to verify that the min-transmit bitrate respects incoming REMB.
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000973//
974// Note that the test starts at "high" bitrate and does not ramp up to "higher"
975// bitrate since no receiver block or remb is sent in the initial phase.
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000976TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
977 static const int kMinTransmitBitrateBps = 400000;
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000978 static const int kHighBitrateBps = 150000;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000979 static const int kRembBitrateBps = 80000;
980 static const int kRembRespectedBitrateBps = 100000;
stefanf116bd02015-10-27 08:29:42 -0700981 class BitrateObserver : public test::SendTest {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000982 public:
983 BitrateObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000984 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000985 bitrate_capped_(false) {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000986 }
987
988 private:
stefanf116bd02015-10-27 08:29:42 -0700989 virtual Action OnSendRtp(const uint8_t* packet, size_t length) {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000990 if (RtpHeaderParser::IsRtcp(packet, length))
stefanf116bd02015-10-27 08:29:42 -0700991 return DROP_PACKET;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000992
993 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000994 if (!parser_->Parse(packet, length, &header))
stefanf116bd02015-10-27 08:29:42 -0700995 return DROP_PACKET;
henrikg91d6ede2015-09-17 00:24:34 -0700996 RTC_DCHECK(stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000997 VideoSendStream::Stats stats = stream_->GetStats();
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000998 if (!stats.substreams.empty()) {
999 EXPECT_EQ(1u, stats.substreams.size());
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001000 int total_bitrate_bps =
1001 stats.substreams.begin()->second.total_bitrate_bps;
1002 test::PrintResult("bitrate_stats_",
1003 "min_transmit_bitrate_low_remb",
1004 "bitrate_bps",
1005 static_cast<size_t>(total_bitrate_bps),
1006 "bps",
1007 false);
1008 if (total_bitrate_bps > kHighBitrateBps) {
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001009 rtp_rtcp_->SetREMBData(kRembBitrateBps,
1010 std::vector<uint32_t>(1, header.ssrc));
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001011 rtp_rtcp_->Process();
1012 bitrate_capped_ = true;
1013 } else if (bitrate_capped_ &&
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001014 total_bitrate_bps < kRembRespectedBitrateBps) {
Peter Boström5811a392015-12-10 13:02:50 +01001015 observation_complete_.Set();
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001016 }
1017 }
stefanf116bd02015-10-27 08:29:42 -07001018 // Packets don't have to be delivered since the test is the receiver.
1019 return DROP_PACKET;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001020 }
1021
stefanff483612015-12-21 03:14:00 -08001022 void OnVideoStreamsCreated(
stefanf116bd02015-10-27 08:29:42 -07001023 VideoSendStream* send_stream,
1024 const std::vector<VideoReceiveStream*>& receive_streams) override {
1025 stream_ = send_stream;
1026 RtpRtcp::Configuration config;
1027 config.outgoing_transport = feedback_transport_.get();
1028 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1029 rtp_rtcp_->SetREMBStatus(true);
1030 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001031 }
1032
stefanff483612015-12-21 03:14:00 -08001033 void ModifyVideoConfigs(
1034 VideoSendStream::Config* send_config,
1035 std::vector<VideoReceiveStream::Config>* receive_configs,
1036 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -07001037 feedback_transport_.reset(
1038 new internal::TransportAdapter(send_config->send_transport));
1039 feedback_transport_->Enable();
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00001040 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001041 }
1042
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001043 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001044 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001045 << "Timeout while waiting for low bitrate stats after REMB.";
1046 }
1047
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001048 rtc::scoped_ptr<RtpRtcp> rtp_rtcp_;
stefanf116bd02015-10-27 08:29:42 -07001049 rtc::scoped_ptr<internal::TransportAdapter> feedback_transport_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001050 VideoSendStream* stream_;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001051 bool bitrate_capped_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001052 } test;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001053
stefane74eef12016-01-08 06:47:13 -08001054 RunBaseTest(&test);
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001055}
1056
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001057TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) {
1058 class StartBitrateObserver : public test::FakeEncoder {
1059 public:
1060 StartBitrateObserver()
1061 : FakeEncoder(Clock::GetRealTimeClock()), start_bitrate_kbps_(0) {}
1062 int32_t InitEncode(const VideoCodec* config,
1063 int32_t number_of_cores,
1064 size_t max_payload_size) override {
1065 rtc::CritScope lock(&crit_);
1066 start_bitrate_kbps_ = config->startBitrate;
1067 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1068 }
1069
1070 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
1071 rtc::CritScope lock(&crit_);
1072 start_bitrate_kbps_ = new_target_bitrate;
1073 return FakeEncoder::SetRates(new_target_bitrate, framerate);
1074 }
1075
1076 int GetStartBitrateKbps() const {
1077 rtc::CritScope lock(&crit_);
1078 return start_bitrate_kbps_;
1079 }
1080
1081 private:
pbos5ad935c2016-01-25 03:52:44 -08001082 rtc::CriticalSection crit_;
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001083 int start_bitrate_kbps_ GUARDED_BY(crit_);
1084 };
1085
solenberg4fbae2b2015-08-28 04:07:10 -07001086 CreateSenderCall(Call::Config());
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001087
solenberg4fbae2b2015-08-28 04:07:10 -07001088 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001089 CreateSendConfig(1, 0, &transport);
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001090
1091 Call::Config::BitrateConfig bitrate_config;
1092 bitrate_config.start_bitrate_bps =
stefanff483612015-12-21 03:14:00 -08001093 2 * video_encoder_config_.streams[0].max_bitrate_bps;
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001094 sender_call_->SetBitrateConfig(bitrate_config);
1095
1096 StartBitrateObserver encoder;
stefanff483612015-12-21 03:14:00 -08001097 video_send_config_.encoder_settings.encoder = &encoder;
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001098
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001099 CreateVideoStreams();
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001100
stefanff483612015-12-21 03:14:00 -08001101 EXPECT_EQ(video_encoder_config_.streams[0].max_bitrate_bps / 1000,
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001102 encoder.GetStartBitrateKbps());
1103
stefanff483612015-12-21 03:14:00 -08001104 video_encoder_config_.streams[0].max_bitrate_bps =
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001105 2 * bitrate_config.start_bitrate_bps;
stefanff483612015-12-21 03:14:00 -08001106 video_send_stream_->ReconfigureVideoEncoder(video_encoder_config_);
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001107
1108 // New bitrate should be reconfigured above the previous max. As there's no
1109 // network connection this shouldn't be flaky, as no bitrate should've been
1110 // reported in between.
1111 EXPECT_EQ(bitrate_config.start_bitrate_bps / 1000,
1112 encoder.GetStartBitrateKbps());
1113
1114 DestroyStreams();
1115}
1116
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001117TEST_F(VideoSendStreamTest, CapturesTextureAndVideoFrames) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001118 class FrameObserver : public I420FrameCallback {
1119 public:
Peter Boström5811a392015-12-10 13:02:50 +01001120 FrameObserver() : output_frame_event_(false, false) {}
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001121
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001122 void FrameCallback(VideoFrame* video_frame) override {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001123 output_frames_.push_back(*video_frame);
Peter Boström5811a392015-12-10 13:02:50 +01001124 output_frame_event_.Set();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001125 }
1126
1127 void WaitOutputFrame() {
Peter Boström5811a392015-12-10 13:02:50 +01001128 const int kWaitFrameTimeoutMs = 3000;
1129 EXPECT_TRUE(output_frame_event_.Wait(kWaitFrameTimeoutMs))
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001130 << "Timeout while waiting for output frames.";
1131 }
1132
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001133 const std::vector<VideoFrame>& output_frames() const {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001134 return output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001135 }
1136
1137 private:
1138 // Delivered output frames.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001139 std::vector<VideoFrame> output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001140
1141 // Indicate an output frame has arrived.
Peter Boström5811a392015-12-10 13:02:50 +01001142 rtc::Event output_frame_event_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001143 };
1144
1145 // Initialize send stream.
solenberg4fbae2b2015-08-28 04:07:10 -07001146 CreateSenderCall(Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001147
solenberg4fbae2b2015-08-28 04:07:10 -07001148 test::NullTransport transport;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001149 CreateSendConfig(1, 0, &transport);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001150 FrameObserver observer;
stefanff483612015-12-21 03:14:00 -08001151 video_send_config_.pre_encode_callback = &observer;
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001152 CreateVideoStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001153
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001154 // Prepare five input frames. Send ordinary VideoFrame and texture frames
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001155 // alternatively.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001156 std::vector<VideoFrame> input_frames;
stefanff483612015-12-21 03:14:00 -08001157 int width = static_cast<int>(video_encoder_config_.streams[0].width);
1158 int height = static_cast<int>(video_encoder_config_.streams[0].height);
Peter Boströmeb66e802015-06-05 11:08:03 +02001159 test::FakeNativeHandle* handle1 = new test::FakeNativeHandle();
1160 test::FakeNativeHandle* handle2 = new test::FakeNativeHandle();
1161 test::FakeNativeHandle* handle3 = new test::FakeNativeHandle();
Peter Boström13f61df2016-01-04 22:36:38 +01001162 input_frames.push_back(test::FakeNativeHandle::CreateFrame(
Peter Boströmeb66e802015-06-05 11:08:03 +02001163 handle1, width, height, 1, 1, kVideoRotation_0));
Peter Boström13f61df2016-01-04 22:36:38 +01001164 input_frames.push_back(test::FakeNativeHandle::CreateFrame(
Peter Boströmeb66e802015-06-05 11:08:03 +02001165 handle2, width, height, 2, 2, kVideoRotation_0));
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001166 input_frames.push_back(CreateVideoFrame(width, height, 3));
1167 input_frames.push_back(CreateVideoFrame(width, height, 4));
Peter Boström13f61df2016-01-04 22:36:38 +01001168 input_frames.push_back(test::FakeNativeHandle::CreateFrame(
Peter Boströmeb66e802015-06-05 11:08:03 +02001169 handle3, width, height, 5, 5, kVideoRotation_0));
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001170
stefanff483612015-12-21 03:14:00 -08001171 video_send_stream_->Start();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001172 for (size_t i = 0; i < input_frames.size(); i++) {
stefanff483612015-12-21 03:14:00 -08001173 video_send_stream_->Input()->IncomingCapturedFrame(input_frames[i]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001174 // Do not send the next frame too fast, so the frame dropper won't drop it.
1175 if (i < input_frames.size() - 1)
stefanff483612015-12-21 03:14:00 -08001176 SleepMs(1000 / video_encoder_config_.streams[0].max_framerate);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001177 // Wait until the output frame is received before sending the next input
1178 // frame. Or the previous input frame may be replaced without delivering.
1179 observer.WaitOutputFrame();
1180 }
stefanff483612015-12-21 03:14:00 -08001181 video_send_stream_->Stop();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001182
1183 // Test if the input and output frames are the same. render_time_ms and
1184 // timestamp are not compared because capturer sets those values.
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001185 ExpectEqualFramesVector(input_frames, observer.output_frames());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001186
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001187 DestroyStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001188}
1189
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001190void ExpectEqualFrames(const VideoFrame& frame1, const VideoFrame& frame2) {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001191 if (frame1.native_handle() != nullptr || frame2.native_handle() != nullptr)
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001192 ExpectEqualTextureFrames(frame1, frame2);
1193 else
1194 ExpectEqualBufferFrames(frame1, frame2);
1195}
1196
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001197void ExpectEqualTextureFrames(const VideoFrame& frame1,
1198 const VideoFrame& frame2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001199 EXPECT_EQ(frame1.native_handle(), frame2.native_handle());
1200 EXPECT_EQ(frame1.width(), frame2.width());
1201 EXPECT_EQ(frame1.height(), frame2.height());
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001202 EXPECT_EQ(frame1.render_time_ms(), frame2.render_time_ms());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001203}
1204
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001205void ExpectEqualBufferFrames(const VideoFrame& frame1,
1206 const VideoFrame& frame2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001207 EXPECT_EQ(frame1.width(), frame2.width());
1208 EXPECT_EQ(frame1.height(), frame2.height());
1209 EXPECT_EQ(frame1.stride(kYPlane), frame2.stride(kYPlane));
1210 EXPECT_EQ(frame1.stride(kUPlane), frame2.stride(kUPlane));
1211 EXPECT_EQ(frame1.stride(kVPlane), frame2.stride(kVPlane));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001212 EXPECT_EQ(frame1.render_time_ms(), frame2.render_time_ms());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001213 ASSERT_EQ(frame1.allocated_size(kYPlane), frame2.allocated_size(kYPlane));
1214 EXPECT_EQ(0,
1215 memcmp(frame1.buffer(kYPlane),
1216 frame2.buffer(kYPlane),
1217 frame1.allocated_size(kYPlane)));
1218 ASSERT_EQ(frame1.allocated_size(kUPlane), frame2.allocated_size(kUPlane));
1219 EXPECT_EQ(0,
1220 memcmp(frame1.buffer(kUPlane),
1221 frame2.buffer(kUPlane),
1222 frame1.allocated_size(kUPlane)));
1223 ASSERT_EQ(frame1.allocated_size(kVPlane), frame2.allocated_size(kVPlane));
1224 EXPECT_EQ(0,
1225 memcmp(frame1.buffer(kVPlane),
1226 frame2.buffer(kVPlane),
1227 frame1.allocated_size(kVPlane)));
1228}
1229
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001230void ExpectEqualFramesVector(const std::vector<VideoFrame>& frames1,
1231 const std::vector<VideoFrame>& frames2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001232 EXPECT_EQ(frames1.size(), frames2.size());
1233 for (size_t i = 0; i < std::min(frames1.size(), frames2.size()); ++i)
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001234 ExpectEqualFrames(frames1[i], frames2[i]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001235}
1236
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001237VideoFrame CreateVideoFrame(int width, int height, uint8_t data) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001238 const int kSizeY = width * height * 2;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001239 rtc::scoped_ptr<uint8_t[]> buffer(new uint8_t[kSizeY]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001240 memset(buffer.get(), data, kSizeY);
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001241 VideoFrame frame;
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001242 frame.CreateFrame(buffer.get(), buffer.get(), buffer.get(), width, height,
1243 width, width / 2, width / 2);
1244 frame.set_timestamp(data);
1245 frame.set_render_time_ms(data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001246 return frame;
1247}
1248
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001249TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
1250 class EncoderStateObserver : public test::SendTest, public VideoEncoder {
1251 public:
1252 EncoderStateObserver()
1253 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001254 initialized_(false),
1255 callback_registered_(false),
1256 num_releases_(0),
1257 released_(false) {}
1258
1259 bool IsReleased() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001260 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001261 return released_;
1262 }
1263
1264 bool IsReadyForEncode() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001265 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001266 return initialized_ && callback_registered_;
1267 }
1268
1269 size_t num_releases() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001270 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001271 return num_releases_;
1272 }
1273
1274 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001275 int32_t InitEncode(const VideoCodec* codecSettings,
1276 int32_t numberOfCores,
1277 size_t maxPayloadSize) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001278 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001279 EXPECT_FALSE(initialized_);
1280 initialized_ = true;
1281 released_ = false;
1282 return 0;
1283 }
1284
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001285 int32_t Encode(const VideoFrame& inputImage,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001286 const CodecSpecificInfo* codecSpecificInfo,
pbos22993e12015-10-19 02:39:06 -07001287 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001288 EXPECT_TRUE(IsReadyForEncode());
1289
Peter Boström5811a392015-12-10 13:02:50 +01001290 observation_complete_.Set();
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001291 return 0;
1292 }
1293
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001294 int32_t RegisterEncodeCompleteCallback(
1295 EncodedImageCallback* callback) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001296 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001297 EXPECT_TRUE(initialized_);
1298 callback_registered_ = true;
1299 return 0;
1300 }
1301
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001302 int32_t Release() override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001303 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001304 EXPECT_TRUE(IsReadyForEncode());
1305 EXPECT_FALSE(released_);
1306 initialized_ = false;
1307 callback_registered_ = false;
1308 released_ = true;
1309 ++num_releases_;
1310 return 0;
1311 }
1312
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001313 int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001314 EXPECT_TRUE(IsReadyForEncode());
1315 return 0;
1316 }
1317
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001318 int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001319 EXPECT_TRUE(IsReadyForEncode());
1320 return 0;
1321 }
1322
stefanff483612015-12-21 03:14:00 -08001323 void OnVideoStreamsCreated(
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001324 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001325 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001326 // Encoder initialization should be done in stream construction before
1327 // starting.
1328 EXPECT_TRUE(IsReadyForEncode());
1329 stream_ = send_stream;
1330 }
1331
stefanff483612015-12-21 03:14:00 -08001332 void ModifyVideoConfigs(
1333 VideoSendStream::Config* send_config,
1334 std::vector<VideoReceiveStream::Config>* receive_configs,
1335 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001336 send_config->encoder_settings.encoder = this;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001337 encoder_config_ = *encoder_config;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001338 }
1339
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001340 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001341 EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001342 EXPECT_EQ(0u, num_releases());
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001343 stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001344 EXPECT_EQ(0u, num_releases());
1345 stream_->Stop();
1346 // Encoder should not be released before destroying the VideoSendStream.
1347 EXPECT_FALSE(IsReleased());
1348 EXPECT_TRUE(IsReadyForEncode());
1349 stream_->Start();
1350 // Sanity check, make sure we still encode frames with this encoder.
Peter Boström5811a392015-12-10 13:02:50 +01001351 EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001352 }
1353
Peter Boströmf2f82832015-05-01 13:00:41 +02001354 rtc::CriticalSection crit_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001355 VideoSendStream* stream_;
1356 bool initialized_ GUARDED_BY(crit_);
1357 bool callback_registered_ GUARDED_BY(crit_);
1358 size_t num_releases_ GUARDED_BY(crit_);
1359 bool released_ GUARDED_BY(crit_);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001360 VideoEncoderConfig encoder_config_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001361 } test_encoder;
1362
stefane74eef12016-01-08 06:47:13 -08001363 RunBaseTest(&test_encoder);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001364
1365 EXPECT_TRUE(test_encoder.IsReleased());
1366 EXPECT_EQ(1u, test_encoder.num_releases());
1367}
1368
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001369TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
1370 class VideoCodecConfigObserver : public test::SendTest,
1371 public test::FakeEncoder {
1372 public:
1373 VideoCodecConfigObserver()
1374 : SendTest(kDefaultTimeoutMs),
1375 FakeEncoder(Clock::GetRealTimeClock()),
1376 num_initializations_(0) {}
1377
1378 private:
stefanff483612015-12-21 03:14:00 -08001379 void ModifyVideoConfigs(
1380 VideoSendStream::Config* send_config,
1381 std::vector<VideoReceiveStream::Config>* receive_configs,
1382 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001383 send_config->encoder_settings.encoder = this;
1384 encoder_config_ = *encoder_config;
1385 }
1386
stefanff483612015-12-21 03:14:00 -08001387 void OnVideoStreamsCreated(
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001388 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001389 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001390 stream_ = send_stream;
1391 }
1392
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001393 int32_t InitEncode(const VideoCodec* config,
1394 int32_t number_of_cores,
1395 size_t max_payload_size) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001396 if (num_initializations_ == 0) {
1397 // Verify default values.
1398 EXPECT_EQ(kRealtimeVideo, config->mode);
1399 } else {
1400 // Verify that changed values are propagated.
1401 EXPECT_EQ(kScreensharing, config->mode);
1402 }
1403 ++num_initializations_;
1404 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1405 }
1406
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001407 void PerformTest() override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001408 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1409
Erik Språng143cec12015-04-28 10:01:41 +02001410 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001411 stream_->ReconfigureVideoEncoder(encoder_config_);
1412 EXPECT_EQ(2u, num_initializations_)
1413 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1414 "new encoder settings.";
1415 }
1416
1417 size_t num_initializations_;
1418 VideoSendStream* stream_;
1419 VideoEncoderConfig encoder_config_;
1420 } test;
1421
stefane74eef12016-01-08 06:47:13 -08001422 RunBaseTest(&test);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001423}
1424
Peter Boström53eda3d2015-03-27 15:53:18 +01001425static const size_t kVideoCodecConfigObserverNumberOfTemporalLayers = 4;
1426template <typename T>
1427class VideoCodecConfigObserver : public test::SendTest,
1428 public test::FakeEncoder {
Peter Boström53eda3d2015-03-27 15:53:18 +01001429 public:
1430 VideoCodecConfigObserver(VideoCodecType video_codec_type,
1431 const char* codec_name)
1432 : SendTest(VideoSendStreamTest::kDefaultTimeoutMs),
1433 FakeEncoder(Clock::GetRealTimeClock()),
1434 video_codec_type_(video_codec_type),
1435 codec_name_(codec_name),
1436 num_initializations_(0) {
1437 memset(&encoder_settings_, 0, sizeof(encoder_settings_));
1438 }
1439
1440 private:
stefanff483612015-12-21 03:14:00 -08001441 void ModifyVideoConfigs(
1442 VideoSendStream::Config* send_config,
1443 std::vector<VideoReceiveStream::Config>* receive_configs,
1444 VideoEncoderConfig* encoder_config) override {
Peter Boström53eda3d2015-03-27 15:53:18 +01001445 send_config->encoder_settings.encoder = this;
1446 send_config->encoder_settings.payload_name = codec_name_;
1447
1448 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
1449 encoder_config->streams[i].temporal_layer_thresholds_bps.resize(
1450 kVideoCodecConfigObserverNumberOfTemporalLayers - 1);
1451 }
1452
1453 encoder_config->encoder_specific_settings = &encoder_settings_;
1454 encoder_config_ = *encoder_config;
1455 }
1456
stefanff483612015-12-21 03:14:00 -08001457 void OnVideoStreamsCreated(
Peter Boström53eda3d2015-03-27 15:53:18 +01001458 VideoSendStream* send_stream,
1459 const std::vector<VideoReceiveStream*>& receive_streams) override {
1460 stream_ = send_stream;
1461 }
1462
1463 int32_t InitEncode(const VideoCodec* config,
1464 int32_t number_of_cores,
1465 size_t max_payload_size) override {
1466 EXPECT_EQ(video_codec_type_, config->codecType);
1467 VerifyCodecSpecifics(*config);
1468 ++num_initializations_;
1469 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1470 }
1471
1472 void VerifyCodecSpecifics(const VideoCodec& config) const;
1473
1474 void PerformTest() override {
1475 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1476
1477 encoder_settings_.frameDroppingOn = true;
1478 stream_->ReconfigureVideoEncoder(encoder_config_);
1479 EXPECT_EQ(2u, num_initializations_)
1480 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1481 "new encoder settings.";
1482 }
1483
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001484 int32_t Encode(const VideoFrame& input_image,
Peter Boström53eda3d2015-03-27 15:53:18 +01001485 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07001486 const std::vector<FrameType>* frame_types) override {
Peter Boström53eda3d2015-03-27 15:53:18 +01001487 // Silently skip the encode, FakeEncoder::Encode doesn't produce VP8.
1488 return 0;
1489 }
1490
1491 T encoder_settings_;
1492 const VideoCodecType video_codec_type_;
1493 const char* const codec_name_;
1494 size_t num_initializations_;
1495 VideoSendStream* stream_;
1496 VideoEncoderConfig encoder_config_;
1497};
1498
1499template <>
1500void VideoCodecConfigObserver<VideoCodecH264>::VerifyCodecSpecifics(
1501 const VideoCodec& config) const {
1502 EXPECT_EQ(0, memcmp(&config.codecSpecific.H264, &encoder_settings_,
1503 sizeof(encoder_settings_)));
1504}
1505template <>
1506void VideoCodecConfigObserver<VideoCodecVP8>::VerifyCodecSpecifics(
1507 const VideoCodec& config) const {
1508 // Check that the number of temporal layers has propagated properly to
1509 // VideoCodec.
1510 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1511 config.codecSpecific.VP8.numberOfTemporalLayers);
1512
1513 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1514 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1515 config.simulcastStream[i].numberOfTemporalLayers);
1516 }
1517
1518 // Set expected temporal layers as they should have been set when
1519 // reconfiguring the encoder and not match the set config.
1520 VideoCodecVP8 encoder_settings = encoder_settings_;
1521 encoder_settings.numberOfTemporalLayers =
1522 kVideoCodecConfigObserverNumberOfTemporalLayers;
1523 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP8, &encoder_settings,
1524 sizeof(encoder_settings_)));
1525}
1526template <>
1527void VideoCodecConfigObserver<VideoCodecVP9>::VerifyCodecSpecifics(
1528 const VideoCodec& config) const {
1529 // Check that the number of temporal layers has propagated properly to
1530 // VideoCodec.
1531 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1532 config.codecSpecific.VP9.numberOfTemporalLayers);
1533
1534 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1535 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1536 config.simulcastStream[i].numberOfTemporalLayers);
1537 }
1538
1539 // Set expected temporal layers as they should have been set when
1540 // reconfiguring the encoder and not match the set config.
1541 VideoCodecVP9 encoder_settings = encoder_settings_;
1542 encoder_settings.numberOfTemporalLayers =
1543 kVideoCodecConfigObserverNumberOfTemporalLayers;
1544 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP9, &encoder_settings,
1545 sizeof(encoder_settings_)));
1546}
1547
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001548TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp8Config) {
Peter Boström53eda3d2015-03-27 15:53:18 +01001549 VideoCodecConfigObserver<VideoCodecVP8> test(kVideoCodecVP8, "VP8");
stefane74eef12016-01-08 06:47:13 -08001550 RunBaseTest(&test);
Peter Boström53eda3d2015-03-27 15:53:18 +01001551}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001552
Peter Boström53eda3d2015-03-27 15:53:18 +01001553TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp9Config) {
1554 VideoCodecConfigObserver<VideoCodecVP9> test(kVideoCodecVP9, "VP9");
stefane74eef12016-01-08 06:47:13 -08001555 RunBaseTest(&test);
Peter Boström53eda3d2015-03-27 15:53:18 +01001556}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001557
Peter Boström53eda3d2015-03-27 15:53:18 +01001558TEST_F(VideoSendStreamTest, EncoderSetupPropagatesH264Config) {
1559 VideoCodecConfigObserver<VideoCodecH264> test(kVideoCodecH264, "H264");
stefane74eef12016-01-08 06:47:13 -08001560 RunBaseTest(&test);
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001561}
1562
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001563TEST_F(VideoSendStreamTest, RtcpSenderReportContainsMediaBytesSent) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001564 class RtcpSenderReportTest : public test::SendTest {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001565 public:
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001566 RtcpSenderReportTest() : SendTest(kDefaultTimeoutMs),
1567 rtp_packets_sent_(0),
1568 media_bytes_sent_(0) {}
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001569
1570 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001571 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan4b569042015-11-11 06:39:57 -08001572 rtc::CritScope lock(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001573 RTPHeader header;
1574 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001575 ++rtp_packets_sent_;
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001576 media_bytes_sent_ += length - header.headerLength - header.paddingLength;
1577 return SEND_PACKET;
1578 }
1579
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001580 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan4b569042015-11-11 06:39:57 -08001581 rtc::CritScope lock(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001582 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1583 EXPECT_TRUE(parser.IsValid());
1584
1585 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001586 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1587 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001588 // Only compare sent media bytes if SenderPacketCount matches the
1589 // number of sent rtp packets (a new rtp packet could be sent before
1590 // the rtcp packet).
1591 if (parser.Packet().SR.SenderOctetCount > 0 &&
1592 parser.Packet().SR.SenderPacketCount == rtp_packets_sent_) {
1593 EXPECT_EQ(media_bytes_sent_, parser.Packet().SR.SenderOctetCount);
Peter Boström5811a392015-12-10 13:02:50 +01001594 observation_complete_.Set();
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001595 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001596 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001597 packet_type = parser.Iterate();
1598 }
1599
1600 return SEND_PACKET;
1601 }
1602
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001603 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001604 EXPECT_TRUE(Wait()) << "Timed out while waiting for RTCP sender report.";
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001605 }
1606
stefan4b569042015-11-11 06:39:57 -08001607 rtc::CriticalSection crit_;
1608 size_t rtp_packets_sent_ GUARDED_BY(&crit_);
1609 size_t media_bytes_sent_ GUARDED_BY(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001610 } test;
1611
stefane74eef12016-01-08 06:47:13 -08001612 RunBaseTest(&test);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001613}
1614
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001615TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
1616 static const int kScreencastTargetBitrateKbps = 200;
1617 class ScreencastTargetBitrateTest : public test::SendTest,
1618 public test::FakeEncoder {
1619 public:
1620 ScreencastTargetBitrateTest()
1621 : SendTest(kDefaultTimeoutMs),
1622 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1623
1624 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001625 int32_t InitEncode(const VideoCodec* config,
1626 int32_t number_of_cores,
1627 size_t max_payload_size) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001628 EXPECT_EQ(static_cast<unsigned int>(kScreencastTargetBitrateKbps),
1629 config->targetBitrate);
Peter Boström5811a392015-12-10 13:02:50 +01001630 observation_complete_.Set();
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001631 return test::FakeEncoder::InitEncode(
1632 config, number_of_cores, max_payload_size);
1633 }
stefanff483612015-12-21 03:14:00 -08001634 void ModifyVideoConfigs(
1635 VideoSendStream::Config* send_config,
1636 std::vector<VideoReceiveStream::Config>* receive_configs,
1637 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001638 send_config->encoder_settings.encoder = this;
1639 EXPECT_EQ(1u, encoder_config->streams.size());
1640 EXPECT_TRUE(
1641 encoder_config->streams[0].temporal_layer_thresholds_bps.empty());
1642 encoder_config->streams[0].temporal_layer_thresholds_bps.push_back(
1643 kScreencastTargetBitrateKbps * 1000);
Erik Språng143cec12015-04-28 10:01:41 +02001644 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001645 }
1646
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001647 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001648 EXPECT_TRUE(Wait())
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001649 << "Timed out while waiting for the encoder to be initialized.";
1650 }
1651 } test;
1652
stefane74eef12016-01-08 06:47:13 -08001653 RunBaseTest(&test);
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001654}
pbos@webrtc.org00873182014-11-25 14:03:34 +00001655
honghaizcfb7f01f2015-12-21 13:34:54 -08001656// Disabled on LinuxAsan:
1657// https://bugs.chromium.org/p/webrtc/issues/detail?id=5382
1658#if defined(ADDRESS_SANITIZER) && defined(WEBRTC_LINUX)
1659#define MAYBE_ReconfigureBitratesSetsEncoderBitratesCorrectly \
1660 DISABLED_ReconfigureBitratesSetsEncoderBitratesCorrectly
1661#else
1662#define MAYBE_ReconfigureBitratesSetsEncoderBitratesCorrectly \
1663 ReconfigureBitratesSetsEncoderBitratesCorrectly
1664#endif
1665
1666TEST_F(VideoSendStreamTest,
1667 MAYBE_ReconfigureBitratesSetsEncoderBitratesCorrectly) {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001668 // These are chosen to be "kind of odd" to not be accidentally checked against
1669 // default values.
1670 static const int kMinBitrateKbps = 137;
1671 static const int kStartBitrateKbps = 345;
1672 static const int kLowerMaxBitrateKbps = 312;
1673 static const int kMaxBitrateKbps = 413;
1674 static const int kIncreasedStartBitrateKbps = 451;
1675 static const int kIncreasedMaxBitrateKbps = 597;
1676 class EncoderBitrateThresholdObserver : public test::SendTest,
1677 public test::FakeEncoder {
1678 public:
1679 EncoderBitrateThresholdObserver()
1680 : SendTest(kDefaultTimeoutMs),
1681 FakeEncoder(Clock::GetRealTimeClock()),
1682 num_initializations_(0) {}
1683
1684 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001685 int32_t InitEncode(const VideoCodec* codecSettings,
1686 int32_t numberOfCores,
1687 size_t maxPayloadSize) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001688 if (num_initializations_ == 0) {
1689 EXPECT_EQ(static_cast<unsigned int>(kMinBitrateKbps),
1690 codecSettings->minBitrate);
1691 EXPECT_EQ(static_cast<unsigned int>(kStartBitrateKbps),
1692 codecSettings->startBitrate);
1693 EXPECT_EQ(static_cast<unsigned int>(kMaxBitrateKbps),
1694 codecSettings->maxBitrate);
Peter Boström5811a392015-12-10 13:02:50 +01001695 observation_complete_.Set();
pbos@webrtc.org00873182014-11-25 14:03:34 +00001696 } else if (num_initializations_ == 1) {
1697 EXPECT_EQ(static_cast<unsigned int>(kLowerMaxBitrateKbps),
1698 codecSettings->maxBitrate);
1699 // The start bitrate should be kept (-1) and capped to the max bitrate.
1700 // Since this is not an end-to-end call no receiver should have been
1701 // returning a REMB that could lower this estimate.
1702 EXPECT_EQ(codecSettings->startBitrate, codecSettings->maxBitrate);
1703 } else if (num_initializations_ == 2) {
1704 EXPECT_EQ(static_cast<unsigned int>(kIncreasedMaxBitrateKbps),
1705 codecSettings->maxBitrate);
1706 EXPECT_EQ(static_cast<unsigned int>(kIncreasedStartBitrateKbps),
1707 codecSettings->startBitrate);
1708 }
1709 ++num_initializations_;
1710 return FakeEncoder::InitEncode(codecSettings, numberOfCores,
1711 maxPayloadSize);
1712 }
1713
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001714 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -07001715 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +01001716 config.bitrate_config.min_bitrate_bps = kMinBitrateKbps * 1000;
1717 config.bitrate_config.start_bitrate_bps = kStartBitrateKbps * 1000;
1718 config.bitrate_config.max_bitrate_bps = kMaxBitrateKbps * 1000;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001719 return config;
1720 }
1721
stefanff483612015-12-21 03:14:00 -08001722 void ModifyVideoConfigs(
1723 VideoSendStream::Config* send_config,
1724 std::vector<VideoReceiveStream::Config>* receive_configs,
1725 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001726 send_config->encoder_settings.encoder = this;
1727 // Set bitrates lower/higher than min/max to make sure they are properly
1728 // capped.
Stefan Holmere5904162015-03-26 11:11:06 +01001729 encoder_config->streams.front().min_bitrate_bps = kMinBitrateKbps * 1000;
1730 encoder_config->streams.front().max_bitrate_bps = kMaxBitrateKbps * 1000;
1731 encoder_config_ = *encoder_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001732 }
1733
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001734 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001735 call_ = sender_call;
1736 }
1737
stefanff483612015-12-21 03:14:00 -08001738 void OnVideoStreamsCreated(
Stefan Holmere5904162015-03-26 11:11:06 +01001739 VideoSendStream* send_stream,
1740 const std::vector<VideoReceiveStream*>& receive_streams) override {
1741 send_stream_ = send_stream;
1742 }
1743
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001744 void PerformTest() override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001745 Call::Config::BitrateConfig bitrate_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001746 bitrate_config.start_bitrate_bps = kIncreasedStartBitrateKbps * 1000;
1747 bitrate_config.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000;
1748 call_->SetBitrateConfig(bitrate_config);
Peter Boström5811a392015-12-10 13:02:50 +01001749 EXPECT_TRUE(Wait())
Stefan Holmere5904162015-03-26 11:11:06 +01001750 << "Timed out while waiting encoder to be configured.";
1751 encoder_config_.streams[0].min_bitrate_bps = 0;
1752 encoder_config_.streams[0].max_bitrate_bps = kLowerMaxBitrateKbps * 1000;
1753 send_stream_->ReconfigureVideoEncoder(encoder_config_);
1754 EXPECT_EQ(2, num_initializations_)
1755 << "Encoder should have been reconfigured with the new value.";
1756 encoder_config_.streams[0].target_bitrate_bps =
1757 encoder_config_.streams[0].min_bitrate_bps;
1758 encoder_config_.streams[0].max_bitrate_bps =
1759 kIncreasedMaxBitrateKbps * 1000;
1760 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org00873182014-11-25 14:03:34 +00001761 EXPECT_EQ(3, num_initializations_)
1762 << "Encoder should have been reconfigured with the new value.";
1763 }
1764
1765 int num_initializations_;
1766 webrtc::Call* call_;
Stefan Holmere5904162015-03-26 11:11:06 +01001767 webrtc::VideoSendStream* send_stream_;
1768 webrtc::VideoEncoderConfig encoder_config_;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001769 } test;
1770
stefane74eef12016-01-08 06:47:13 -08001771 RunBaseTest(&test);
pbos@webrtc.org00873182014-11-25 14:03:34 +00001772}
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001773
1774TEST_F(VideoSendStreamTest, ReportsSentResolution) {
1775 static const size_t kNumStreams = 3;
1776 // Unusual resolutions to make sure that they are the ones being reported.
1777 static const struct {
1778 int width;
1779 int height;
1780 } kEncodedResolution[kNumStreams] = {
1781 {241, 181}, {300, 121}, {121, 221}};
1782 class ScreencastTargetBitrateTest : public test::SendTest,
1783 public test::FakeEncoder {
1784 public:
1785 ScreencastTargetBitrateTest()
1786 : SendTest(kDefaultTimeoutMs),
1787 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1788
1789 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001790 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001791 const CodecSpecificInfo* codecSpecificInfo,
pbos22993e12015-10-19 02:39:06 -07001792 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001793 CodecSpecificInfo specifics;
1794 memset(&specifics, 0, sizeof(specifics));
1795 specifics.codecType = kVideoCodecGeneric;
1796
1797 uint8_t buffer[16] = {0};
1798 EncodedImage encoded(buffer, sizeof(buffer), sizeof(buffer));
1799 encoded._timeStamp = input_image.timestamp();
1800 encoded.capture_time_ms_ = input_image.render_time_ms();
1801
1802 for (size_t i = 0; i < kNumStreams; ++i) {
1803 specifics.codecSpecific.generic.simulcast_idx = static_cast<uint8_t>(i);
1804 encoded._frameType = (*frame_types)[i];
1805 encoded._encodedWidth = kEncodedResolution[i].width;
1806 encoded._encodedHeight = kEncodedResolution[i].height;
henrikg91d6ede2015-09-17 00:24:34 -07001807 RTC_DCHECK(callback_ != nullptr);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001808 if (callback_->Encoded(encoded, &specifics, nullptr) != 0)
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001809 return -1;
1810 }
1811
Peter Boström5811a392015-12-10 13:02:50 +01001812 observation_complete_.Set();
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001813 return 0;
1814 }
stefanff483612015-12-21 03:14:00 -08001815 void ModifyVideoConfigs(
1816 VideoSendStream::Config* send_config,
1817 std::vector<VideoReceiveStream::Config>* receive_configs,
1818 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001819 send_config->encoder_settings.encoder = this;
1820 EXPECT_EQ(kNumStreams, encoder_config->streams.size());
1821 }
1822
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001823 size_t GetNumVideoStreams() const override { return kNumStreams; }
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001824
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001825 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001826 EXPECT_TRUE(Wait())
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001827 << "Timed out while waiting for the encoder to send one frame.";
1828 VideoSendStream::Stats stats = send_stream_->GetStats();
1829
1830 for (size_t i = 0; i < kNumStreams; ++i) {
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001831 ASSERT_TRUE(stats.substreams.find(kVideoSendSsrcs[i]) !=
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001832 stats.substreams.end())
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001833 << "No stats for SSRC: " << kVideoSendSsrcs[i]
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001834 << ", stats should exist as soon as frames have been encoded.";
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001835 VideoSendStream::StreamStats ssrc_stats =
Stefan Holmer9fea80f2016-01-07 17:43:18 +01001836 stats.substreams[kVideoSendSsrcs[i]];
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001837 EXPECT_EQ(kEncodedResolution[i].width, ssrc_stats.width);
1838 EXPECT_EQ(kEncodedResolution[i].height, ssrc_stats.height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001839 }
1840 }
1841
stefanff483612015-12-21 03:14:00 -08001842 void OnVideoStreamsCreated(
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001843 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001844 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001845 send_stream_ = send_stream;
1846 }
1847
1848 VideoSendStream* send_stream_;
1849 } test;
1850
stefane74eef12016-01-08 06:47:13 -08001851 RunBaseTest(&test);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001852}
philipel0f9af012015-09-01 07:01:51 -07001853
Åsa Perssonff24c042015-12-04 10:58:08 +01001854class Vp9HeaderObserver : public test::SendTest {
philipel0f9af012015-09-01 07:01:51 -07001855 public:
Åsa Perssonff24c042015-12-04 10:58:08 +01001856 Vp9HeaderObserver()
1857 : SendTest(VideoSendStreamTest::kLongTimeoutMs),
philipel7fabd462015-09-03 04:42:32 -07001858 vp9_encoder_(VP9Encoder::Create()),
Åsa Perssonff24c042015-12-04 10:58:08 +01001859 vp9_settings_(VideoEncoder::GetDefaultVp9Settings()),
1860 packets_sent_(0),
1861 frames_sent_(0) {}
philipel7fabd462015-09-03 04:42:32 -07001862
stefanff483612015-12-21 03:14:00 -08001863 virtual void ModifyVideoConfigsHook(
philipel0f9af012015-09-01 07:01:51 -07001864 VideoSendStream::Config* send_config,
1865 std::vector<VideoReceiveStream::Config>* receive_configs,
1866 VideoEncoderConfig* encoder_config) {}
1867
Åsa Perssonff24c042015-12-04 10:58:08 +01001868 virtual void InspectHeader(const RTPVideoHeaderVP9& vp9) = 0;
philipel0f9af012015-09-01 07:01:51 -07001869
1870 private:
1871 const int kVp9PayloadType = 105;
1872
stefanff483612015-12-21 03:14:00 -08001873 void ModifyVideoConfigs(
1874 VideoSendStream::Config* send_config,
1875 std::vector<VideoReceiveStream::Config>* receive_configs,
1876 VideoEncoderConfig* encoder_config) override {
philipel0f9af012015-09-01 07:01:51 -07001877 encoder_config->encoder_specific_settings = &vp9_settings_;
philipel7fabd462015-09-03 04:42:32 -07001878 send_config->encoder_settings.encoder = vp9_encoder_.get();
philipel0f9af012015-09-01 07:01:51 -07001879 send_config->encoder_settings.payload_name = "VP9";
1880 send_config->encoder_settings.payload_type = kVp9PayloadType;
stefanff483612015-12-21 03:14:00 -08001881 ModifyVideoConfigsHook(send_config, receive_configs, encoder_config);
Åsa Perssonff24c042015-12-04 10:58:08 +01001882 EXPECT_EQ(1u, encoder_config->streams.size());
1883 encoder_config->streams[0].temporal_layer_thresholds_bps.resize(
1884 vp9_settings_.numberOfTemporalLayers - 1);
1885 encoder_config_ = *encoder_config;
philipel0f9af012015-09-01 07:01:51 -07001886 }
1887
1888 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001889 EXPECT_TRUE(Wait()) << "Test timed out waiting for VP9 packet, num frames "
1890 << frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07001891 }
1892
1893 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1894 RTPHeader header;
1895 EXPECT_TRUE(parser_->Parse(packet, length, &header));
1896
Åsa Perssonff24c042015-12-04 10:58:08 +01001897 EXPECT_EQ(kVp9PayloadType, header.payloadType);
1898 const uint8_t* payload = packet + header.headerLength;
1899 size_t payload_length = length - header.headerLength - header.paddingLength;
philipel0f9af012015-09-01 07:01:51 -07001900
Åsa Perssonff24c042015-12-04 10:58:08 +01001901 bool new_packet = packets_sent_ == 0 ||
1902 IsNewerSequenceNumber(header.sequenceNumber,
1903 last_header_.sequenceNumber);
1904 if (payload_length > 0 && new_packet) {
1905 RtpDepacketizer::ParsedPayload parsed;
1906 RtpDepacketizerVp9 depacketizer;
1907 EXPECT_TRUE(depacketizer.Parse(&parsed, payload, payload_length));
1908 EXPECT_EQ(RtpVideoCodecTypes::kRtpVideoVp9, parsed.type.Video.codec);
1909 // Verify common fields for all configurations.
1910 VerifyCommonHeader(parsed.type.Video.codecHeader.VP9);
1911 CompareConsecutiveFrames(header, parsed.type.Video);
1912 // Verify configuration specific settings.
1913 InspectHeader(parsed.type.Video.codecHeader.VP9);
philipel0f9af012015-09-01 07:01:51 -07001914
Åsa Perssonff24c042015-12-04 10:58:08 +01001915 ++packets_sent_;
1916 if (header.markerBit) {
1917 ++frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07001918 }
Åsa Perssonff24c042015-12-04 10:58:08 +01001919 last_header_ = header;
1920 last_vp9_ = parsed.type.Video.codecHeader.VP9;
philipel0f9af012015-09-01 07:01:51 -07001921 }
philipel0f9af012015-09-01 07:01:51 -07001922 return SEND_PACKET;
1923 }
1924
philipel7fabd462015-09-03 04:42:32 -07001925 protected:
Åsa Perssonff24c042015-12-04 10:58:08 +01001926 bool ContinuousPictureId(const RTPVideoHeaderVP9& vp9) const {
1927 if (last_vp9_.picture_id > vp9.picture_id) {
1928 return vp9.picture_id == 0; // Wrap.
1929 } else {
1930 return vp9.picture_id == last_vp9_.picture_id + 1;
1931 }
1932 }
1933
1934 void VerifySpatialIdxWithinFrame(const RTPVideoHeaderVP9& vp9) const {
Åsa Perssonff24c042015-12-04 10:58:08 +01001935 bool new_layer = vp9.spatial_idx != last_vp9_.spatial_idx;
1936 EXPECT_EQ(new_layer, vp9.beginning_of_frame);
1937 EXPECT_EQ(new_layer, last_vp9_.end_of_frame);
1938 EXPECT_EQ(new_layer ? last_vp9_.spatial_idx + 1 : last_vp9_.spatial_idx,
1939 vp9.spatial_idx);
1940 }
1941
1942 void VerifyFixedTemporalLayerStructure(const RTPVideoHeaderVP9& vp9,
1943 uint8_t num_layers) const {
1944 switch (num_layers) {
1945 case 0:
1946 VerifyTemporalLayerStructure0(vp9);
1947 break;
1948 case 1:
1949 VerifyTemporalLayerStructure1(vp9);
1950 break;
1951 case 2:
1952 VerifyTemporalLayerStructure2(vp9);
1953 break;
1954 case 3:
1955 VerifyTemporalLayerStructure3(vp9);
1956 break;
1957 default:
1958 RTC_NOTREACHED();
1959 }
1960 }
1961
1962 void VerifyTemporalLayerStructure0(const RTPVideoHeaderVP9& vp9) const {
1963 EXPECT_EQ(kNoTl0PicIdx, vp9.tl0_pic_idx);
1964 EXPECT_EQ(kNoTemporalIdx, vp9.temporal_idx); // no tid
1965 EXPECT_FALSE(vp9.temporal_up_switch);
1966 }
1967
1968 void VerifyTemporalLayerStructure1(const RTPVideoHeaderVP9& vp9) const {
1969 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
1970 EXPECT_EQ(0, vp9.temporal_idx); // 0,0,0,...
1971 EXPECT_FALSE(vp9.temporal_up_switch);
1972 }
1973
1974 void VerifyTemporalLayerStructure2(const RTPVideoHeaderVP9& vp9) const {
1975 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
1976 EXPECT_GE(vp9.temporal_idx, 0); // 0,1,0,1,... (tid reset on I-frames).
1977 EXPECT_LE(vp9.temporal_idx, 1);
1978 EXPECT_EQ(vp9.temporal_idx > 0, vp9.temporal_up_switch);
1979 if (IsNewPictureId(vp9)) {
1980 uint8_t expected_tid =
1981 (!vp9.inter_pic_predicted || last_vp9_.temporal_idx == 1) ? 0 : 1;
1982 EXPECT_EQ(expected_tid, vp9.temporal_idx);
1983 }
1984 }
1985
1986 void VerifyTemporalLayerStructure3(const RTPVideoHeaderVP9& vp9) const {
1987 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
1988 EXPECT_GE(vp9.temporal_idx, 0); // 0,2,1,2,... (tid reset on I-frames).
1989 EXPECT_LE(vp9.temporal_idx, 2);
1990 if (IsNewPictureId(vp9) && vp9.inter_pic_predicted) {
1991 EXPECT_NE(vp9.temporal_idx, last_vp9_.temporal_idx);
1992 switch (vp9.temporal_idx) {
1993 case 0:
1994 EXPECT_EQ(2, last_vp9_.temporal_idx);
1995 EXPECT_FALSE(vp9.temporal_up_switch);
1996 break;
1997 case 1:
1998 EXPECT_EQ(2, last_vp9_.temporal_idx);
1999 EXPECT_TRUE(vp9.temporal_up_switch);
2000 break;
2001 case 2:
2002 EXPECT_EQ(last_vp9_.temporal_idx == 0, vp9.temporal_up_switch);
2003 break;
2004 }
2005 }
2006 }
2007
2008 void VerifyTl0Idx(const RTPVideoHeaderVP9& vp9) const {
2009 if (vp9.tl0_pic_idx == kNoTl0PicIdx)
2010 return;
2011
2012 uint8_t expected_tl0_idx = last_vp9_.tl0_pic_idx;
2013 if (vp9.temporal_idx == 0)
2014 ++expected_tl0_idx;
2015 EXPECT_EQ(expected_tl0_idx, vp9.tl0_pic_idx);
2016 }
2017
2018 bool IsNewPictureId(const RTPVideoHeaderVP9& vp9) const {
2019 return frames_sent_ > 0 && (vp9.picture_id != last_vp9_.picture_id);
2020 }
2021
2022 // Flexible mode (F=1): Non-flexible mode (F=0):
2023 //
2024 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2025 // |I|P|L|F|B|E|V|-| |I|P|L|F|B|E|V|-|
2026 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2027 // I: |M| PICTURE ID | I: |M| PICTURE ID |
2028 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2029 // M: | EXTENDED PID | M: | EXTENDED PID |
2030 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2031 // L: | T |U| S |D| L: | T |U| S |D|
2032 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2033 // P,F: | P_DIFF |X|N| | TL0PICIDX |
2034 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2035 // X: |EXTENDED P_DIFF| V: | SS .. |
2036 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2037 // V: | SS .. |
2038 // +-+-+-+-+-+-+-+-+
2039 void VerifyCommonHeader(const RTPVideoHeaderVP9& vp9) const {
2040 EXPECT_EQ(kMaxTwoBytePictureId, vp9.max_picture_id); // M:1
2041 EXPECT_NE(kNoPictureId, vp9.picture_id); // I:1
2042 EXPECT_EQ(vp9_settings_.flexibleMode, vp9.flexible_mode); // F
2043 EXPECT_GE(vp9.spatial_idx, 0); // S
2044 EXPECT_LT(vp9.spatial_idx, vp9_settings_.numberOfSpatialLayers);
2045 if (vp9.ss_data_available) // V
2046 VerifySsData(vp9);
2047
2048 if (frames_sent_ == 0)
2049 EXPECT_FALSE(vp9.inter_pic_predicted); // P
2050
2051 if (!vp9.inter_pic_predicted) {
2052 EXPECT_TRUE(vp9.temporal_idx == 0 || vp9.temporal_idx == kNoTemporalIdx);
2053 EXPECT_FALSE(vp9.temporal_up_switch);
2054 }
2055 }
2056
2057 // Scalability structure (SS).
2058 //
2059 // +-+-+-+-+-+-+-+-+
2060 // V: | N_S |Y|G|-|-|-|
2061 // +-+-+-+-+-+-+-+-+
2062 // Y: | WIDTH | N_S + 1 times
2063 // +-+-+-+-+-+-+-+-+
2064 // | HEIGHT |
2065 // +-+-+-+-+-+-+-+-+
2066 // G: | N_G |
2067 // +-+-+-+-+-+-+-+-+
2068 // N_G: | T |U| R |-|-| N_G times
2069 // +-+-+-+-+-+-+-+-+
2070 // | P_DIFF | R times
2071 // +-+-+-+-+-+-+-+-+
2072 void VerifySsData(const RTPVideoHeaderVP9& vp9) const {
2073 EXPECT_TRUE(vp9.ss_data_available); // V
2074 EXPECT_EQ(vp9_settings_.numberOfSpatialLayers, // N_S + 1
2075 vp9.num_spatial_layers);
2076 EXPECT_TRUE(vp9.spatial_layer_resolution_present); // Y:1
2077 size_t expected_width = encoder_config_.streams[0].width;
2078 size_t expected_height = encoder_config_.streams[0].height;
2079 for (int i = vp9.num_spatial_layers - 1; i >= 0; --i) {
2080 EXPECT_EQ(expected_width, vp9.width[i]); // WIDTH
2081 EXPECT_EQ(expected_height, vp9.height[i]); // HEIGHT
2082 expected_width /= 2;
2083 expected_height /= 2;
2084 }
2085 }
2086
2087 void CompareConsecutiveFrames(const RTPHeader& header,
2088 const RTPVideoHeader& video) const {
2089 const RTPVideoHeaderVP9& vp9 = video.codecHeader.VP9;
2090
2091 bool new_frame = packets_sent_ == 0 ||
2092 IsNewerTimestamp(header.timestamp, last_header_.timestamp);
2093 EXPECT_EQ(new_frame, video.isFirstPacket);
2094 if (!new_frame) {
2095 EXPECT_FALSE(last_header_.markerBit);
2096 EXPECT_EQ(last_header_.timestamp, header.timestamp);
2097 EXPECT_EQ(last_vp9_.picture_id, vp9.picture_id);
2098 EXPECT_EQ(last_vp9_.temporal_idx, vp9.temporal_idx);
2099 EXPECT_EQ(last_vp9_.tl0_pic_idx, vp9.tl0_pic_idx);
2100 VerifySpatialIdxWithinFrame(vp9);
2101 return;
2102 }
2103 // New frame.
2104 EXPECT_TRUE(vp9.beginning_of_frame);
2105
2106 // Compare with last packet in previous frame.
2107 if (frames_sent_ == 0)
2108 return;
2109 EXPECT_TRUE(last_vp9_.end_of_frame);
2110 EXPECT_TRUE(last_header_.markerBit);
2111 EXPECT_TRUE(ContinuousPictureId(vp9));
2112 VerifyTl0Idx(vp9);
2113 }
2114
philipel7fabd462015-09-03 04:42:32 -07002115 rtc::scoped_ptr<VP9Encoder> vp9_encoder_;
philipel0f9af012015-09-01 07:01:51 -07002116 VideoCodecVP9 vp9_settings_;
Åsa Perssonff24c042015-12-04 10:58:08 +01002117 webrtc::VideoEncoderConfig encoder_config_;
2118 RTPHeader last_header_;
2119 RTPVideoHeaderVP9 last_vp9_;
2120 size_t packets_sent_;
2121 size_t frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07002122};
2123
Åsa Perssonff24c042015-12-04 10:58:08 +01002124TEST_F(VideoSendStreamTest, Vp9NonFlexMode_1Tl1SLayers) {
2125 const uint8_t kNumTemporalLayers = 1;
2126 const uint8_t kNumSpatialLayers = 1;
2127 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2128}
2129
2130TEST_F(VideoSendStreamTest, Vp9NonFlexMode_2Tl1SLayers) {
2131 const uint8_t kNumTemporalLayers = 2;
2132 const uint8_t kNumSpatialLayers = 1;
2133 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2134}
2135
2136TEST_F(VideoSendStreamTest, Vp9NonFlexMode_3Tl1SLayers) {
2137 const uint8_t kNumTemporalLayers = 3;
2138 const uint8_t kNumSpatialLayers = 1;
2139 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2140}
2141
2142TEST_F(VideoSendStreamTest, Vp9NonFlexMode_1Tl2SLayers) {
2143 const uint8_t kNumTemporalLayers = 1;
2144 const uint8_t kNumSpatialLayers = 2;
2145 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2146}
2147
2148TEST_F(VideoSendStreamTest, Vp9NonFlexMode_2Tl2SLayers) {
2149 const uint8_t kNumTemporalLayers = 2;
2150 const uint8_t kNumSpatialLayers = 2;
2151 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2152}
2153
2154TEST_F(VideoSendStreamTest, Vp9NonFlexMode_3Tl2SLayers) {
2155 const uint8_t kNumTemporalLayers = 3;
2156 const uint8_t kNumSpatialLayers = 2;
2157 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2158}
2159
2160void VideoSendStreamTest::TestVp9NonFlexMode(uint8_t num_temporal_layers,
2161 uint8_t num_spatial_layers) {
2162 static const size_t kNumFramesToSend = 100;
2163 // Set to < kNumFramesToSend and coprime to length of temporal layer
2164 // structures to verify temporal id reset on key frame.
2165 static const int kKeyFrameInterval = 31;
2166 class NonFlexibleMode : public Vp9HeaderObserver {
2167 public:
2168 NonFlexibleMode(uint8_t num_temporal_layers, uint8_t num_spatial_layers)
2169 : num_temporal_layers_(num_temporal_layers),
2170 num_spatial_layers_(num_spatial_layers),
2171 l_field_(num_temporal_layers > 1 || num_spatial_layers > 1) {}
stefanff483612015-12-21 03:14:00 -08002172 void ModifyVideoConfigsHook(
philipel0f9af012015-09-01 07:01:51 -07002173 VideoSendStream::Config* send_config,
2174 std::vector<VideoReceiveStream::Config>* receive_configs,
2175 VideoEncoderConfig* encoder_config) override {
Åsa Perssonff24c042015-12-04 10:58:08 +01002176 vp9_settings_.flexibleMode = false;
2177 vp9_settings_.frameDroppingOn = false;
2178 vp9_settings_.keyFrameInterval = kKeyFrameInterval;
2179 vp9_settings_.numberOfTemporalLayers = num_temporal_layers_;
2180 vp9_settings_.numberOfSpatialLayers = num_spatial_layers_;
philipel0f9af012015-09-01 07:01:51 -07002181 }
2182
Åsa Perssonff24c042015-12-04 10:58:08 +01002183 void InspectHeader(const RTPVideoHeaderVP9& vp9) override {
2184 bool ss_data_expected = !vp9.inter_pic_predicted &&
2185 vp9.beginning_of_frame && vp9.spatial_idx == 0;
2186 EXPECT_EQ(ss_data_expected, vp9.ss_data_available);
2187 EXPECT_EQ(vp9.spatial_idx > 0, vp9.inter_layer_predicted); // D
asapersson38bb8ad2015-12-14 01:41:19 -08002188 EXPECT_EQ(!vp9.inter_pic_predicted,
2189 frames_sent_ % kKeyFrameInterval == 0);
Åsa Perssonff24c042015-12-04 10:58:08 +01002190
2191 if (IsNewPictureId(vp9)) {
2192 EXPECT_EQ(0, vp9.spatial_idx);
2193 EXPECT_EQ(num_spatial_layers_ - 1, last_vp9_.spatial_idx);
2194 }
2195
2196 VerifyFixedTemporalLayerStructure(vp9,
2197 l_field_ ? num_temporal_layers_ : 0);
2198
2199 if (frames_sent_ > kNumFramesToSend)
Peter Boström5811a392015-12-10 13:02:50 +01002200 observation_complete_.Set();
philipel0f9af012015-09-01 07:01:51 -07002201 }
Åsa Perssonff24c042015-12-04 10:58:08 +01002202 const uint8_t num_temporal_layers_;
2203 const uint8_t num_spatial_layers_;
2204 const bool l_field_;
2205 } test(num_temporal_layers, num_spatial_layers);
philipelcfc319b2015-11-10 07:17:23 -08002206
stefane74eef12016-01-08 06:47:13 -08002207 RunBaseTest(&test);
philipelcfc319b2015-11-10 07:17:23 -08002208}
2209
asaperssond9f641e2016-01-21 01:11:35 -08002210TEST_F(VideoSendStreamTest, Vp9NonFlexModeSmallResolution) {
2211 static const size_t kNumFramesToSend = 50;
2212 static const int kWidth = 4;
2213 static const int kHeight = 4;
2214 class NonFlexibleModeResolution : public Vp9HeaderObserver {
2215 void ModifyVideoConfigsHook(
2216 VideoSendStream::Config* send_config,
2217 std::vector<VideoReceiveStream::Config>* receive_configs,
2218 VideoEncoderConfig* encoder_config) override {
2219 vp9_settings_.flexibleMode = false;
2220 vp9_settings_.numberOfTemporalLayers = 1;
2221 vp9_settings_.numberOfSpatialLayers = 1;
2222
2223 EXPECT_EQ(1u, encoder_config->streams.size());
2224 encoder_config->streams[0].width = kWidth;
2225 encoder_config->streams[0].height = kHeight;
2226 }
2227
2228 void InspectHeader(const RTPVideoHeaderVP9& vp9_header) override {
2229 if (frames_sent_ > kNumFramesToSend)
2230 observation_complete_.Set();
2231 }
2232 } test;
2233
2234 RunBaseTest(&test);
2235}
2236
kjellander44cc7952016-01-06 22:12:27 -08002237#if !defined(MEMORY_SANITIZER)
2238// Fails under MemorySanitizer:
2239// See https://code.google.com/p/webrtc/issues/detail?id=5402.
Åsa Perssonff24c042015-12-04 10:58:08 +01002240TEST_F(VideoSendStreamTest, Vp9FlexModeRefCount) {
2241 class FlexibleMode : public Vp9HeaderObserver {
stefanff483612015-12-21 03:14:00 -08002242 void ModifyVideoConfigsHook(
philipelcfc319b2015-11-10 07:17:23 -08002243 VideoSendStream::Config* send_config,
2244 std::vector<VideoReceiveStream::Config>* receive_configs,
2245 VideoEncoderConfig* encoder_config) override {
Åsa Perssonff24c042015-12-04 10:58:08 +01002246 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
philipelcfc319b2015-11-10 07:17:23 -08002247 vp9_settings_.flexibleMode = true;
Åsa Perssonff24c042015-12-04 10:58:08 +01002248 vp9_settings_.numberOfTemporalLayers = 1;
2249 vp9_settings_.numberOfSpatialLayers = 2;
philipelcfc319b2015-11-10 07:17:23 -08002250 }
2251
Åsa Perssonff24c042015-12-04 10:58:08 +01002252 void InspectHeader(const RTPVideoHeaderVP9& vp9_header) override {
2253 EXPECT_TRUE(vp9_header.flexible_mode);
2254 EXPECT_EQ(kNoTl0PicIdx, vp9_header.tl0_pic_idx);
2255 if (vp9_header.inter_pic_predicted) {
2256 EXPECT_GT(vp9_header.num_ref_pics, 0u);
Peter Boström5811a392015-12-10 13:02:50 +01002257 observation_complete_.Set();
philipelcfc319b2015-11-10 07:17:23 -08002258 }
2259 }
2260 } test;
2261
stefane74eef12016-01-08 06:47:13 -08002262 RunBaseTest(&test);
philipelcfc319b2015-11-10 07:17:23 -08002263}
kjellander44cc7952016-01-06 22:12:27 -08002264#endif
philipelcfc319b2015-11-10 07:17:23 -08002265
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +00002266} // namespace webrtc