blob: 9474c385322284b376fefb3f779f6ff2fbf81b12 [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/critical_section_wrapper.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010032#include "webrtc/system_wrappers/include/ref_count.h"
33#include "webrtc/system_wrappers/include/sleep.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000034#include "webrtc/test/call_test.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000035#include "webrtc/test/configurable_frame_size_encoder.h"
Peter Boströmeb66e802015-06-05 11:08:03 +020036#include "webrtc/test/fake_texture_frame.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000037#include "webrtc/test/null_transport.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000038#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.org273a4142014-12-01 15:23:21 +000039#include "webrtc/video/send_statistics_proxy.h"
Thiago Farina9bfe3da2015-04-10 12:52:13 +020040#include "webrtc/video_frame.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000041#include "webrtc/video_send_stream.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000042
43namespace webrtc {
44
sprang@webrtc.org346094c2014-02-18 08:40:33 +000045enum VideoFormat { kGeneric, kVP8, };
46
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070047void ExpectEqualFrames(const VideoFrame& frame1, const VideoFrame& frame2);
48void ExpectEqualTextureFrames(const VideoFrame& frame1,
49 const VideoFrame& frame2);
50void ExpectEqualBufferFrames(const VideoFrame& frame1,
51 const VideoFrame& frame2);
52void ExpectEqualFramesVector(const std::vector<VideoFrame>& frames1,
53 const std::vector<VideoFrame>& frames2);
54VideoFrame CreateVideoFrame(int width, int height, uint8_t data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000055
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000056class VideoSendStreamTest : public test::CallTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000057 protected:
stefan@webrtc.org69969e22013-11-15 12:32:15 +000058 void TestNackRetransmission(uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +000059 uint8_t retransmit_payload_type);
sprang@webrtc.org346094c2014-02-18 08:40:33 +000060 void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
Åsa Perssonff24c042015-12-04 10:58:08 +010061
62 void TestVp9NonFlexMode(uint8_t num_temporal_layers,
63 uint8_t num_spatial_layers);
pbos@webrtc.org013d9942013-08-22 09:42:17 +000064};
65
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000066TEST_F(VideoSendStreamTest, CanStartStartedStream) {
solenberg4fbae2b2015-08-28 04:07:10 -070067 Call::Config call_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000068 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000069
solenberg4fbae2b2015-08-28 04:07:10 -070070 test::NullTransport transport;
71 CreateSendConfig(1, &transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000072 CreateStreams();
73 send_stream_->Start();
74 send_stream_->Start();
75 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000076}
77
78TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
solenberg4fbae2b2015-08-28 04:07:10 -070079 Call::Config call_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000080 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000081
solenberg4fbae2b2015-08-28 04:07:10 -070082 test::NullTransport transport;
83 CreateSendConfig(1, &transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000084 CreateStreams();
85 send_stream_->Stop();
86 send_stream_->Stop();
87 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000088}
89
pbos@webrtc.org013d9942013-08-22 09:42:17 +000090TEST_F(VideoSendStreamTest, SupportsCName) {
91 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000092 class CNameObserver : public test::SendTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000093 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000094 CNameObserver() : SendTest(kDefaultTimeoutMs) {}
pbos@webrtc.org013d9942013-08-22 09:42:17 +000095
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000096 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000097 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000098 RTCPUtility::RTCPParserV2 parser(packet, length, true);
99 EXPECT_TRUE(parser.IsValid());
100
101 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200102 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
103 if (packet_type == RTCPUtility::RTCPPacketTypes::kSdesChunk) {
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000104 EXPECT_EQ(parser.Packet().CName.CName, kCName);
Peter Boström5811a392015-12-10 13:02:50 +0100105 observation_complete_.Set();
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000106 }
107
108 packet_type = parser.Iterate();
109 }
110
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000111 return SEND_PACKET;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000112 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000113
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000114 void ModifyConfigs(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
stefanf116bd02015-10-27 08:29:42 -0700125 RunBaseTest(&test, FakeNetworkPipe::Config());
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
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000149 void ModifyConfigs(VideoSendStream::Config* send_config,
150 std::vector<VideoReceiveStream::Config>* receive_configs,
151 VideoEncoderConfig* encoder_config) override {
Erik Språng95261872015-04-10 11:58:49 +0200152 send_config->rtp.extensions.clear();
Stefan Holmer4654d202015-12-08 09:10:43 +0100153 send_config->rtp.extensions.push_back(RtpExtension(
154 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000155 }
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +0000156
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000157 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100158 EXPECT_TRUE(Wait()) << "Timed out while waiting for single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000159 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000160 } test;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000161
stefanf116bd02015-10-27 08:29:42 -0700162 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000163}
164
pbos@webrtc.org29023282013-09-11 10:14:56 +0000165TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000166 static const int kEncodeDelayMs = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000167 class TransmissionTimeOffsetObserver : public test::SendTest {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000168 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000169 TransmissionTimeOffsetObserver()
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000170 : SendTest(kDefaultTimeoutMs),
171 encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000172 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
Stefan Holmer12952972015-10-29 15:13:24 +0100173 kRtpExtensionTransmissionTimeOffset, test::kTOffsetExtensionId));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000174 }
175
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000176 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000177 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000178 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000179 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000180
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000181 EXPECT_TRUE(header.extension.hasTransmissionTimeOffset);
182 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000183 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000184 EXPECT_EQ(header.extension.absoluteSendTime, 0u);
Peter Boström5811a392015-12-10 13:02:50 +0100185 observation_complete_.Set();
pbos@webrtc.org29023282013-09-11 10:14:56 +0000186
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000187 return SEND_PACKET;
pbos@webrtc.org29023282013-09-11 10:14:56 +0000188 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000189
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000190 void ModifyConfigs(VideoSendStream::Config* send_config,
191 std::vector<VideoReceiveStream::Config>* receive_configs,
192 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000193 send_config->encoder_settings.encoder = &encoder_;
Stefan Holmer12952972015-10-29 15:13:24 +0100194 send_config->rtp.extensions.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000195 send_config->rtp.extensions.push_back(
Stefan Holmer12952972015-10-29 15:13:24 +0100196 RtpExtension(RtpExtension::kTOffset, test::kTOffsetExtensionId));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000197 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000198
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000199 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100200 EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000201 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000202
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000203 test::DelayedEncoder encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000204 } test;
205
stefanf116bd02015-10-27 08:29:42 -0700206 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org29023282013-09-11 10:14:56 +0000207}
208
sprang867fb522015-08-03 04:38:41 -0700209TEST_F(VideoSendStreamTest, SupportsTransportWideSequenceNumbers) {
210 static const uint8_t kExtensionId = 13;
211 class TransportWideSequenceNumberObserver : public test::SendTest {
212 public:
213 TransportWideSequenceNumberObserver()
214 : SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) {
215 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
216 kRtpExtensionTransportSequenceNumber, kExtensionId));
217 }
218
219 private:
220 Action OnSendRtp(const uint8_t* packet, size_t length) override {
221 RTPHeader header;
222 EXPECT_TRUE(parser_->Parse(packet, length, &header));
223
224 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
225 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
226 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
227
Peter Boström5811a392015-12-10 13:02:50 +0100228 observation_complete_.Set();
sprang867fb522015-08-03 04:38:41 -0700229
230 return SEND_PACKET;
231 }
232
233 void ModifyConfigs(VideoSendStream::Config* send_config,
234 std::vector<VideoReceiveStream::Config>* receive_configs,
235 VideoEncoderConfig* encoder_config) override {
236 send_config->encoder_settings.encoder = &encoder_;
Stefan Holmer12952972015-10-29 15:13:24 +0100237 send_config->rtp.extensions.clear();
sprang867fb522015-08-03 04:38:41 -0700238 send_config->rtp.extensions.push_back(
239 RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
240 }
241
242 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100243 EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
sprang867fb522015-08-03 04:38:41 -0700244 }
245
246 test::FakeEncoder encoder_;
247 } test;
248
stefanf116bd02015-10-27 08:29:42 -0700249 RunBaseTest(&test, FakeNetworkPipe::Config());
sprang867fb522015-08-03 04:38:41 -0700250}
251
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000252class FakeReceiveStatistics : public NullReceiveStatistics {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000253 public:
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000254 FakeReceiveStatistics(uint32_t send_ssrc,
255 uint32_t last_sequence_number,
256 uint32_t cumulative_lost,
257 uint8_t fraction_lost)
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000258 : lossy_stats_(new LossyStatistician(last_sequence_number,
259 cumulative_lost,
260 fraction_lost)) {
261 stats_map_[send_ssrc] = lossy_stats_.get();
262 }
263
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000264 StatisticianMap GetActiveStatisticians() const override { return stats_map_; }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000265
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000266 StreamStatistician* GetStatistician(uint32_t ssrc) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000267 return lossy_stats_.get();
268 }
269
270 private:
271 class LossyStatistician : public StreamStatistician {
272 public:
273 LossyStatistician(uint32_t extended_max_sequence_number,
274 uint32_t cumulative_lost,
275 uint8_t fraction_lost) {
276 stats_.fraction_lost = fraction_lost;
277 stats_.cumulative_lost = cumulative_lost;
278 stats_.extended_max_sequence_number = extended_max_sequence_number;
279 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000280 bool GetStatistics(RtcpStatistics* statistics, bool reset) override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000281 *statistics = stats_;
282 return true;
283 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000284 void GetDataCounters(size_t* bytes_received,
285 uint32_t* packets_received) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000286 *bytes_received = 0;
287 *packets_received = 0;
288 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000289 void GetReceiveStreamDataCounters(
290 StreamDataCounters* data_counters) const override {}
291 uint32_t BitrateReceived() const override { return 0; }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000292 bool IsRetransmitOfOldPacket(const RTPHeader& header,
293 int64_t min_rtt) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000294 return false;
295 }
296
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000297 bool IsPacketInOrder(uint16_t sequence_number) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000298 return true;
299 }
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000300
301 RtcpStatistics stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000302 };
303
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000304 rtc::scoped_ptr<LossyStatistician> lossy_stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000305 StatisticianMap stats_map_;
306};
307
Stefan Holmer4654d202015-12-08 09:10:43 +0100308class FecObserver : public test::SendTest {
309 public:
310 explicit FecObserver(bool header_extensions_enabled)
311 : SendTest(VideoSendStreamTest::kDefaultTimeoutMs),
312 send_count_(0),
313 received_media_(false),
314 received_fec_(false),
315 header_extensions_enabled_(header_extensions_enabled) {}
316
317 private:
318 Action OnSendRtp(const uint8_t* packet, size_t length) override {
319 RTPHeader header;
320 EXPECT_TRUE(parser_->Parse(packet, length, &header));
321
322 // Send lossy receive reports to trigger FEC enabling.
323 if (send_count_++ % 2 != 0) {
324 // Receive statistics reporting having lost 50% of the packets.
325 FakeReceiveStatistics lossy_receive_stats(
326 VideoSendStreamTest::kSendSsrcs[0], header.sequenceNumber,
327 send_count_ / 2, 127);
328 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
329 &lossy_receive_stats, nullptr,
330 transport_adapter_.get());
331
332 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
333 rtcp_sender.SetRemoteSSRC(VideoSendStreamTest::kSendSsrcs[0]);
334
335 RTCPSender::FeedbackState feedback_state;
336
337 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000338 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000339
Stefan Holmer4654d202015-12-08 09:10:43 +0100340 int encapsulated_payload_type = -1;
341 if (header.payloadType == VideoSendStreamTest::kRedPayloadType) {
342 encapsulated_payload_type = static_cast<int>(packet[header.headerLength]);
343 if (encapsulated_payload_type !=
344 VideoSendStreamTest::kFakeSendPayloadType)
345 EXPECT_EQ(VideoSendStreamTest::kUlpfecPayloadType,
346 encapsulated_payload_type);
347 } else {
348 EXPECT_EQ(VideoSendStreamTest::kFakeSendPayloadType, header.payloadType);
349 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000350
Stefan Holmer4654d202015-12-08 09:10:43 +0100351 if (header_extensions_enabled_) {
352 EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
353 uint32_t kHalf24BitsSpace = 0xFFFFFF / 2;
354 if (header.extension.absoluteSendTime <= kHalf24BitsSpace &&
355 prev_header_.extension.absoluteSendTime > kHalf24BitsSpace) {
356 // 24 bits wrap.
357 EXPECT_GT(prev_header_.extension.absoluteSendTime,
358 header.extension.absoluteSendTime);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000359 } else {
Stefan Holmer4654d202015-12-08 09:10:43 +0100360 EXPECT_GE(header.extension.absoluteSendTime,
361 prev_header_.extension.absoluteSendTime);
Stefan Holmer01b48882015-05-05 10:21:24 +0200362 }
Stefan Holmer4654d202015-12-08 09:10:43 +0100363 EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
364 uint16_t seq_num_diff = header.extension.transportSequenceNumber -
365 prev_header_.extension.transportSequenceNumber;
366 EXPECT_EQ(1, seq_num_diff);
367 }
Stefan Holmer01b48882015-05-05 10:21:24 +0200368
Stefan Holmer4654d202015-12-08 09:10:43 +0100369 if (encapsulated_payload_type != -1) {
370 if (encapsulated_payload_type ==
371 VideoSendStreamTest::kUlpfecPayloadType) {
372 received_fec_ = true;
373 } else {
374 received_media_ = true;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000375 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000376 }
377
Stefan Holmer4654d202015-12-08 09:10:43 +0100378 if (received_media_ && received_fec_ && send_count_ > 100)
Peter Boström5811a392015-12-10 13:02:50 +0100379 observation_complete_.Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000380
Stefan Holmer4654d202015-12-08 09:10:43 +0100381 prev_header_ = header;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000382
Stefan Holmer4654d202015-12-08 09:10:43 +0100383 return SEND_PACKET;
384 }
385
386 void ModifyConfigs(VideoSendStream::Config* send_config,
387 std::vector<VideoReceiveStream::Config>* receive_configs,
388 VideoEncoderConfig* encoder_config) override {
389 transport_adapter_.reset(
390 new internal::TransportAdapter(send_config->send_transport));
391 transport_adapter_->Enable();
392 send_config->rtp.fec.red_payload_type =
393 VideoSendStreamTest::kRedPayloadType;
394 send_config->rtp.fec.ulpfec_payload_type =
395 VideoSendStreamTest::kUlpfecPayloadType;
396 if (header_extensions_enabled_) {
397 send_config->rtp.extensions.push_back(RtpExtension(
398 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId));
399 send_config->rtp.extensions.push_back(
400 RtpExtension(RtpExtension::kTransportSequenceNumber,
401 test::kTransportSequenceNumberExtensionId));
402 }
403 }
404
405 void PerformTest() override {
406 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
407 }
408
409 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
410 int send_count_;
411 bool received_media_;
412 bool received_fec_;
413 bool header_extensions_enabled_;
414 RTPHeader prev_header_;
415};
416
417TEST_F(VideoSendStreamTest, SupportsFecWithExtensions) {
418 FecObserver test(true);
419
420 RunBaseTest(&test, FakeNetworkPipe::Config());
421}
422
423TEST_F(VideoSendStreamTest, SupportsFecWithoutExtensions) {
424 FecObserver test(false);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000425
stefanf116bd02015-10-27 08:29:42 -0700426 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000427}
428
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000429void VideoSendStreamTest::TestNackRetransmission(
430 uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000431 uint8_t retransmit_payload_type) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000432 class NackObserver : public test::SendTest {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000433 public:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000434 explicit NackObserver(uint32_t retransmit_ssrc,
435 uint8_t retransmit_payload_type)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000436 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000437 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000438 retransmit_ssrc_(retransmit_ssrc),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000439 retransmit_payload_type_(retransmit_payload_type),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000440 nacked_sequence_number_(-1) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000441 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000442
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000443 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000444 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000445 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000446 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000447
448 // Nack second packet after receiving the third one.
449 if (++send_count_ == 3) {
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000450 uint16_t nack_sequence_number = header.sequenceNumber - 1;
451 nacked_sequence_number_ = nack_sequence_number;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000452 NullReceiveStatistics null_stats;
Peter Boströmac547a62015-09-17 23:03:57 +0200453 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), &null_stats,
stefanf116bd02015-10-27 08:29:42 -0700454 nullptr, transport_adapter_.get());
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000455
pbosda903ea2015-10-02 02:36:56 -0700456 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000457 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000458
459 RTCPSender::FeedbackState feedback_state;
460
461 EXPECT_EQ(0,
462 rtcp_sender.SendRTCP(
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000463 feedback_state, kRtcpNack, 1, &nack_sequence_number));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000464 }
465
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000466 uint16_t sequence_number = header.sequenceNumber;
467
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000468 if (header.ssrc == retransmit_ssrc_ &&
469 retransmit_ssrc_ != kSendSsrcs[0]) {
470 // Not kSendSsrcs[0], assume correct RTX packet. Extract sequence
471 // number.
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000472 const uint8_t* rtx_header = packet + header.headerLength;
473 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
474 }
475
476 if (sequence_number == nacked_sequence_number_) {
477 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000478 EXPECT_EQ(retransmit_payload_type_, header.payloadType);
Peter Boström5811a392015-12-10 13:02:50 +0100479 observation_complete_.Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000480 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000481
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000482 return SEND_PACKET;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000483 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000484
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000485 void ModifyConfigs(VideoSendStream::Config* send_config,
486 std::vector<VideoReceiveStream::Config>* receive_configs,
487 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700488 transport_adapter_.reset(
489 new internal::TransportAdapter(send_config->send_transport));
490 transport_adapter_->Enable();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000491 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000492 send_config->rtp.rtx.payload_type = retransmit_payload_type_;
493 if (retransmit_ssrc_ != kSendSsrcs[0])
494 send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
495 }
496
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000497 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100498 EXPECT_TRUE(Wait()) << "Timed out while waiting for NACK retransmission.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000499 }
500
stefanf116bd02015-10-27 08:29:42 -0700501 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000502 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000503 uint32_t retransmit_ssrc_;
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000504 uint8_t retransmit_payload_type_;
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000505 int nacked_sequence_number_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000506 } test(retransmit_ssrc, retransmit_payload_type);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000507
stefanf116bd02015-10-27 08:29:42 -0700508 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000509}
510
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000511TEST_F(VideoSendStreamTest, RetransmitsNack) {
512 // Normal NACKs should use the send SSRC.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000513 TestNackRetransmission(kSendSsrcs[0], kFakeSendPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000514}
515
516TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
517 // NACKs over RTX should use a separate SSRC.
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000518 TestNackRetransmission(kSendRtxSsrcs[0], kSendRtxPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000519}
520
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000521void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
522 bool with_fec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000523 // Use a fake encoder to output a frame of every size in the range [90, 290],
524 // for each size making sure that the exact number of payload bytes received
525 // is correct and that packets are fragmented to respect max packet size.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000526 static const size_t kMaxPacketSize = 128;
527 static const size_t start = 90;
528 static const size_t stop = 290;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000529
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000530 // Observer that verifies that the expected number of packets and bytes
531 // arrive for each frame size, from start_size to stop_size.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000532 class FrameFragmentationTest : public test::SendTest,
533 public EncodedFrameObserver {
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000534 public:
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000535 FrameFragmentationTest(size_t max_packet_size,
536 size_t start_size,
537 size_t stop_size,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000538 bool test_generic_packetization,
539 bool use_fec)
540 : SendTest(kLongTimeoutMs),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000541 encoder_(stop),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000542 max_packet_size_(max_packet_size),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000543 stop_size_(stop_size),
544 test_generic_packetization_(test_generic_packetization),
545 use_fec_(use_fec),
546 packet_count_(0),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000547 accumulated_size_(0),
548 accumulated_payload_(0),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000549 fec_packet_received_(false),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000550 current_size_rtp_(start_size),
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000551 current_size_frame_(static_cast<int32_t>(start_size)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000552 // Fragmentation required, this test doesn't make sense without it.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000553 encoder_.SetFrameSize(start_size);
henrikg91d6ede2015-09-17 00:24:34 -0700554 RTC_DCHECK_GT(stop_size, max_packet_size);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000555 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000556
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000557 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000558 Action OnSendRtp(const uint8_t* packet, size_t size) override {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000559 size_t length = size;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000560 RTPHeader header;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000561 EXPECT_TRUE(parser_->Parse(packet, length, &header));
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000562
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000563 EXPECT_LE(length, max_packet_size_);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000564
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000565 if (use_fec_) {
566 uint8_t payload_type = packet[header.headerLength];
567 bool is_fec = header.payloadType == kRedPayloadType &&
568 payload_type == kUlpfecPayloadType;
569 if (is_fec) {
570 fec_packet_received_ = true;
571 return SEND_PACKET;
572 }
573 }
574
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000575 accumulated_size_ += length;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000576
577 if (use_fec_)
578 TriggerLossReport(header);
579
580 if (test_generic_packetization_) {
Stefan Holmer586b19b2015-09-18 11:14:31 +0200581 size_t overhead = header.headerLength + header.paddingLength;
582 // Only remove payload header and RED header if the packet actually
583 // contains payload.
584 if (length > overhead) {
585 overhead += (1 /* Generic header */);
586 if (use_fec_)
587 overhead += 1; // RED for FEC header.
588 }
589 EXPECT_GE(length, overhead);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000590 accumulated_payload_ += length - overhead;
591 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000592
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000593 // Marker bit set indicates last packet of a frame.
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000594 if (header.markerBit) {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000595 if (use_fec_ && accumulated_payload_ == current_size_rtp_ - 1) {
596 // With FEC enabled, frame size is incremented asynchronously, so
597 // "old" frames one byte too small may arrive. Accept, but don't
598 // increase expected frame size.
599 accumulated_size_ = 0;
600 accumulated_payload_ = 0;
601 return SEND_PACKET;
602 }
603
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000604 EXPECT_GE(accumulated_size_, current_size_rtp_);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000605 if (test_generic_packetization_) {
606 EXPECT_EQ(current_size_rtp_, accumulated_payload_);
607 }
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000608
609 // Last packet of frame; reset counters.
610 accumulated_size_ = 0;
611 accumulated_payload_ = 0;
612 if (current_size_rtp_ == stop_size_) {
613 // Done! (Don't increase size again, might arrive more @ stop_size).
Peter Boström5811a392015-12-10 13:02:50 +0100614 observation_complete_.Set();
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000615 } else {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000616 // Increase next expected frame size. If testing with FEC, make sure
617 // a FEC packet has been received for this frame size before
618 // proceeding, to make sure that redundancy packets don't exceed
619 // size limit.
620 if (!use_fec_) {
621 ++current_size_rtp_;
622 } else if (fec_packet_received_) {
623 fec_packet_received_ = false;
624 ++current_size_rtp_;
625 ++current_size_frame_;
626 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000627 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000628 }
629
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000630 return SEND_PACKET;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000631 }
632
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000633 void TriggerLossReport(const RTPHeader& header) {
634 // Send lossy receive reports to trigger FEC enabling.
635 if (packet_count_++ % 2 != 0) {
636 // Receive statistics reporting having lost 50% of the packets.
637 FakeReceiveStatistics lossy_receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000638 kSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127);
Peter Boströmac547a62015-09-17 23:03:57 +0200639 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
sprang86fd9ed2015-09-29 04:45:43 -0700640 &lossy_receive_stats, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700641 transport_adapter_.get());
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000642
pbosda903ea2015-10-02 02:36:56 -0700643 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000644 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000645
646 RTCPSender::FeedbackState feedback_state;
647
648 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
649 }
650 }
651
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000652 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
653 // Increase frame size for next encoded frame, in the context of the
654 // encoder thread.
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000655 if (!use_fec_ &&
656 current_size_frame_.Value() < static_cast<int32_t>(stop_size_)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000657 ++current_size_frame_;
658 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000659 encoder_.SetFrameSize(static_cast<size_t>(current_size_frame_.Value()));
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000660 }
661
Stefan Holmere5904162015-03-26 11:11:06 +0100662 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -0700663 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +0100664 const int kMinBitrateBps = 30000;
665 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
666 return config;
667 }
668
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000669 void ModifyConfigs(VideoSendStream::Config* send_config,
670 std::vector<VideoReceiveStream::Config>* receive_configs,
671 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700672 transport_adapter_.reset(
673 new internal::TransportAdapter(send_config->send_transport));
674 transport_adapter_->Enable();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000675 if (use_fec_) {
676 send_config->rtp.fec.red_payload_type = kRedPayloadType;
677 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
678 }
679
680 if (!test_generic_packetization_)
681 send_config->encoder_settings.payload_name = "VP8";
682
683 send_config->encoder_settings.encoder = &encoder_;
684 send_config->rtp.max_packet_size = kMaxPacketSize;
685 send_config->post_encode_callback = this;
686
Erik Språng95261872015-04-10 11:58:49 +0200687 // Make sure there is at least one extension header, to make the RTP
688 // header larger than the base length of 12 bytes.
689 EXPECT_FALSE(send_config->rtp.extensions.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000690 }
691
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000692 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100693 EXPECT_TRUE(Wait()) << "Timed out while observing incoming RTP packets.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000694 }
695
stefanf116bd02015-10-27 08:29:42 -0700696 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000697 test::ConfigurableFrameSizeEncoder encoder_;
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000698
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000699 const size_t max_packet_size_;
700 const size_t stop_size_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000701 const bool test_generic_packetization_;
702 const bool use_fec_;
703
704 uint32_t packet_count_;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000705 size_t accumulated_size_;
706 size_t accumulated_payload_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000707 bool fec_packet_received_;
708
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000709 size_t current_size_rtp_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000710 Atomic32 current_size_frame_;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000711 };
712
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000713 // Don't auto increment if FEC is used; continue sending frame size until
714 // a FEC packet has been received.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000715 FrameFragmentationTest test(
716 kMaxPacketSize, start, stop, format == kGeneric, with_fec);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000717
stefanf116bd02015-10-27 08:29:42 -0700718 RunBaseTest(&test, FakeNetworkPipe::Config());
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000719}
720
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000721// TODO(sprang): Is there any way of speeding up these tests?
722TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSize) {
723 TestPacketFragmentationSize(kGeneric, false);
724}
725
726TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSizeWithFec) {
727 TestPacketFragmentationSize(kGeneric, true);
728}
729
730TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSize) {
731 TestPacketFragmentationSize(kVP8, false);
732}
733
734TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSizeWithFec) {
735 TestPacketFragmentationSize(kVP8, true);
736}
737
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000738// The test will go through a number of phases.
739// 1. Start sending packets.
740// 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 +0000741// suspend the stream.
742// 3. Wait until |kSuspendTimeFrames| have been captured without seeing any RTP
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000743// packets.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000744// 4. Signal a high REMB and then wait for the RTP stream to start again.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000745// When the stream is detected again, and the stats show that the stream
746// is no longer suspended, the test ends.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000747TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
748 static const int kSuspendTimeFrames = 60; // Suspend for 2 seconds @ 30 fps.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000749
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000750 class RembObserver : public test::SendTest, public I420FrameCallback {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000751 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000752 RembObserver()
753 : SendTest(kDefaultTimeoutMs),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000754 clock_(Clock::GetRealTimeClock()),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000755 test_state_(kBeforeSuspend),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000756 rtp_count_(0),
757 last_sequence_number_(0),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000758 suspended_frame_count_(0),
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000759 low_remb_bps_(0),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000760 high_remb_bps_(0) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000761 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000762
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000763 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000764 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200765 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000766 ++rtp_count_;
767 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000768 EXPECT_TRUE(parser_->Parse(packet, length, &header));
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000769 last_sequence_number_ = header.sequenceNumber;
770
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000771 if (test_state_ == kBeforeSuspend) {
772 // The stream has started. Try to suspend it.
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000773 SendRtcpFeedback(low_remb_bps_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000774 test_state_ = kDuringSuspend;
775 } else if (test_state_ == kDuringSuspend) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000776 if (header.paddingLength == 0) {
777 // Received non-padding packet during suspension period. Reset the
778 // counter.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000779 suspended_frame_count_ = 0;
780 }
stefanf116bd02015-10-27 08:29:42 -0700781 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000782 } else if (test_state_ == kWaitingForPacket) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000783 if (header.paddingLength == 0) {
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000784 // Non-padding packet observed. Test is almost complete. Will just
785 // have to wait for the stats to change.
786 test_state_ = kWaitingForStats;
787 }
stefanf116bd02015-10-27 08:29:42 -0700788 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000789 } else if (test_state_ == kWaitingForStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000790 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000791 if (stats.suspended == false) {
792 // Stats flipped to false. Test is complete.
Peter Boström5811a392015-12-10 13:02:50 +0100793 observation_complete_.Set();
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000794 }
stefanf116bd02015-10-27 08:29:42 -0700795 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000796 }
797
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000798 return SEND_PACKET;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000799 }
800
801 // This method implements the I420FrameCallback.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700802 void FrameCallback(VideoFrame* video_frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200803 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000804 if (test_state_ == kDuringSuspend &&
805 ++suspended_frame_count_ > kSuspendTimeFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000806 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000807 EXPECT_TRUE(stats.suspended);
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000808 SendRtcpFeedback(high_remb_bps_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000809 test_state_ = kWaitingForPacket;
810 }
811 }
812
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000813 void set_low_remb_bps(int value) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200814 rtc::CritScope lock(&crit_);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000815 low_remb_bps_ = value;
816 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000817
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000818 void set_high_remb_bps(int value) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200819 rtc::CritScope lock(&crit_);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000820 high_remb_bps_ = value;
821 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000822
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000823 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000824 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000825 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000826 stream_ = send_stream;
827 }
828
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000829 void ModifyConfigs(VideoSendStream::Config* send_config,
830 std::vector<VideoReceiveStream::Config>* receive_configs,
831 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -0700832 transport_adapter_.reset(
833 new internal::TransportAdapter(send_config->send_transport));
834 transport_adapter_->Enable();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000835 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000836 send_config->pre_encode_callback = this;
837 send_config->suspend_below_min_bitrate = true;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000838 int min_bitrate_bps = encoder_config->streams[0].min_bitrate_bps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000839 set_low_remb_bps(min_bitrate_bps - 10000);
840 int threshold_window = std::max(min_bitrate_bps / 10, 10000);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000841 ASSERT_GT(encoder_config->streams[0].max_bitrate_bps,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000842 min_bitrate_bps + threshold_window + 5000);
843 set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
844 }
845
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000846 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100847 EXPECT_TRUE(Wait()) << "Timed out during suspend-below-min-bitrate test.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000848 }
849
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000850 enum TestState {
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000851 kBeforeSuspend,
852 kDuringSuspend,
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000853 kWaitingForPacket,
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000854 kWaitingForStats
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000855 };
856
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000857 virtual void SendRtcpFeedback(int remb_value)
858 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000859 FakeReceiveStatistics receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000860 kSendSsrcs[0], last_sequence_number_, rtp_count_, 0);
sprang86fd9ed2015-09-29 04:45:43 -0700861 RTCPSender rtcp_sender(false, clock_, &receive_stats, nullptr,
stefanf116bd02015-10-27 08:29:42 -0700862 transport_adapter_.get());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000863
pbosda903ea2015-10-02 02:36:56 -0700864 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000865 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000866 if (remb_value > 0) {
867 rtcp_sender.SetREMBStatus(true);
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000868 rtcp_sender.SetREMBData(remb_value, std::vector<uint32_t>());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000869 }
870 RTCPSender::FeedbackState feedback_state;
871 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
872 }
873
stefanf116bd02015-10-27 08:29:42 -0700874 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000875 Clock* const clock_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000876 VideoSendStream* stream_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000877
Peter Boströmf2f82832015-05-01 13:00:41 +0200878 rtc::CriticalSection crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000879 TestState test_state_ GUARDED_BY(crit_);
880 int rtp_count_ GUARDED_BY(crit_);
881 int last_sequence_number_ GUARDED_BY(crit_);
882 int suspended_frame_count_ GUARDED_BY(crit_);
883 int low_remb_bps_ GUARDED_BY(crit_);
884 int high_remb_bps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000885 } test;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000886
stefanf116bd02015-10-27 08:29:42 -0700887 RunBaseTest(&test, FakeNetworkPipe::Config());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000888}
889
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000890TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000891 class NoPaddingWhenVideoIsMuted : public test::SendTest {
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000892 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000893 NoPaddingWhenVideoIsMuted()
894 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000895 clock_(Clock::GetRealTimeClock()),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000896 last_packet_time_ms_(-1),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000897 capturer_(nullptr) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000898 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000899
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000900 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000901 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200902 rtc::CritScope lock(&crit_);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000903 last_packet_time_ms_ = clock_->TimeInMilliseconds();
904 capturer_->Stop();
905 return SEND_PACKET;
906 }
907
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000908 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200909 rtc::CritScope lock(&crit_);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000910 const int kVideoMutedThresholdMs = 10000;
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000911 if (last_packet_time_ms_ > 0 &&
912 clock_->TimeInMilliseconds() - last_packet_time_ms_ >
913 kVideoMutedThresholdMs)
Peter Boström5811a392015-12-10 13:02:50 +0100914 observation_complete_.Set();
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000915 // Receive statistics reporting having lost 50% of the packets.
916 FakeReceiveStatistics receive_stats(kSendSsrcs[0], 1, 1, 0);
Peter Boströmac547a62015-09-17 23:03:57 +0200917 RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), &receive_stats,
stefanf116bd02015-10-27 08:29:42 -0700918 nullptr, transport_adapter_.get());
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000919
pbosda903ea2015-10-02 02:36:56 -0700920 rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000921 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
922
923 RTCPSender::FeedbackState feedback_state;
924
925 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
926 return SEND_PACKET;
927 }
928
stefanf116bd02015-10-27 08:29:42 -0700929 void OnTransportsCreated(
930 test::PacketTransport* send_transport,
931 test::PacketTransport* receive_transport) override {
932 transport_adapter_.reset(
933 new internal::TransportAdapter(receive_transport));
934 transport_adapter_->Enable();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000935 }
936
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000937 size_t GetNumStreams() const override { return 3; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000938
939 virtual void OnFrameGeneratorCapturerCreated(
940 test::FrameGeneratorCapturer* frame_generator_capturer) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200941 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000942 capturer_ = frame_generator_capturer;
943 }
944
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000945 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +0100946 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000947 << "Timed out while waiting for RTP packets to stop being sent.";
948 }
949
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000950 Clock* const clock_;
stefanf116bd02015-10-27 08:29:42 -0700951 rtc::scoped_ptr<internal::TransportAdapter> transport_adapter_;
Peter Boströmf2f82832015-05-01 13:00:41 +0200952 rtc::CriticalSection crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000953 int64_t last_packet_time_ms_ GUARDED_BY(crit_);
954 test::FrameGeneratorCapturer* capturer_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000955 } test;
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000956
stefanf116bd02015-10-27 08:29:42 -0700957 RunBaseTest(&test, FakeNetworkPipe::Config());
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000958}
959
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000960// This test first observes "high" bitrate use at which point it sends a REMB to
961// indicate that it should be lowered significantly. The test then observes that
962// the bitrate observed is sinking well below the min-transmit-bitrate threshold
963// to verify that the min-transmit bitrate respects incoming REMB.
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000964//
965// Note that the test starts at "high" bitrate and does not ramp up to "higher"
966// bitrate since no receiver block or remb is sent in the initial phase.
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000967TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
968 static const int kMinTransmitBitrateBps = 400000;
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000969 static const int kHighBitrateBps = 150000;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000970 static const int kRembBitrateBps = 80000;
971 static const int kRembRespectedBitrateBps = 100000;
stefanf116bd02015-10-27 08:29:42 -0700972 class BitrateObserver : public test::SendTest {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000973 public:
974 BitrateObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000975 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000976 bitrate_capped_(false) {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000977 }
978
979 private:
stefanf116bd02015-10-27 08:29:42 -0700980 virtual Action OnSendRtp(const uint8_t* packet, size_t length) {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000981 if (RtpHeaderParser::IsRtcp(packet, length))
stefanf116bd02015-10-27 08:29:42 -0700982 return DROP_PACKET;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000983
984 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000985 if (!parser_->Parse(packet, length, &header))
stefanf116bd02015-10-27 08:29:42 -0700986 return DROP_PACKET;
henrikg91d6ede2015-09-17 00:24:34 -0700987 RTC_DCHECK(stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000988 VideoSendStream::Stats stats = stream_->GetStats();
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000989 if (!stats.substreams.empty()) {
990 EXPECT_EQ(1u, stats.substreams.size());
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000991 int total_bitrate_bps =
992 stats.substreams.begin()->second.total_bitrate_bps;
993 test::PrintResult("bitrate_stats_",
994 "min_transmit_bitrate_low_remb",
995 "bitrate_bps",
996 static_cast<size_t>(total_bitrate_bps),
997 "bps",
998 false);
999 if (total_bitrate_bps > kHighBitrateBps) {
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001000 rtp_rtcp_->SetREMBData(kRembBitrateBps,
1001 std::vector<uint32_t>(1, header.ssrc));
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001002 rtp_rtcp_->Process();
1003 bitrate_capped_ = true;
1004 } else if (bitrate_capped_ &&
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001005 total_bitrate_bps < kRembRespectedBitrateBps) {
Peter Boström5811a392015-12-10 13:02:50 +01001006 observation_complete_.Set();
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001007 }
1008 }
stefanf116bd02015-10-27 08:29:42 -07001009 // Packets don't have to be delivered since the test is the receiver.
1010 return DROP_PACKET;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001011 }
1012
stefanf116bd02015-10-27 08:29:42 -07001013 void OnStreamsCreated(
1014 VideoSendStream* send_stream,
1015 const std::vector<VideoReceiveStream*>& receive_streams) override {
1016 stream_ = send_stream;
1017 RtpRtcp::Configuration config;
1018 config.outgoing_transport = feedback_transport_.get();
1019 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1020 rtp_rtcp_->SetREMBStatus(true);
1021 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001022 }
1023
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001024 void ModifyConfigs(VideoSendStream::Config* send_config,
1025 std::vector<VideoReceiveStream::Config>* receive_configs,
1026 VideoEncoderConfig* encoder_config) override {
stefanf116bd02015-10-27 08:29:42 -07001027 feedback_transport_.reset(
1028 new internal::TransportAdapter(send_config->send_transport));
1029 feedback_transport_->Enable();
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00001030 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001031 }
1032
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001033 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001034 EXPECT_TRUE(Wait())
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001035 << "Timeout while waiting for low bitrate stats after REMB.";
1036 }
1037
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001038 rtc::scoped_ptr<RtpRtcp> rtp_rtcp_;
stefanf116bd02015-10-27 08:29:42 -07001039 rtc::scoped_ptr<internal::TransportAdapter> feedback_transport_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001040 VideoSendStream* stream_;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001041 bool bitrate_capped_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001042 } test;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001043
stefanf116bd02015-10-27 08:29:42 -07001044 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001045}
1046
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001047TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) {
1048 class StartBitrateObserver : public test::FakeEncoder {
1049 public:
1050 StartBitrateObserver()
1051 : FakeEncoder(Clock::GetRealTimeClock()), start_bitrate_kbps_(0) {}
1052 int32_t InitEncode(const VideoCodec* config,
1053 int32_t number_of_cores,
1054 size_t max_payload_size) override {
1055 rtc::CritScope lock(&crit_);
1056 start_bitrate_kbps_ = config->startBitrate;
1057 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1058 }
1059
1060 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
1061 rtc::CritScope lock(&crit_);
1062 start_bitrate_kbps_ = new_target_bitrate;
1063 return FakeEncoder::SetRates(new_target_bitrate, framerate);
1064 }
1065
1066 int GetStartBitrateKbps() const {
1067 rtc::CritScope lock(&crit_);
1068 return start_bitrate_kbps_;
1069 }
1070
1071 private:
1072 mutable rtc::CriticalSection crit_;
1073 int start_bitrate_kbps_ GUARDED_BY(crit_);
1074 };
1075
solenberg4fbae2b2015-08-28 04:07:10 -07001076 CreateSenderCall(Call::Config());
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001077
solenberg4fbae2b2015-08-28 04:07:10 -07001078 test::NullTransport transport;
1079 CreateSendConfig(1, &transport);
pbos@webrtc.org143451d2015-03-18 14:40:03 +00001080
1081 Call::Config::BitrateConfig bitrate_config;
1082 bitrate_config.start_bitrate_bps =
1083 2 * encoder_config_.streams[0].max_bitrate_bps;
1084 sender_call_->SetBitrateConfig(bitrate_config);
1085
1086 StartBitrateObserver encoder;
1087 send_config_.encoder_settings.encoder = &encoder;
1088
1089 CreateStreams();
1090
1091 EXPECT_EQ(encoder_config_.streams[0].max_bitrate_bps / 1000,
1092 encoder.GetStartBitrateKbps());
1093
1094 encoder_config_.streams[0].max_bitrate_bps =
1095 2 * bitrate_config.start_bitrate_bps;
1096 send_stream_->ReconfigureVideoEncoder(encoder_config_);
1097
1098 // New bitrate should be reconfigured above the previous max. As there's no
1099 // network connection this shouldn't be flaky, as no bitrate should've been
1100 // reported in between.
1101 EXPECT_EQ(bitrate_config.start_bitrate_bps / 1000,
1102 encoder.GetStartBitrateKbps());
1103
1104 DestroyStreams();
1105}
1106
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001107TEST_F(VideoSendStreamTest, CapturesTextureAndVideoFrames) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001108 class FrameObserver : public I420FrameCallback {
1109 public:
Peter Boström5811a392015-12-10 13:02:50 +01001110 FrameObserver() : output_frame_event_(false, false) {}
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001111
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001112 void FrameCallback(VideoFrame* video_frame) override {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001113 output_frames_.push_back(*video_frame);
Peter Boström5811a392015-12-10 13:02:50 +01001114 output_frame_event_.Set();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001115 }
1116
1117 void WaitOutputFrame() {
Peter Boström5811a392015-12-10 13:02:50 +01001118 const int kWaitFrameTimeoutMs = 3000;
1119 EXPECT_TRUE(output_frame_event_.Wait(kWaitFrameTimeoutMs))
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001120 << "Timeout while waiting for output frames.";
1121 }
1122
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001123 const std::vector<VideoFrame>& output_frames() const {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001124 return output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001125 }
1126
1127 private:
1128 // Delivered output frames.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001129 std::vector<VideoFrame> output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001130
1131 // Indicate an output frame has arrived.
Peter Boström5811a392015-12-10 13:02:50 +01001132 rtc::Event output_frame_event_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001133 };
1134
1135 // Initialize send stream.
solenberg4fbae2b2015-08-28 04:07:10 -07001136 CreateSenderCall(Call::Config());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001137
solenberg4fbae2b2015-08-28 04:07:10 -07001138 test::NullTransport transport;
1139 CreateSendConfig(1, &transport);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001140 FrameObserver observer;
1141 send_config_.pre_encode_callback = &observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001142 CreateStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001143
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001144 // Prepare five input frames. Send ordinary VideoFrame and texture frames
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001145 // alternatively.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001146 std::vector<VideoFrame> input_frames;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001147 int width = static_cast<int>(encoder_config_.streams[0].width);
1148 int height = static_cast<int>(encoder_config_.streams[0].height);
Peter Boströmeb66e802015-06-05 11:08:03 +02001149 test::FakeNativeHandle* handle1 = new test::FakeNativeHandle();
1150 test::FakeNativeHandle* handle2 = new test::FakeNativeHandle();
1151 test::FakeNativeHandle* handle3 = new test::FakeNativeHandle();
1152 input_frames.push_back(test::CreateFakeNativeHandleFrame(
1153 handle1, width, height, 1, 1, kVideoRotation_0));
1154 input_frames.push_back(test::CreateFakeNativeHandleFrame(
1155 handle2, width, height, 2, 2, kVideoRotation_0));
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001156 input_frames.push_back(CreateVideoFrame(width, height, 3));
1157 input_frames.push_back(CreateVideoFrame(width, height, 4));
Peter Boströmeb66e802015-06-05 11:08:03 +02001158 input_frames.push_back(test::CreateFakeNativeHandleFrame(
1159 handle3, width, height, 5, 5, kVideoRotation_0));
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001160
1161 send_stream_->Start();
1162 for (size_t i = 0; i < input_frames.size(); i++) {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001163 send_stream_->Input()->IncomingCapturedFrame(input_frames[i]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001164 // Do not send the next frame too fast, so the frame dropper won't drop it.
1165 if (i < input_frames.size() - 1)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001166 SleepMs(1000 / encoder_config_.streams[0].max_framerate);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001167 // Wait until the output frame is received before sending the next input
1168 // frame. Or the previous input frame may be replaced without delivering.
1169 observer.WaitOutputFrame();
1170 }
1171 send_stream_->Stop();
1172
1173 // Test if the input and output frames are the same. render_time_ms and
1174 // timestamp are not compared because capturer sets those values.
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001175 ExpectEqualFramesVector(input_frames, observer.output_frames());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001176
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001177 DestroyStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001178}
1179
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001180void ExpectEqualFrames(const VideoFrame& frame1, const VideoFrame& frame2) {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001181 if (frame1.native_handle() != nullptr || frame2.native_handle() != nullptr)
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001182 ExpectEqualTextureFrames(frame1, frame2);
1183 else
1184 ExpectEqualBufferFrames(frame1, frame2);
1185}
1186
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001187void ExpectEqualTextureFrames(const VideoFrame& frame1,
1188 const VideoFrame& frame2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001189 EXPECT_EQ(frame1.native_handle(), frame2.native_handle());
1190 EXPECT_EQ(frame1.width(), frame2.width());
1191 EXPECT_EQ(frame1.height(), frame2.height());
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001192 EXPECT_EQ(frame1.render_time_ms(), frame2.render_time_ms());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001193}
1194
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001195void ExpectEqualBufferFrames(const VideoFrame& frame1,
1196 const VideoFrame& frame2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001197 EXPECT_EQ(frame1.width(), frame2.width());
1198 EXPECT_EQ(frame1.height(), frame2.height());
1199 EXPECT_EQ(frame1.stride(kYPlane), frame2.stride(kYPlane));
1200 EXPECT_EQ(frame1.stride(kUPlane), frame2.stride(kUPlane));
1201 EXPECT_EQ(frame1.stride(kVPlane), frame2.stride(kVPlane));
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 ASSERT_EQ(frame1.allocated_size(kYPlane), frame2.allocated_size(kYPlane));
1204 EXPECT_EQ(0,
1205 memcmp(frame1.buffer(kYPlane),
1206 frame2.buffer(kYPlane),
1207 frame1.allocated_size(kYPlane)));
1208 ASSERT_EQ(frame1.allocated_size(kUPlane), frame2.allocated_size(kUPlane));
1209 EXPECT_EQ(0,
1210 memcmp(frame1.buffer(kUPlane),
1211 frame2.buffer(kUPlane),
1212 frame1.allocated_size(kUPlane)));
1213 ASSERT_EQ(frame1.allocated_size(kVPlane), frame2.allocated_size(kVPlane));
1214 EXPECT_EQ(0,
1215 memcmp(frame1.buffer(kVPlane),
1216 frame2.buffer(kVPlane),
1217 frame1.allocated_size(kVPlane)));
1218}
1219
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001220void ExpectEqualFramesVector(const std::vector<VideoFrame>& frames1,
1221 const std::vector<VideoFrame>& frames2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001222 EXPECT_EQ(frames1.size(), frames2.size());
1223 for (size_t i = 0; i < std::min(frames1.size(), frames2.size()); ++i)
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001224 ExpectEqualFrames(frames1[i], frames2[i]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001225}
1226
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001227VideoFrame CreateVideoFrame(int width, int height, uint8_t data) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001228 const int kSizeY = width * height * 2;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001229 rtc::scoped_ptr<uint8_t[]> buffer(new uint8_t[kSizeY]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001230 memset(buffer.get(), data, kSizeY);
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001231 VideoFrame frame;
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001232 frame.CreateFrame(buffer.get(), buffer.get(), buffer.get(), width, height,
1233 width, width / 2, width / 2);
1234 frame.set_timestamp(data);
1235 frame.set_render_time_ms(data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001236 return frame;
1237}
1238
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001239TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
1240 class EncoderStateObserver : public test::SendTest, public VideoEncoder {
1241 public:
1242 EncoderStateObserver()
1243 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001244 initialized_(false),
1245 callback_registered_(false),
1246 num_releases_(0),
1247 released_(false) {}
1248
1249 bool IsReleased() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001250 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001251 return released_;
1252 }
1253
1254 bool IsReadyForEncode() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001255 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001256 return initialized_ && callback_registered_;
1257 }
1258
1259 size_t num_releases() {
Peter Boströmf2f82832015-05-01 13:00:41 +02001260 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001261 return num_releases_;
1262 }
1263
1264 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001265 int32_t InitEncode(const VideoCodec* codecSettings,
1266 int32_t numberOfCores,
1267 size_t maxPayloadSize) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001268 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001269 EXPECT_FALSE(initialized_);
1270 initialized_ = true;
1271 released_ = false;
1272 return 0;
1273 }
1274
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001275 int32_t Encode(const VideoFrame& inputImage,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001276 const CodecSpecificInfo* codecSpecificInfo,
pbos22993e12015-10-19 02:39:06 -07001277 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001278 EXPECT_TRUE(IsReadyForEncode());
1279
Peter Boström5811a392015-12-10 13:02:50 +01001280 observation_complete_.Set();
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001281 return 0;
1282 }
1283
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001284 int32_t RegisterEncodeCompleteCallback(
1285 EncodedImageCallback* callback) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001286 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001287 EXPECT_TRUE(initialized_);
1288 callback_registered_ = true;
1289 return 0;
1290 }
1291
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001292 int32_t Release() override {
Peter Boströmf2f82832015-05-01 13:00:41 +02001293 rtc::CritScope lock(&crit_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001294 EXPECT_TRUE(IsReadyForEncode());
1295 EXPECT_FALSE(released_);
1296 initialized_ = false;
1297 callback_registered_ = false;
1298 released_ = true;
1299 ++num_releases_;
1300 return 0;
1301 }
1302
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001303 int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001304 EXPECT_TRUE(IsReadyForEncode());
1305 return 0;
1306 }
1307
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001308 int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001309 EXPECT_TRUE(IsReadyForEncode());
1310 return 0;
1311 }
1312
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001313 void OnStreamsCreated(
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001314 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001315 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001316 // Encoder initialization should be done in stream construction before
1317 // starting.
1318 EXPECT_TRUE(IsReadyForEncode());
1319 stream_ = send_stream;
1320 }
1321
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001322 void ModifyConfigs(VideoSendStream::Config* send_config,
1323 std::vector<VideoReceiveStream::Config>* receive_configs,
1324 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001325 send_config->encoder_settings.encoder = this;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001326 encoder_config_ = *encoder_config;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001327 }
1328
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001329 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001330 EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001331 EXPECT_EQ(0u, num_releases());
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001332 stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001333 EXPECT_EQ(0u, num_releases());
1334 stream_->Stop();
1335 // Encoder should not be released before destroying the VideoSendStream.
1336 EXPECT_FALSE(IsReleased());
1337 EXPECT_TRUE(IsReadyForEncode());
1338 stream_->Start();
1339 // Sanity check, make sure we still encode frames with this encoder.
Peter Boström5811a392015-12-10 13:02:50 +01001340 EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001341 }
1342
Peter Boströmf2f82832015-05-01 13:00:41 +02001343 rtc::CriticalSection crit_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001344 VideoSendStream* stream_;
1345 bool initialized_ GUARDED_BY(crit_);
1346 bool callback_registered_ GUARDED_BY(crit_);
1347 size_t num_releases_ GUARDED_BY(crit_);
1348 bool released_ GUARDED_BY(crit_);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001349 VideoEncoderConfig encoder_config_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001350 } test_encoder;
1351
stefanf116bd02015-10-27 08:29:42 -07001352 RunBaseTest(&test_encoder, FakeNetworkPipe::Config());
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001353
1354 EXPECT_TRUE(test_encoder.IsReleased());
1355 EXPECT_EQ(1u, test_encoder.num_releases());
1356}
1357
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001358TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
1359 class VideoCodecConfigObserver : public test::SendTest,
1360 public test::FakeEncoder {
1361 public:
1362 VideoCodecConfigObserver()
1363 : SendTest(kDefaultTimeoutMs),
1364 FakeEncoder(Clock::GetRealTimeClock()),
1365 num_initializations_(0) {}
1366
1367 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001368 void ModifyConfigs(VideoSendStream::Config* send_config,
1369 std::vector<VideoReceiveStream::Config>* receive_configs,
1370 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001371 send_config->encoder_settings.encoder = this;
1372 encoder_config_ = *encoder_config;
1373 }
1374
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001375 void OnStreamsCreated(
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001376 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001377 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001378 stream_ = send_stream;
1379 }
1380
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001381 int32_t InitEncode(const VideoCodec* config,
1382 int32_t number_of_cores,
1383 size_t max_payload_size) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001384 if (num_initializations_ == 0) {
1385 // Verify default values.
1386 EXPECT_EQ(kRealtimeVideo, config->mode);
1387 } else {
1388 // Verify that changed values are propagated.
1389 EXPECT_EQ(kScreensharing, config->mode);
1390 }
1391 ++num_initializations_;
1392 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1393 }
1394
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001395 void PerformTest() override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001396 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1397
Erik Språng143cec12015-04-28 10:01:41 +02001398 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001399 stream_->ReconfigureVideoEncoder(encoder_config_);
1400 EXPECT_EQ(2u, num_initializations_)
1401 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1402 "new encoder settings.";
1403 }
1404
1405 size_t num_initializations_;
1406 VideoSendStream* stream_;
1407 VideoEncoderConfig encoder_config_;
1408 } test;
1409
stefanf116bd02015-10-27 08:29:42 -07001410 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001411}
1412
Peter Boström53eda3d2015-03-27 15:53:18 +01001413static const size_t kVideoCodecConfigObserverNumberOfTemporalLayers = 4;
1414template <typename T>
1415class VideoCodecConfigObserver : public test::SendTest,
1416 public test::FakeEncoder {
Peter Boström53eda3d2015-03-27 15:53:18 +01001417 public:
1418 VideoCodecConfigObserver(VideoCodecType video_codec_type,
1419 const char* codec_name)
1420 : SendTest(VideoSendStreamTest::kDefaultTimeoutMs),
1421 FakeEncoder(Clock::GetRealTimeClock()),
1422 video_codec_type_(video_codec_type),
1423 codec_name_(codec_name),
1424 num_initializations_(0) {
1425 memset(&encoder_settings_, 0, sizeof(encoder_settings_));
1426 }
1427
1428 private:
1429 void ModifyConfigs(VideoSendStream::Config* send_config,
1430 std::vector<VideoReceiveStream::Config>* receive_configs,
1431 VideoEncoderConfig* encoder_config) override {
1432 send_config->encoder_settings.encoder = this;
1433 send_config->encoder_settings.payload_name = codec_name_;
1434
1435 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
1436 encoder_config->streams[i].temporal_layer_thresholds_bps.resize(
1437 kVideoCodecConfigObserverNumberOfTemporalLayers - 1);
1438 }
1439
1440 encoder_config->encoder_specific_settings = &encoder_settings_;
1441 encoder_config_ = *encoder_config;
1442 }
1443
1444 void OnStreamsCreated(
1445 VideoSendStream* send_stream,
1446 const std::vector<VideoReceiveStream*>& receive_streams) override {
1447 stream_ = send_stream;
1448 }
1449
1450 int32_t InitEncode(const VideoCodec* config,
1451 int32_t number_of_cores,
1452 size_t max_payload_size) override {
1453 EXPECT_EQ(video_codec_type_, config->codecType);
1454 VerifyCodecSpecifics(*config);
1455 ++num_initializations_;
1456 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1457 }
1458
1459 void VerifyCodecSpecifics(const VideoCodec& config) const;
1460
1461 void PerformTest() override {
1462 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1463
1464 encoder_settings_.frameDroppingOn = true;
1465 stream_->ReconfigureVideoEncoder(encoder_config_);
1466 EXPECT_EQ(2u, num_initializations_)
1467 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1468 "new encoder settings.";
1469 }
1470
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001471 int32_t Encode(const VideoFrame& input_image,
Peter Boström53eda3d2015-03-27 15:53:18 +01001472 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -07001473 const std::vector<FrameType>* frame_types) override {
Peter Boström53eda3d2015-03-27 15:53:18 +01001474 // Silently skip the encode, FakeEncoder::Encode doesn't produce VP8.
1475 return 0;
1476 }
1477
1478 T encoder_settings_;
1479 const VideoCodecType video_codec_type_;
1480 const char* const codec_name_;
1481 size_t num_initializations_;
1482 VideoSendStream* stream_;
1483 VideoEncoderConfig encoder_config_;
1484};
1485
1486template <>
1487void VideoCodecConfigObserver<VideoCodecH264>::VerifyCodecSpecifics(
1488 const VideoCodec& config) const {
1489 EXPECT_EQ(0, memcmp(&config.codecSpecific.H264, &encoder_settings_,
1490 sizeof(encoder_settings_)));
1491}
1492template <>
1493void VideoCodecConfigObserver<VideoCodecVP8>::VerifyCodecSpecifics(
1494 const VideoCodec& config) const {
1495 // Check that the number of temporal layers has propagated properly to
1496 // VideoCodec.
1497 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1498 config.codecSpecific.VP8.numberOfTemporalLayers);
1499
1500 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1501 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1502 config.simulcastStream[i].numberOfTemporalLayers);
1503 }
1504
1505 // Set expected temporal layers as they should have been set when
1506 // reconfiguring the encoder and not match the set config.
1507 VideoCodecVP8 encoder_settings = encoder_settings_;
1508 encoder_settings.numberOfTemporalLayers =
1509 kVideoCodecConfigObserverNumberOfTemporalLayers;
1510 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP8, &encoder_settings,
1511 sizeof(encoder_settings_)));
1512}
1513template <>
1514void VideoCodecConfigObserver<VideoCodecVP9>::VerifyCodecSpecifics(
1515 const VideoCodec& config) const {
1516 // Check that the number of temporal layers has propagated properly to
1517 // VideoCodec.
1518 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1519 config.codecSpecific.VP9.numberOfTemporalLayers);
1520
1521 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1522 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1523 config.simulcastStream[i].numberOfTemporalLayers);
1524 }
1525
1526 // Set expected temporal layers as they should have been set when
1527 // reconfiguring the encoder and not match the set config.
1528 VideoCodecVP9 encoder_settings = encoder_settings_;
1529 encoder_settings.numberOfTemporalLayers =
1530 kVideoCodecConfigObserverNumberOfTemporalLayers;
1531 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP9, &encoder_settings,
1532 sizeof(encoder_settings_)));
1533}
1534
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001535TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp8Config) {
Peter Boström53eda3d2015-03-27 15:53:18 +01001536 VideoCodecConfigObserver<VideoCodecVP8> test(kVideoCodecVP8, "VP8");
stefanf116bd02015-10-27 08:29:42 -07001537 RunBaseTest(&test, FakeNetworkPipe::Config());
Peter Boström53eda3d2015-03-27 15:53:18 +01001538}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001539
Peter Boström53eda3d2015-03-27 15:53:18 +01001540TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp9Config) {
1541 VideoCodecConfigObserver<VideoCodecVP9> test(kVideoCodecVP9, "VP9");
stefanf116bd02015-10-27 08:29:42 -07001542 RunBaseTest(&test, FakeNetworkPipe::Config());
Peter Boström53eda3d2015-03-27 15:53:18 +01001543}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001544
Peter Boström53eda3d2015-03-27 15:53:18 +01001545TEST_F(VideoSendStreamTest, EncoderSetupPropagatesH264Config) {
1546 VideoCodecConfigObserver<VideoCodecH264> test(kVideoCodecH264, "H264");
stefanf116bd02015-10-27 08:29:42 -07001547 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001548}
1549
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001550TEST_F(VideoSendStreamTest, RtcpSenderReportContainsMediaBytesSent) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001551 class RtcpSenderReportTest : public test::SendTest {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001552 public:
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001553 RtcpSenderReportTest() : SendTest(kDefaultTimeoutMs),
1554 rtp_packets_sent_(0),
1555 media_bytes_sent_(0) {}
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001556
1557 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001558 Action OnSendRtp(const uint8_t* packet, size_t length) override {
stefan4b569042015-11-11 06:39:57 -08001559 rtc::CritScope lock(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001560 RTPHeader header;
1561 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001562 ++rtp_packets_sent_;
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001563 media_bytes_sent_ += length - header.headerLength - header.paddingLength;
1564 return SEND_PACKET;
1565 }
1566
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001567 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
stefan4b569042015-11-11 06:39:57 -08001568 rtc::CritScope lock(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001569 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1570 EXPECT_TRUE(parser.IsValid());
1571
1572 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001573 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1574 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001575 // Only compare sent media bytes if SenderPacketCount matches the
1576 // number of sent rtp packets (a new rtp packet could be sent before
1577 // the rtcp packet).
1578 if (parser.Packet().SR.SenderOctetCount > 0 &&
1579 parser.Packet().SR.SenderPacketCount == rtp_packets_sent_) {
1580 EXPECT_EQ(media_bytes_sent_, parser.Packet().SR.SenderOctetCount);
Peter Boström5811a392015-12-10 13:02:50 +01001581 observation_complete_.Set();
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001582 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001583 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001584 packet_type = parser.Iterate();
1585 }
1586
1587 return SEND_PACKET;
1588 }
1589
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001590 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001591 EXPECT_TRUE(Wait()) << "Timed out while waiting for RTCP sender report.";
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001592 }
1593
stefan4b569042015-11-11 06:39:57 -08001594 rtc::CriticalSection crit_;
1595 size_t rtp_packets_sent_ GUARDED_BY(&crit_);
1596 size_t media_bytes_sent_ GUARDED_BY(&crit_);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001597 } test;
1598
stefanf116bd02015-10-27 08:29:42 -07001599 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001600}
1601
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001602TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
1603 static const int kScreencastTargetBitrateKbps = 200;
1604 class ScreencastTargetBitrateTest : public test::SendTest,
1605 public test::FakeEncoder {
1606 public:
1607 ScreencastTargetBitrateTest()
1608 : SendTest(kDefaultTimeoutMs),
1609 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1610
1611 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001612 int32_t InitEncode(const VideoCodec* config,
1613 int32_t number_of_cores,
1614 size_t max_payload_size) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001615 EXPECT_EQ(static_cast<unsigned int>(kScreencastTargetBitrateKbps),
1616 config->targetBitrate);
Peter Boström5811a392015-12-10 13:02:50 +01001617 observation_complete_.Set();
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001618 return test::FakeEncoder::InitEncode(
1619 config, number_of_cores, max_payload_size);
1620 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001621 void ModifyConfigs(VideoSendStream::Config* send_config,
1622 std::vector<VideoReceiveStream::Config>* receive_configs,
1623 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001624 send_config->encoder_settings.encoder = this;
1625 EXPECT_EQ(1u, encoder_config->streams.size());
1626 EXPECT_TRUE(
1627 encoder_config->streams[0].temporal_layer_thresholds_bps.empty());
1628 encoder_config->streams[0].temporal_layer_thresholds_bps.push_back(
1629 kScreencastTargetBitrateKbps * 1000);
Erik Språng143cec12015-04-28 10:01:41 +02001630 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001631 }
1632
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001633 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001634 EXPECT_TRUE(Wait())
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001635 << "Timed out while waiting for the encoder to be initialized.";
1636 }
1637 } test;
1638
stefanf116bd02015-10-27 08:29:42 -07001639 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001640}
pbos@webrtc.org00873182014-11-25 14:03:34 +00001641
Stefan Holmere5904162015-03-26 11:11:06 +01001642TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001643 // These are chosen to be "kind of odd" to not be accidentally checked against
1644 // default values.
1645 static const int kMinBitrateKbps = 137;
1646 static const int kStartBitrateKbps = 345;
1647 static const int kLowerMaxBitrateKbps = 312;
1648 static const int kMaxBitrateKbps = 413;
1649 static const int kIncreasedStartBitrateKbps = 451;
1650 static const int kIncreasedMaxBitrateKbps = 597;
1651 class EncoderBitrateThresholdObserver : public test::SendTest,
1652 public test::FakeEncoder {
1653 public:
1654 EncoderBitrateThresholdObserver()
1655 : SendTest(kDefaultTimeoutMs),
1656 FakeEncoder(Clock::GetRealTimeClock()),
1657 num_initializations_(0) {}
1658
1659 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001660 int32_t InitEncode(const VideoCodec* codecSettings,
1661 int32_t numberOfCores,
1662 size_t maxPayloadSize) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001663 if (num_initializations_ == 0) {
1664 EXPECT_EQ(static_cast<unsigned int>(kMinBitrateKbps),
1665 codecSettings->minBitrate);
1666 EXPECT_EQ(static_cast<unsigned int>(kStartBitrateKbps),
1667 codecSettings->startBitrate);
1668 EXPECT_EQ(static_cast<unsigned int>(kMaxBitrateKbps),
1669 codecSettings->maxBitrate);
Peter Boström5811a392015-12-10 13:02:50 +01001670 observation_complete_.Set();
pbos@webrtc.org00873182014-11-25 14:03:34 +00001671 } else if (num_initializations_ == 1) {
1672 EXPECT_EQ(static_cast<unsigned int>(kLowerMaxBitrateKbps),
1673 codecSettings->maxBitrate);
1674 // The start bitrate should be kept (-1) and capped to the max bitrate.
1675 // Since this is not an end-to-end call no receiver should have been
1676 // returning a REMB that could lower this estimate.
1677 EXPECT_EQ(codecSettings->startBitrate, codecSettings->maxBitrate);
1678 } else if (num_initializations_ == 2) {
1679 EXPECT_EQ(static_cast<unsigned int>(kIncreasedMaxBitrateKbps),
1680 codecSettings->maxBitrate);
1681 EXPECT_EQ(static_cast<unsigned int>(kIncreasedStartBitrateKbps),
1682 codecSettings->startBitrate);
1683 }
1684 ++num_initializations_;
1685 return FakeEncoder::InitEncode(codecSettings, numberOfCores,
1686 maxPayloadSize);
1687 }
1688
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001689 Call::Config GetSenderCallConfig() override {
solenberg4fbae2b2015-08-28 04:07:10 -07001690 Call::Config config;
Stefan Holmere5904162015-03-26 11:11:06 +01001691 config.bitrate_config.min_bitrate_bps = kMinBitrateKbps * 1000;
1692 config.bitrate_config.start_bitrate_bps = kStartBitrateKbps * 1000;
1693 config.bitrate_config.max_bitrate_bps = kMaxBitrateKbps * 1000;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001694 return config;
1695 }
1696
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001697 void ModifyConfigs(VideoSendStream::Config* send_config,
1698 std::vector<VideoReceiveStream::Config>* receive_configs,
1699 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001700 send_config->encoder_settings.encoder = this;
1701 // Set bitrates lower/higher than min/max to make sure they are properly
1702 // capped.
Stefan Holmere5904162015-03-26 11:11:06 +01001703 encoder_config->streams.front().min_bitrate_bps = kMinBitrateKbps * 1000;
1704 encoder_config->streams.front().max_bitrate_bps = kMaxBitrateKbps * 1000;
1705 encoder_config_ = *encoder_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001706 }
1707
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001708 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001709 call_ = sender_call;
1710 }
1711
Stefan Holmere5904162015-03-26 11:11:06 +01001712 void OnStreamsCreated(
1713 VideoSendStream* send_stream,
1714 const std::vector<VideoReceiveStream*>& receive_streams) override {
1715 send_stream_ = send_stream;
1716 }
1717
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001718 void PerformTest() override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001719 Call::Config::BitrateConfig bitrate_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001720 bitrate_config.start_bitrate_bps = kIncreasedStartBitrateKbps * 1000;
1721 bitrate_config.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000;
1722 call_->SetBitrateConfig(bitrate_config);
Peter Boström5811a392015-12-10 13:02:50 +01001723 EXPECT_TRUE(Wait())
Stefan Holmere5904162015-03-26 11:11:06 +01001724 << "Timed out while waiting encoder to be configured.";
1725 encoder_config_.streams[0].min_bitrate_bps = 0;
1726 encoder_config_.streams[0].max_bitrate_bps = kLowerMaxBitrateKbps * 1000;
1727 send_stream_->ReconfigureVideoEncoder(encoder_config_);
1728 EXPECT_EQ(2, num_initializations_)
1729 << "Encoder should have been reconfigured with the new value.";
1730 encoder_config_.streams[0].target_bitrate_bps =
1731 encoder_config_.streams[0].min_bitrate_bps;
1732 encoder_config_.streams[0].max_bitrate_bps =
1733 kIncreasedMaxBitrateKbps * 1000;
1734 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org00873182014-11-25 14:03:34 +00001735 EXPECT_EQ(3, num_initializations_)
1736 << "Encoder should have been reconfigured with the new value.";
1737 }
1738
1739 int num_initializations_;
1740 webrtc::Call* call_;
Stefan Holmere5904162015-03-26 11:11:06 +01001741 webrtc::VideoSendStream* send_stream_;
1742 webrtc::VideoEncoderConfig encoder_config_;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001743 } test;
1744
stefanf116bd02015-10-27 08:29:42 -07001745 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org00873182014-11-25 14:03:34 +00001746}
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001747
1748TEST_F(VideoSendStreamTest, ReportsSentResolution) {
1749 static const size_t kNumStreams = 3;
1750 // Unusual resolutions to make sure that they are the ones being reported.
1751 static const struct {
1752 int width;
1753 int height;
1754 } kEncodedResolution[kNumStreams] = {
1755 {241, 181}, {300, 121}, {121, 221}};
1756 class ScreencastTargetBitrateTest : public test::SendTest,
1757 public test::FakeEncoder {
1758 public:
1759 ScreencastTargetBitrateTest()
1760 : SendTest(kDefaultTimeoutMs),
1761 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1762
1763 private:
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001764 int32_t Encode(const VideoFrame& input_image,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001765 const CodecSpecificInfo* codecSpecificInfo,
pbos22993e12015-10-19 02:39:06 -07001766 const std::vector<FrameType>* frame_types) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001767 CodecSpecificInfo specifics;
1768 memset(&specifics, 0, sizeof(specifics));
1769 specifics.codecType = kVideoCodecGeneric;
1770
1771 uint8_t buffer[16] = {0};
1772 EncodedImage encoded(buffer, sizeof(buffer), sizeof(buffer));
1773 encoded._timeStamp = input_image.timestamp();
1774 encoded.capture_time_ms_ = input_image.render_time_ms();
1775
1776 for (size_t i = 0; i < kNumStreams; ++i) {
1777 specifics.codecSpecific.generic.simulcast_idx = static_cast<uint8_t>(i);
1778 encoded._frameType = (*frame_types)[i];
1779 encoded._encodedWidth = kEncodedResolution[i].width;
1780 encoded._encodedHeight = kEncodedResolution[i].height;
henrikg91d6ede2015-09-17 00:24:34 -07001781 RTC_DCHECK(callback_ != nullptr);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001782 if (callback_->Encoded(encoded, &specifics, nullptr) != 0)
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001783 return -1;
1784 }
1785
Peter Boström5811a392015-12-10 13:02:50 +01001786 observation_complete_.Set();
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001787 return 0;
1788 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001789 void ModifyConfigs(VideoSendStream::Config* send_config,
1790 std::vector<VideoReceiveStream::Config>* receive_configs,
1791 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001792 send_config->encoder_settings.encoder = this;
1793 EXPECT_EQ(kNumStreams, encoder_config->streams.size());
1794 }
1795
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001796 size_t GetNumStreams() const override { return kNumStreams; }
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001797
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001798 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001799 EXPECT_TRUE(Wait())
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001800 << "Timed out while waiting for the encoder to send one frame.";
1801 VideoSendStream::Stats stats = send_stream_->GetStats();
1802
1803 for (size_t i = 0; i < kNumStreams; ++i) {
1804 ASSERT_TRUE(stats.substreams.find(kSendSsrcs[i]) !=
1805 stats.substreams.end())
1806 << "No stats for SSRC: " << kSendSsrcs[i]
1807 << ", stats should exist as soon as frames have been encoded.";
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001808 VideoSendStream::StreamStats ssrc_stats =
1809 stats.substreams[kSendSsrcs[i]];
1810 EXPECT_EQ(kEncodedResolution[i].width, ssrc_stats.width);
1811 EXPECT_EQ(kEncodedResolution[i].height, ssrc_stats.height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001812 }
1813 }
1814
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001815 void OnStreamsCreated(
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001816 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001817 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001818 send_stream_ = send_stream;
1819 }
1820
1821 VideoSendStream* send_stream_;
1822 } test;
1823
stefanf116bd02015-10-27 08:29:42 -07001824 RunBaseTest(&test, FakeNetworkPipe::Config());
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001825}
philipel0f9af012015-09-01 07:01:51 -07001826
Åsa Perssonff24c042015-12-04 10:58:08 +01001827class Vp9HeaderObserver : public test::SendTest {
philipel0f9af012015-09-01 07:01:51 -07001828 public:
Åsa Perssonff24c042015-12-04 10:58:08 +01001829 Vp9HeaderObserver()
1830 : SendTest(VideoSendStreamTest::kLongTimeoutMs),
philipel7fabd462015-09-03 04:42:32 -07001831 vp9_encoder_(VP9Encoder::Create()),
Åsa Perssonff24c042015-12-04 10:58:08 +01001832 vp9_settings_(VideoEncoder::GetDefaultVp9Settings()),
1833 packets_sent_(0),
1834 frames_sent_(0) {}
philipel7fabd462015-09-03 04:42:32 -07001835
philipel0f9af012015-09-01 07:01:51 -07001836 virtual void ModifyConfigsHook(
1837 VideoSendStream::Config* send_config,
1838 std::vector<VideoReceiveStream::Config>* receive_configs,
1839 VideoEncoderConfig* encoder_config) {}
1840
Åsa Perssonff24c042015-12-04 10:58:08 +01001841 virtual void InspectHeader(const RTPVideoHeaderVP9& vp9) = 0;
philipel0f9af012015-09-01 07:01:51 -07001842
1843 private:
1844 const int kVp9PayloadType = 105;
1845
1846 void ModifyConfigs(VideoSendStream::Config* send_config,
1847 std::vector<VideoReceiveStream::Config>* receive_configs,
1848 VideoEncoderConfig* encoder_config) override {
1849 encoder_config->encoder_specific_settings = &vp9_settings_;
philipel7fabd462015-09-03 04:42:32 -07001850 send_config->encoder_settings.encoder = vp9_encoder_.get();
philipel0f9af012015-09-01 07:01:51 -07001851 send_config->encoder_settings.payload_name = "VP9";
1852 send_config->encoder_settings.payload_type = kVp9PayloadType;
1853 ModifyConfigsHook(send_config, receive_configs, encoder_config);
Åsa Perssonff24c042015-12-04 10:58:08 +01001854 EXPECT_EQ(1u, encoder_config->streams.size());
1855 encoder_config->streams[0].temporal_layer_thresholds_bps.resize(
1856 vp9_settings_.numberOfTemporalLayers - 1);
1857 encoder_config_ = *encoder_config;
philipel0f9af012015-09-01 07:01:51 -07001858 }
1859
1860 void PerformTest() override {
Peter Boström5811a392015-12-10 13:02:50 +01001861 EXPECT_TRUE(Wait()) << "Test timed out waiting for VP9 packet, num frames "
1862 << frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07001863 }
1864
1865 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1866 RTPHeader header;
1867 EXPECT_TRUE(parser_->Parse(packet, length, &header));
1868
Åsa Perssonff24c042015-12-04 10:58:08 +01001869 EXPECT_EQ(kVp9PayloadType, header.payloadType);
1870 const uint8_t* payload = packet + header.headerLength;
1871 size_t payload_length = length - header.headerLength - header.paddingLength;
philipel0f9af012015-09-01 07:01:51 -07001872
Åsa Perssonff24c042015-12-04 10:58:08 +01001873 bool new_packet = packets_sent_ == 0 ||
1874 IsNewerSequenceNumber(header.sequenceNumber,
1875 last_header_.sequenceNumber);
1876 if (payload_length > 0 && new_packet) {
1877 RtpDepacketizer::ParsedPayload parsed;
1878 RtpDepacketizerVp9 depacketizer;
1879 EXPECT_TRUE(depacketizer.Parse(&parsed, payload, payload_length));
1880 EXPECT_EQ(RtpVideoCodecTypes::kRtpVideoVp9, parsed.type.Video.codec);
1881 // Verify common fields for all configurations.
1882 VerifyCommonHeader(parsed.type.Video.codecHeader.VP9);
1883 CompareConsecutiveFrames(header, parsed.type.Video);
1884 // Verify configuration specific settings.
1885 InspectHeader(parsed.type.Video.codecHeader.VP9);
philipel0f9af012015-09-01 07:01:51 -07001886
Åsa Perssonff24c042015-12-04 10:58:08 +01001887 ++packets_sent_;
1888 if (header.markerBit) {
1889 ++frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07001890 }
Åsa Perssonff24c042015-12-04 10:58:08 +01001891 last_header_ = header;
1892 last_vp9_ = parsed.type.Video.codecHeader.VP9;
philipel0f9af012015-09-01 07:01:51 -07001893 }
philipel0f9af012015-09-01 07:01:51 -07001894 return SEND_PACKET;
1895 }
1896
philipel7fabd462015-09-03 04:42:32 -07001897 protected:
Åsa Perssonff24c042015-12-04 10:58:08 +01001898 bool ContinuousPictureId(const RTPVideoHeaderVP9& vp9) const {
1899 if (last_vp9_.picture_id > vp9.picture_id) {
1900 return vp9.picture_id == 0; // Wrap.
1901 } else {
1902 return vp9.picture_id == last_vp9_.picture_id + 1;
1903 }
1904 }
1905
1906 void VerifySpatialIdxWithinFrame(const RTPVideoHeaderVP9& vp9) const {
1907 if (frames_sent_ == 0)
1908 return;
1909
1910 bool new_layer = vp9.spatial_idx != last_vp9_.spatial_idx;
1911 EXPECT_EQ(new_layer, vp9.beginning_of_frame);
1912 EXPECT_EQ(new_layer, last_vp9_.end_of_frame);
1913 EXPECT_EQ(new_layer ? last_vp9_.spatial_idx + 1 : last_vp9_.spatial_idx,
1914 vp9.spatial_idx);
1915 }
1916
1917 void VerifyFixedTemporalLayerStructure(const RTPVideoHeaderVP9& vp9,
1918 uint8_t num_layers) const {
1919 switch (num_layers) {
1920 case 0:
1921 VerifyTemporalLayerStructure0(vp9);
1922 break;
1923 case 1:
1924 VerifyTemporalLayerStructure1(vp9);
1925 break;
1926 case 2:
1927 VerifyTemporalLayerStructure2(vp9);
1928 break;
1929 case 3:
1930 VerifyTemporalLayerStructure3(vp9);
1931 break;
1932 default:
1933 RTC_NOTREACHED();
1934 }
1935 }
1936
1937 void VerifyTemporalLayerStructure0(const RTPVideoHeaderVP9& vp9) const {
1938 EXPECT_EQ(kNoTl0PicIdx, vp9.tl0_pic_idx);
1939 EXPECT_EQ(kNoTemporalIdx, vp9.temporal_idx); // no tid
1940 EXPECT_FALSE(vp9.temporal_up_switch);
1941 }
1942
1943 void VerifyTemporalLayerStructure1(const RTPVideoHeaderVP9& vp9) const {
1944 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
1945 EXPECT_EQ(0, vp9.temporal_idx); // 0,0,0,...
1946 EXPECT_FALSE(vp9.temporal_up_switch);
1947 }
1948
1949 void VerifyTemporalLayerStructure2(const RTPVideoHeaderVP9& vp9) const {
1950 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
1951 EXPECT_GE(vp9.temporal_idx, 0); // 0,1,0,1,... (tid reset on I-frames).
1952 EXPECT_LE(vp9.temporal_idx, 1);
1953 EXPECT_EQ(vp9.temporal_idx > 0, vp9.temporal_up_switch);
1954 if (IsNewPictureId(vp9)) {
1955 uint8_t expected_tid =
1956 (!vp9.inter_pic_predicted || last_vp9_.temporal_idx == 1) ? 0 : 1;
1957 EXPECT_EQ(expected_tid, vp9.temporal_idx);
1958 }
1959 }
1960
1961 void VerifyTemporalLayerStructure3(const RTPVideoHeaderVP9& vp9) const {
1962 EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
1963 EXPECT_GE(vp9.temporal_idx, 0); // 0,2,1,2,... (tid reset on I-frames).
1964 EXPECT_LE(vp9.temporal_idx, 2);
1965 if (IsNewPictureId(vp9) && vp9.inter_pic_predicted) {
1966 EXPECT_NE(vp9.temporal_idx, last_vp9_.temporal_idx);
1967 switch (vp9.temporal_idx) {
1968 case 0:
1969 EXPECT_EQ(2, last_vp9_.temporal_idx);
1970 EXPECT_FALSE(vp9.temporal_up_switch);
1971 break;
1972 case 1:
1973 EXPECT_EQ(2, last_vp9_.temporal_idx);
1974 EXPECT_TRUE(vp9.temporal_up_switch);
1975 break;
1976 case 2:
1977 EXPECT_EQ(last_vp9_.temporal_idx == 0, vp9.temporal_up_switch);
1978 break;
1979 }
1980 }
1981 }
1982
1983 void VerifyTl0Idx(const RTPVideoHeaderVP9& vp9) const {
1984 if (vp9.tl0_pic_idx == kNoTl0PicIdx)
1985 return;
1986
1987 uint8_t expected_tl0_idx = last_vp9_.tl0_pic_idx;
1988 if (vp9.temporal_idx == 0)
1989 ++expected_tl0_idx;
1990 EXPECT_EQ(expected_tl0_idx, vp9.tl0_pic_idx);
1991 }
1992
1993 bool IsNewPictureId(const RTPVideoHeaderVP9& vp9) const {
1994 return frames_sent_ > 0 && (vp9.picture_id != last_vp9_.picture_id);
1995 }
1996
1997 // Flexible mode (F=1): Non-flexible mode (F=0):
1998 //
1999 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2000 // |I|P|L|F|B|E|V|-| |I|P|L|F|B|E|V|-|
2001 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2002 // I: |M| PICTURE ID | I: |M| PICTURE ID |
2003 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2004 // M: | EXTENDED PID | M: | EXTENDED PID |
2005 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2006 // L: | T |U| S |D| L: | T |U| S |D|
2007 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2008 // P,F: | P_DIFF |X|N| | TL0PICIDX |
2009 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2010 // X: |EXTENDED P_DIFF| V: | SS .. |
2011 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2012 // V: | SS .. |
2013 // +-+-+-+-+-+-+-+-+
2014 void VerifyCommonHeader(const RTPVideoHeaderVP9& vp9) const {
2015 EXPECT_EQ(kMaxTwoBytePictureId, vp9.max_picture_id); // M:1
2016 EXPECT_NE(kNoPictureId, vp9.picture_id); // I:1
2017 EXPECT_EQ(vp9_settings_.flexibleMode, vp9.flexible_mode); // F
2018 EXPECT_GE(vp9.spatial_idx, 0); // S
2019 EXPECT_LT(vp9.spatial_idx, vp9_settings_.numberOfSpatialLayers);
2020 if (vp9.ss_data_available) // V
2021 VerifySsData(vp9);
2022
2023 if (frames_sent_ == 0)
2024 EXPECT_FALSE(vp9.inter_pic_predicted); // P
2025
2026 if (!vp9.inter_pic_predicted) {
2027 EXPECT_TRUE(vp9.temporal_idx == 0 || vp9.temporal_idx == kNoTemporalIdx);
2028 EXPECT_FALSE(vp9.temporal_up_switch);
2029 }
2030 }
2031
2032 // Scalability structure (SS).
2033 //
2034 // +-+-+-+-+-+-+-+-+
2035 // V: | N_S |Y|G|-|-|-|
2036 // +-+-+-+-+-+-+-+-+
2037 // Y: | WIDTH | N_S + 1 times
2038 // +-+-+-+-+-+-+-+-+
2039 // | HEIGHT |
2040 // +-+-+-+-+-+-+-+-+
2041 // G: | N_G |
2042 // +-+-+-+-+-+-+-+-+
2043 // N_G: | T |U| R |-|-| N_G times
2044 // +-+-+-+-+-+-+-+-+
2045 // | P_DIFF | R times
2046 // +-+-+-+-+-+-+-+-+
2047 void VerifySsData(const RTPVideoHeaderVP9& vp9) const {
2048 EXPECT_TRUE(vp9.ss_data_available); // V
2049 EXPECT_EQ(vp9_settings_.numberOfSpatialLayers, // N_S + 1
2050 vp9.num_spatial_layers);
2051 EXPECT_TRUE(vp9.spatial_layer_resolution_present); // Y:1
2052 size_t expected_width = encoder_config_.streams[0].width;
2053 size_t expected_height = encoder_config_.streams[0].height;
2054 for (int i = vp9.num_spatial_layers - 1; i >= 0; --i) {
2055 EXPECT_EQ(expected_width, vp9.width[i]); // WIDTH
2056 EXPECT_EQ(expected_height, vp9.height[i]); // HEIGHT
2057 expected_width /= 2;
2058 expected_height /= 2;
2059 }
2060 }
2061
2062 void CompareConsecutiveFrames(const RTPHeader& header,
2063 const RTPVideoHeader& video) const {
2064 const RTPVideoHeaderVP9& vp9 = video.codecHeader.VP9;
2065
2066 bool new_frame = packets_sent_ == 0 ||
2067 IsNewerTimestamp(header.timestamp, last_header_.timestamp);
2068 EXPECT_EQ(new_frame, video.isFirstPacket);
2069 if (!new_frame) {
2070 EXPECT_FALSE(last_header_.markerBit);
2071 EXPECT_EQ(last_header_.timestamp, header.timestamp);
2072 EXPECT_EQ(last_vp9_.picture_id, vp9.picture_id);
2073 EXPECT_EQ(last_vp9_.temporal_idx, vp9.temporal_idx);
2074 EXPECT_EQ(last_vp9_.tl0_pic_idx, vp9.tl0_pic_idx);
2075 VerifySpatialIdxWithinFrame(vp9);
2076 return;
2077 }
2078 // New frame.
2079 EXPECT_TRUE(vp9.beginning_of_frame);
2080
2081 // Compare with last packet in previous frame.
2082 if (frames_sent_ == 0)
2083 return;
2084 EXPECT_TRUE(last_vp9_.end_of_frame);
2085 EXPECT_TRUE(last_header_.markerBit);
2086 EXPECT_TRUE(ContinuousPictureId(vp9));
2087 VerifyTl0Idx(vp9);
2088 }
2089
philipel7fabd462015-09-03 04:42:32 -07002090 rtc::scoped_ptr<VP9Encoder> vp9_encoder_;
philipel0f9af012015-09-01 07:01:51 -07002091 VideoCodecVP9 vp9_settings_;
Åsa Perssonff24c042015-12-04 10:58:08 +01002092 webrtc::VideoEncoderConfig encoder_config_;
2093 RTPHeader last_header_;
2094 RTPVideoHeaderVP9 last_vp9_;
2095 size_t packets_sent_;
2096 size_t frames_sent_;
philipel0f9af012015-09-01 07:01:51 -07002097};
2098
Åsa Perssonff24c042015-12-04 10:58:08 +01002099TEST_F(VideoSendStreamTest, Vp9NonFlexMode_1Tl1SLayers) {
2100 const uint8_t kNumTemporalLayers = 1;
2101 const uint8_t kNumSpatialLayers = 1;
2102 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2103}
2104
2105TEST_F(VideoSendStreamTest, Vp9NonFlexMode_2Tl1SLayers) {
2106 const uint8_t kNumTemporalLayers = 2;
2107 const uint8_t kNumSpatialLayers = 1;
2108 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2109}
2110
2111TEST_F(VideoSendStreamTest, Vp9NonFlexMode_3Tl1SLayers) {
2112 const uint8_t kNumTemporalLayers = 3;
2113 const uint8_t kNumSpatialLayers = 1;
2114 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2115}
2116
2117TEST_F(VideoSendStreamTest, Vp9NonFlexMode_1Tl2SLayers) {
2118 const uint8_t kNumTemporalLayers = 1;
2119 const uint8_t kNumSpatialLayers = 2;
2120 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2121}
2122
2123TEST_F(VideoSendStreamTest, Vp9NonFlexMode_2Tl2SLayers) {
2124 const uint8_t kNumTemporalLayers = 2;
2125 const uint8_t kNumSpatialLayers = 2;
2126 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2127}
2128
2129TEST_F(VideoSendStreamTest, Vp9NonFlexMode_3Tl2SLayers) {
2130 const uint8_t kNumTemporalLayers = 3;
2131 const uint8_t kNumSpatialLayers = 2;
2132 TestVp9NonFlexMode(kNumTemporalLayers, kNumSpatialLayers);
2133}
2134
2135void VideoSendStreamTest::TestVp9NonFlexMode(uint8_t num_temporal_layers,
2136 uint8_t num_spatial_layers) {
2137 static const size_t kNumFramesToSend = 100;
2138 // Set to < kNumFramesToSend and coprime to length of temporal layer
2139 // structures to verify temporal id reset on key frame.
2140 static const int kKeyFrameInterval = 31;
2141 class NonFlexibleMode : public Vp9HeaderObserver {
2142 public:
2143 NonFlexibleMode(uint8_t num_temporal_layers, uint8_t num_spatial_layers)
2144 : num_temporal_layers_(num_temporal_layers),
2145 num_spatial_layers_(num_spatial_layers),
2146 l_field_(num_temporal_layers > 1 || num_spatial_layers > 1) {}
philipel0f9af012015-09-01 07:01:51 -07002147 void ModifyConfigsHook(
2148 VideoSendStream::Config* send_config,
2149 std::vector<VideoReceiveStream::Config>* receive_configs,
2150 VideoEncoderConfig* encoder_config) override {
Åsa Perssonff24c042015-12-04 10:58:08 +01002151 vp9_settings_.flexibleMode = false;
2152 vp9_settings_.frameDroppingOn = false;
2153 vp9_settings_.keyFrameInterval = kKeyFrameInterval;
2154 vp9_settings_.numberOfTemporalLayers = num_temporal_layers_;
2155 vp9_settings_.numberOfSpatialLayers = num_spatial_layers_;
philipel0f9af012015-09-01 07:01:51 -07002156 }
2157
Åsa Perssonff24c042015-12-04 10:58:08 +01002158 void InspectHeader(const RTPVideoHeaderVP9& vp9) override {
2159 bool ss_data_expected = !vp9.inter_pic_predicted &&
2160 vp9.beginning_of_frame && vp9.spatial_idx == 0;
2161 EXPECT_EQ(ss_data_expected, vp9.ss_data_available);
2162 EXPECT_EQ(vp9.spatial_idx > 0, vp9.inter_layer_predicted); // D
2163
2164 if (IsNewPictureId(vp9)) {
2165 EXPECT_EQ(0, vp9.spatial_idx);
2166 EXPECT_EQ(num_spatial_layers_ - 1, last_vp9_.spatial_idx);
2167 }
2168
2169 VerifyFixedTemporalLayerStructure(vp9,
2170 l_field_ ? num_temporal_layers_ : 0);
2171
2172 if (frames_sent_ > kNumFramesToSend)
Peter Boström5811a392015-12-10 13:02:50 +01002173 observation_complete_.Set();
philipel0f9af012015-09-01 07:01:51 -07002174 }
Åsa Perssonff24c042015-12-04 10:58:08 +01002175 const uint8_t num_temporal_layers_;
2176 const uint8_t num_spatial_layers_;
2177 const bool l_field_;
2178 } test(num_temporal_layers, num_spatial_layers);
philipelcfc319b2015-11-10 07:17:23 -08002179
2180 RunBaseTest(&test, FakeNetworkPipe::Config());
2181}
2182
Åsa Perssonff24c042015-12-04 10:58:08 +01002183TEST_F(VideoSendStreamTest, Vp9FlexModeRefCount) {
2184 class FlexibleMode : public Vp9HeaderObserver {
philipelcfc319b2015-11-10 07:17:23 -08002185 void ModifyConfigsHook(
2186 VideoSendStream::Config* send_config,
2187 std::vector<VideoReceiveStream::Config>* receive_configs,
2188 VideoEncoderConfig* encoder_config) override {
Åsa Perssonff24c042015-12-04 10:58:08 +01002189 encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
philipelcfc319b2015-11-10 07:17:23 -08002190 vp9_settings_.flexibleMode = true;
Åsa Perssonff24c042015-12-04 10:58:08 +01002191 vp9_settings_.numberOfTemporalLayers = 1;
2192 vp9_settings_.numberOfSpatialLayers = 2;
philipelcfc319b2015-11-10 07:17:23 -08002193 }
2194
Åsa Perssonff24c042015-12-04 10:58:08 +01002195 void InspectHeader(const RTPVideoHeaderVP9& vp9_header) override {
2196 EXPECT_TRUE(vp9_header.flexible_mode);
2197 EXPECT_EQ(kNoTl0PicIdx, vp9_header.tl0_pic_idx);
2198 if (vp9_header.inter_pic_predicted) {
2199 EXPECT_GT(vp9_header.num_ref_pics, 0u);
Peter Boström5811a392015-12-10 13:02:50 +01002200 observation_complete_.Set();
philipelcfc319b2015-11-10 07:17:23 -08002201 }
2202 }
2203 } test;
2204
2205 RunBaseTest(&test, FakeNetworkPipe::Config());
2206}
2207
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +00002208} // namespace webrtc