blob: 428a2735c10d97e2e43a0e1efe7812d43feb6fe5 [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
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000015#include "webrtc/base/checks.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000016#include "webrtc/base/scoped_ptr.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000017#include "webrtc/call.h"
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +000018#include "webrtc/common_video/interface/i420_video_frame.h"
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000019#include "webrtc/common_video/interface/native_handle.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000020#include "webrtc/frame_callback.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000021#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000022#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000023#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
pbos@webrtc.org013d9942013-08-22 09:42:17 +000024#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +000025#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000026#include "webrtc/system_wrappers/interface/event_wrapper.h"
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000027#include "webrtc/system_wrappers/interface/ref_count.h"
pbos@webrtc.org29023282013-09-11 10:14:56 +000028#include "webrtc/system_wrappers/interface/sleep.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000029#include "webrtc/system_wrappers/interface/thread_wrapper.h"
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000030#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000031#include "webrtc/test/call_test.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000032#include "webrtc/test/configurable_frame_size_encoder.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000033#include "webrtc/test/null_transport.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000034#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.org273a4142014-12-01 15:23:21 +000035#include "webrtc/video/send_statistics_proxy.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000036#include "webrtc/video/transport_adapter.h"
37#include "webrtc/video_send_stream.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000038
39namespace webrtc {
40
sprang@webrtc.org346094c2014-02-18 08:40:33 +000041enum VideoFormat { kGeneric, kVP8, };
42
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000043void ExpectEqualFrames(const I420VideoFrame& frame1,
44 const I420VideoFrame& frame2);
45void ExpectEqualTextureFrames(const I420VideoFrame& frame1,
46 const I420VideoFrame& frame2);
47void ExpectEqualBufferFrames(const I420VideoFrame& frame1,
48 const I420VideoFrame& frame2);
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +000049void ExpectEqualFramesVector(const std::vector<I420VideoFrame>& frames1,
50 const std::vector<I420VideoFrame>& frames2);
51I420VideoFrame CreateI420VideoFrame(int width, int height, uint8_t data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000052
53class FakeNativeHandle : public NativeHandle {
54 public:
55 FakeNativeHandle() {}
56 virtual ~FakeNativeHandle() {}
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000057 virtual void* GetHandle() { return nullptr; }
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000058};
59
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000060class VideoSendStreamTest : public test::CallTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000061 protected:
stefan@webrtc.org69969e22013-11-15 12:32:15 +000062 void TestNackRetransmission(uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +000063 uint8_t retransmit_payload_type);
sprang@webrtc.org346094c2014-02-18 08:40:33 +000064 void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
pbos@webrtc.org013d9942013-08-22 09:42:17 +000065};
66
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000067TEST_F(VideoSendStreamTest, CanStartStartedStream) {
68 test::NullTransport transport;
69 Call::Config call_config(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000070 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000071
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000072 CreateSendConfig(1);
73 CreateStreams();
74 send_stream_->Start();
75 send_stream_->Start();
76 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000077}
78
79TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
80 test::NullTransport transport;
81 Call::Config call_config(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000082 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000083
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000084 CreateSendConfig(1);
85 CreateStreams();
86 send_stream_->Stop();
87 send_stream_->Stop();
88 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000089}
90
pbos@webrtc.org013d9942013-08-22 09:42:17 +000091TEST_F(VideoSendStreamTest, SupportsCName) {
92 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000093 class CNameObserver : public test::SendTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000094 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000095 CNameObserver() : SendTest(kDefaultTimeoutMs) {}
pbos@webrtc.org013d9942013-08-22 09:42:17 +000096
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000097 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000098 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000099 RTCPUtility::RTCPParserV2 parser(packet, length, true);
100 EXPECT_TRUE(parser.IsValid());
101
102 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
103 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
104 if (packet_type == RTCPUtility::kRtcpSdesChunkCode) {
105 EXPECT_EQ(parser.Packet().CName.CName, kCName);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000106 observation_complete_->Set();
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000107 }
108
109 packet_type = parser.Iterate();
110 }
111
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000112 return SEND_PACKET;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000113 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000114
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000115 void ModifyConfigs(VideoSendStream::Config* send_config,
116 std::vector<VideoReceiveStream::Config>* receive_configs,
117 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000118 send_config->rtp.c_name = kCName;
119 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000120
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000121 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000122 EXPECT_EQ(kEventSignaled, Wait())
123 << "Timed out while waiting for RTCP with CNAME.";
124 }
125 } test;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000126
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000127 RunBaseTest(&test);
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000128}
129
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000130TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
131 static const uint8_t kAbsSendTimeExtensionId = 13;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000132 class AbsoluteSendTimeObserver : public test::SendTest {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000133 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000134 AbsoluteSendTimeObserver() : SendTest(kDefaultTimeoutMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000135 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000136 kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId));
137 }
138
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000139 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000140 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000141 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000142
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000143 EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
144 EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
145 EXPECT_EQ(header.extension.transmissionTimeOffset, 0);
146 EXPECT_GT(header.extension.absoluteSendTime, 0u);
147 observation_complete_->Set();
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000148
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000149 return SEND_PACKET;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000150 }
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000151
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000152 void ModifyConfigs(VideoSendStream::Config* send_config,
153 std::vector<VideoReceiveStream::Config>* receive_configs,
154 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000155 send_config->rtp.extensions.push_back(
156 RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
157 }
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +0000158
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000159 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000160 EXPECT_EQ(kEventSignaled, Wait())
161 << "Timed out while waiting for single RTP packet.";
162 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000163 } test;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000164
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000165 RunBaseTest(&test);
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000166}
167
pbos@webrtc.org29023282013-09-11 10:14:56 +0000168TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
169 static const uint8_t kTOffsetExtensionId = 13;
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000170 static const int kEncodeDelayMs = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000171 class TransmissionTimeOffsetObserver : public test::SendTest {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000172 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000173 TransmissionTimeOffsetObserver()
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000174 : SendTest(kDefaultTimeoutMs),
175 encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000176 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
pbos@webrtc.org29023282013-09-11 10:14:56 +0000177 kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId));
178 }
179
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000180 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000181 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000182 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000183 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000184
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000185 EXPECT_TRUE(header.extension.hasTransmissionTimeOffset);
186 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000187 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000188 EXPECT_EQ(header.extension.absoluteSendTime, 0u);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000189 observation_complete_->Set();
pbos@webrtc.org29023282013-09-11 10:14:56 +0000190
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000191 return SEND_PACKET;
pbos@webrtc.org29023282013-09-11 10:14:56 +0000192 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000193
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000194 void ModifyConfigs(VideoSendStream::Config* send_config,
195 std::vector<VideoReceiveStream::Config>* receive_configs,
196 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000197 send_config->encoder_settings.encoder = &encoder_;
198 send_config->rtp.extensions.push_back(
199 RtpExtension(RtpExtension::kTOffset, kTOffsetExtensionId));
200 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000201
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000202 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000203 EXPECT_EQ(kEventSignaled, Wait())
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +0000204 << "Timed out while waiting for a single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000205 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000206
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000207 test::DelayedEncoder encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000208 } test;
209
210 RunBaseTest(&test);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000211}
212
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000213class FakeReceiveStatistics : public NullReceiveStatistics {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000214 public:
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000215 FakeReceiveStatistics(uint32_t send_ssrc,
216 uint32_t last_sequence_number,
217 uint32_t cumulative_lost,
218 uint8_t fraction_lost)
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000219 : lossy_stats_(new LossyStatistician(last_sequence_number,
220 cumulative_lost,
221 fraction_lost)) {
222 stats_map_[send_ssrc] = lossy_stats_.get();
223 }
224
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000225 StatisticianMap GetActiveStatisticians() const override { return stats_map_; }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000226
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000227 StreamStatistician* GetStatistician(uint32_t ssrc) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000228 return lossy_stats_.get();
229 }
230
231 private:
232 class LossyStatistician : public StreamStatistician {
233 public:
234 LossyStatistician(uint32_t extended_max_sequence_number,
235 uint32_t cumulative_lost,
236 uint8_t fraction_lost) {
237 stats_.fraction_lost = fraction_lost;
238 stats_.cumulative_lost = cumulative_lost;
239 stats_.extended_max_sequence_number = extended_max_sequence_number;
240 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000241 bool GetStatistics(RtcpStatistics* statistics, bool reset) override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000242 *statistics = stats_;
243 return true;
244 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000245 void GetDataCounters(size_t* bytes_received,
246 uint32_t* packets_received) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000247 *bytes_received = 0;
248 *packets_received = 0;
249 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000250 void GetReceiveStreamDataCounters(
251 StreamDataCounters* data_counters) const override {}
252 uint32_t BitrateReceived() const override { return 0; }
253 void ResetStatistics() override {}
254 bool IsRetransmitOfOldPacket(const RTPHeader& header,
255 int64_t min_rtt) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000256 return false;
257 }
258
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000259 bool IsPacketInOrder(uint16_t sequence_number) const override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000260 return true;
261 }
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000262
263 RtcpStatistics stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000264 };
265
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000266 rtc::scoped_ptr<LossyStatistician> lossy_stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000267 StatisticianMap stats_map_;
268};
269
270TEST_F(VideoSendStreamTest, SupportsFec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000271 class FecObserver : public test::SendTest {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000272 public:
273 FecObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000274 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000275 transport_adapter_(SendTransport()),
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000276 send_count_(0),
277 received_media_(false),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000278 received_fec_(false) {
279 transport_adapter_.Enable();
280 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000281
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000282 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000283 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000284 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000285 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000286
287 // Send lossy receive reports to trigger FEC enabling.
288 if (send_count_++ % 2 != 0) {
289 // Receive statistics reporting having lost 50% of the packets.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000290 FakeReceiveStatistics lossy_receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000291 kSendSsrcs[0], header.sequenceNumber, send_count_ / 2, 127);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000292 RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(),
293 &lossy_receive_stats, nullptr);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000294 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
295
296 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000297 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000298
299 RTCPSender::FeedbackState feedback_state;
300
301 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
302 }
303
304 EXPECT_EQ(kRedPayloadType, header.payloadType);
305
306 uint8_t encapsulated_payload_type = packet[header.headerLength];
307
308 if (encapsulated_payload_type == kUlpfecPayloadType) {
309 received_fec_ = true;
310 } else {
311 received_media_ = true;
312 }
313
314 if (received_media_ && received_fec_)
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000315 observation_complete_->Set();
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000316
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000317 return SEND_PACKET;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000318 }
319
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000320 void ModifyConfigs(VideoSendStream::Config* send_config,
321 std::vector<VideoReceiveStream::Config>* receive_configs,
322 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000323 send_config->rtp.fec.red_payload_type = kRedPayloadType;
324 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
325 }
326
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000327 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000328 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
329 }
330
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000331 internal::TransportAdapter transport_adapter_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000332 int send_count_;
333 bool received_media_;
334 bool received_fec_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000335 } test;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000336
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000337 RunBaseTest(&test);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000338}
339
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000340void VideoSendStreamTest::TestNackRetransmission(
341 uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000342 uint8_t retransmit_payload_type) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000343 class NackObserver : public test::SendTest {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000344 public:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000345 explicit NackObserver(uint32_t retransmit_ssrc,
346 uint8_t retransmit_payload_type)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000347 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000348 transport_adapter_(SendTransport()),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000349 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000350 retransmit_ssrc_(retransmit_ssrc),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000351 retransmit_payload_type_(retransmit_payload_type),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000352 nacked_sequence_number_(-1) {
353 transport_adapter_.Enable();
354 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000355
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000356 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000357 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000358 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000359 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000360
361 // Nack second packet after receiving the third one.
362 if (++send_count_ == 3) {
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000363 uint16_t nack_sequence_number = header.sequenceNumber - 1;
364 nacked_sequence_number_ = nack_sequence_number;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000365 NullReceiveStatistics null_stats;
366 RTCPSender rtcp_sender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000367 0, false, Clock::GetRealTimeClock(), &null_stats, nullptr);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000368 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
369
370 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000371 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000372
373 RTCPSender::FeedbackState feedback_state;
374
375 EXPECT_EQ(0,
376 rtcp_sender.SendRTCP(
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000377 feedback_state, kRtcpNack, 1, &nack_sequence_number));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000378 }
379
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000380 uint16_t sequence_number = header.sequenceNumber;
381
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000382 if (header.ssrc == retransmit_ssrc_ &&
383 retransmit_ssrc_ != kSendSsrcs[0]) {
384 // Not kSendSsrcs[0], assume correct RTX packet. Extract sequence
385 // number.
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000386 const uint8_t* rtx_header = packet + header.headerLength;
387 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
388 }
389
390 if (sequence_number == nacked_sequence_number_) {
391 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000392 EXPECT_EQ(retransmit_payload_type_, header.payloadType);
393 observation_complete_->Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000394 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000395
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000396 return SEND_PACKET;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000397 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000398
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000399 void ModifyConfigs(VideoSendStream::Config* send_config,
400 std::vector<VideoReceiveStream::Config>* receive_configs,
401 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000402 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000403 send_config->rtp.rtx.payload_type = retransmit_payload_type_;
404 if (retransmit_ssrc_ != kSendSsrcs[0])
405 send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
406 }
407
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000408 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000409 EXPECT_EQ(kEventSignaled, Wait())
410 << "Timed out while waiting for NACK retransmission.";
411 }
412
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000413 internal::TransportAdapter transport_adapter_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000414 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000415 uint32_t retransmit_ssrc_;
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000416 uint8_t retransmit_payload_type_;
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000417 int nacked_sequence_number_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000418 } test(retransmit_ssrc, retransmit_payload_type);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000419
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000420 RunBaseTest(&test);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000421}
422
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000423TEST_F(VideoSendStreamTest, RetransmitsNack) {
424 // Normal NACKs should use the send SSRC.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000425 TestNackRetransmission(kSendSsrcs[0], kFakeSendPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000426}
427
428TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
429 // NACKs over RTX should use a separate SSRC.
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000430 TestNackRetransmission(kSendRtxSsrcs[0], kSendRtxPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000431}
432
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000433void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
434 bool with_fec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000435 // Use a fake encoder to output a frame of every size in the range [90, 290],
436 // for each size making sure that the exact number of payload bytes received
437 // is correct and that packets are fragmented to respect max packet size.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000438 static const size_t kMaxPacketSize = 128;
439 static const size_t start = 90;
440 static const size_t stop = 290;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000441
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000442 // Observer that verifies that the expected number of packets and bytes
443 // arrive for each frame size, from start_size to stop_size.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000444 class FrameFragmentationTest : public test::SendTest,
445 public EncodedFrameObserver {
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000446 public:
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000447 FrameFragmentationTest(size_t max_packet_size,
448 size_t start_size,
449 size_t stop_size,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000450 bool test_generic_packetization,
451 bool use_fec)
452 : SendTest(kLongTimeoutMs),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000453 transport_adapter_(SendTransport()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000454 encoder_(stop),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000455 max_packet_size_(max_packet_size),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000456 stop_size_(stop_size),
457 test_generic_packetization_(test_generic_packetization),
458 use_fec_(use_fec),
459 packet_count_(0),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000460 accumulated_size_(0),
461 accumulated_payload_(0),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000462 fec_packet_received_(false),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000463 current_size_rtp_(start_size),
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000464 current_size_frame_(static_cast<int32_t>(start_size)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000465 // Fragmentation required, this test doesn't make sense without it.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000466 encoder_.SetFrameSize(start_size);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000467 DCHECK_GT(stop_size, max_packet_size);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000468 transport_adapter_.Enable();
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000469 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000470
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000471 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000472 Action OnSendRtp(const uint8_t* packet, size_t size) override {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000473 size_t length = size;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000474 RTPHeader header;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000475 EXPECT_TRUE(parser_->Parse(packet, length, &header));
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000476
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000477 EXPECT_LE(length, max_packet_size_);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000478
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000479 if (use_fec_) {
480 uint8_t payload_type = packet[header.headerLength];
481 bool is_fec = header.payloadType == kRedPayloadType &&
482 payload_type == kUlpfecPayloadType;
483 if (is_fec) {
484 fec_packet_received_ = true;
485 return SEND_PACKET;
486 }
487 }
488
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000489 accumulated_size_ += length;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000490
491 if (use_fec_)
492 TriggerLossReport(header);
493
494 if (test_generic_packetization_) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000495 size_t overhead = header.headerLength + header.paddingLength +
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000496 (1 /* Generic header */);
497 if (use_fec_)
498 overhead += 1; // RED for FEC header.
499 accumulated_payload_ += length - overhead;
500 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000501
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000502 // Marker bit set indicates last packet of a frame.
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000503 if (header.markerBit) {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000504 if (use_fec_ && accumulated_payload_ == current_size_rtp_ - 1) {
505 // With FEC enabled, frame size is incremented asynchronously, so
506 // "old" frames one byte too small may arrive. Accept, but don't
507 // increase expected frame size.
508 accumulated_size_ = 0;
509 accumulated_payload_ = 0;
510 return SEND_PACKET;
511 }
512
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000513 EXPECT_GE(accumulated_size_, current_size_rtp_);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000514 if (test_generic_packetization_) {
515 EXPECT_EQ(current_size_rtp_, accumulated_payload_);
516 }
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000517
518 // Last packet of frame; reset counters.
519 accumulated_size_ = 0;
520 accumulated_payload_ = 0;
521 if (current_size_rtp_ == stop_size_) {
522 // Done! (Don't increase size again, might arrive more @ stop_size).
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000523 observation_complete_->Set();
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000524 } else {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000525 // Increase next expected frame size. If testing with FEC, make sure
526 // a FEC packet has been received for this frame size before
527 // proceeding, to make sure that redundancy packets don't exceed
528 // size limit.
529 if (!use_fec_) {
530 ++current_size_rtp_;
531 } else if (fec_packet_received_) {
532 fec_packet_received_ = false;
533 ++current_size_rtp_;
534 ++current_size_frame_;
535 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000536 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000537 }
538
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000539 return SEND_PACKET;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000540 }
541
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000542 void TriggerLossReport(const RTPHeader& header) {
543 // Send lossy receive reports to trigger FEC enabling.
544 if (packet_count_++ % 2 != 0) {
545 // Receive statistics reporting having lost 50% of the packets.
546 FakeReceiveStatistics lossy_receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000547 kSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000548 RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(),
549 &lossy_receive_stats, nullptr);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000550 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
551
552 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000553 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000554
555 RTCPSender::FeedbackState feedback_state;
556
557 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
558 }
559 }
560
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000561 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
562 // Increase frame size for next encoded frame, in the context of the
563 // encoder thread.
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000564 if (!use_fec_ &&
565 current_size_frame_.Value() < static_cast<int32_t>(stop_size_)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000566 ++current_size_frame_;
567 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000568 encoder_.SetFrameSize(static_cast<size_t>(current_size_frame_.Value()));
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000569 }
570
Stefan Holmere5904162015-03-26 11:11:06 +0100571 Call::Config GetSenderCallConfig() override {
572 Call::Config config(SendTransport());
573 const int kMinBitrateBps = 30000;
574 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
575 return config;
576 }
577
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000578 void ModifyConfigs(VideoSendStream::Config* send_config,
579 std::vector<VideoReceiveStream::Config>* receive_configs,
580 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000581 if (use_fec_) {
582 send_config->rtp.fec.red_payload_type = kRedPayloadType;
583 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
584 }
585
586 if (!test_generic_packetization_)
587 send_config->encoder_settings.payload_name = "VP8";
588
589 send_config->encoder_settings.encoder = &encoder_;
590 send_config->rtp.max_packet_size = kMaxPacketSize;
591 send_config->post_encode_callback = this;
592
593 // Add an extension header, to make the RTP header larger than the base
594 // length of 12 bytes.
595 static const uint8_t kAbsSendTimeExtensionId = 13;
596 send_config->rtp.extensions.push_back(
597 RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
598 }
599
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000600 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000601 EXPECT_EQ(kEventSignaled, Wait())
602 << "Timed out while observing incoming RTP packets.";
603 }
604
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000605 internal::TransportAdapter transport_adapter_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000606 test::ConfigurableFrameSizeEncoder encoder_;
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000607
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000608 const size_t max_packet_size_;
609 const size_t stop_size_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000610 const bool test_generic_packetization_;
611 const bool use_fec_;
612
613 uint32_t packet_count_;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000614 size_t accumulated_size_;
615 size_t accumulated_payload_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000616 bool fec_packet_received_;
617
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000618 size_t current_size_rtp_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000619 Atomic32 current_size_frame_;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000620 };
621
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000622 // Don't auto increment if FEC is used; continue sending frame size until
623 // a FEC packet has been received.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000624 FrameFragmentationTest test(
625 kMaxPacketSize, start, stop, format == kGeneric, with_fec);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000626
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000627 RunBaseTest(&test);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000628}
629
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000630// TODO(sprang): Is there any way of speeding up these tests?
631TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSize) {
632 TestPacketFragmentationSize(kGeneric, false);
633}
634
635TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSizeWithFec) {
636 TestPacketFragmentationSize(kGeneric, true);
637}
638
639TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSize) {
640 TestPacketFragmentationSize(kVP8, false);
641}
642
643TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSizeWithFec) {
644 TestPacketFragmentationSize(kVP8, true);
645}
646
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000647// The test will go through a number of phases.
648// 1. Start sending packets.
649// 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 +0000650// suspend the stream.
651// 3. Wait until |kSuspendTimeFrames| have been captured without seeing any RTP
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000652// packets.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000653// 4. Signal a high REMB and then wait for the RTP stream to start again.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000654// When the stream is detected again, and the stats show that the stream
655// is no longer suspended, the test ends.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000656TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
657 static const int kSuspendTimeFrames = 60; // Suspend for 2 seconds @ 30 fps.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000658
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000659 class RembObserver : public test::SendTest, public I420FrameCallback {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000660 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000661 RembObserver()
662 : SendTest(kDefaultTimeoutMs),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000663 transport_adapter_(&transport_),
664 clock_(Clock::GetRealTimeClock()),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000665 crit_(CriticalSectionWrapper::CreateCriticalSection()),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000666 test_state_(kBeforeSuspend),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000667 rtp_count_(0),
668 last_sequence_number_(0),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000669 suspended_frame_count_(0),
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000670 low_remb_bps_(0),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000671 high_remb_bps_(0) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000672 transport_adapter_.Enable();
673 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000674
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000675 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000676 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000677 // Receive statistics reporting having lost 0% of the packets.
678 // This is needed for the send-side bitrate controller to work properly.
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000679 CriticalSectionScoped lock(crit_.get());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000680 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000681 return SEND_PACKET;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000682 }
683
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000684 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000685 CriticalSectionScoped lock(crit_.get());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000686 ++rtp_count_;
687 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000688 EXPECT_TRUE(parser_->Parse(packet, length, &header));
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000689 last_sequence_number_ = header.sequenceNumber;
690
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000691 if (test_state_ == kBeforeSuspend) {
692 // The stream has started. Try to suspend it.
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000693 SendRtcpFeedback(low_remb_bps_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000694 test_state_ = kDuringSuspend;
695 } else if (test_state_ == kDuringSuspend) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000696 if (header.paddingLength == 0) {
697 // Received non-padding packet during suspension period. Reset the
698 // counter.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000699 suspended_frame_count_ = 0;
700 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000701 } else if (test_state_ == kWaitingForPacket) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000702 if (header.paddingLength == 0) {
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000703 // Non-padding packet observed. Test is almost complete. Will just
704 // have to wait for the stats to change.
705 test_state_ = kWaitingForStats;
706 }
707 } else if (test_state_ == kWaitingForStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000708 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000709 if (stats.suspended == false) {
710 // Stats flipped to false. Test is complete.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000711 observation_complete_->Set();
712 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000713 }
714
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000715 return SEND_PACKET;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000716 }
717
718 // This method implements the I420FrameCallback.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000719 void FrameCallback(I420VideoFrame* video_frame) override {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000720 CriticalSectionScoped lock(crit_.get());
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000721 if (test_state_ == kDuringSuspend &&
722 ++suspended_frame_count_ > kSuspendTimeFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000723 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000724 EXPECT_TRUE(stats.suspended);
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000725 SendRtcpFeedback(high_remb_bps_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000726 test_state_ = kWaitingForPacket;
727 }
728 }
729
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000730 void set_low_remb_bps(int value) {
731 CriticalSectionScoped lock(crit_.get());
732 low_remb_bps_ = value;
733 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000734
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000735 void set_high_remb_bps(int value) {
736 CriticalSectionScoped lock(crit_.get());
737 high_remb_bps_ = value;
738 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000739
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000740 void SetReceivers(PacketReceiver* send_transport_receiver,
741 PacketReceiver* receive_transport_receiver) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000742 transport_.SetReceiver(send_transport_receiver);
743 }
pbos@webrtc.orgdef22b42013-10-29 10:12:10 +0000744
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000745 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000746 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000747 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000748 stream_ = send_stream;
749 }
750
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000751 void ModifyConfigs(VideoSendStream::Config* send_config,
752 std::vector<VideoReceiveStream::Config>* receive_configs,
753 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000754 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000755 send_config->pre_encode_callback = this;
756 send_config->suspend_below_min_bitrate = true;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000757 int min_bitrate_bps = encoder_config->streams[0].min_bitrate_bps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000758 set_low_remb_bps(min_bitrate_bps - 10000);
759 int threshold_window = std::max(min_bitrate_bps / 10, 10000);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000760 ASSERT_GT(encoder_config->streams[0].max_bitrate_bps,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000761 min_bitrate_bps + threshold_window + 5000);
762 set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
763 }
764
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000765 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000766 EXPECT_EQ(kEventSignaled, Wait())
767 << "Timed out during suspend-below-min-bitrate test.";
768 transport_.StopSending();
769 }
770
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000771 enum TestState {
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000772 kBeforeSuspend,
773 kDuringSuspend,
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000774 kWaitingForPacket,
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000775 kWaitingForStats
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000776 };
777
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000778 virtual void SendRtcpFeedback(int remb_value)
779 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000780 FakeReceiveStatistics receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000781 kSendSsrcs[0], last_sequence_number_, rtp_count_, 0);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000782 RTCPSender rtcp_sender(0, false, clock_, &receive_stats, nullptr);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000783 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
784
785 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000786 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000787 if (remb_value > 0) {
788 rtcp_sender.SetREMBStatus(true);
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000789 rtcp_sender.SetREMBData(remb_value, std::vector<uint32_t>());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000790 }
791 RTCPSender::FeedbackState feedback_state;
792 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
793 }
794
795 internal::TransportAdapter transport_adapter_;
796 test::DirectTransport transport_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000797 Clock* const clock_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000798 VideoSendStream* stream_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000799
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000800 const rtc::scoped_ptr<CriticalSectionWrapper> crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000801 TestState test_state_ GUARDED_BY(crit_);
802 int rtp_count_ GUARDED_BY(crit_);
803 int last_sequence_number_ GUARDED_BY(crit_);
804 int suspended_frame_count_ GUARDED_BY(crit_);
805 int low_remb_bps_ GUARDED_BY(crit_);
806 int high_remb_bps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000807 } test;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000808
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000809 RunBaseTest(&test);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000810}
811
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000812TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000813 class NoPaddingWhenVideoIsMuted : public test::SendTest {
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000814 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000815 NoPaddingWhenVideoIsMuted()
816 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000817 clock_(Clock::GetRealTimeClock()),
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000818 transport_adapter_(ReceiveTransport()),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000819 crit_(CriticalSectionWrapper::CreateCriticalSection()),
820 last_packet_time_ms_(-1),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000821 capturer_(nullptr) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000822 transport_adapter_.Enable();
823 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000824
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000825 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000826 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000827 CriticalSectionScoped lock(crit_.get());
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000828 last_packet_time_ms_ = clock_->TimeInMilliseconds();
829 capturer_->Stop();
830 return SEND_PACKET;
831 }
832
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000833 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000834 CriticalSectionScoped lock(crit_.get());
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000835 const int kVideoMutedThresholdMs = 10000;
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000836 if (last_packet_time_ms_ > 0 &&
837 clock_->TimeInMilliseconds() - last_packet_time_ms_ >
838 kVideoMutedThresholdMs)
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000839 observation_complete_->Set();
840 // Receive statistics reporting having lost 50% of the packets.
841 FakeReceiveStatistics receive_stats(kSendSsrcs[0], 1, 1, 0);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000842 RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(),
843 &receive_stats, nullptr);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000844 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
845
846 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
847 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
848
849 RTCPSender::FeedbackState feedback_state;
850
851 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
852 return SEND_PACKET;
853 }
854
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000855 void SetReceivers(PacketReceiver* send_transport_receiver,
856 PacketReceiver* receive_transport_receiver) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000857 RtpRtcpObserver::SetReceivers(send_transport_receiver,
858 send_transport_receiver);
859 }
860
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000861 size_t GetNumStreams() const override { return 3; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000862
863 virtual void OnFrameGeneratorCapturerCreated(
864 test::FrameGeneratorCapturer* frame_generator_capturer) {
865 CriticalSectionScoped lock(crit_.get());
866 capturer_ = frame_generator_capturer;
867 }
868
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000869 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000870 EXPECT_EQ(kEventSignaled, Wait())
871 << "Timed out while waiting for RTP packets to stop being sent.";
872 }
873
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000874 Clock* const clock_;
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000875 internal::TransportAdapter transport_adapter_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000876 const rtc::scoped_ptr<CriticalSectionWrapper> crit_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000877 int64_t last_packet_time_ms_ GUARDED_BY(crit_);
878 test::FrameGeneratorCapturer* capturer_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000879 } test;
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000880
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000881 RunBaseTest(&test);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000882}
883
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000884// This test first observes "high" bitrate use at which point it sends a REMB to
885// indicate that it should be lowered significantly. The test then observes that
886// the bitrate observed is sinking well below the min-transmit-bitrate threshold
887// to verify that the min-transmit bitrate respects incoming REMB.
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000888//
889// Note that the test starts at "high" bitrate and does not ramp up to "higher"
890// bitrate since no receiver block or remb is sent in the initial phase.
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000891TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
892 static const int kMinTransmitBitrateBps = 400000;
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000893 static const int kHighBitrateBps = 150000;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000894 static const int kRembBitrateBps = 80000;
895 static const int kRembRespectedBitrateBps = 100000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000896 class BitrateObserver : public test::SendTest, public PacketReceiver {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000897 public:
898 BitrateObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000899 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000900 feedback_transport_(ReceiveTransport()),
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000901 bitrate_capped_(false) {
902 RtpRtcp::Configuration config;
903 feedback_transport_.Enable();
904 config.outgoing_transport = &feedback_transport_;
905 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
906 rtp_rtcp_->SetREMBStatus(true);
907 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
908 }
909
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000910 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000911 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000912 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000913 stream_ = send_stream;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000914 }
915
916 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000917 DeliveryStatus DeliverPacket(const uint8_t* packet,
918 size_t length) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000919 if (RtpHeaderParser::IsRtcp(packet, length))
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000920 return DELIVERY_OK;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000921
922 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000923 if (!parser_->Parse(packet, length, &header))
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000924 return DELIVERY_PACKET_ERROR;
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000925 DCHECK(stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000926 VideoSendStream::Stats stats = stream_->GetStats();
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000927 if (!stats.substreams.empty()) {
928 EXPECT_EQ(1u, stats.substreams.size());
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000929 int total_bitrate_bps =
930 stats.substreams.begin()->second.total_bitrate_bps;
931 test::PrintResult("bitrate_stats_",
932 "min_transmit_bitrate_low_remb",
933 "bitrate_bps",
934 static_cast<size_t>(total_bitrate_bps),
935 "bps",
936 false);
937 if (total_bitrate_bps > kHighBitrateBps) {
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000938 rtp_rtcp_->SetREMBData(kRembBitrateBps,
939 std::vector<uint32_t>(1, header.ssrc));
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000940 rtp_rtcp_->Process();
941 bitrate_capped_ = true;
942 } else if (bitrate_capped_ &&
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000943 total_bitrate_bps < kRembRespectedBitrateBps) {
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000944 observation_complete_->Set();
945 }
946 }
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +0000947 return DELIVERY_OK;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000948 }
949
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000950 void SetReceivers(PacketReceiver* send_transport_receiver,
951 PacketReceiver* receive_transport_receiver) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000952 RtpRtcpObserver::SetReceivers(this, send_transport_receiver);
953 }
954
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000955 void ModifyConfigs(VideoSendStream::Config* send_config,
956 std::vector<VideoReceiveStream::Config>* receive_configs,
957 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +0000958 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000959 }
960
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000961 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000962 EXPECT_EQ(kEventSignaled, Wait())
963 << "Timeout while waiting for low bitrate stats after REMB.";
964 }
965
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000966 rtc::scoped_ptr<RtpRtcp> rtp_rtcp_;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000967 internal::TransportAdapter feedback_transport_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000968 VideoSendStream* stream_;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000969 bool bitrate_capped_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000970 } test;
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000971
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000972 RunBaseTest(&test);
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000973}
974
pbos@webrtc.org143451d2015-03-18 14:40:03 +0000975TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) {
976 class StartBitrateObserver : public test::FakeEncoder {
977 public:
978 StartBitrateObserver()
979 : FakeEncoder(Clock::GetRealTimeClock()), start_bitrate_kbps_(0) {}
980 int32_t InitEncode(const VideoCodec* config,
981 int32_t number_of_cores,
982 size_t max_payload_size) override {
983 rtc::CritScope lock(&crit_);
984 start_bitrate_kbps_ = config->startBitrate;
985 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
986 }
987
988 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
989 rtc::CritScope lock(&crit_);
990 start_bitrate_kbps_ = new_target_bitrate;
991 return FakeEncoder::SetRates(new_target_bitrate, framerate);
992 }
993
994 int GetStartBitrateKbps() const {
995 rtc::CritScope lock(&crit_);
996 return start_bitrate_kbps_;
997 }
998
999 private:
1000 mutable rtc::CriticalSection crit_;
1001 int start_bitrate_kbps_ GUARDED_BY(crit_);
1002 };
1003
1004 test::NullTransport transport;
1005 CreateSenderCall(Call::Config(&transport));
1006
1007 CreateSendConfig(1);
1008
1009 Call::Config::BitrateConfig bitrate_config;
1010 bitrate_config.start_bitrate_bps =
1011 2 * encoder_config_.streams[0].max_bitrate_bps;
1012 sender_call_->SetBitrateConfig(bitrate_config);
1013
1014 StartBitrateObserver encoder;
1015 send_config_.encoder_settings.encoder = &encoder;
1016
1017 CreateStreams();
1018
1019 EXPECT_EQ(encoder_config_.streams[0].max_bitrate_bps / 1000,
1020 encoder.GetStartBitrateKbps());
1021
1022 encoder_config_.streams[0].max_bitrate_bps =
1023 2 * bitrate_config.start_bitrate_bps;
1024 send_stream_->ReconfigureVideoEncoder(encoder_config_);
1025
1026 // New bitrate should be reconfigured above the previous max. As there's no
1027 // network connection this shouldn't be flaky, as no bitrate should've been
1028 // reported in between.
1029 EXPECT_EQ(bitrate_config.start_bitrate_bps / 1000,
1030 encoder.GetStartBitrateKbps());
1031
1032 DestroyStreams();
1033}
1034
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001035TEST_F(VideoSendStreamTest, CapturesTextureAndI420VideoFrames) {
1036 class FrameObserver : public I420FrameCallback {
1037 public:
1038 FrameObserver() : output_frame_event_(EventWrapper::Create()) {}
1039
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001040 void FrameCallback(I420VideoFrame* video_frame) override {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001041 output_frames_.push_back(*video_frame);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001042 output_frame_event_->Set();
1043 }
1044
1045 void WaitOutputFrame() {
1046 const unsigned long kWaitFrameTimeoutMs = 3000;
1047 EXPECT_EQ(kEventSignaled, output_frame_event_->Wait(kWaitFrameTimeoutMs))
1048 << "Timeout while waiting for output frames.";
1049 }
1050
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001051 const std::vector<I420VideoFrame>& output_frames() const {
1052 return output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001053 }
1054
1055 private:
1056 // Delivered output frames.
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001057 std::vector<I420VideoFrame> output_frames_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001058
1059 // Indicate an output frame has arrived.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001060 rtc::scoped_ptr<EventWrapper> output_frame_event_;
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001061 };
1062
1063 // Initialize send stream.
1064 test::NullTransport transport;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001065 CreateSenderCall(Call::Config(&transport));
1066
1067 CreateSendConfig(1);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001068 FrameObserver observer;
1069 send_config_.pre_encode_callback = &observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001070 CreateStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001071
magjed@webrtc.org45cdcce2015-03-06 10:41:00 +00001072 // Prepare five input frames. Send ordinary I420VideoFrame and texture frames
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001073 // alternatively.
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001074 std::vector<I420VideoFrame> input_frames;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001075 int width = static_cast<int>(encoder_config_.streams[0].width);
1076 int height = static_cast<int>(encoder_config_.streams[0].height);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001077 webrtc::RefCountImpl<FakeNativeHandle>* handle1 =
1078 new webrtc::RefCountImpl<FakeNativeHandle>();
1079 webrtc::RefCountImpl<FakeNativeHandle>* handle2 =
1080 new webrtc::RefCountImpl<FakeNativeHandle>();
1081 webrtc::RefCountImpl<FakeNativeHandle>* handle3 =
1082 new webrtc::RefCountImpl<FakeNativeHandle>();
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001083 input_frames.push_back(I420VideoFrame(handle1, width, height, 1, 1));
1084 input_frames.push_back(I420VideoFrame(handle2, width, height, 2, 2));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001085 input_frames.push_back(CreateI420VideoFrame(width, height, 3));
1086 input_frames.push_back(CreateI420VideoFrame(width, height, 4));
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001087 input_frames.push_back(I420VideoFrame(handle3, width, height, 5, 5));
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001088
1089 send_stream_->Start();
1090 for (size_t i = 0; i < input_frames.size(); i++) {
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001091 send_stream_->Input()->IncomingCapturedFrame(input_frames[i]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001092 // Do not send the next frame too fast, so the frame dropper won't drop it.
1093 if (i < input_frames.size() - 1)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001094 SleepMs(1000 / encoder_config_.streams[0].max_framerate);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001095 // Wait until the output frame is received before sending the next input
1096 // frame. Or the previous input frame may be replaced without delivering.
1097 observer.WaitOutputFrame();
1098 }
1099 send_stream_->Stop();
1100
1101 // Test if the input and output frames are the same. render_time_ms and
1102 // timestamp are not compared because capturer sets those values.
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001103 ExpectEqualFramesVector(input_frames, observer.output_frames());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001104
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001105 DestroyStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001106}
1107
1108void ExpectEqualFrames(const I420VideoFrame& frame1,
1109 const I420VideoFrame& frame2) {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001110 if (frame1.native_handle() != nullptr || frame2.native_handle() != nullptr)
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001111 ExpectEqualTextureFrames(frame1, frame2);
1112 else
1113 ExpectEqualBufferFrames(frame1, frame2);
1114}
1115
1116void ExpectEqualTextureFrames(const I420VideoFrame& frame1,
1117 const I420VideoFrame& frame2) {
1118 EXPECT_EQ(frame1.native_handle(), frame2.native_handle());
1119 EXPECT_EQ(frame1.width(), frame2.width());
1120 EXPECT_EQ(frame1.height(), frame2.height());
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001121 EXPECT_EQ(frame1.render_time_ms(), frame2.render_time_ms());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001122}
1123
1124void ExpectEqualBufferFrames(const I420VideoFrame& frame1,
1125 const I420VideoFrame& frame2) {
1126 EXPECT_EQ(frame1.width(), frame2.width());
1127 EXPECT_EQ(frame1.height(), frame2.height());
1128 EXPECT_EQ(frame1.stride(kYPlane), frame2.stride(kYPlane));
1129 EXPECT_EQ(frame1.stride(kUPlane), frame2.stride(kUPlane));
1130 EXPECT_EQ(frame1.stride(kVPlane), frame2.stride(kVPlane));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001131 EXPECT_EQ(frame1.render_time_ms(), frame2.render_time_ms());
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001132 ASSERT_EQ(frame1.allocated_size(kYPlane), frame2.allocated_size(kYPlane));
1133 EXPECT_EQ(0,
1134 memcmp(frame1.buffer(kYPlane),
1135 frame2.buffer(kYPlane),
1136 frame1.allocated_size(kYPlane)));
1137 ASSERT_EQ(frame1.allocated_size(kUPlane), frame2.allocated_size(kUPlane));
1138 EXPECT_EQ(0,
1139 memcmp(frame1.buffer(kUPlane),
1140 frame2.buffer(kUPlane),
1141 frame1.allocated_size(kUPlane)));
1142 ASSERT_EQ(frame1.allocated_size(kVPlane), frame2.allocated_size(kVPlane));
1143 EXPECT_EQ(0,
1144 memcmp(frame1.buffer(kVPlane),
1145 frame2.buffer(kVPlane),
1146 frame1.allocated_size(kVPlane)));
1147}
1148
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001149void ExpectEqualFramesVector(const std::vector<I420VideoFrame>& frames1,
1150 const std::vector<I420VideoFrame>& frames2) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001151 EXPECT_EQ(frames1.size(), frames2.size());
1152 for (size_t i = 0; i < std::min(frames1.size(), frames2.size()); ++i)
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001153 ExpectEqualFrames(frames1[i], frames2[i]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001154}
1155
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001156I420VideoFrame CreateI420VideoFrame(int width, int height, uint8_t data) {
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001157 const int kSizeY = width * height * 2;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001158 rtc::scoped_ptr<uint8_t[]> buffer(new uint8_t[kSizeY]);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001159 memset(buffer.get(), data, kSizeY);
magjed@webrtc.org2d2a30c2015-03-24 12:37:36 +00001160 I420VideoFrame frame;
1161 frame.CreateFrame(buffer.get(), buffer.get(), buffer.get(), width, height,
1162 width, width / 2, width / 2);
1163 frame.set_timestamp(data);
1164 frame.set_render_time_ms(data);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001165 return frame;
1166}
1167
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001168TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
1169 class EncoderStateObserver : public test::SendTest, public VideoEncoder {
1170 public:
1171 EncoderStateObserver()
1172 : SendTest(kDefaultTimeoutMs),
1173 crit_(CriticalSectionWrapper::CreateCriticalSection()),
1174 initialized_(false),
1175 callback_registered_(false),
1176 num_releases_(0),
1177 released_(false) {}
1178
1179 bool IsReleased() {
1180 CriticalSectionScoped lock(crit_.get());
1181 return released_;
1182 }
1183
1184 bool IsReadyForEncode() {
1185 CriticalSectionScoped lock(crit_.get());
1186 return initialized_ && callback_registered_;
1187 }
1188
1189 size_t num_releases() {
1190 CriticalSectionScoped lock(crit_.get());
1191 return num_releases_;
1192 }
1193
1194 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001195 int32_t InitEncode(const VideoCodec* codecSettings,
1196 int32_t numberOfCores,
1197 size_t maxPayloadSize) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001198 CriticalSectionScoped lock(crit_.get());
1199 EXPECT_FALSE(initialized_);
1200 initialized_ = true;
1201 released_ = false;
1202 return 0;
1203 }
1204
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001205 int32_t Encode(const I420VideoFrame& inputImage,
1206 const CodecSpecificInfo* codecSpecificInfo,
1207 const std::vector<VideoFrameType>* frame_types) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001208 EXPECT_TRUE(IsReadyForEncode());
1209
1210 observation_complete_->Set();
1211 return 0;
1212 }
1213
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001214 int32_t RegisterEncodeCompleteCallback(
1215 EncodedImageCallback* callback) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001216 CriticalSectionScoped lock(crit_.get());
1217 EXPECT_TRUE(initialized_);
1218 callback_registered_ = true;
1219 return 0;
1220 }
1221
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001222 int32_t Release() override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001223 CriticalSectionScoped lock(crit_.get());
1224 EXPECT_TRUE(IsReadyForEncode());
1225 EXPECT_FALSE(released_);
1226 initialized_ = false;
1227 callback_registered_ = false;
1228 released_ = true;
1229 ++num_releases_;
1230 return 0;
1231 }
1232
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001233 int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001234 EXPECT_TRUE(IsReadyForEncode());
1235 return 0;
1236 }
1237
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001238 int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001239 EXPECT_TRUE(IsReadyForEncode());
1240 return 0;
1241 }
1242
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001243 void OnStreamsCreated(
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001244 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001245 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001246 // Encoder initialization should be done in stream construction before
1247 // starting.
1248 EXPECT_TRUE(IsReadyForEncode());
1249 stream_ = send_stream;
1250 }
1251
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001252 void ModifyConfigs(VideoSendStream::Config* send_config,
1253 std::vector<VideoReceiveStream::Config>* receive_configs,
1254 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001255 send_config->encoder_settings.encoder = this;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001256 encoder_config_ = *encoder_config;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001257 }
1258
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001259 void PerformTest() override {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001260 EXPECT_EQ(kEventSignaled, Wait())
1261 << "Timed out while waiting for Encode.";
1262 EXPECT_EQ(0u, num_releases());
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001263 stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001264 EXPECT_EQ(0u, num_releases());
1265 stream_->Stop();
1266 // Encoder should not be released before destroying the VideoSendStream.
1267 EXPECT_FALSE(IsReleased());
1268 EXPECT_TRUE(IsReadyForEncode());
1269 stream_->Start();
1270 // Sanity check, make sure we still encode frames with this encoder.
1271 EXPECT_EQ(kEventSignaled, Wait())
1272 << "Timed out while waiting for Encode.";
1273 }
1274
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001275 rtc::scoped_ptr<CriticalSectionWrapper> crit_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001276 VideoSendStream* stream_;
1277 bool initialized_ GUARDED_BY(crit_);
1278 bool callback_registered_ GUARDED_BY(crit_);
1279 size_t num_releases_ GUARDED_BY(crit_);
1280 bool released_ GUARDED_BY(crit_);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001281 VideoEncoderConfig encoder_config_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001282 } test_encoder;
1283
1284 RunBaseTest(&test_encoder);
1285
1286 EXPECT_TRUE(test_encoder.IsReleased());
1287 EXPECT_EQ(1u, test_encoder.num_releases());
1288}
1289
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001290TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
1291 class VideoCodecConfigObserver : public test::SendTest,
1292 public test::FakeEncoder {
1293 public:
1294 VideoCodecConfigObserver()
1295 : SendTest(kDefaultTimeoutMs),
1296 FakeEncoder(Clock::GetRealTimeClock()),
1297 num_initializations_(0) {}
1298
1299 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001300 void ModifyConfigs(VideoSendStream::Config* send_config,
1301 std::vector<VideoReceiveStream::Config>* receive_configs,
1302 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001303 send_config->encoder_settings.encoder = this;
1304 encoder_config_ = *encoder_config;
1305 }
1306
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001307 void OnStreamsCreated(
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001308 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001309 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001310 stream_ = send_stream;
1311 }
1312
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001313 int32_t InitEncode(const VideoCodec* config,
1314 int32_t number_of_cores,
1315 size_t max_payload_size) override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001316 if (num_initializations_ == 0) {
1317 // Verify default values.
1318 EXPECT_EQ(kRealtimeVideo, config->mode);
1319 } else {
1320 // Verify that changed values are propagated.
1321 EXPECT_EQ(kScreensharing, config->mode);
1322 }
1323 ++num_initializations_;
1324 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1325 }
1326
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001327 void PerformTest() override {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001328 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1329
1330 encoder_config_.content_type = VideoEncoderConfig::kScreenshare;
1331 stream_->ReconfigureVideoEncoder(encoder_config_);
1332 EXPECT_EQ(2u, num_initializations_)
1333 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1334 "new encoder settings.";
1335 }
1336
1337 size_t num_initializations_;
1338 VideoSendStream* stream_;
1339 VideoEncoderConfig encoder_config_;
1340 } test;
1341
1342 RunBaseTest(&test);
1343}
1344
Peter Boström53eda3d2015-03-27 15:53:18 +01001345static const size_t kVideoCodecConfigObserverNumberOfTemporalLayers = 4;
1346template <typename T>
1347class VideoCodecConfigObserver : public test::SendTest,
1348 public test::FakeEncoder {
1349
1350 public:
1351 VideoCodecConfigObserver(VideoCodecType video_codec_type,
1352 const char* codec_name)
1353 : SendTest(VideoSendStreamTest::kDefaultTimeoutMs),
1354 FakeEncoder(Clock::GetRealTimeClock()),
1355 video_codec_type_(video_codec_type),
1356 codec_name_(codec_name),
1357 num_initializations_(0) {
1358 memset(&encoder_settings_, 0, sizeof(encoder_settings_));
1359 }
1360
1361 private:
1362 void ModifyConfigs(VideoSendStream::Config* send_config,
1363 std::vector<VideoReceiveStream::Config>* receive_configs,
1364 VideoEncoderConfig* encoder_config) override {
1365 send_config->encoder_settings.encoder = this;
1366 send_config->encoder_settings.payload_name = codec_name_;
1367
1368 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
1369 encoder_config->streams[i].temporal_layer_thresholds_bps.resize(
1370 kVideoCodecConfigObserverNumberOfTemporalLayers - 1);
1371 }
1372
1373 encoder_config->encoder_specific_settings = &encoder_settings_;
1374 encoder_config_ = *encoder_config;
1375 }
1376
1377 void OnStreamsCreated(
1378 VideoSendStream* send_stream,
1379 const std::vector<VideoReceiveStream*>& receive_streams) override {
1380 stream_ = send_stream;
1381 }
1382
1383 int32_t InitEncode(const VideoCodec* config,
1384 int32_t number_of_cores,
1385 size_t max_payload_size) override {
1386 EXPECT_EQ(video_codec_type_, config->codecType);
1387 VerifyCodecSpecifics(*config);
1388 ++num_initializations_;
1389 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1390 }
1391
1392 void VerifyCodecSpecifics(const VideoCodec& config) const;
1393
1394 void PerformTest() override {
1395 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1396
1397 encoder_settings_.frameDroppingOn = true;
1398 stream_->ReconfigureVideoEncoder(encoder_config_);
1399 EXPECT_EQ(2u, num_initializations_)
1400 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1401 "new encoder settings.";
1402 }
1403
1404 int32_t Encode(const I420VideoFrame& input_image,
1405 const CodecSpecificInfo* codec_specific_info,
1406 const std::vector<VideoFrameType>* frame_types) override {
1407 // Silently skip the encode, FakeEncoder::Encode doesn't produce VP8.
1408 return 0;
1409 }
1410
1411 T encoder_settings_;
1412 const VideoCodecType video_codec_type_;
1413 const char* const codec_name_;
1414 size_t num_initializations_;
1415 VideoSendStream* stream_;
1416 VideoEncoderConfig encoder_config_;
1417};
1418
1419template <>
1420void VideoCodecConfigObserver<VideoCodecH264>::VerifyCodecSpecifics(
1421 const VideoCodec& config) const {
1422 EXPECT_EQ(0, memcmp(&config.codecSpecific.H264, &encoder_settings_,
1423 sizeof(encoder_settings_)));
1424}
1425template <>
1426void VideoCodecConfigObserver<VideoCodecVP8>::VerifyCodecSpecifics(
1427 const VideoCodec& config) const {
1428 // Check that the number of temporal layers has propagated properly to
1429 // VideoCodec.
1430 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1431 config.codecSpecific.VP8.numberOfTemporalLayers);
1432
1433 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1434 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1435 config.simulcastStream[i].numberOfTemporalLayers);
1436 }
1437
1438 // Set expected temporal layers as they should have been set when
1439 // reconfiguring the encoder and not match the set config.
1440 VideoCodecVP8 encoder_settings = encoder_settings_;
1441 encoder_settings.numberOfTemporalLayers =
1442 kVideoCodecConfigObserverNumberOfTemporalLayers;
1443 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP8, &encoder_settings,
1444 sizeof(encoder_settings_)));
1445}
1446template <>
1447void VideoCodecConfigObserver<VideoCodecVP9>::VerifyCodecSpecifics(
1448 const VideoCodec& config) const {
1449 // Check that the number of temporal layers has propagated properly to
1450 // VideoCodec.
1451 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1452 config.codecSpecific.VP9.numberOfTemporalLayers);
1453
1454 for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
1455 EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
1456 config.simulcastStream[i].numberOfTemporalLayers);
1457 }
1458
1459 // Set expected temporal layers as they should have been set when
1460 // reconfiguring the encoder and not match the set config.
1461 VideoCodecVP9 encoder_settings = encoder_settings_;
1462 encoder_settings.numberOfTemporalLayers =
1463 kVideoCodecConfigObserverNumberOfTemporalLayers;
1464 EXPECT_EQ(0, memcmp(&config.codecSpecific.VP9, &encoder_settings,
1465 sizeof(encoder_settings_)));
1466}
1467
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001468TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp8Config) {
Peter Boström53eda3d2015-03-27 15:53:18 +01001469 VideoCodecConfigObserver<VideoCodecVP8> test(kVideoCodecVP8, "VP8");
1470 RunBaseTest(&test);
1471}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001472
Peter Boström53eda3d2015-03-27 15:53:18 +01001473TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp9Config) {
1474 VideoCodecConfigObserver<VideoCodecVP9> test(kVideoCodecVP9, "VP9");
1475 RunBaseTest(&test);
1476}
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001477
Peter Boström53eda3d2015-03-27 15:53:18 +01001478TEST_F(VideoSendStreamTest, EncoderSetupPropagatesH264Config) {
1479 VideoCodecConfigObserver<VideoCodecH264> test(kVideoCodecH264, "H264");
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001480 RunBaseTest(&test);
1481}
1482
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001483TEST_F(VideoSendStreamTest, RtcpSenderReportContainsMediaBytesSent) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001484 class RtcpSenderReportTest : public test::SendTest {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001485 public:
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001486 RtcpSenderReportTest() : SendTest(kDefaultTimeoutMs),
1487 rtp_packets_sent_(0),
1488 media_bytes_sent_(0) {}
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001489
1490 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001491 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001492 RTPHeader header;
1493 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001494 ++rtp_packets_sent_;
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001495 media_bytes_sent_ += length - header.headerLength - header.paddingLength;
1496 return SEND_PACKET;
1497 }
1498
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001499 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001500 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1501 EXPECT_TRUE(parser.IsValid());
1502
1503 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001504 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1505 if (packet_type == RTCPUtility::kRtcpSrCode) {
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001506 // Only compare sent media bytes if SenderPacketCount matches the
1507 // number of sent rtp packets (a new rtp packet could be sent before
1508 // the rtcp packet).
1509 if (parser.Packet().SR.SenderOctetCount > 0 &&
1510 parser.Packet().SR.SenderPacketCount == rtp_packets_sent_) {
1511 EXPECT_EQ(media_bytes_sent_, parser.Packet().SR.SenderOctetCount);
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001512 observation_complete_->Set();
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001513 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001514 }
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001515 packet_type = parser.Iterate();
1516 }
1517
1518 return SEND_PACKET;
1519 }
1520
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001521 void PerformTest() override {
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001522 EXPECT_EQ(kEventSignaled, Wait())
1523 << "Timed out while waiting for RTCP sender report.";
1524 }
1525
asapersson@webrtc.org14674212015-02-23 08:14:07 +00001526 size_t rtp_packets_sent_;
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001527 size_t media_bytes_sent_;
1528 } test;
1529
1530 RunBaseTest(&test);
1531}
1532
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001533TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
1534 static const int kScreencastTargetBitrateKbps = 200;
1535 class ScreencastTargetBitrateTest : public test::SendTest,
1536 public test::FakeEncoder {
1537 public:
1538 ScreencastTargetBitrateTest()
1539 : SendTest(kDefaultTimeoutMs),
1540 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1541
1542 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001543 int32_t InitEncode(const VideoCodec* config,
1544 int32_t number_of_cores,
1545 size_t max_payload_size) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001546 EXPECT_EQ(static_cast<unsigned int>(kScreencastTargetBitrateKbps),
1547 config->targetBitrate);
1548 observation_complete_->Set();
1549 return test::FakeEncoder::InitEncode(
1550 config, number_of_cores, max_payload_size);
1551 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001552 void ModifyConfigs(VideoSendStream::Config* send_config,
1553 std::vector<VideoReceiveStream::Config>* receive_configs,
1554 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001555 send_config->encoder_settings.encoder = this;
1556 EXPECT_EQ(1u, encoder_config->streams.size());
1557 EXPECT_TRUE(
1558 encoder_config->streams[0].temporal_layer_thresholds_bps.empty());
1559 encoder_config->streams[0].temporal_layer_thresholds_bps.push_back(
1560 kScreencastTargetBitrateKbps * 1000);
1561 encoder_config->content_type = VideoEncoderConfig::kScreenshare;
1562 }
1563
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001564 void PerformTest() override {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001565 EXPECT_EQ(kEventSignaled, Wait())
1566 << "Timed out while waiting for the encoder to be initialized.";
1567 }
1568 } test;
1569
1570 RunBaseTest(&test);
1571}
pbos@webrtc.org00873182014-11-25 14:03:34 +00001572
Stefan Holmere5904162015-03-26 11:11:06 +01001573TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001574 // These are chosen to be "kind of odd" to not be accidentally checked against
1575 // default values.
1576 static const int kMinBitrateKbps = 137;
1577 static const int kStartBitrateKbps = 345;
1578 static const int kLowerMaxBitrateKbps = 312;
1579 static const int kMaxBitrateKbps = 413;
1580 static const int kIncreasedStartBitrateKbps = 451;
1581 static const int kIncreasedMaxBitrateKbps = 597;
1582 class EncoderBitrateThresholdObserver : public test::SendTest,
1583 public test::FakeEncoder {
1584 public:
1585 EncoderBitrateThresholdObserver()
1586 : SendTest(kDefaultTimeoutMs),
1587 FakeEncoder(Clock::GetRealTimeClock()),
1588 num_initializations_(0) {}
1589
1590 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001591 int32_t InitEncode(const VideoCodec* codecSettings,
1592 int32_t numberOfCores,
1593 size_t maxPayloadSize) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001594 if (num_initializations_ == 0) {
1595 EXPECT_EQ(static_cast<unsigned int>(kMinBitrateKbps),
1596 codecSettings->minBitrate);
1597 EXPECT_EQ(static_cast<unsigned int>(kStartBitrateKbps),
1598 codecSettings->startBitrate);
1599 EXPECT_EQ(static_cast<unsigned int>(kMaxBitrateKbps),
1600 codecSettings->maxBitrate);
1601 observation_complete_->Set();
1602 } else if (num_initializations_ == 1) {
1603 EXPECT_EQ(static_cast<unsigned int>(kLowerMaxBitrateKbps),
1604 codecSettings->maxBitrate);
1605 // The start bitrate should be kept (-1) and capped to the max bitrate.
1606 // Since this is not an end-to-end call no receiver should have been
1607 // returning a REMB that could lower this estimate.
1608 EXPECT_EQ(codecSettings->startBitrate, codecSettings->maxBitrate);
1609 } else if (num_initializations_ == 2) {
1610 EXPECT_EQ(static_cast<unsigned int>(kIncreasedMaxBitrateKbps),
1611 codecSettings->maxBitrate);
1612 EXPECT_EQ(static_cast<unsigned int>(kIncreasedStartBitrateKbps),
1613 codecSettings->startBitrate);
1614 }
1615 ++num_initializations_;
1616 return FakeEncoder::InitEncode(codecSettings, numberOfCores,
1617 maxPayloadSize);
1618 }
1619
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001620 Call::Config GetSenderCallConfig() override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001621 Call::Config config(SendTransport());
Stefan Holmere5904162015-03-26 11:11:06 +01001622 config.bitrate_config.min_bitrate_bps = kMinBitrateKbps * 1000;
1623 config.bitrate_config.start_bitrate_bps = kStartBitrateKbps * 1000;
1624 config.bitrate_config.max_bitrate_bps = kMaxBitrateKbps * 1000;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001625 return config;
1626 }
1627
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001628 void ModifyConfigs(VideoSendStream::Config* send_config,
1629 std::vector<VideoReceiveStream::Config>* receive_configs,
1630 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001631 send_config->encoder_settings.encoder = this;
1632 // Set bitrates lower/higher than min/max to make sure they are properly
1633 // capped.
Stefan Holmere5904162015-03-26 11:11:06 +01001634 encoder_config->streams.front().min_bitrate_bps = kMinBitrateKbps * 1000;
1635 encoder_config->streams.front().max_bitrate_bps = kMaxBitrateKbps * 1000;
1636 encoder_config_ = *encoder_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001637 }
1638
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001639 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001640 call_ = sender_call;
1641 }
1642
Stefan Holmere5904162015-03-26 11:11:06 +01001643 void OnStreamsCreated(
1644 VideoSendStream* send_stream,
1645 const std::vector<VideoReceiveStream*>& receive_streams) override {
1646 send_stream_ = send_stream;
1647 }
1648
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001649 void PerformTest() override {
pbos@webrtc.org00873182014-11-25 14:03:34 +00001650 Call::Config::BitrateConfig bitrate_config;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001651 bitrate_config.start_bitrate_bps = kIncreasedStartBitrateKbps * 1000;
1652 bitrate_config.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000;
1653 call_->SetBitrateConfig(bitrate_config);
Stefan Holmere5904162015-03-26 11:11:06 +01001654 EXPECT_EQ(kEventSignaled, Wait())
1655 << "Timed out while waiting encoder to be configured.";
1656 encoder_config_.streams[0].min_bitrate_bps = 0;
1657 encoder_config_.streams[0].max_bitrate_bps = kLowerMaxBitrateKbps * 1000;
1658 send_stream_->ReconfigureVideoEncoder(encoder_config_);
1659 EXPECT_EQ(2, num_initializations_)
1660 << "Encoder should have been reconfigured with the new value.";
1661 encoder_config_.streams[0].target_bitrate_bps =
1662 encoder_config_.streams[0].min_bitrate_bps;
1663 encoder_config_.streams[0].max_bitrate_bps =
1664 kIncreasedMaxBitrateKbps * 1000;
1665 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org00873182014-11-25 14:03:34 +00001666 EXPECT_EQ(3, num_initializations_)
1667 << "Encoder should have been reconfigured with the new value.";
1668 }
1669
1670 int num_initializations_;
1671 webrtc::Call* call_;
Stefan Holmere5904162015-03-26 11:11:06 +01001672 webrtc::VideoSendStream* send_stream_;
1673 webrtc::VideoEncoderConfig encoder_config_;
pbos@webrtc.org00873182014-11-25 14:03:34 +00001674 } test;
1675
1676 RunBaseTest(&test);
1677}
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001678
1679TEST_F(VideoSendStreamTest, ReportsSentResolution) {
1680 static const size_t kNumStreams = 3;
1681 // Unusual resolutions to make sure that they are the ones being reported.
1682 static const struct {
1683 int width;
1684 int height;
1685 } kEncodedResolution[kNumStreams] = {
1686 {241, 181}, {300, 121}, {121, 221}};
1687 class ScreencastTargetBitrateTest : public test::SendTest,
1688 public test::FakeEncoder {
1689 public:
1690 ScreencastTargetBitrateTest()
1691 : SendTest(kDefaultTimeoutMs),
1692 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1693
1694 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001695 int32_t Encode(const I420VideoFrame& input_image,
1696 const CodecSpecificInfo* codecSpecificInfo,
1697 const std::vector<VideoFrameType>* frame_types) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001698 CodecSpecificInfo specifics;
1699 memset(&specifics, 0, sizeof(specifics));
1700 specifics.codecType = kVideoCodecGeneric;
1701
1702 uint8_t buffer[16] = {0};
1703 EncodedImage encoded(buffer, sizeof(buffer), sizeof(buffer));
1704 encoded._timeStamp = input_image.timestamp();
1705 encoded.capture_time_ms_ = input_image.render_time_ms();
1706
1707 for (size_t i = 0; i < kNumStreams; ++i) {
1708 specifics.codecSpecific.generic.simulcast_idx = static_cast<uint8_t>(i);
1709 encoded._frameType = (*frame_types)[i];
1710 encoded._encodedWidth = kEncodedResolution[i].width;
1711 encoded._encodedHeight = kEncodedResolution[i].height;
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001712 DCHECK(callback_ != nullptr);
1713 if (callback_->Encoded(encoded, &specifics, nullptr) != 0)
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001714 return -1;
1715 }
1716
1717 observation_complete_->Set();
1718 return 0;
1719 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001720 void ModifyConfigs(VideoSendStream::Config* send_config,
1721 std::vector<VideoReceiveStream::Config>* receive_configs,
1722 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001723 send_config->encoder_settings.encoder = this;
1724 EXPECT_EQ(kNumStreams, encoder_config->streams.size());
1725 }
1726
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001727 size_t GetNumStreams() const override { return kNumStreams; }
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001728
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001729 void PerformTest() override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001730 EXPECT_EQ(kEventSignaled, Wait())
1731 << "Timed out while waiting for the encoder to send one frame.";
1732 VideoSendStream::Stats stats = send_stream_->GetStats();
1733
1734 for (size_t i = 0; i < kNumStreams; ++i) {
1735 ASSERT_TRUE(stats.substreams.find(kSendSsrcs[i]) !=
1736 stats.substreams.end())
1737 << "No stats for SSRC: " << kSendSsrcs[i]
1738 << ", stats should exist as soon as frames have been encoded.";
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001739 VideoSendStream::StreamStats ssrc_stats =
1740 stats.substreams[kSendSsrcs[i]];
1741 EXPECT_EQ(kEncodedResolution[i].width, ssrc_stats.width);
1742 EXPECT_EQ(kEncodedResolution[i].height, ssrc_stats.height);
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001743 }
1744 }
1745
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001746 void OnStreamsCreated(
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001747 VideoSendStream* send_stream,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001748 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001749 send_stream_ = send_stream;
1750 }
1751
1752 VideoSendStream* send_stream_;
1753 } test;
1754
1755 RunBaseTest(&test);
1756}
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +00001757} // namespace webrtc