blob: 746b140a0d0932aff2e1ddd91ca7d1de8d4dd12b [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
11
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000012#include "testing/gtest/include/gtest/gtest.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000013
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000014#include "webrtc/base/scoped_ptr.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000015#include "webrtc/call.h"
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +000016#include "webrtc/common_video/interface/i420_video_frame.h"
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000017#include "webrtc/common_video/interface/native_handle.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000018#include "webrtc/frame_callback.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000019#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000020#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000021#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
pbos@webrtc.org013d9942013-08-22 09:42:17 +000022#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +000023#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000024#include "webrtc/system_wrappers/interface/event_wrapper.h"
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000025#include "webrtc/system_wrappers/interface/ref_count.h"
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000026#include "webrtc/system_wrappers/interface/scoped_vector.h"
pbos@webrtc.org29023282013-09-11 10:14:56 +000027#include "webrtc/system_wrappers/interface/sleep.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000028#include "webrtc/system_wrappers/interface/thread_wrapper.h"
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000029#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000030#include "webrtc/test/call_test.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000031#include "webrtc/test/configurable_frame_size_encoder.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000032#include "webrtc/test/null_transport.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000033#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.org273a4142014-12-01 15:23:21 +000034#include "webrtc/video/send_statistics_proxy.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000035#include "webrtc/video/transport_adapter.h"
36#include "webrtc/video_send_stream.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000037
38namespace webrtc {
39
sprang@webrtc.org346094c2014-02-18 08:40:33 +000040enum VideoFormat { kGeneric, kVP8, };
41
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000042void ExpectEqualFrames(const I420VideoFrame& frame1,
43 const I420VideoFrame& frame2);
44void ExpectEqualTextureFrames(const I420VideoFrame& frame1,
45 const I420VideoFrame& frame2);
46void ExpectEqualBufferFrames(const I420VideoFrame& frame1,
47 const I420VideoFrame& frame2);
48void ExpectEqualFramesVector(const std::vector<I420VideoFrame*>& frames1,
49 const std::vector<I420VideoFrame*>& frames2);
50I420VideoFrame* CreateI420VideoFrame(int width, int height, uint8_t data);
51
52class FakeNativeHandle : public NativeHandle {
53 public:
54 FakeNativeHandle() {}
55 virtual ~FakeNativeHandle() {}
56 virtual void* GetHandle() { return NULL; }
57};
58
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000059class VideoSendStreamTest : public test::CallTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000060 protected:
stefan@webrtc.org69969e22013-11-15 12:32:15 +000061 void TestNackRetransmission(uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +000062 uint8_t retransmit_payload_type);
sprang@webrtc.org346094c2014-02-18 08:40:33 +000063 void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
pbos@webrtc.org013d9942013-08-22 09:42:17 +000064};
65
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000066TEST_F(VideoSendStreamTest, CanStartStartedStream) {
67 test::NullTransport transport;
68 Call::Config call_config(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000069 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000070
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000071 CreateSendConfig(1);
72 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) {
79 test::NullTransport transport;
80 Call::Config call_config(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000081 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000082
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000083 CreateSendConfig(1);
84 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();
102 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
103 if (packet_type == RTCPUtility::kRtcpSdesChunkCode) {
104 EXPECT_EQ(parser.Packet().CName.CName, kCName);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000105 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 {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000121 EXPECT_EQ(kEventSignaled, Wait())
122 << "Timed out while waiting for RTCP with CNAME.";
123 }
124 } test;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000125
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000126 RunBaseTest(&test);
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000127}
128
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000129TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
130 static const uint8_t kAbsSendTimeExtensionId = 13;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000131 class AbsoluteSendTimeObserver : public test::SendTest {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000132 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000133 AbsoluteSendTimeObserver() : SendTest(kDefaultTimeoutMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000134 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000135 kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId));
136 }
137
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000138 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000139 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000140 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000141
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000142 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
143 EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
144 EXPECT_EQ(header.extension.transmissionTimeOffset, 0);
145 EXPECT_GT(header.extension.absoluteSendTime, 0u);
146 observation_complete_->Set();
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000147
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000148 return SEND_PACKET;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000149 }
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000150
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000151 void ModifyConfigs(VideoSendStream::Config* send_config,
152 std::vector<VideoReceiveStream::Config>* receive_configs,
153 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000154 send_config->rtp.extensions.push_back(
155 RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
156 }
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +0000157
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000158 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000159 EXPECT_EQ(kEventSignaled, Wait())
160 << "Timed out while waiting for single RTP packet.";
161 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000162 } test;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000163
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000164 RunBaseTest(&test);
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000165}
166
pbos@webrtc.org29023282013-09-11 10:14:56 +0000167TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
168 static const uint8_t kTOffsetExtensionId = 13;
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000169 static const int kEncodeDelayMs = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000170 class TransmissionTimeOffsetObserver : public test::SendTest {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000171 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000172 TransmissionTimeOffsetObserver()
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000173 : SendTest(kDefaultTimeoutMs),
174 encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000175 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
pbos@webrtc.org29023282013-09-11 10:14:56 +0000176 kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId));
177 }
178
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000179 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000180 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000181 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000182 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000183
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000184 EXPECT_TRUE(header.extension.hasTransmissionTimeOffset);
185 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000186 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000187 EXPECT_EQ(header.extension.absoluteSendTime, 0u);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000188 observation_complete_->Set();
pbos@webrtc.org29023282013-09-11 10:14:56 +0000189
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000190 return SEND_PACKET;
pbos@webrtc.org29023282013-09-11 10:14:56 +0000191 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000192
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000193 void ModifyConfigs(VideoSendStream::Config* send_config,
194 std::vector<VideoReceiveStream::Config>* receive_configs,
195 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000196 send_config->encoder_settings.encoder = &encoder_;
197 send_config->rtp.extensions.push_back(
198 RtpExtension(RtpExtension::kTOffset, kTOffsetExtensionId));
199 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000200
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000201 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000202 EXPECT_EQ(kEventSignaled, Wait())
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +0000203 << "Timed out while waiting for a single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000204 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000205
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000206 test::DelayedEncoder encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000207 } test;
208
209 RunBaseTest(&test);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000210}
211
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000212class FakeReceiveStatistics : public NullReceiveStatistics {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000213 public:
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000214 FakeReceiveStatistics(uint32_t send_ssrc,
215 uint32_t last_sequence_number,
216 uint32_t cumulative_lost,
217 uint8_t fraction_lost)
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000218 : lossy_stats_(new LossyStatistician(last_sequence_number,
219 cumulative_lost,
220 fraction_lost)) {
221 stats_map_[send_ssrc] = lossy_stats_.get();
222 }
223
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000224 StatisticianMap GetActiveStatisticians() const override { return stats_map_; }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000225
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000226 StreamStatistician* GetStatistician(uint32_t ssrc) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000227 return lossy_stats_.get();
228 }
229
230 private:
231 class LossyStatistician : public StreamStatistician {
232 public:
233 LossyStatistician(uint32_t extended_max_sequence_number,
234 uint32_t cumulative_lost,
235 uint8_t fraction_lost) {
236 stats_.fraction_lost = fraction_lost;
237 stats_.cumulative_lost = cumulative_lost;
238 stats_.extended_max_sequence_number = extended_max_sequence_number;
239 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000240 bool GetStatistics(RtcpStatistics* statistics, bool reset) override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000241 *statistics = stats_;
242 return true;
243 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000244 void GetDataCounters(size_t* bytes_received,
245 uint32_t* packets_received) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000246 *bytes_received = 0;
247 *packets_received = 0;
248 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000249 void GetReceiveStreamDataCounters(
250 StreamDataCounters* data_counters) const override {}
251 uint32_t BitrateReceived() const override { return 0; }
252 void ResetStatistics() override {}
253 bool IsRetransmitOfOldPacket(const RTPHeader& header,
254 int64_t min_rtt) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000255 return false;
256 }
257
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000258 bool IsPacketInOrder(uint16_t sequence_number) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000259 return true;
260 }
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000261
262 RtcpStatistics stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000263 };
264
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000265 rtc::scoped_ptr<LossyStatistician> lossy_stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000266 StatisticianMap stats_map_;
267};
268
269TEST_F(VideoSendStreamTest, SupportsFec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000270 class FecObserver : public test::SendTest {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000271 public:
272 FecObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000273 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000274 transport_adapter_(SendTransport()),
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000275 send_count_(0),
276 received_media_(false),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000277 received_fec_(false) {
278 transport_adapter_.Enable();
279 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000280
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000281 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000282 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000283 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000284 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000285
286 // Send lossy receive reports to trigger FEC enabling.
287 if (send_count_++ % 2 != 0) {
288 // Receive statistics reporting having lost 50% of the packets.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000289 FakeReceiveStatistics lossy_receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000290 kSendSsrcs[0], header.sequenceNumber, send_count_ / 2, 127);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000291 RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(),
292 &lossy_receive_stats, nullptr);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000293 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
294
295 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000296 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000297
298 RTCPSender::FeedbackState feedback_state;
299
300 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
301 }
302
303 EXPECT_EQ(kRedPayloadType, header.payloadType);
304
305 uint8_t encapsulated_payload_type = packet[header.headerLength];
306
307 if (encapsulated_payload_type == kUlpfecPayloadType) {
308 received_fec_ = true;
309 } else {
310 received_media_ = true;
311 }
312
313 if (received_media_ && received_fec_)
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000314 observation_complete_->Set();
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000315
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000316 return SEND_PACKET;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000317 }
318
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000319 void ModifyConfigs(VideoSendStream::Config* send_config,
320 std::vector<VideoReceiveStream::Config>* receive_configs,
321 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000322 send_config->rtp.fec.red_payload_type = kRedPayloadType;
323 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
324 }
325
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000326 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000327 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
328 }
329
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000330 internal::TransportAdapter transport_adapter_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000331 int send_count_;
332 bool received_media_;
333 bool received_fec_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000334 } test;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000335
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000336 RunBaseTest(&test);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000337}
338
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000339void VideoSendStreamTest::TestNackRetransmission(
340 uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000341 uint8_t retransmit_payload_type) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000342 class NackObserver : public test::SendTest {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000343 public:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000344 explicit NackObserver(uint32_t retransmit_ssrc,
345 uint8_t retransmit_payload_type)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000346 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000347 transport_adapter_(SendTransport()),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000348 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000349 retransmit_ssrc_(retransmit_ssrc),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000350 retransmit_payload_type_(retransmit_payload_type),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000351 nacked_sequence_number_(-1) {
352 transport_adapter_.Enable();
353 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000354
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000355 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000356 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000357 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000358 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000359
360 // Nack second packet after receiving the third one.
361 if (++send_count_ == 3) {
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000362 uint16_t nack_sequence_number = header.sequenceNumber - 1;
363 nacked_sequence_number_ = nack_sequence_number;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000364 NullReceiveStatistics null_stats;
365 RTCPSender rtcp_sender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000366 0, false, Clock::GetRealTimeClock(), &null_stats, nullptr);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000367 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
368
369 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000370 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000371
372 RTCPSender::FeedbackState feedback_state;
373
374 EXPECT_EQ(0,
375 rtcp_sender.SendRTCP(
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000376 feedback_state, kRtcpNack, 1, &nack_sequence_number));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000377 }
378
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000379 uint16_t sequence_number = header.sequenceNumber;
380
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000381 if (header.ssrc == retransmit_ssrc_ &&
382 retransmit_ssrc_ != kSendSsrcs[0]) {
383 // Not kSendSsrcs[0], assume correct RTX packet. Extract sequence
384 // number.
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000385 const uint8_t* rtx_header = packet + header.headerLength;
386 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
387 }
388
389 if (sequence_number == nacked_sequence_number_) {
390 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000391 EXPECT_EQ(retransmit_payload_type_, header.payloadType);
392 observation_complete_->Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000393 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000394
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000395 return SEND_PACKET;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000396 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000397
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000398 void ModifyConfigs(VideoSendStream::Config* send_config,
399 std::vector<VideoReceiveStream::Config>* receive_configs,
400 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000401 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000402 send_config->rtp.rtx.payload_type = retransmit_payload_type_;
403 if (retransmit_ssrc_ != kSendSsrcs[0])
404 send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
405 }
406
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000407 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000408 EXPECT_EQ(kEventSignaled, Wait())
409 << "Timed out while waiting for NACK retransmission.";
410 }
411
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000412 internal::TransportAdapter transport_adapter_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000413 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000414 uint32_t retransmit_ssrc_;
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000415 uint8_t retransmit_payload_type_;
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000416 int nacked_sequence_number_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000417 } test(retransmit_ssrc, retransmit_payload_type);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000418
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000419 RunBaseTest(&test);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000420}
421
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000422TEST_F(VideoSendStreamTest, RetransmitsNack) {
423 // Normal NACKs should use the send SSRC.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000424 TestNackRetransmission(kSendSsrcs[0], kFakeSendPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000425}
426
427TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
428 // NACKs over RTX should use a separate SSRC.
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000429 TestNackRetransmission(kSendRtxSsrcs[0], kSendRtxPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000430}
431
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000432void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
433 bool with_fec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000434 // Use a fake encoder to output a frame of every size in the range [90, 290],
435 // for each size making sure that the exact number of payload bytes received
436 // is correct and that packets are fragmented to respect max packet size.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000437 static const size_t kMaxPacketSize = 128;
438 static const size_t start = 90;
439 static const size_t stop = 290;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000440
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000441 // Observer that verifies that the expected number of packets and bytes
442 // arrive for each frame size, from start_size to stop_size.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000443 class FrameFragmentationTest : public test::SendTest,
444 public EncodedFrameObserver {
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000445 public:
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000446 FrameFragmentationTest(size_t max_packet_size,
447 size_t start_size,
448 size_t stop_size,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000449 bool test_generic_packetization,
450 bool use_fec)
451 : SendTest(kLongTimeoutMs),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000452 transport_adapter_(SendTransport()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000453 encoder_(stop),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000454 max_packet_size_(max_packet_size),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000455 stop_size_(stop_size),
456 test_generic_packetization_(test_generic_packetization),
457 use_fec_(use_fec),
458 packet_count_(0),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000459 accumulated_size_(0),
460 accumulated_payload_(0),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000461 fec_packet_received_(false),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000462 current_size_rtp_(start_size),
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000463 current_size_frame_(static_cast<int32_t>(start_size)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000464 // Fragmentation required, this test doesn't make sense without it.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000465 encoder_.SetFrameSize(start_size);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000466 assert(stop_size > max_packet_size);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000467 transport_adapter_.Enable();
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000468 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000469
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000470 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000471 Action OnSendRtp(const uint8_t* packet, size_t size) override {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000472 size_t length = size;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000473 RTPHeader header;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000474 EXPECT_TRUE(parser_->Parse(packet, length, &header));
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000475
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000476 EXPECT_LE(length, max_packet_size_);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000477
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000478 if (use_fec_) {
479 uint8_t payload_type = packet[header.headerLength];
480 bool is_fec = header.payloadType == kRedPayloadType &&
481 payload_type == kUlpfecPayloadType;
482 if (is_fec) {
483 fec_packet_received_ = true;
484 return SEND_PACKET;
485 }
486 }
487
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000488 accumulated_size_ += length;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000489
490 if (use_fec_)
491 TriggerLossReport(header);
492
493 if (test_generic_packetization_) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000494 size_t overhead = header.headerLength + header.paddingLength +
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000495 (1 /* Generic header */);
496 if (use_fec_)
497 overhead += 1; // RED for FEC header.
498 accumulated_payload_ += length - overhead;
499 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000500
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000501 // Marker bit set indicates last packet of a frame.
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000502 if (header.markerBit) {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000503 if (use_fec_ && accumulated_payload_ == current_size_rtp_ - 1) {
504 // With FEC enabled, frame size is incremented asynchronously, so
505 // "old" frames one byte too small may arrive. Accept, but don't
506 // increase expected frame size.
507 accumulated_size_ = 0;
508 accumulated_payload_ = 0;
509 return SEND_PACKET;
510 }
511
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000512 EXPECT_GE(accumulated_size_, current_size_rtp_);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000513 if (test_generic_packetization_) {
514 EXPECT_EQ(current_size_rtp_, accumulated_payload_);
515 }
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000516
517 // Last packet of frame; reset counters.
518 accumulated_size_ = 0;
519 accumulated_payload_ = 0;
520 if (current_size_rtp_ == stop_size_) {
521 // Done! (Don't increase size again, might arrive more @ stop_size).
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000522 observation_complete_->Set();
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000523 } else {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000524 // Increase next expected frame size. If testing with FEC, make sure
525 // a FEC packet has been received for this frame size before
526 // proceeding, to make sure that redundancy packets don't exceed
527 // size limit.
528 if (!use_fec_) {
529 ++current_size_rtp_;
530 } else if (fec_packet_received_) {
531 fec_packet_received_ = false;
532 ++current_size_rtp_;
533 ++current_size_frame_;
534 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000535 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000536 }
537
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000538 return SEND_PACKET;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000539 }
540
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000541 void TriggerLossReport(const RTPHeader& header) {
542 // Send lossy receive reports to trigger FEC enabling.
543 if (packet_count_++ % 2 != 0) {
544 // Receive statistics reporting having lost 50% of the packets.
545 FakeReceiveStatistics lossy_receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000546 kSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000547 RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(),
548 &lossy_receive_stats, nullptr);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000549 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
550
551 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000552 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000553
554 RTCPSender::FeedbackState feedback_state;
555
556 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
557 }
558 }
559
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000560 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
561 // Increase frame size for next encoded frame, in the context of the
562 // encoder thread.
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000563 if (!use_fec_ &&
564 current_size_frame_.Value() < static_cast<int32_t>(stop_size_)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000565 ++current_size_frame_;
566 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000567 encoder_.SetFrameSize(static_cast<size_t>(current_size_frame_.Value()));
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000568 }
569
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000570 void ModifyConfigs(VideoSendStream::Config* send_config,
571 std::vector<VideoReceiveStream::Config>* receive_configs,
572 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000573 if (use_fec_) {
574 send_config->rtp.fec.red_payload_type = kRedPayloadType;
575 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
576 }
577
578 if (!test_generic_packetization_)
579 send_config->encoder_settings.payload_name = "VP8";
580
581 send_config->encoder_settings.encoder = &encoder_;
582 send_config->rtp.max_packet_size = kMaxPacketSize;
583 send_config->post_encode_callback = this;
584
585 // Add an extension header, to make the RTP header larger than the base
586 // length of 12 bytes.
587 static const uint8_t kAbsSendTimeExtensionId = 13;
588 send_config->rtp.extensions.push_back(
589 RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
590 }
591
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000592 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000593 EXPECT_EQ(kEventSignaled, Wait())
594 << "Timed out while observing incoming RTP packets.";
595 }
596
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000597 internal::TransportAdapter transport_adapter_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000598 test::ConfigurableFrameSizeEncoder encoder_;
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000599
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000600 const size_t max_packet_size_;
601 const size_t stop_size_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000602 const bool test_generic_packetization_;
603 const bool use_fec_;
604
605 uint32_t packet_count_;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000606 size_t accumulated_size_;
607 size_t accumulated_payload_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000608 bool fec_packet_received_;
609
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000610 size_t current_size_rtp_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000611 Atomic32 current_size_frame_;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000612 };
613
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000614 // Don't auto increment if FEC is used; continue sending frame size until
615 // a FEC packet has been received.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000616 FrameFragmentationTest test(
617 kMaxPacketSize, start, stop, format == kGeneric, with_fec);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000618
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000619 RunBaseTest(&test);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000620}
621
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000622// TODO(sprang): Is there any way of speeding up these tests?
623TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSize) {
624 TestPacketFragmentationSize(kGeneric, false);
625}
626
627TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSizeWithFec) {
628 TestPacketFragmentationSize(kGeneric, true);
629}
630
631TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSize) {
632 TestPacketFragmentationSize(kVP8, false);
633}
634
635TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSizeWithFec) {
636 TestPacketFragmentationSize(kVP8, true);
637}
638
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000639// The test will go through a number of phases.
640// 1. Start sending packets.
641// 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 +0000642// suspend the stream.
643// 3. Wait until |kSuspendTimeFrames| have been captured without seeing any RTP
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000644// packets.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000645// 4. Signal a high REMB and then wait for the RTP stream to start again.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000646// When the stream is detected again, and the stats show that the stream
647// is no longer suspended, the test ends.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000648TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
649 static const int kSuspendTimeFrames = 60; // Suspend for 2 seconds @ 30 fps.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000650
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000651 class RembObserver : public test::SendTest, public I420FrameCallback {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000652 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000653 RembObserver()
654 : SendTest(kDefaultTimeoutMs),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000655 transport_adapter_(&transport_),
656 clock_(Clock::GetRealTimeClock()),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000657 crit_(CriticalSectionWrapper::CreateCriticalSection()),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000658 test_state_(kBeforeSuspend),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000659 rtp_count_(0),
660 last_sequence_number_(0),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000661 suspended_frame_count_(0),
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000662 low_remb_bps_(0),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000663 high_remb_bps_(0) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000664 transport_adapter_.Enable();
665 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000666
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000667 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000668 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000669 // Receive statistics reporting having lost 0% of the packets.
670 // This is needed for the send-side bitrate controller to work properly.
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000671 CriticalSectionScoped lock(crit_.get());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000672 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000673 return SEND_PACKET;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000674 }
675
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000676 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000677 CriticalSectionScoped lock(crit_.get());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000678 ++rtp_count_;
679 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000680 EXPECT_TRUE(parser_->Parse(packet, length, &header));
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000681 last_sequence_number_ = header.sequenceNumber;
682
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000683 if (test_state_ == kBeforeSuspend) {
684 // The stream has started. Try to suspend it.
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000685 SendRtcpFeedback(low_remb_bps_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000686 test_state_ = kDuringSuspend;
687 } else if (test_state_ == kDuringSuspend) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000688 if (header.paddingLength == 0) {
689 // Received non-padding packet during suspension period. Reset the
690 // counter.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000691 suspended_frame_count_ = 0;
692 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000693 } else if (test_state_ == kWaitingForPacket) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000694 if (header.paddingLength == 0) {
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000695 // Non-padding packet observed. Test is almost complete. Will just
696 // have to wait for the stats to change.
697 test_state_ = kWaitingForStats;
698 }
699 } else if (test_state_ == kWaitingForStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000700 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000701 if (stats.suspended == false) {
702 // Stats flipped to false. Test is complete.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000703 observation_complete_->Set();
704 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000705 }
706
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000707 return SEND_PACKET;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000708 }
709
710 // This method implements the I420FrameCallback.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000711 void FrameCallback(I420VideoFrame* video_frame) override {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000712 CriticalSectionScoped lock(crit_.get());
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000713 if (test_state_ == kDuringSuspend &&
714 ++suspended_frame_count_ > kSuspendTimeFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000715 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000716 EXPECT_TRUE(stats.suspended);
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000717 SendRtcpFeedback(high_remb_bps_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000718 test_state_ = kWaitingForPacket;
719 }
720 }
721
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000722 void set_low_remb_bps(int value) {
723 CriticalSectionScoped lock(crit_.get());
724 low_remb_bps_ = value;
725 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000726
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000727 void set_high_remb_bps(int value) {
728 CriticalSectionScoped lock(crit_.get());
729 high_remb_bps_ = value;
730 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000731
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000732 void SetReceivers(PacketReceiver* send_transport_receiver,
733 PacketReceiver* receive_transport_receiver) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000734 transport_.SetReceiver(send_transport_receiver);
735 }
pbos@webrtc.orgdef22b42013-10-29 10:12:10 +0000736
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000737 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000738 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000739 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000740 stream_ = send_stream;
741 }
742
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000743 void ModifyConfigs(VideoSendStream::Config* send_config,
744 std::vector<VideoReceiveStream::Config>* receive_configs,
745 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000746 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000747 send_config->pre_encode_callback = this;
748 send_config->suspend_below_min_bitrate = true;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000749 int min_bitrate_bps = encoder_config->streams[0].min_bitrate_bps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000750 set_low_remb_bps(min_bitrate_bps - 10000);
751 int threshold_window = std::max(min_bitrate_bps / 10, 10000);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000752 ASSERT_GT(encoder_config->streams[0].max_bitrate_bps,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000753 min_bitrate_bps + threshold_window + 5000);
754 set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
755 }
756
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000757 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000758 EXPECT_EQ(kEventSignaled, Wait())
759 << "Timed out during suspend-below-min-bitrate test.";
760 transport_.StopSending();
761 }
762
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000763 enum TestState {
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000764 kBeforeSuspend,
765 kDuringSuspend,
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000766 kWaitingForPacket,
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000767 kWaitingForStats
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000768 };
769
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000770 virtual void SendRtcpFeedback(int remb_value)
771 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000772 FakeReceiveStatistics receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000773 kSendSsrcs[0], last_sequence_number_, rtp_count_, 0);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000774 RTCPSender rtcp_sender(0, false, clock_, &receive_stats, nullptr);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000775 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
776
777 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000778 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000779 if (remb_value > 0) {
780 rtcp_sender.SetREMBStatus(true);
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000781 rtcp_sender.SetREMBData(remb_value, std::vector<uint32_t>());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000782 }
783 RTCPSender::FeedbackState feedback_state;
784 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
785 }
786
787 internal::TransportAdapter transport_adapter_;
788 test::DirectTransport transport_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000789 Clock* const clock_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000790 VideoSendStream* stream_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000791
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000792 const rtc::scoped_ptr<CriticalSectionWrapper> crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000793 TestState test_state_ GUARDED_BY(crit_);
794 int rtp_count_ GUARDED_BY(crit_);
795 int last_sequence_number_ GUARDED_BY(crit_);
796 int suspended_frame_count_ GUARDED_BY(crit_);
797 int low_remb_bps_ GUARDED_BY(crit_);
798 int high_remb_bps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000799 } test;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000800
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000801 RunBaseTest(&test);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000802}
803
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000804TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000805 class NoPaddingWhenVideoIsMuted : public test::SendTest {
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000806 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000807 NoPaddingWhenVideoIsMuted()
808 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000809 clock_(Clock::GetRealTimeClock()),
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000810 transport_adapter_(ReceiveTransport()),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000811 crit_(CriticalSectionWrapper::CreateCriticalSection()),
812 last_packet_time_ms_(-1),
813 capturer_(NULL) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000814 transport_adapter_.Enable();
815 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000816
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000817 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000818 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000819 CriticalSectionScoped lock(crit_.get());
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000820 last_packet_time_ms_ = clock_->TimeInMilliseconds();
821 capturer_->Stop();
822 return SEND_PACKET;
823 }
824
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000825 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000826 CriticalSectionScoped lock(crit_.get());
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000827 const int kVideoMutedThresholdMs = 10000;
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000828 if (last_packet_time_ms_ > 0 &&
829 clock_->TimeInMilliseconds() - last_packet_time_ms_ >
830 kVideoMutedThresholdMs)
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000831 observation_complete_->Set();
832 // Receive statistics reporting having lost 50% of the packets.
833 FakeReceiveStatistics receive_stats(kSendSsrcs[0], 1, 1, 0);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000834 RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(),
835 &receive_stats, nullptr);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000836 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
837
838 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
839 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
840
841 RTCPSender::FeedbackState feedback_state;
842
843 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
844 return SEND_PACKET;
845 }
846
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000847 void SetReceivers(PacketReceiver* send_transport_receiver,
848 PacketReceiver* receive_transport_receiver) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000849 RtpRtcpObserver::SetReceivers(send_transport_receiver,
850 send_transport_receiver);
851 }
852
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000853 size_t GetNumStreams() const override { return 3; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000854
855 virtual void OnFrameGeneratorCapturerCreated(
856 test::FrameGeneratorCapturer* frame_generator_capturer) {
857 CriticalSectionScoped lock(crit_.get());
858 capturer_ = frame_generator_capturer;
859 }
860
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000861 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000862 EXPECT_EQ(kEventSignaled, Wait())
863 << "Timed out while waiting for RTP packets to stop being sent.";
864 }
865
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000866 Clock* const clock_;
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000867 internal::TransportAdapter transport_adapter_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000868 const rtc::scoped_ptr<CriticalSectionWrapper> crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000869 int64_t last_packet_time_ms_ GUARDED_BY(crit_);
870 test::FrameGeneratorCapturer* capturer_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000871 } test;
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000872
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000873 RunBaseTest(&test);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000874}
875
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000876// This test first observes "high" bitrate use at which point it sends a REMB to
877// indicate that it should be lowered significantly. The test then observes that
878// the bitrate observed is sinking well below the min-transmit-bitrate threshold
879// to verify that the min-transmit bitrate respects incoming REMB.
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000880//
881// Note that the test starts at "high" bitrate and does not ramp up to "higher"
882// bitrate since no receiver block or remb is sent in the initial phase.
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000883TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
884 static const int kMinTransmitBitrateBps = 400000;
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000885 static const int kHighBitrateBps = 150000;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000886 static const int kRembBitrateBps = 80000;
887 static const int kRembRespectedBitrateBps = 100000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000888 class BitrateObserver : public test::SendTest, public PacketReceiver {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000889 public:
890 BitrateObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000891 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000892 feedback_transport_(ReceiveTransport()),
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000893 bitrate_capped_(false) {
894 RtpRtcp::Configuration config;
895 feedback_transport_.Enable();
896 config.outgoing_transport = &feedback_transport_;
897 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
898 rtp_rtcp_->SetREMBStatus(true);
899 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
900 }
901
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000902 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000903 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000904 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000905 stream_ = send_stream;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000906 }
907
908 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000909 DeliveryStatus DeliverPacket(const uint8_t* packet,
910 size_t length) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000911 if (RtpHeaderParser::IsRtcp(packet, length))
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000912 return DELIVERY_OK;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000913
914 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000915 if (!parser_->Parse(packet, length, &header))
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000916 return DELIVERY_PACKET_ERROR;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000917 assert(stream_ != NULL);
918 VideoSendStream::Stats stats = stream_->GetStats();
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000919 if (!stats.substreams.empty()) {
920 EXPECT_EQ(1u, stats.substreams.size());
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000921 int total_bitrate_bps =
922 stats.substreams.begin()->second.total_bitrate_bps;
923 test::PrintResult("bitrate_stats_",
924 "min_transmit_bitrate_low_remb",
925 "bitrate_bps",
926 static_cast<size_t>(total_bitrate_bps),
927 "bps",
928 false);
929 if (total_bitrate_bps > kHighBitrateBps) {
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000930 rtp_rtcp_->SetREMBData(kRembBitrateBps,
931 std::vector<uint32_t>(1, header.ssrc));
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000932 rtp_rtcp_->Process();
933 bitrate_capped_ = true;
934 } else if (bitrate_capped_ &&
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000935 total_bitrate_bps < kRembRespectedBitrateBps) {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000936 observation_complete_->Set();
937 }
938 }
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000939 return DELIVERY_OK;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000940 }
941
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000942 void SetReceivers(PacketReceiver* send_transport_receiver,
943 PacketReceiver* receive_transport_receiver) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000944 RtpRtcpObserver::SetReceivers(this, send_transport_receiver);
945 }
946
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000947 void ModifyConfigs(VideoSendStream::Config* send_config,
948 std::vector<VideoReceiveStream::Config>* receive_configs,
949 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +0000950 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000951 }
952
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000953 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000954 EXPECT_EQ(kEventSignaled, Wait())
955 << "Timeout while waiting for low bitrate stats after REMB.";
956 }
957
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000958 rtc::scoped_ptr<RtpRtcp> rtp_rtcp_;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000959 internal::TransportAdapter feedback_transport_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000960 VideoSendStream* stream_;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000961 bool bitrate_capped_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000962 } test;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000963
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000964 RunBaseTest(&test);
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000965}
966
pbos@webrtc.org143451d2015-03-18 14:40:03 +0000967TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) {
968 class StartBitrateObserver : public test::FakeEncoder {
969 public:
970 StartBitrateObserver()
971 : FakeEncoder(Clock::GetRealTimeClock()), start_bitrate_kbps_(0) {}
972 int32_t InitEncode(const VideoCodec* config,
973 int32_t number_of_cores,
974 size_t max_payload_size) override {
975 rtc::CritScope lock(&crit_);
976 start_bitrate_kbps_ = config->startBitrate;
977 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
978 }
979
980 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
981 rtc::CritScope lock(&crit_);
982 start_bitrate_kbps_ = new_target_bitrate;
983 return FakeEncoder::SetRates(new_target_bitrate, framerate);
984 }
985
986 int GetStartBitrateKbps() const {
987 rtc::CritScope lock(&crit_);
988 return start_bitrate_kbps_;
989 }
990
991 private:
992 mutable rtc::CriticalSection crit_;
993 int start_bitrate_kbps_ GUARDED_BY(crit_);
994 };
995
996 test::NullTransport transport;
997 CreateSenderCall(Call::Config(&transport));
998
999 CreateSendConfig(1);
1000
1001 Call::Config::BitrateConfig bitrate_config;
1002 bitrate_config.start_bitrate_bps =
1003 2 * encoder_config_.streams[0].max_bitrate_bps;
1004 sender_call_->SetBitrateConfig(bitrate_config);
1005
1006 StartBitrateObserver encoder;
1007 send_config_.encoder_settings.encoder = &encoder;
1008
1009 CreateStreams();
1010
1011 EXPECT_EQ(encoder_config_.streams[0].max_bitrate_bps / 1000,
1012 encoder.GetStartBitrateKbps());
1013
1014 encoder_config_.streams[0].max_bitrate_bps =
1015 2 * bitrate_config.start_bitrate_bps;
1016 send_stream_->ReconfigureVideoEncoder(encoder_config_);
1017
1018 // New bitrate should be reconfigured above the previous max. As there's no
1019 // network connection this shouldn't be flaky, as no bitrate should've been
1020 // reported in between.
1021 EXPECT_EQ(bitrate_config.start_bitrate_bps / 1000,
1022 encoder.GetStartBitrateKbps());
1023
1024 DestroyStreams();
1025}
1026
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001027TEST_F(VideoSendStreamTest, CapturesTextureAndI420VideoFrames) {
1028 class FrameObserver : public I420FrameCallback {
1029 public:
1030 FrameObserver() : output_frame_event_(EventWrapper::Create()) {}
1031
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001032 void FrameCallback(I420VideoFrame* video_frame) override {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001033 // Clone the frame because the caller owns it.
1034 output_frames_.push_back(video_frame->CloneFrame());
1035 output_frame_event_->Set();
1036 }
1037
1038 void WaitOutputFrame() {
1039 const unsigned long kWaitFrameTimeoutMs = 3000;
1040 EXPECT_EQ(kEventSignaled, output_frame_event_->Wait(kWaitFrameTimeoutMs))
1041 << "Timeout while waiting for output frames.";
1042 }
1043
1044 const std::vector<I420VideoFrame*>& output_frames() const {
1045 return output_frames_.get();
1046 }
1047
1048 private:
1049 // Delivered output frames.
1050 ScopedVector<I420VideoFrame> output_frames_;
1051
1052 // Indicate an output frame has arrived.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001053 rtc::scoped_ptr<EventWrapper> output_frame_event_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001054 };
1055
1056 // Initialize send stream.
1057 test::NullTransport transport;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001058 CreateSenderCall(Call::Config(&transport));
1059
1060 CreateSendConfig(1);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001061 FrameObserver observer;
1062 send_config_.pre_encode_callback = &observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001063 CreateStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001064
magjed@webrtc.org45cdcce2015-03-06 10:41:00 +00001065 // Prepare five input frames. Send ordinary I420VideoFrame and texture frames
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001066 // alternatively.
1067 ScopedVector<I420VideoFrame> input_frames;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001068 int width = static_cast<int>(encoder_config_.streams[0].width);
1069 int height = static_cast<int>(encoder_config_.streams[0].height);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001070 webrtc::RefCountImpl<FakeNativeHandle>* handle1 =
1071 new webrtc::RefCountImpl<FakeNativeHandle>();
1072 webrtc::RefCountImpl<FakeNativeHandle>* handle2 =
1073 new webrtc::RefCountImpl<FakeNativeHandle>();
1074 webrtc::RefCountImpl<FakeNativeHandle>* handle3 =
1075 new webrtc::RefCountImpl<FakeNativeHandle>();
magjed@webrtc.org45cdcce2015-03-06 10:41:00 +00001076 input_frames.push_back(new I420VideoFrame(handle1, width, height, 1, 1));
1077 input_frames.push_back(new I420VideoFrame(handle2, width, height, 2, 2));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001078 input_frames.push_back(CreateI420VideoFrame(width, height, 3));
1079 input_frames.push_back(CreateI420VideoFrame(width, height, 4));
1080 input_frames.push_back(new I420VideoFrame(handle3, width, height, 5, 5));
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001081
1082 send_stream_->Start();
1083 for (size_t i = 0; i < input_frames.size(); i++) {
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001084 send_stream_->Input()->IncomingCapturedFrame(*input_frames[i]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001085 // Do not send the next frame too fast, so the frame dropper won't drop it.
1086 if (i < input_frames.size() - 1)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001087 SleepMs(1000 / encoder_config_.streams[0].max_framerate);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001088 // Wait until the output frame is received before sending the next input
1089 // frame. Or the previous input frame may be replaced without delivering.
1090 observer.WaitOutputFrame();
1091 }
1092 send_stream_->Stop();
1093
1094 // Test if the input and output frames are the same. render_time_ms and
1095 // timestamp are not compared because capturer sets those values.
1096 ExpectEqualFramesVector(input_frames.get(), observer.output_frames());
1097
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001098 DestroyStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001099}
1100
1101void ExpectEqualFrames(const I420VideoFrame& frame1,
1102 const I420VideoFrame& frame2) {
1103 if (frame1.native_handle() != NULL || frame2.native_handle() != NULL)
1104 ExpectEqualTextureFrames(frame1, frame2);
1105 else
1106 ExpectEqualBufferFrames(frame1, frame2);
1107}
1108
1109void ExpectEqualTextureFrames(const I420VideoFrame& frame1,
1110 const I420VideoFrame& frame2) {
1111 EXPECT_EQ(frame1.native_handle(), frame2.native_handle());
1112 EXPECT_EQ(frame1.width(), frame2.width());
1113 EXPECT_EQ(frame1.height(), frame2.height());
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001114 EXPECT_EQ(frame1.render_time_ms(), frame2.render_time_ms());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001115}
1116
1117void ExpectEqualBufferFrames(const I420VideoFrame& frame1,
1118 const I420VideoFrame& frame2) {
1119 EXPECT_EQ(frame1.width(), frame2.width());
1120 EXPECT_EQ(frame1.height(), frame2.height());
1121 EXPECT_EQ(frame1.stride(kYPlane), frame2.stride(kYPlane));
1122 EXPECT_EQ(frame1.stride(kUPlane), frame2.stride(kUPlane));
1123 EXPECT_EQ(frame1.stride(kVPlane), frame2.stride(kVPlane));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001124 EXPECT_EQ(frame1.render_time_ms(), frame2.render_time_ms());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001125 ASSERT_EQ(frame1.allocated_size(kYPlane), frame2.allocated_size(kYPlane));
1126 EXPECT_EQ(0,
1127 memcmp(frame1.buffer(kYPlane),
1128 frame2.buffer(kYPlane),
1129 frame1.allocated_size(kYPlane)));
1130 ASSERT_EQ(frame1.allocated_size(kUPlane), frame2.allocated_size(kUPlane));
1131 EXPECT_EQ(0,
1132 memcmp(frame1.buffer(kUPlane),
1133 frame2.buffer(kUPlane),
1134 frame1.allocated_size(kUPlane)));
1135 ASSERT_EQ(frame1.allocated_size(kVPlane), frame2.allocated_size(kVPlane));
1136 EXPECT_EQ(0,
1137 memcmp(frame1.buffer(kVPlane),
1138 frame2.buffer(kVPlane),
1139 frame1.allocated_size(kVPlane)));
1140}
1141
1142void ExpectEqualFramesVector(const std::vector<I420VideoFrame*>& frames1,
1143 const std::vector<I420VideoFrame*>& frames2) {
1144 EXPECT_EQ(frames1.size(), frames2.size());
1145 for (size_t i = 0; i < std::min(frames1.size(), frames2.size()); ++i)
1146 ExpectEqualFrames(*frames1[i], *frames2[i]);
1147}
1148
1149I420VideoFrame* CreateI420VideoFrame(int width, int height, uint8_t data) {
1150 I420VideoFrame* frame = new I420VideoFrame();
1151 const int kSizeY = width * height * 2;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001152 rtc::scoped_ptr<uint8_t[]> buffer(new uint8_t[kSizeY]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001153 memset(buffer.get(), data, kSizeY);
hbos@webrtc.org93d9d652015-03-16 13:26:00 +00001154 frame->CreateFrame(buffer.get(),
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001155 buffer.get(),
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001156 buffer.get(),
1157 width,
1158 height,
1159 width,
1160 width / 2,
1161 width / 2);
1162 frame->set_timestamp(data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001163 frame->set_render_time_ms(data);
1164 return frame;
1165}
1166
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001167TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
1168 class EncoderStateObserver : public test::SendTest, public VideoEncoder {
1169 public:
1170 EncoderStateObserver()
1171 : SendTest(kDefaultTimeoutMs),
1172 crit_(CriticalSectionWrapper::CreateCriticalSection()),
1173 initialized_(false),
1174 callback_registered_(false),
1175 num_releases_(0),
1176 released_(false) {}
1177
1178 bool IsReleased() {
1179 CriticalSectionScoped lock(crit_.get());
1180 return released_;
1181 }
1182
1183 bool IsReadyForEncode() {
1184 CriticalSectionScoped lock(crit_.get());
1185 return initialized_ && callback_registered_;
1186 }
1187
1188 size_t num_releases() {
1189 CriticalSectionScoped lock(crit_.get());
1190 return num_releases_;
1191 }
1192
1193 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001194 int32_t InitEncode(const VideoCodec* codecSettings,
1195 int32_t numberOfCores,
1196 size_t maxPayloadSize) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001197 CriticalSectionScoped lock(crit_.get());
1198 EXPECT_FALSE(initialized_);
1199 initialized_ = true;
1200 released_ = false;
1201 return 0;
1202 }
1203
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001204 int32_t Encode(const I420VideoFrame& inputImage,
1205 const CodecSpecificInfo* codecSpecificInfo,
1206 const std::vector<VideoFrameType>* frame_types) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001207 EXPECT_TRUE(IsReadyForEncode());
1208
1209 observation_complete_->Set();
1210 return 0;
1211 }
1212
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001213 int32_t RegisterEncodeCompleteCallback(
1214 EncodedImageCallback* callback) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001215 CriticalSectionScoped lock(crit_.get());
1216 EXPECT_TRUE(initialized_);
1217 callback_registered_ = true;
1218 return 0;
1219 }
1220
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001221 int32_t Release() override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001222 CriticalSectionScoped lock(crit_.get());
1223 EXPECT_TRUE(IsReadyForEncode());
1224 EXPECT_FALSE(released_);
1225 initialized_ = false;
1226 callback_registered_ = false;
1227 released_ = true;
1228 ++num_releases_;
1229 return 0;
1230 }
1231
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001232 int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001233 EXPECT_TRUE(IsReadyForEncode());
1234 return 0;
1235 }
1236
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001237 int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001238 EXPECT_TRUE(IsReadyForEncode());
1239 return 0;
1240 }
1241
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001242 void OnStreamsCreated(
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001243 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001244 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001245 // Encoder initialization should be done in stream construction before
1246 // starting.
1247 EXPECT_TRUE(IsReadyForEncode());
1248 stream_ = send_stream;
1249 }
1250
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001251 void ModifyConfigs(VideoSendStream::Config* send_config,
1252 std::vector<VideoReceiveStream::Config>* receive_configs,
1253 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001254 send_config->encoder_settings.encoder = this;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001255 encoder_config_ = *encoder_config;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001256 }
1257
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001258 void PerformTest() override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001259 EXPECT_EQ(kEventSignaled, Wait())
1260 << "Timed out while waiting for Encode.";
1261 EXPECT_EQ(0u, num_releases());
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001262 stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001263 EXPECT_EQ(0u, num_releases());
1264 stream_->Stop();
1265 // Encoder should not be released before destroying the VideoSendStream.
1266 EXPECT_FALSE(IsReleased());
1267 EXPECT_TRUE(IsReadyForEncode());
1268 stream_->Start();
1269 // Sanity check, make sure we still encode frames with this encoder.
1270 EXPECT_EQ(kEventSignaled, Wait())
1271 << "Timed out while waiting for Encode.";
1272 }
1273
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001274 rtc::scoped_ptr<CriticalSectionWrapper> crit_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001275 VideoSendStream* stream_;
1276 bool initialized_ GUARDED_BY(crit_);
1277 bool callback_registered_ GUARDED_BY(crit_);
1278 size_t num_releases_ GUARDED_BY(crit_);
1279 bool released_ GUARDED_BY(crit_);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001280 VideoEncoderConfig encoder_config_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001281 } test_encoder;
1282
1283 RunBaseTest(&test_encoder);
1284
1285 EXPECT_TRUE(test_encoder.IsReleased());
1286 EXPECT_EQ(1u, test_encoder.num_releases());
1287}
1288
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001289TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
1290 class VideoCodecConfigObserver : public test::SendTest,
1291 public test::FakeEncoder {
1292 public:
1293 VideoCodecConfigObserver()
1294 : SendTest(kDefaultTimeoutMs),
1295 FakeEncoder(Clock::GetRealTimeClock()),
1296 num_initializations_(0) {}
1297
1298 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001299 void ModifyConfigs(VideoSendStream::Config* send_config,
1300 std::vector<VideoReceiveStream::Config>* receive_configs,
1301 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001302 send_config->encoder_settings.encoder = this;
1303 encoder_config_ = *encoder_config;
1304 }
1305
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001306 void OnStreamsCreated(
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001307 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001308 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001309 stream_ = send_stream;
1310 }
1311
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001312 int32_t InitEncode(const VideoCodec* config,
1313 int32_t number_of_cores,
1314 size_t max_payload_size) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001315 if (num_initializations_ == 0) {
1316 // Verify default values.
1317 EXPECT_EQ(kRealtimeVideo, config->mode);
1318 } else {
1319 // Verify that changed values are propagated.
1320 EXPECT_EQ(kScreensharing, config->mode);
1321 }
1322 ++num_initializations_;
1323 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1324 }
1325
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001326 void PerformTest() override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001327 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1328
1329 encoder_config_.content_type = VideoEncoderConfig::kScreenshare;
1330 stream_->ReconfigureVideoEncoder(encoder_config_);
1331 EXPECT_EQ(2u, num_initializations_)
1332 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1333 "new encoder settings.";
1334 }
1335
1336 size_t num_initializations_;
1337 VideoSendStream* stream_;
1338 VideoEncoderConfig encoder_config_;
1339 } test;
1340
1341 RunBaseTest(&test);
1342}
1343
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001344TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp8Config) {
pbos@webrtc.org759982d2014-09-22 09:32:46 +00001345 static const size_t kNumberOfTemporalLayers = 4;
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001346 class VideoCodecConfigObserver : public test::SendTest,
1347 public test::FakeEncoder {
1348 public:
1349 VideoCodecConfigObserver()
1350 : SendTest(kDefaultTimeoutMs),
1351 FakeEncoder(Clock::GetRealTimeClock()),
1352 num_initializations_(0) {
1353 memset(&vp8_settings_, 0, sizeof(vp8_settings_));
1354 }
1355
1356 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001357 void ModifyConfigs(VideoSendStream::Config* send_config,
1358 std::vector<VideoReceiveStream::Config>* receive_configs,
1359 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001360 send_config->encoder_settings.encoder = this;
1361 send_config->encoder_settings.payload_name = "VP8";
1362
pbos@webrtc.org759982d2014-09-22 09:32:46 +00001363 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001364 encoder_config->streams[i].temporal_layer_thresholds_bps.resize(
1365 kNumberOfTemporalLayers - 1);
pbos@webrtc.org759982d2014-09-22 09:32:46 +00001366 }
1367
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001368 encoder_config->encoder_specific_settings = &vp8_settings_;
1369 encoder_config_ = *encoder_config;
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001370 }
1371
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001372 void OnStreamsCreated(
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001373 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001374 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001375 stream_ = send_stream;
1376 }
1377
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001378 int32_t InitEncode(const VideoCodec* config,
1379 int32_t number_of_cores,
1380 size_t max_payload_size) override {
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001381 EXPECT_EQ(kVideoCodecVP8, config->codecType);
pbos@webrtc.org759982d2014-09-22 09:32:46 +00001382
1383 // Check that the number of temporal layers has propagated properly to
1384 // VideoCodec.
1385 EXPECT_EQ(kNumberOfTemporalLayers,
1386 config->codecSpecific.VP8.numberOfTemporalLayers);
1387
1388 for (unsigned char i = 0; i < config->numberOfSimulcastStreams; ++i) {
1389 EXPECT_EQ(kNumberOfTemporalLayers,
1390 config->simulcastStream[i].numberOfTemporalLayers);
1391 }
1392
1393 // Set expected temporal layers as they should have been set when
1394 // reconfiguring the encoder and not match the set config.
1395 vp8_settings_.numberOfTemporalLayers = kNumberOfTemporalLayers;
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001396 EXPECT_EQ(0,
1397 memcmp(&config->codecSpecific.VP8,
1398 &vp8_settings_,
1399 sizeof(vp8_settings_)));
1400 ++num_initializations_;
1401 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1402 }
1403
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001404 void PerformTest() override {
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001405 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1406
1407 vp8_settings_.denoisingOn = true;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001408 stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001409 EXPECT_EQ(2u, num_initializations_)
1410 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1411 "new encoder settings.";
1412 }
1413
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001414 int32_t Encode(const I420VideoFrame& input_image,
1415 const CodecSpecificInfo* codec_specific_info,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001416 const std::vector<VideoFrameType>* frame_types) override {
pbos@webrtc.orgbd9c0922014-07-10 13:21:40 +00001417 // Silently skip the encode, FakeEncoder::Encode doesn't produce VP8.
1418 return 0;
1419 }
1420
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001421 VideoCodecVP8 vp8_settings_;
1422 size_t num_initializations_;
1423 VideoSendStream* stream_;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001424 VideoEncoderConfig encoder_config_;
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001425 } test;
1426
1427 RunBaseTest(&test);
1428}
1429
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001430TEST_F(VideoSendStreamTest, RtcpSenderReportContainsMediaBytesSent) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001431 class RtcpSenderReportTest : public test::SendTest {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001432 public:
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001433 RtcpSenderReportTest() : SendTest(kDefaultTimeoutMs),
1434 rtp_packets_sent_(0),
1435 media_bytes_sent_(0) {}
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001436
1437 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001438 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001439 RTPHeader header;
1440 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001441 ++rtp_packets_sent_;
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001442 media_bytes_sent_ += length - header.headerLength - header.paddingLength;
1443 return SEND_PACKET;
1444 }
1445
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001446 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001447 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1448 EXPECT_TRUE(parser.IsValid());
1449
1450 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001451 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1452 if (packet_type == RTCPUtility::kRtcpSrCode) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001453 // Only compare sent media bytes if SenderPacketCount matches the
1454 // number of sent rtp packets (a new rtp packet could be sent before
1455 // the rtcp packet).
1456 if (parser.Packet().SR.SenderOctetCount > 0 &&
1457 parser.Packet().SR.SenderPacketCount == rtp_packets_sent_) {
1458 EXPECT_EQ(media_bytes_sent_, parser.Packet().SR.SenderOctetCount);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001459 observation_complete_->Set();
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001460 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001461 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001462 packet_type = parser.Iterate();
1463 }
1464
1465 return SEND_PACKET;
1466 }
1467
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001468 void PerformTest() override {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001469 EXPECT_EQ(kEventSignaled, Wait())
1470 << "Timed out while waiting for RTCP sender report.";
1471 }
1472
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001473 size_t rtp_packets_sent_;
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001474 size_t media_bytes_sent_;
1475 } test;
1476
1477 RunBaseTest(&test);
1478}
1479
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001480TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
1481 static const int kScreencastTargetBitrateKbps = 200;
1482 class ScreencastTargetBitrateTest : public test::SendTest,
1483 public test::FakeEncoder {
1484 public:
1485 ScreencastTargetBitrateTest()
1486 : SendTest(kDefaultTimeoutMs),
1487 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1488
1489 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001490 int32_t InitEncode(const VideoCodec* config,
1491 int32_t number_of_cores,
1492 size_t max_payload_size) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001493 EXPECT_EQ(static_cast<unsigned int>(kScreencastTargetBitrateKbps),
1494 config->targetBitrate);
1495 observation_complete_->Set();
1496 return test::FakeEncoder::InitEncode(
1497 config, number_of_cores, max_payload_size);
1498 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001499 void ModifyConfigs(VideoSendStream::Config* send_config,
1500 std::vector<VideoReceiveStream::Config>* receive_configs,
1501 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001502 send_config->encoder_settings.encoder = this;
1503 EXPECT_EQ(1u, encoder_config->streams.size());
1504 EXPECT_TRUE(
1505 encoder_config->streams[0].temporal_layer_thresholds_bps.empty());
1506 encoder_config->streams[0].temporal_layer_thresholds_bps.push_back(
1507 kScreencastTargetBitrateKbps * 1000);
1508 encoder_config->content_type = VideoEncoderConfig::kScreenshare;
1509 }
1510
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001511 void PerformTest() override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001512 EXPECT_EQ(kEventSignaled, Wait())
1513 << "Timed out while waiting for the encoder to be initialized.";
1514 }
1515 } test;
1516
1517 RunBaseTest(&test);
1518}
pbos@webrtc.org00873182014-11-25 14:03:34 +00001519
1520TEST_F(VideoSendStreamTest, UsesCallStreamBitratesAndCanReconfigureBitrates) {
1521 // These are chosen to be "kind of odd" to not be accidentally checked against
1522 // default values.
1523 static const int kMinBitrateKbps = 137;
1524 static const int kStartBitrateKbps = 345;
1525 static const int kLowerMaxBitrateKbps = 312;
1526 static const int kMaxBitrateKbps = 413;
1527 static const int kIncreasedStartBitrateKbps = 451;
1528 static const int kIncreasedMaxBitrateKbps = 597;
1529 class EncoderBitrateThresholdObserver : public test::SendTest,
1530 public test::FakeEncoder {
1531 public:
1532 EncoderBitrateThresholdObserver()
1533 : SendTest(kDefaultTimeoutMs),
1534 FakeEncoder(Clock::GetRealTimeClock()),
1535 num_initializations_(0) {}
1536
1537 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001538 int32_t InitEncode(const VideoCodec* codecSettings,
1539 int32_t numberOfCores,
1540 size_t maxPayloadSize) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001541 if (num_initializations_ == 0) {
1542 EXPECT_EQ(static_cast<unsigned int>(kMinBitrateKbps),
1543 codecSettings->minBitrate);
1544 EXPECT_EQ(static_cast<unsigned int>(kStartBitrateKbps),
1545 codecSettings->startBitrate);
1546 EXPECT_EQ(static_cast<unsigned int>(kMaxBitrateKbps),
1547 codecSettings->maxBitrate);
1548 observation_complete_->Set();
1549 } else if (num_initializations_ == 1) {
1550 EXPECT_EQ(static_cast<unsigned int>(kLowerMaxBitrateKbps),
1551 codecSettings->maxBitrate);
1552 // The start bitrate should be kept (-1) and capped to the max bitrate.
1553 // Since this is not an end-to-end call no receiver should have been
1554 // returning a REMB that could lower this estimate.
1555 EXPECT_EQ(codecSettings->startBitrate, codecSettings->maxBitrate);
1556 } else if (num_initializations_ == 2) {
1557 EXPECT_EQ(static_cast<unsigned int>(kIncreasedMaxBitrateKbps),
1558 codecSettings->maxBitrate);
1559 EXPECT_EQ(static_cast<unsigned int>(kIncreasedStartBitrateKbps),
1560 codecSettings->startBitrate);
1561 }
1562 ++num_initializations_;
1563 return FakeEncoder::InitEncode(codecSettings, numberOfCores,
1564 maxPayloadSize);
1565 }
1566
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001567 Call::Config GetSenderCallConfig() override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001568 Call::Config config(SendTransport());
1569 config.stream_bitrates.min_bitrate_bps = kMinBitrateKbps * 1000;
1570 config.stream_bitrates.start_bitrate_bps = kStartBitrateKbps * 1000;
1571 config.stream_bitrates.max_bitrate_bps = kMaxBitrateKbps * 1000;
1572 return config;
1573 }
1574
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001575 void ModifyConfigs(VideoSendStream::Config* send_config,
1576 std::vector<VideoReceiveStream::Config>* receive_configs,
1577 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001578 send_config->encoder_settings.encoder = this;
1579 // Set bitrates lower/higher than min/max to make sure they are properly
1580 // capped.
1581 encoder_config->streams.front().min_bitrate_bps =
1582 (kMinBitrateKbps - 10) * 1000;
1583 encoder_config->streams.front().max_bitrate_bps =
1584 (kIncreasedMaxBitrateKbps + 10) * 1000;
1585 }
1586
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001587 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001588 call_ = sender_call;
1589 }
1590
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001591 void PerformTest() override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001592 EXPECT_EQ(kEventSignaled, Wait())
1593 << "Timed out while waiting encoder to be configured.";
1594 Call::Config::BitrateConfig bitrate_config;
1595 bitrate_config.min_bitrate_bps = 0;
1596 bitrate_config.start_bitrate_bps = -1;
1597 bitrate_config.max_bitrate_bps = kLowerMaxBitrateKbps * 1000;
1598 call_->SetBitrateConfig(bitrate_config);
1599 EXPECT_EQ(2, num_initializations_)
1600 << "Encoder should have been reconfigured with the new value.";
1601 bitrate_config.start_bitrate_bps = kIncreasedStartBitrateKbps * 1000;
1602 bitrate_config.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000;
1603 call_->SetBitrateConfig(bitrate_config);
1604 EXPECT_EQ(3, num_initializations_)
1605 << "Encoder should have been reconfigured with the new value.";
1606 }
1607
1608 int num_initializations_;
1609 webrtc::Call* call_;
1610 } test;
1611
1612 RunBaseTest(&test);
1613}
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001614
1615TEST_F(VideoSendStreamTest, ReportsSentResolution) {
1616 static const size_t kNumStreams = 3;
1617 // Unusual resolutions to make sure that they are the ones being reported.
1618 static const struct {
1619 int width;
1620 int height;
1621 } kEncodedResolution[kNumStreams] = {
1622 {241, 181}, {300, 121}, {121, 221}};
1623 class ScreencastTargetBitrateTest : public test::SendTest,
1624 public test::FakeEncoder {
1625 public:
1626 ScreencastTargetBitrateTest()
1627 : SendTest(kDefaultTimeoutMs),
1628 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1629
1630 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001631 int32_t Encode(const I420VideoFrame& input_image,
1632 const CodecSpecificInfo* codecSpecificInfo,
1633 const std::vector<VideoFrameType>* frame_types) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001634 CodecSpecificInfo specifics;
1635 memset(&specifics, 0, sizeof(specifics));
1636 specifics.codecType = kVideoCodecGeneric;
1637
1638 uint8_t buffer[16] = {0};
1639 EncodedImage encoded(buffer, sizeof(buffer), sizeof(buffer));
1640 encoded._timeStamp = input_image.timestamp();
1641 encoded.capture_time_ms_ = input_image.render_time_ms();
1642
1643 for (size_t i = 0; i < kNumStreams; ++i) {
1644 specifics.codecSpecific.generic.simulcast_idx = static_cast<uint8_t>(i);
1645 encoded._frameType = (*frame_types)[i];
1646 encoded._encodedWidth = kEncodedResolution[i].width;
1647 encoded._encodedHeight = kEncodedResolution[i].height;
1648 assert(callback_ != NULL);
1649 if (callback_->Encoded(encoded, &specifics, NULL) != 0)
1650 return -1;
1651 }
1652
1653 observation_complete_->Set();
1654 return 0;
1655 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001656 void ModifyConfigs(VideoSendStream::Config* send_config,
1657 std::vector<VideoReceiveStream::Config>* receive_configs,
1658 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001659 send_config->encoder_settings.encoder = this;
1660 EXPECT_EQ(kNumStreams, encoder_config->streams.size());
1661 }
1662
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001663 size_t GetNumStreams() const override { return kNumStreams; }
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001664
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001665 void PerformTest() override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001666 EXPECT_EQ(kEventSignaled, Wait())
1667 << "Timed out while waiting for the encoder to send one frame.";
1668 VideoSendStream::Stats stats = send_stream_->GetStats();
1669
1670 for (size_t i = 0; i < kNumStreams; ++i) {
1671 ASSERT_TRUE(stats.substreams.find(kSendSsrcs[i]) !=
1672 stats.substreams.end())
1673 << "No stats for SSRC: " << kSendSsrcs[i]
1674 << ", stats should exist as soon as frames have been encoded.";
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001675 VideoSendStream::StreamStats ssrc_stats =
1676 stats.substreams[kSendSsrcs[i]];
1677 EXPECT_EQ(kEncodedResolution[i].width, ssrc_stats.width);
1678 EXPECT_EQ(kEncodedResolution[i].height, ssrc_stats.height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001679 }
1680 }
1681
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001682 void OnStreamsCreated(
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001683 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001684 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001685 send_stream_ = send_stream;
1686 }
1687
1688 VideoSendStream* send_stream_;
1689 } test;
1690
1691 RunBaseTest(&test);
1692}
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +00001693} // namespace webrtc