blob: bbfd3822aa4cefe4c185dfb22245575ba1655202 [file] [log] [blame]
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +000010#include <algorithm> // max
11
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000012#include "testing/gtest/include/gtest/gtest.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000013
14#include "webrtc/call.h"
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +000015#include "webrtc/common_video/interface/i420_video_frame.h"
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000016#include "webrtc/common_video/interface/native_handle.h"
17#include "webrtc/common_video/interface/texture_video_frame.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000018#include "webrtc/frame_callback.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000019#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
pbos@webrtc.org709e2972014-03-19 10:59:52 +000020#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000021#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
pbos@webrtc.org013d9942013-08-22 09:42:17 +000022#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +000023#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000024#include "webrtc/system_wrappers/interface/event_wrapper.h"
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000025#include "webrtc/system_wrappers/interface/ref_count.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000026#include "webrtc/system_wrappers/interface/scoped_ptr.h"
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000027#include "webrtc/system_wrappers/interface/scoped_vector.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.org16e03b72013-10-28 16:32:01 +000035#include "webrtc/video/transport_adapter.h"
36#include "webrtc/video_send_stream.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000037
38namespace webrtc {
39
sprang@webrtc.org346094c2014-02-18 08:40:33 +000040enum VideoFormat { kGeneric, kVP8, };
41
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +000042void ExpectEqualFrames(const I420VideoFrame& frame1,
43 const I420VideoFrame& frame2);
44void ExpectEqualTextureFrames(const I420VideoFrame& frame1,
45 const I420VideoFrame& frame2);
46void ExpectEqualBufferFrames(const I420VideoFrame& frame1,
47 const I420VideoFrame& frame2);
48void ExpectEqualFramesVector(const std::vector<I420VideoFrame*>& frames1,
49 const std::vector<I420VideoFrame*>& frames2);
50I420VideoFrame* CreateI420VideoFrame(int width, int height, uint8_t data);
51
52class FakeNativeHandle : public NativeHandle {
53 public:
54 FakeNativeHandle() {}
55 virtual ~FakeNativeHandle() {}
56 virtual void* GetHandle() { return NULL; }
57};
58
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000059class VideoSendStreamTest : public test::CallTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000060 protected:
stefan@webrtc.org69969e22013-11-15 12:32:15 +000061 void TestNackRetransmission(uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +000062 uint8_t retransmit_payload_type);
sprang@webrtc.org346094c2014-02-18 08:40:33 +000063 void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
pbos@webrtc.org013d9942013-08-22 09:42:17 +000064};
65
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000066TEST_F(VideoSendStreamTest, CanStartStartedStream) {
67 test::NullTransport transport;
68 Call::Config call_config(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000069 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000070
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000071 CreateSendConfig(1);
72 CreateStreams();
73 send_stream_->Start();
74 send_stream_->Start();
75 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000076}
77
78TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
79 test::NullTransport transport;
80 Call::Config call_config(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000081 CreateSenderCall(call_config);
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000082
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000083 CreateSendConfig(1);
84 CreateStreams();
85 send_stream_->Stop();
86 send_stream_->Stop();
87 DestroyStreams();
pbos@webrtc.orgf777cf22014-01-10 18:47:32 +000088}
89
pbos@webrtc.org013d9942013-08-22 09:42:17 +000090TEST_F(VideoSendStreamTest, SupportsCName) {
91 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000092 class CNameObserver : public test::SendTest {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000093 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000094 CNameObserver() : SendTest(kDefaultTimeoutMs) {}
pbos@webrtc.org013d9942013-08-22 09:42:17 +000095
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000096 private:
stefan@webrtc.org69969e22013-11-15 12:32:15 +000097 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.org013d9942013-08-22 09:42:17 +000098 RTCPUtility::RTCPParserV2 parser(packet, length, true);
99 EXPECT_TRUE(parser.IsValid());
100
101 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
102 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
103 if (packet_type == RTCPUtility::kRtcpSdesChunkCode) {
104 EXPECT_EQ(parser.Packet().CName.CName, kCName);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000105 observation_complete_->Set();
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000106 }
107
108 packet_type = parser.Iterate();
109 }
110
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000111 return SEND_PACKET;
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000112 }
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000113
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000114 virtual void ModifyConfigs(
115 VideoSendStream::Config* send_config,
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000116 std::vector<VideoReceiveStream::Config>* receive_configs,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000117 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
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000121 virtual void PerformTest() OVERRIDE {
122 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
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000139 virtual 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
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000152 virtual void ModifyConfigs(
153 VideoSendStream::Config* send_config,
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000154 std::vector<VideoReceiveStream::Config>* receive_configs,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000155 VideoEncoderConfig* encoder_config) OVERRIDE {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000156 send_config->rtp.extensions.push_back(
157 RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
158 }
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +0000159
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000160 virtual void PerformTest() OVERRIDE {
161 EXPECT_EQ(kEventSignaled, Wait())
162 << "Timed out while waiting for single RTP packet.";
163 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000164 } test;
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000165
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000166 RunBaseTest(&test);
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000167}
168
pbos@webrtc.org29023282013-09-11 10:14:56 +0000169TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
170 static const uint8_t kTOffsetExtensionId = 13;
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000171 static const int kEncodeDelayMs = 5;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000172 class TransmissionTimeOffsetObserver : public test::SendTest {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000173 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000174 TransmissionTimeOffsetObserver()
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000175 : SendTest(kDefaultTimeoutMs),
176 encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) {
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000177 EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
pbos@webrtc.org29023282013-09-11 10:14:56 +0000178 kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId));
179 }
180
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000181 private:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000182 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.org29023282013-09-11 10:14:56 +0000183 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000184 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000185
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000186 EXPECT_TRUE(header.extension.hasTransmissionTimeOffset);
187 EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000188 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000189 EXPECT_EQ(header.extension.absoluteSendTime, 0u);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000190 observation_complete_->Set();
pbos@webrtc.org29023282013-09-11 10:14:56 +0000191
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000192 return SEND_PACKET;
pbos@webrtc.org29023282013-09-11 10:14:56 +0000193 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000194
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000195 virtual void ModifyConfigs(
196 VideoSendStream::Config* send_config,
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000197 std::vector<VideoReceiveStream::Config>* receive_configs,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000198 VideoEncoderConfig* encoder_config) OVERRIDE {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000199 send_config->encoder_settings.encoder = &encoder_;
200 send_config->rtp.extensions.push_back(
201 RtpExtension(RtpExtension::kTOffset, kTOffsetExtensionId));
202 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000203
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000204 virtual void PerformTest() OVERRIDE {
205 EXPECT_EQ(kEventSignaled, Wait())
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +0000206 << "Timed out while waiting for a single RTP packet.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000207 }
pbos@webrtc.org29023282013-09-11 10:14:56 +0000208
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000209 test::DelayedEncoder encoder_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000210 } test;
211
212 RunBaseTest(&test);
pbos@webrtc.org29023282013-09-11 10:14:56 +0000213}
214
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000215class FakeReceiveStatistics : public NullReceiveStatistics {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000216 public:
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000217 FakeReceiveStatistics(uint32_t send_ssrc,
218 uint32_t last_sequence_number,
219 uint32_t cumulative_lost,
220 uint8_t fraction_lost)
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000221 : lossy_stats_(new LossyStatistician(last_sequence_number,
222 cumulative_lost,
223 fraction_lost)) {
224 stats_map_[send_ssrc] = lossy_stats_.get();
225 }
226
227 virtual StatisticianMap GetActiveStatisticians() const OVERRIDE {
228 return stats_map_;
229 }
230
231 virtual StreamStatistician* GetStatistician(uint32_t ssrc) const OVERRIDE {
232 return lossy_stats_.get();
233 }
234
235 private:
236 class LossyStatistician : public StreamStatistician {
237 public:
238 LossyStatistician(uint32_t extended_max_sequence_number,
239 uint32_t cumulative_lost,
240 uint8_t fraction_lost) {
241 stats_.fraction_lost = fraction_lost;
242 stats_.cumulative_lost = cumulative_lost;
243 stats_.extended_max_sequence_number = extended_max_sequence_number;
244 }
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000245 virtual bool GetStatistics(RtcpStatistics* statistics,
246 bool reset) OVERRIDE {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000247 *statistics = stats_;
248 return true;
249 }
250 virtual void GetDataCounters(uint32_t* bytes_received,
251 uint32_t* packets_received) const OVERRIDE {
252 *bytes_received = 0;
253 *packets_received = 0;
254 }
255 virtual uint32_t BitrateReceived() const OVERRIDE { return 0; }
256 virtual void ResetStatistics() OVERRIDE {}
257 virtual bool IsRetransmitOfOldPacket(const RTPHeader& header,
258 int min_rtt) const OVERRIDE {
259 return false;
260 }
261
262 virtual bool IsPacketInOrder(uint16_t sequence_number) const OVERRIDE {
263 return true;
264 }
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000265
266 RtcpStatistics stats_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000267 };
268
269 scoped_ptr<LossyStatistician> lossy_stats_;
270 StatisticianMap stats_map_;
271};
272
pbos@webrtc.org724947b2013-12-11 16:26:16 +0000273TEST_F(VideoSendStreamTest, SwapsI420VideoFrames) {
274 static const size_t kWidth = 320;
275 static const size_t kHeight = 240;
276
277 test::NullTransport transport;
278 Call::Config call_config(&transport);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000279 CreateSenderCall(call_config);
pbos@webrtc.org724947b2013-12-11 16:26:16 +0000280
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000281 CreateSendConfig(1);
282 CreateStreams();
283 send_stream_->Start();
pbos@webrtc.org724947b2013-12-11 16:26:16 +0000284
285 I420VideoFrame frame;
magjed@webrtc.org0b3d89b2014-11-12 08:58:49 +0000286 const int stride_uv = (kWidth + 1) / 2;
287 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, stride_uv, stride_uv);
pbos@webrtc.org724947b2013-12-11 16:26:16 +0000288 uint8_t* old_y_buffer = frame.buffer(kYPlane);
magjed@webrtc.org0b3d89b2014-11-12 08:58:49 +0000289 // Initialize memory to avoid DrMemory errors.
290 const int half_height = (kHeight + 1) / 2;
291 memset(frame.buffer(kYPlane), 0, kWidth * kHeight);
292 memset(frame.buffer(kUPlane), 0, stride_uv * half_height);
293 memset(frame.buffer(kVPlane), 0, stride_uv * half_height);
pbos@webrtc.org724947b2013-12-11 16:26:16 +0000294
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000295 send_stream_->Input()->SwapFrame(&frame);
pbos@webrtc.org724947b2013-12-11 16:26:16 +0000296
297 EXPECT_NE(frame.buffer(kYPlane), old_y_buffer);
298
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000299 DestroyStreams();
pbos@webrtc.org724947b2013-12-11 16:26:16 +0000300}
301
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000302TEST_F(VideoSendStreamTest, SupportsFec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000303 class FecObserver : public test::SendTest {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000304 public:
305 FecObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000306 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000307 transport_adapter_(SendTransport()),
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000308 send_count_(0),
309 received_media_(false),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000310 received_fec_(false) {
311 transport_adapter_.Enable();
312 }
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000313
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000314 private:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000315 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000316 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000317 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000318
319 // Send lossy receive reports to trigger FEC enabling.
320 if (send_count_++ % 2 != 0) {
321 // Receive statistics reporting having lost 50% of the packets.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000322 FakeReceiveStatistics lossy_receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000323 kSendSsrcs[0], header.sequenceNumber, send_count_ / 2, 127);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000324 RTCPSender rtcp_sender(
325 0, false, Clock::GetRealTimeClock(), &lossy_receive_stats);
326 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
327
328 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000329 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000330
331 RTCPSender::FeedbackState feedback_state;
332
333 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
334 }
335
336 EXPECT_EQ(kRedPayloadType, header.payloadType);
337
338 uint8_t encapsulated_payload_type = packet[header.headerLength];
339
340 if (encapsulated_payload_type == kUlpfecPayloadType) {
341 received_fec_ = true;
342 } else {
343 received_media_ = true;
344 }
345
346 if (received_media_ && received_fec_)
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000347 observation_complete_->Set();
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000348
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000349 return SEND_PACKET;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000350 }
351
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000352 virtual void ModifyConfigs(
353 VideoSendStream::Config* send_config,
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000354 std::vector<VideoReceiveStream::Config>* receive_configs,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000355 VideoEncoderConfig* encoder_config) OVERRIDE {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000356 send_config->rtp.fec.red_payload_type = kRedPayloadType;
357 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
358 }
359
360 virtual void PerformTest() OVERRIDE {
361 EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
362 }
363
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000364 internal::TransportAdapter transport_adapter_;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000365 int send_count_;
366 bool received_media_;
367 bool received_fec_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000368 } test;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000369
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000370 RunBaseTest(&test);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000371}
372
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000373void VideoSendStreamTest::TestNackRetransmission(
374 uint32_t retransmit_ssrc,
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000375 uint8_t retransmit_payload_type) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000376 class NackObserver : public test::SendTest {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000377 public:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000378 explicit NackObserver(uint32_t retransmit_ssrc,
379 uint8_t retransmit_payload_type)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000380 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000381 transport_adapter_(SendTransport()),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000382 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000383 retransmit_ssrc_(retransmit_ssrc),
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000384 retransmit_payload_type_(retransmit_payload_type),
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000385 nacked_sequence_number_(-1) {
386 transport_adapter_.Enable();
387 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000388
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000389 private:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000390 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000391 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000392 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000393
394 // Nack second packet after receiving the third one.
395 if (++send_count_ == 3) {
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000396 uint16_t nack_sequence_number = header.sequenceNumber - 1;
397 nacked_sequence_number_ = nack_sequence_number;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000398 NullReceiveStatistics null_stats;
399 RTCPSender rtcp_sender(
400 0, false, Clock::GetRealTimeClock(), &null_stats);
401 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
402
403 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000404 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000405
406 RTCPSender::FeedbackState feedback_state;
407
408 EXPECT_EQ(0,
409 rtcp_sender.SendRTCP(
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000410 feedback_state, kRtcpNack, 1, &nack_sequence_number));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000411 }
412
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000413 uint16_t sequence_number = header.sequenceNumber;
414
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000415 if (header.ssrc == retransmit_ssrc_ &&
416 retransmit_ssrc_ != kSendSsrcs[0]) {
417 // Not kSendSsrcs[0], assume correct RTX packet. Extract sequence
418 // number.
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000419 const uint8_t* rtx_header = packet + header.headerLength;
420 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
421 }
422
423 if (sequence_number == nacked_sequence_number_) {
424 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000425 EXPECT_EQ(retransmit_payload_type_, header.payloadType);
426 observation_complete_->Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000427 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000428
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000429 return SEND_PACKET;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000430 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000431
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000432 virtual void ModifyConfigs(
433 VideoSendStream::Config* send_config,
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000434 std::vector<VideoReceiveStream::Config>* receive_configs,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000435 VideoEncoderConfig* encoder_config) OVERRIDE {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000436 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000437 send_config->rtp.rtx.payload_type = retransmit_payload_type_;
438 if (retransmit_ssrc_ != kSendSsrcs[0])
439 send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
440 }
441
442 virtual void PerformTest() OVERRIDE {
443 EXPECT_EQ(kEventSignaled, Wait())
444 << "Timed out while waiting for NACK retransmission.";
445 }
446
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000447 internal::TransportAdapter transport_adapter_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000448 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000449 uint32_t retransmit_ssrc_;
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000450 uint8_t retransmit_payload_type_;
pbos@webrtc.orge7223e72014-01-23 16:14:34 +0000451 int nacked_sequence_number_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000452 } test(retransmit_ssrc, retransmit_payload_type);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000453
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000454 RunBaseTest(&test);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000455}
456
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000457TEST_F(VideoSendStreamTest, RetransmitsNack) {
458 // Normal NACKs should use the send SSRC.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000459 TestNackRetransmission(kSendSsrcs[0], kFakeSendPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000460}
461
462TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
463 // NACKs over RTX should use a separate SSRC.
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000464 TestNackRetransmission(kSendRtxSsrcs[0], kSendRtxPayloadType);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000465}
466
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000467void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
468 bool with_fec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000469 // Use a fake encoder to output a frame of every size in the range [90, 290],
470 // for each size making sure that the exact number of payload bytes received
471 // is correct and that packets are fragmented to respect max packet size.
472 static const uint32_t kMaxPacketSize = 128;
473 static const uint32_t start = 90;
474 static const uint32_t stop = 290;
475
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000476 // Observer that verifies that the expected number of packets and bytes
477 // arrive for each frame size, from start_size to stop_size.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000478 class FrameFragmentationTest : public test::SendTest,
479 public EncodedFrameObserver {
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000480 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000481 FrameFragmentationTest(uint32_t max_packet_size,
482 uint32_t start_size,
483 uint32_t stop_size,
484 bool test_generic_packetization,
485 bool use_fec)
486 : SendTest(kLongTimeoutMs),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000487 transport_adapter_(SendTransport()),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000488 encoder_(stop),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000489 max_packet_size_(max_packet_size),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000490 stop_size_(stop_size),
491 test_generic_packetization_(test_generic_packetization),
492 use_fec_(use_fec),
493 packet_count_(0),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000494 accumulated_size_(0),
495 accumulated_payload_(0),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000496 fec_packet_received_(false),
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000497 current_size_rtp_(start_size),
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000498 current_size_frame_(start_size) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000499 // Fragmentation required, this test doesn't make sense without it.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000500 encoder_.SetFrameSize(start);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000501 assert(stop_size > max_packet_size);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000502 transport_adapter_.Enable();
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000503 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000504
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000505 private:
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000506 virtual Action OnSendRtp(const uint8_t* packet, size_t size) OVERRIDE {
507 uint32_t length = static_cast<int>(size);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000508 RTPHeader header;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000509 EXPECT_TRUE(parser_->Parse(packet, length, &header));
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000510
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000511 EXPECT_LE(length, max_packet_size_);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000512
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000513 if (use_fec_) {
514 uint8_t payload_type = packet[header.headerLength];
515 bool is_fec = header.payloadType == kRedPayloadType &&
516 payload_type == kUlpfecPayloadType;
517 if (is_fec) {
518 fec_packet_received_ = true;
519 return SEND_PACKET;
520 }
521 }
522
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000523 accumulated_size_ += length;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000524
525 if (use_fec_)
526 TriggerLossReport(header);
527
528 if (test_generic_packetization_) {
529 uint32_t overhead = header.headerLength + header.paddingLength +
530 (1 /* Generic header */);
531 if (use_fec_)
532 overhead += 1; // RED for FEC header.
533 accumulated_payload_ += length - overhead;
534 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000535
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000536 // Marker bit set indicates last packet of a frame.
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000537 if (header.markerBit) {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000538 if (use_fec_ && accumulated_payload_ == current_size_rtp_ - 1) {
539 // With FEC enabled, frame size is incremented asynchronously, so
540 // "old" frames one byte too small may arrive. Accept, but don't
541 // increase expected frame size.
542 accumulated_size_ = 0;
543 accumulated_payload_ = 0;
544 return SEND_PACKET;
545 }
546
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000547 EXPECT_GE(accumulated_size_, current_size_rtp_);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000548 if (test_generic_packetization_) {
549 EXPECT_EQ(current_size_rtp_, accumulated_payload_);
550 }
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000551
552 // Last packet of frame; reset counters.
553 accumulated_size_ = 0;
554 accumulated_payload_ = 0;
555 if (current_size_rtp_ == stop_size_) {
556 // Done! (Don't increase size again, might arrive more @ stop_size).
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000557 observation_complete_->Set();
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000558 } else {
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000559 // Increase next expected frame size. If testing with FEC, make sure
560 // a FEC packet has been received for this frame size before
561 // proceeding, to make sure that redundancy packets don't exceed
562 // size limit.
563 if (!use_fec_) {
564 ++current_size_rtp_;
565 } else if (fec_packet_received_) {
566 fec_packet_received_ = false;
567 ++current_size_rtp_;
568 ++current_size_frame_;
569 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000570 }
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000571 }
572
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000573 return SEND_PACKET;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000574 }
575
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000576 void TriggerLossReport(const RTPHeader& header) {
577 // Send lossy receive reports to trigger FEC enabling.
578 if (packet_count_++ % 2 != 0) {
579 // Receive statistics reporting having lost 50% of the packets.
580 FakeReceiveStatistics lossy_receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000581 kSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000582 RTCPSender rtcp_sender(
583 0, false, Clock::GetRealTimeClock(), &lossy_receive_stats);
584 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
585
586 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000587 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000588
589 RTCPSender::FeedbackState feedback_state;
590
591 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
592 }
593 }
594
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000595 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
596 // Increase frame size for next encoded frame, in the context of the
597 // encoder thread.
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000598 if (!use_fec_ &&
599 current_size_frame_.Value() < static_cast<int32_t>(stop_size_)) {
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000600 ++current_size_frame_;
601 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000602 encoder_.SetFrameSize(current_size_frame_.Value());
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000603 }
604
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000605 virtual void ModifyConfigs(
606 VideoSendStream::Config* send_config,
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000607 std::vector<VideoReceiveStream::Config>* receive_configs,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000608 VideoEncoderConfig* encoder_config) OVERRIDE {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000609 if (use_fec_) {
610 send_config->rtp.fec.red_payload_type = kRedPayloadType;
611 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
612 }
613
614 if (!test_generic_packetization_)
615 send_config->encoder_settings.payload_name = "VP8";
616
617 send_config->encoder_settings.encoder = &encoder_;
618 send_config->rtp.max_packet_size = kMaxPacketSize;
619 send_config->post_encode_callback = this;
620
621 // Add an extension header, to make the RTP header larger than the base
622 // length of 12 bytes.
623 static const uint8_t kAbsSendTimeExtensionId = 13;
624 send_config->rtp.extensions.push_back(
625 RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
626 }
627
628 virtual void PerformTest() OVERRIDE {
629 EXPECT_EQ(kEventSignaled, Wait())
630 << "Timed out while observing incoming RTP packets.";
631 }
632
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000633 internal::TransportAdapter transport_adapter_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000634 test::ConfigurableFrameSizeEncoder encoder_;
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000635
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000636 const uint32_t max_packet_size_;
637 const uint32_t stop_size_;
638 const bool test_generic_packetization_;
639 const bool use_fec_;
640
641 uint32_t packet_count_;
642 uint32_t accumulated_size_;
643 uint32_t accumulated_payload_;
644 bool fec_packet_received_;
645
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000646 uint32_t current_size_rtp_;
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000647 Atomic32 current_size_frame_;
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000648 };
649
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000650 // Don't auto increment if FEC is used; continue sending frame size until
651 // a FEC packet has been received.
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000652 FrameFragmentationTest test(
653 kMaxPacketSize, start, stop, format == kGeneric, with_fec);
sprang@webrtc.org8b881922013-12-10 10:05:17 +0000654
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000655 RunBaseTest(&test);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000656}
657
sprang@webrtc.org346094c2014-02-18 08:40:33 +0000658// TODO(sprang): Is there any way of speeding up these tests?
659TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSize) {
660 TestPacketFragmentationSize(kGeneric, false);
661}
662
663TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSizeWithFec) {
664 TestPacketFragmentationSize(kGeneric, true);
665}
666
667TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSize) {
668 TestPacketFragmentationSize(kVP8, false);
669}
670
671TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSizeWithFec) {
672 TestPacketFragmentationSize(kVP8, true);
673}
674
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000675// The test will go through a number of phases.
676// 1. Start sending packets.
677// 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 +0000678// suspend the stream.
679// 3. Wait until |kSuspendTimeFrames| have been captured without seeing any RTP
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000680// packets.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000681// 4. Signal a high REMB and then wait for the RTP stream to start again.
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000682// When the stream is detected again, and the stats show that the stream
683// is no longer suspended, the test ends.
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000684TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
685 static const int kSuspendTimeFrames = 60; // Suspend for 2 seconds @ 30 fps.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000686
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000687 class RembObserver : public test::SendTest, public I420FrameCallback {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000688 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000689 RembObserver()
690 : SendTest(kDefaultTimeoutMs),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000691 transport_adapter_(&transport_),
692 clock_(Clock::GetRealTimeClock()),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000693 crit_(CriticalSectionWrapper::CreateCriticalSection()),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000694 test_state_(kBeforeSuspend),
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000695 rtp_count_(0),
696 last_sequence_number_(0),
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000697 suspended_frame_count_(0),
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000698 low_remb_bps_(0),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000699 high_remb_bps_(0) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000700 transport_adapter_.Enable();
701 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000702
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000703 private:
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000704 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000705 // Receive statistics reporting having lost 0% of the packets.
706 // This is needed for the send-side bitrate controller to work properly.
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000707 CriticalSectionScoped lock(crit_.get());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000708 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000709 return SEND_PACKET;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000710 }
711
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000712 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000713 CriticalSectionScoped lock(crit_.get());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000714 ++rtp_count_;
715 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000716 EXPECT_TRUE(parser_->Parse(packet, length, &header));
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000717 last_sequence_number_ = header.sequenceNumber;
718
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000719 if (test_state_ == kBeforeSuspend) {
720 // The stream has started. Try to suspend it.
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000721 SendRtcpFeedback(low_remb_bps_);
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000722 test_state_ = kDuringSuspend;
723 } else if (test_state_ == kDuringSuspend) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000724 if (header.paddingLength == 0) {
725 // Received non-padding packet during suspension period. Reset the
726 // counter.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000727 suspended_frame_count_ = 0;
728 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000729 } else if (test_state_ == kWaitingForPacket) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000730 if (header.paddingLength == 0) {
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000731 // Non-padding packet observed. Test is almost complete. Will just
732 // have to wait for the stats to change.
733 test_state_ = kWaitingForStats;
734 }
735 } else if (test_state_ == kWaitingForStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000736 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000737 if (stats.suspended == false) {
738 // Stats flipped to false. Test is complete.
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000739 observation_complete_->Set();
740 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000741 }
742
stefan@webrtc.org69969e22013-11-15 12:32:15 +0000743 return SEND_PACKET;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000744 }
745
746 // This method implements the I420FrameCallback.
747 void FrameCallback(I420VideoFrame* video_frame) OVERRIDE {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000748 CriticalSectionScoped lock(crit_.get());
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000749 if (test_state_ == kDuringSuspend &&
750 ++suspended_frame_count_ > kSuspendTimeFrames) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000751 VideoSendStream::Stats stats = stream_->GetStats();
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000752 EXPECT_TRUE(stats.suspended);
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000753 SendRtcpFeedback(high_remb_bps_);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000754 test_state_ = kWaitingForPacket;
755 }
756 }
757
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000758 void set_low_remb_bps(int value) {
759 CriticalSectionScoped lock(crit_.get());
760 low_remb_bps_ = value;
761 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000762
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000763 void set_high_remb_bps(int value) {
764 CriticalSectionScoped lock(crit_.get());
765 high_remb_bps_ = value;
766 }
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +0000767
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000768 virtual void SetReceivers(
769 PacketReceiver* send_transport_receiver,
770 PacketReceiver* receive_transport_receiver) OVERRIDE {
771 transport_.SetReceiver(send_transport_receiver);
772 }
pbos@webrtc.orgdef22b42013-10-29 10:12:10 +0000773
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000774 virtual void OnStreamsCreated(
775 VideoSendStream* send_stream,
776 const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000777 stream_ = send_stream;
778 }
779
780 virtual void ModifyConfigs(
781 VideoSendStream::Config* send_config,
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000782 std::vector<VideoReceiveStream::Config>* receive_configs,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000783 VideoEncoderConfig* encoder_config) OVERRIDE {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000784 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000785 send_config->pre_encode_callback = this;
786 send_config->suspend_below_min_bitrate = true;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000787 int min_bitrate_bps = encoder_config->streams[0].min_bitrate_bps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000788 set_low_remb_bps(min_bitrate_bps - 10000);
789 int threshold_window = std::max(min_bitrate_bps / 10, 10000);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000790 ASSERT_GT(encoder_config->streams[0].max_bitrate_bps,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000791 min_bitrate_bps + threshold_window + 5000);
792 set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
793 }
794
795 virtual void PerformTest() OVERRIDE {
796 EXPECT_EQ(kEventSignaled, Wait())
797 << "Timed out during suspend-below-min-bitrate test.";
798 transport_.StopSending();
799 }
800
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000801 enum TestState {
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000802 kBeforeSuspend,
803 kDuringSuspend,
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000804 kWaitingForPacket,
henrik.lundin@webrtc.orged8b2812014-03-18 08:43:29 +0000805 kWaitingForStats
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000806 };
807
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000808 virtual void SendRtcpFeedback(int remb_value)
809 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000810 FakeReceiveStatistics receive_stats(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000811 kSendSsrcs[0], last_sequence_number_, rtp_count_, 0);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000812 RTCPSender rtcp_sender(0, false, clock_, &receive_stats);
813 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
814
815 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000816 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000817 if (remb_value > 0) {
818 rtcp_sender.SetREMBStatus(true);
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000819 rtcp_sender.SetREMBData(remb_value, std::vector<uint32_t>());
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000820 }
821 RTCPSender::FeedbackState feedback_state;
822 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
823 }
824
825 internal::TransportAdapter transport_adapter_;
826 test::DirectTransport transport_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000827 Clock* const clock_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000828 VideoSendStream* stream_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000829
830 const scoped_ptr<CriticalSectionWrapper> crit_;
831 TestState test_state_ GUARDED_BY(crit_);
832 int rtp_count_ GUARDED_BY(crit_);
833 int last_sequence_number_ GUARDED_BY(crit_);
834 int suspended_frame_count_ GUARDED_BY(crit_);
835 int low_remb_bps_ GUARDED_BY(crit_);
836 int high_remb_bps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000837 } test;
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000838
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000839 RunBaseTest(&test);
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000840}
841
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000842TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000843 class NoPaddingWhenVideoIsMuted : public test::SendTest {
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000844 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000845 NoPaddingWhenVideoIsMuted()
846 : SendTest(kDefaultTimeoutMs),
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000847 clock_(Clock::GetRealTimeClock()),
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000848 transport_adapter_(ReceiveTransport()),
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000849 crit_(CriticalSectionWrapper::CreateCriticalSection()),
850 last_packet_time_ms_(-1),
851 capturer_(NULL) {
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +0000852 transport_adapter_.Enable();
853 }
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000854
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000855 private:
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000856 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000857 CriticalSectionScoped lock(crit_.get());
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000858 last_packet_time_ms_ = clock_->TimeInMilliseconds();
859 capturer_->Stop();
860 return SEND_PACKET;
861 }
862
863 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000864 CriticalSectionScoped lock(crit_.get());
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000865 const int kVideoMutedThresholdMs = 10000;
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000866 if (last_packet_time_ms_ > 0 &&
867 clock_->TimeInMilliseconds() - last_packet_time_ms_ >
868 kVideoMutedThresholdMs)
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000869 observation_complete_->Set();
870 // Receive statistics reporting having lost 50% of the packets.
871 FakeReceiveStatistics receive_stats(kSendSsrcs[0], 1, 1, 0);
872 RTCPSender rtcp_sender(
873 0, false, Clock::GetRealTimeClock(), &receive_stats);
874 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
875
876 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
877 rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
878
879 RTCPSender::FeedbackState feedback_state;
880
881 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
882 return SEND_PACKET;
883 }
884
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000885 virtual void SetReceivers(
886 PacketReceiver* send_transport_receiver,
887 PacketReceiver* receive_transport_receiver) OVERRIDE {
888 RtpRtcpObserver::SetReceivers(send_transport_receiver,
889 send_transport_receiver);
890 }
891
892 virtual size_t GetNumStreams() const OVERRIDE { return 3; }
893
894 virtual void OnFrameGeneratorCapturerCreated(
895 test::FrameGeneratorCapturer* frame_generator_capturer) {
896 CriticalSectionScoped lock(crit_.get());
897 capturer_ = frame_generator_capturer;
898 }
899
900 virtual void PerformTest() OVERRIDE {
901 EXPECT_EQ(kEventSignaled, Wait())
902 << "Timed out while waiting for RTP packets to stop being sent.";
903 }
904
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000905 Clock* const clock_;
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000906 internal::TransportAdapter transport_adapter_;
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +0000907 const scoped_ptr<CriticalSectionWrapper> crit_;
908 int64_t last_packet_time_ms_ GUARDED_BY(crit_);
909 test::FrameGeneratorCapturer* capturer_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000910 } test;
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000911
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000912 RunBaseTest(&test);
stefan@webrtc.org4ab4fc02013-11-25 11:54:24 +0000913}
914
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000915TEST_F(VideoSendStreamTest, ProducesStats) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000916 class ProducesStats : public test::SendTest {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000917 public:
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000918 ProducesStats()
919 : SendTest(kDefaultTimeoutMs),
sprang@webrtc.org60ad5fd2014-03-06 10:03:36 +0000920 stream_(NULL),
921 event_(EventWrapper::Create()) {}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000922
923 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
sprang@webrtc.org60ad5fd2014-03-06 10:03:36 +0000924 event_->Set();
925
926 return SEND_PACKET;
927 }
928
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000929 private:
sprang@webrtc.org60ad5fd2014-03-06 10:03:36 +0000930 bool WaitForFilledStats() {
931 Clock* clock = Clock::GetRealTimeClock();
932 int64_t now = clock->TimeInMilliseconds();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000933 int64_t stop_time = now + kDefaultTimeoutMs;
sprang@webrtc.org60ad5fd2014-03-06 10:03:36 +0000934 while (now < stop_time) {
935 int64_t time_left = stop_time - now;
936 if (time_left > 0 && event_->Wait(time_left) == kEventSignaled &&
937 CheckStats()) {
938 return true;
939 }
940 now = clock->TimeInMilliseconds();
941 }
942 return false;
943 }
944
945 bool CheckStats() {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000946 VideoSendStream::Stats stats = stream_->GetStats();
947 // Check that all applicable data sources have been used.
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000948 if (stats.input_frame_rate > 0 && stats.encode_frame_rate > 0
949 && !stats.substreams.empty()) {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000950 uint32_t ssrc = stats.substreams.begin()->first;
951 EXPECT_NE(
952 config_.rtp.ssrcs.end(),
953 std::find(
954 config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end(), ssrc));
955 // Check for data populated by various sources. RTCP excluded as this
956 // data is received from remote side. Tested in call tests instead.
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000957 const SsrcStats& entry = stats.substreams[ssrc];
958 if (entry.key_frames > 0u && entry.total_bitrate_bps > 0 &&
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000959 entry.rtp_stats.packets > 0u && entry.avg_delay_ms > 0 &&
960 entry.max_delay_ms > 0) {
sprang@webrtc.org60ad5fd2014-03-06 10:03:36 +0000961 return true;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000962 }
963 }
sprang@webrtc.org60ad5fd2014-03-06 10:03:36 +0000964 return false;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000965 }
966
967 void SetConfig(const VideoSendStream::Config& config) { config_ = config; }
968
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000969 virtual void ModifyConfigs(
970 VideoSendStream::Config* send_config,
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000971 std::vector<VideoReceiveStream::Config>* receive_configs,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000972 VideoEncoderConfig* encoder_config) OVERRIDE {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000973 SetConfig(*send_config);
974 }
975
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000976 virtual void OnStreamsCreated(
977 VideoSendStream* send_stream,
978 const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000979 stream_ = send_stream;
980 }
981
982 virtual void PerformTest() OVERRIDE {
983 EXPECT_TRUE(WaitForFilledStats())
984 << "Timed out waiting for filled statistics.";
985 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000986
987 VideoSendStream* stream_;
988 VideoSendStream::Config config_;
sprang@webrtc.org60ad5fd2014-03-06 10:03:36 +0000989 scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000990 } test;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000991
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000992 RunBaseTest(&test);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000993}
994
pbos@webrtc.org709e2972014-03-19 10:59:52 +0000995// This test first observes "high" bitrate use at which point it sends a REMB to
996// indicate that it should be lowered significantly. The test then observes that
997// the bitrate observed is sinking well below the min-transmit-bitrate threshold
998// to verify that the min-transmit bitrate respects incoming REMB.
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000999//
1000// Note that the test starts at "high" bitrate and does not ramp up to "higher"
1001// bitrate since no receiver block or remb is sent in the initial phase.
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001002TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
1003 static const int kMinTransmitBitrateBps = 400000;
andresp@webrtc.org44caf012014-03-26 21:00:21 +00001004 static const int kHighBitrateBps = 150000;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001005 static const int kRembBitrateBps = 80000;
1006 static const int kRembRespectedBitrateBps = 100000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001007 class BitrateObserver : public test::SendTest, public PacketReceiver {
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001008 public:
1009 BitrateObserver()
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001010 : SendTest(kDefaultTimeoutMs),
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001011 feedback_transport_(ReceiveTransport()),
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001012 bitrate_capped_(false) {
1013 RtpRtcp::Configuration config;
1014 feedback_transport_.Enable();
1015 config.outgoing_transport = &feedback_transport_;
1016 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
1017 rtp_rtcp_->SetREMBStatus(true);
1018 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
1019 }
1020
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001021 virtual void OnStreamsCreated(
1022 VideoSendStream* send_stream,
1023 const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001024 stream_ = send_stream;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001025 }
1026
1027 private:
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +00001028 virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
1029 size_t length) OVERRIDE {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001030 if (RtpHeaderParser::IsRtcp(packet, length))
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +00001031 return DELIVERY_OK;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001032
1033 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001034 if (!parser_->Parse(packet, length, &header))
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +00001035 return DELIVERY_PACKET_ERROR;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001036 assert(stream_ != NULL);
1037 VideoSendStream::Stats stats = stream_->GetStats();
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001038 if (!stats.substreams.empty()) {
1039 EXPECT_EQ(1u, stats.substreams.size());
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001040 int total_bitrate_bps =
1041 stats.substreams.begin()->second.total_bitrate_bps;
1042 test::PrintResult("bitrate_stats_",
1043 "min_transmit_bitrate_low_remb",
1044 "bitrate_bps",
1045 static_cast<size_t>(total_bitrate_bps),
1046 "bps",
1047 false);
1048 if (total_bitrate_bps > kHighBitrateBps) {
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001049 rtp_rtcp_->SetREMBData(kRembBitrateBps,
1050 std::vector<uint32_t>(1, header.ssrc));
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001051 rtp_rtcp_->Process();
1052 bitrate_capped_ = true;
1053 } else if (bitrate_capped_ &&
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001054 total_bitrate_bps < kRembRespectedBitrateBps) {
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001055 observation_complete_->Set();
1056 }
1057 }
pbos@webrtc.orgcaba2d22014-05-14 13:57:12 +00001058 return DELIVERY_OK;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001059 }
1060
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001061 virtual void SetReceivers(
1062 PacketReceiver* send_transport_receiver,
1063 PacketReceiver* receive_transport_receiver) OVERRIDE {
1064 RtpRtcpObserver::SetReceivers(this, send_transport_receiver);
1065 }
1066
1067 virtual void ModifyConfigs(
1068 VideoSendStream::Config* send_config,
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001069 std::vector<VideoReceiveStream::Config>* receive_configs,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001070 VideoEncoderConfig* encoder_config) OVERRIDE {
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00001071 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001072 }
1073
1074 virtual void PerformTest() OVERRIDE {
1075 EXPECT_EQ(kEventSignaled, Wait())
1076 << "Timeout while waiting for low bitrate stats after REMB.";
1077 }
1078
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001079 scoped_ptr<RtpRtcp> rtp_rtcp_;
1080 internal::TransportAdapter feedback_transport_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001081 VideoSendStream* stream_;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001082 bool bitrate_capped_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001083 } test;
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001084
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001085 RunBaseTest(&test);
pbos@webrtc.org709e2972014-03-19 10:59:52 +00001086}
1087
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001088TEST_F(VideoSendStreamTest, CapturesTextureAndI420VideoFrames) {
1089 class FrameObserver : public I420FrameCallback {
1090 public:
1091 FrameObserver() : output_frame_event_(EventWrapper::Create()) {}
1092
1093 void FrameCallback(I420VideoFrame* video_frame) OVERRIDE {
1094 // Clone the frame because the caller owns it.
1095 output_frames_.push_back(video_frame->CloneFrame());
1096 output_frame_event_->Set();
1097 }
1098
1099 void WaitOutputFrame() {
1100 const unsigned long kWaitFrameTimeoutMs = 3000;
1101 EXPECT_EQ(kEventSignaled, output_frame_event_->Wait(kWaitFrameTimeoutMs))
1102 << "Timeout while waiting for output frames.";
1103 }
1104
1105 const std::vector<I420VideoFrame*>& output_frames() const {
1106 return output_frames_.get();
1107 }
1108
1109 private:
1110 // Delivered output frames.
1111 ScopedVector<I420VideoFrame> output_frames_;
1112
1113 // Indicate an output frame has arrived.
1114 scoped_ptr<EventWrapper> output_frame_event_;
1115 };
1116
1117 // Initialize send stream.
1118 test::NullTransport transport;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001119 CreateSenderCall(Call::Config(&transport));
1120
1121 CreateSendConfig(1);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001122 FrameObserver observer;
1123 send_config_.pre_encode_callback = &observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001124 CreateStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001125
1126 // Prepare five input frames. Send I420VideoFrame and TextureVideoFrame
1127 // alternatively.
1128 ScopedVector<I420VideoFrame> input_frames;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001129 int width = static_cast<int>(encoder_config_.streams[0].width);
1130 int height = static_cast<int>(encoder_config_.streams[0].height);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001131 webrtc::RefCountImpl<FakeNativeHandle>* handle1 =
1132 new webrtc::RefCountImpl<FakeNativeHandle>();
1133 webrtc::RefCountImpl<FakeNativeHandle>* handle2 =
1134 new webrtc::RefCountImpl<FakeNativeHandle>();
1135 webrtc::RefCountImpl<FakeNativeHandle>* handle3 =
1136 new webrtc::RefCountImpl<FakeNativeHandle>();
1137 input_frames.push_back(new TextureVideoFrame(handle1, width, height, 1, 1));
1138 input_frames.push_back(new TextureVideoFrame(handle2, width, height, 2, 2));
1139 input_frames.push_back(CreateI420VideoFrame(width, height, 1));
1140 input_frames.push_back(CreateI420VideoFrame(width, height, 2));
1141 input_frames.push_back(new TextureVideoFrame(handle3, width, height, 3, 3));
1142
1143 send_stream_->Start();
1144 for (size_t i = 0; i < input_frames.size(); i++) {
1145 // Make a copy of the input frame because the buffer will be swapped.
1146 scoped_ptr<I420VideoFrame> frame(input_frames[i]->CloneFrame());
1147 send_stream_->Input()->SwapFrame(frame.get());
1148 // Do not send the next frame too fast, so the frame dropper won't drop it.
1149 if (i < input_frames.size() - 1)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001150 SleepMs(1000 / encoder_config_.streams[0].max_framerate);
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001151 // Wait until the output frame is received before sending the next input
1152 // frame. Or the previous input frame may be replaced without delivering.
1153 observer.WaitOutputFrame();
1154 }
1155 send_stream_->Stop();
1156
1157 // Test if the input and output frames are the same. render_time_ms and
1158 // timestamp are not compared because capturer sets those values.
1159 ExpectEqualFramesVector(input_frames.get(), observer.output_frames());
1160
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001161 DestroyStreams();
wuchengli@chromium.orgf425b552014-06-20 12:04:05 +00001162}
1163
1164void ExpectEqualFrames(const I420VideoFrame& frame1,
1165 const I420VideoFrame& frame2) {
1166 if (frame1.native_handle() != NULL || frame2.native_handle() != NULL)
1167 ExpectEqualTextureFrames(frame1, frame2);
1168 else
1169 ExpectEqualBufferFrames(frame1, frame2);
1170}
1171
1172void ExpectEqualTextureFrames(const I420VideoFrame& frame1,
1173 const I420VideoFrame& frame2) {
1174 EXPECT_EQ(frame1.native_handle(), frame2.native_handle());
1175 EXPECT_EQ(frame1.width(), frame2.width());
1176 EXPECT_EQ(frame1.height(), frame2.height());
1177}
1178
1179void ExpectEqualBufferFrames(const I420VideoFrame& frame1,
1180 const I420VideoFrame& frame2) {
1181 EXPECT_EQ(frame1.width(), frame2.width());
1182 EXPECT_EQ(frame1.height(), frame2.height());
1183 EXPECT_EQ(frame1.stride(kYPlane), frame2.stride(kYPlane));
1184 EXPECT_EQ(frame1.stride(kUPlane), frame2.stride(kUPlane));
1185 EXPECT_EQ(frame1.stride(kVPlane), frame2.stride(kVPlane));
1186 EXPECT_EQ(frame1.ntp_time_ms(), frame2.ntp_time_ms());
1187 ASSERT_EQ(frame1.allocated_size(kYPlane), frame2.allocated_size(kYPlane));
1188 EXPECT_EQ(0,
1189 memcmp(frame1.buffer(kYPlane),
1190 frame2.buffer(kYPlane),
1191 frame1.allocated_size(kYPlane)));
1192 ASSERT_EQ(frame1.allocated_size(kUPlane), frame2.allocated_size(kUPlane));
1193 EXPECT_EQ(0,
1194 memcmp(frame1.buffer(kUPlane),
1195 frame2.buffer(kUPlane),
1196 frame1.allocated_size(kUPlane)));
1197 ASSERT_EQ(frame1.allocated_size(kVPlane), frame2.allocated_size(kVPlane));
1198 EXPECT_EQ(0,
1199 memcmp(frame1.buffer(kVPlane),
1200 frame2.buffer(kVPlane),
1201 frame1.allocated_size(kVPlane)));
1202}
1203
1204void ExpectEqualFramesVector(const std::vector<I420VideoFrame*>& frames1,
1205 const std::vector<I420VideoFrame*>& frames2) {
1206 EXPECT_EQ(frames1.size(), frames2.size());
1207 for (size_t i = 0; i < std::min(frames1.size(), frames2.size()); ++i)
1208 ExpectEqualFrames(*frames1[i], *frames2[i]);
1209}
1210
1211I420VideoFrame* CreateI420VideoFrame(int width, int height, uint8_t data) {
1212 I420VideoFrame* frame = new I420VideoFrame();
1213 const int kSizeY = width * height * 2;
1214 const int kSizeUV = width * height;
1215 scoped_ptr<uint8_t[]> buffer(new uint8_t[kSizeY]);
1216 memset(buffer.get(), data, kSizeY);
1217 frame->CreateFrame(kSizeY,
1218 buffer.get(),
1219 kSizeUV,
1220 buffer.get(),
1221 kSizeUV,
1222 buffer.get(),
1223 width,
1224 height,
1225 width,
1226 width / 2,
1227 width / 2);
1228 frame->set_timestamp(data);
1229 frame->set_ntp_time_ms(data);
1230 frame->set_render_time_ms(data);
1231 return frame;
1232}
1233
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001234TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
1235 class EncoderStateObserver : public test::SendTest, public VideoEncoder {
1236 public:
1237 EncoderStateObserver()
1238 : SendTest(kDefaultTimeoutMs),
1239 crit_(CriticalSectionWrapper::CreateCriticalSection()),
1240 initialized_(false),
1241 callback_registered_(false),
1242 num_releases_(0),
1243 released_(false) {}
1244
1245 bool IsReleased() {
1246 CriticalSectionScoped lock(crit_.get());
1247 return released_;
1248 }
1249
1250 bool IsReadyForEncode() {
1251 CriticalSectionScoped lock(crit_.get());
1252 return initialized_ && callback_registered_;
1253 }
1254
1255 size_t num_releases() {
1256 CriticalSectionScoped lock(crit_.get());
1257 return num_releases_;
1258 }
1259
1260 private:
1261 virtual int32_t InitEncode(const VideoCodec* codecSettings,
1262 int32_t numberOfCores,
1263 uint32_t maxPayloadSize) OVERRIDE {
1264 CriticalSectionScoped lock(crit_.get());
1265 EXPECT_FALSE(initialized_);
1266 initialized_ = true;
1267 released_ = false;
1268 return 0;
1269 }
1270
1271 virtual int32_t Encode(
1272 const I420VideoFrame& inputImage,
1273 const CodecSpecificInfo* codecSpecificInfo,
1274 const std::vector<VideoFrameType>* frame_types) OVERRIDE {
1275 EXPECT_TRUE(IsReadyForEncode());
1276
1277 observation_complete_->Set();
1278 return 0;
1279 }
1280
1281 virtual int32_t RegisterEncodeCompleteCallback(
1282 EncodedImageCallback* callback) OVERRIDE {
1283 CriticalSectionScoped lock(crit_.get());
1284 EXPECT_TRUE(initialized_);
1285 callback_registered_ = true;
1286 return 0;
1287 }
1288
1289 virtual int32_t Release() OVERRIDE {
1290 CriticalSectionScoped lock(crit_.get());
1291 EXPECT_TRUE(IsReadyForEncode());
1292 EXPECT_FALSE(released_);
1293 initialized_ = false;
1294 callback_registered_ = false;
1295 released_ = true;
1296 ++num_releases_;
1297 return 0;
1298 }
1299
1300 virtual int32_t SetChannelParameters(uint32_t packetLoss,
1301 int rtt) OVERRIDE {
1302 EXPECT_TRUE(IsReadyForEncode());
1303 return 0;
1304 }
1305
1306 virtual int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) OVERRIDE {
1307 EXPECT_TRUE(IsReadyForEncode());
1308 return 0;
1309 }
1310
1311 virtual void OnStreamsCreated(
1312 VideoSendStream* send_stream,
1313 const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
1314 // Encoder initialization should be done in stream construction before
1315 // starting.
1316 EXPECT_TRUE(IsReadyForEncode());
1317 stream_ = send_stream;
1318 }
1319
1320 virtual void ModifyConfigs(
1321 VideoSendStream::Config* send_config,
1322 std::vector<VideoReceiveStream::Config>* receive_configs,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001323 VideoEncoderConfig* encoder_config) OVERRIDE {
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001324 send_config->encoder_settings.encoder = this;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001325 encoder_config_ = *encoder_config;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001326 }
1327
1328 virtual void PerformTest() OVERRIDE {
1329 EXPECT_EQ(kEventSignaled, Wait())
1330 << "Timed out while waiting for Encode.";
1331 EXPECT_EQ(0u, num_releases());
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001332 stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001333 EXPECT_EQ(0u, num_releases());
1334 stream_->Stop();
1335 // Encoder should not be released before destroying the VideoSendStream.
1336 EXPECT_FALSE(IsReleased());
1337 EXPECT_TRUE(IsReadyForEncode());
1338 stream_->Start();
1339 // Sanity check, make sure we still encode frames with this encoder.
1340 EXPECT_EQ(kEventSignaled, Wait())
1341 << "Timed out while waiting for Encode.";
1342 }
1343
1344 scoped_ptr<CriticalSectionWrapper> crit_;
1345 VideoSendStream* stream_;
1346 bool initialized_ GUARDED_BY(crit_);
1347 bool callback_registered_ GUARDED_BY(crit_);
1348 size_t num_releases_ GUARDED_BY(crit_);
1349 bool released_ GUARDED_BY(crit_);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001350 VideoEncoderConfig encoder_config_;
pbos@webrtc.org161f8082014-07-07 14:22:35 +00001351 } test_encoder;
1352
1353 RunBaseTest(&test_encoder);
1354
1355 EXPECT_TRUE(test_encoder.IsReleased());
1356 EXPECT_EQ(1u, test_encoder.num_releases());
1357}
1358
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001359TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
1360 class VideoCodecConfigObserver : public test::SendTest,
1361 public test::FakeEncoder {
1362 public:
1363 VideoCodecConfigObserver()
1364 : SendTest(kDefaultTimeoutMs),
1365 FakeEncoder(Clock::GetRealTimeClock()),
1366 num_initializations_(0) {}
1367
1368 private:
1369 virtual void ModifyConfigs(
1370 VideoSendStream::Config* send_config,
1371 std::vector<VideoReceiveStream::Config>* receive_configs,
1372 VideoEncoderConfig* encoder_config) OVERRIDE {
1373 send_config->encoder_settings.encoder = this;
1374 encoder_config_ = *encoder_config;
1375 }
1376
1377 virtual void OnStreamsCreated(
1378 VideoSendStream* send_stream,
1379 const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
1380 stream_ = send_stream;
1381 }
1382
1383 virtual int32_t InitEncode(const VideoCodec* config,
1384 int32_t number_of_cores,
1385 uint32_t max_payload_size) OVERRIDE {
1386 if (num_initializations_ == 0) {
1387 // Verify default values.
1388 EXPECT_EQ(kRealtimeVideo, config->mode);
1389 } else {
1390 // Verify that changed values are propagated.
1391 EXPECT_EQ(kScreensharing, config->mode);
1392 }
1393 ++num_initializations_;
1394 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1395 }
1396
1397 virtual void PerformTest() OVERRIDE {
1398 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1399
1400 encoder_config_.content_type = VideoEncoderConfig::kScreenshare;
1401 stream_->ReconfigureVideoEncoder(encoder_config_);
1402 EXPECT_EQ(2u, num_initializations_)
1403 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1404 "new encoder settings.";
1405 }
1406
1407 size_t num_initializations_;
1408 VideoSendStream* stream_;
1409 VideoEncoderConfig encoder_config_;
1410 } test;
1411
1412 RunBaseTest(&test);
1413}
1414
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001415TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp8Config) {
pbos@webrtc.org759982d2014-09-22 09:32:46 +00001416 static const size_t kNumberOfTemporalLayers = 4;
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001417 class VideoCodecConfigObserver : public test::SendTest,
1418 public test::FakeEncoder {
1419 public:
1420 VideoCodecConfigObserver()
1421 : SendTest(kDefaultTimeoutMs),
1422 FakeEncoder(Clock::GetRealTimeClock()),
1423 num_initializations_(0) {
1424 memset(&vp8_settings_, 0, sizeof(vp8_settings_));
1425 }
1426
1427 private:
1428 virtual void ModifyConfigs(
1429 VideoSendStream::Config* send_config,
1430 std::vector<VideoReceiveStream::Config>* receive_configs,
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001431 VideoEncoderConfig* encoder_config) OVERRIDE {
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001432 send_config->encoder_settings.encoder = this;
1433 send_config->encoder_settings.payload_name = "VP8";
1434
pbos@webrtc.org759982d2014-09-22 09:32:46 +00001435 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001436 encoder_config->streams[i].temporal_layer_thresholds_bps.resize(
1437 kNumberOfTemporalLayers - 1);
pbos@webrtc.org759982d2014-09-22 09:32:46 +00001438 }
1439
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001440 encoder_config->encoder_specific_settings = &vp8_settings_;
1441 encoder_config_ = *encoder_config;
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001442 }
1443
1444 virtual void OnStreamsCreated(
1445 VideoSendStream* send_stream,
1446 const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
1447 stream_ = send_stream;
1448 }
1449
1450 virtual int32_t InitEncode(const VideoCodec* config,
1451 int32_t number_of_cores,
1452 uint32_t max_payload_size) OVERRIDE {
1453 EXPECT_EQ(kVideoCodecVP8, config->codecType);
pbos@webrtc.org759982d2014-09-22 09:32:46 +00001454
1455 // Check that the number of temporal layers has propagated properly to
1456 // VideoCodec.
1457 EXPECT_EQ(kNumberOfTemporalLayers,
1458 config->codecSpecific.VP8.numberOfTemporalLayers);
1459
1460 for (unsigned char i = 0; i < config->numberOfSimulcastStreams; ++i) {
1461 EXPECT_EQ(kNumberOfTemporalLayers,
1462 config->simulcastStream[i].numberOfTemporalLayers);
1463 }
1464
1465 // Set expected temporal layers as they should have been set when
1466 // reconfiguring the encoder and not match the set config.
1467 vp8_settings_.numberOfTemporalLayers = kNumberOfTemporalLayers;
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001468 EXPECT_EQ(0,
1469 memcmp(&config->codecSpecific.VP8,
1470 &vp8_settings_,
1471 sizeof(vp8_settings_)));
1472 ++num_initializations_;
1473 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
1474 }
1475
1476 virtual void PerformTest() OVERRIDE {
1477 EXPECT_EQ(1u, num_initializations_) << "VideoEncoder not initialized.";
1478
1479 vp8_settings_.denoisingOn = true;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001480 stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001481 EXPECT_EQ(2u, num_initializations_)
1482 << "ReconfigureVideoEncoder did not reinitialize the encoder with "
1483 "new encoder settings.";
1484 }
1485
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001486 int32_t Encode(const I420VideoFrame& input_image,
1487 const CodecSpecificInfo* codec_specific_info,
1488 const std::vector<VideoFrameType>* frame_types) OVERRIDE {
pbos@webrtc.orgbd9c0922014-07-10 13:21:40 +00001489 // Silently skip the encode, FakeEncoder::Encode doesn't produce VP8.
1490 return 0;
1491 }
1492
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001493 VideoCodecVP8 vp8_settings_;
1494 size_t num_initializations_;
1495 VideoSendStream* stream_;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001496 VideoEncoderConfig encoder_config_;
pbos@webrtc.org91f17522014-07-10 10:13:37 +00001497 } test;
1498
1499 RunBaseTest(&test);
1500}
1501
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +00001502TEST_F(VideoSendStreamTest, RtcpSenderReportContainsMediaBytesSent) {
1503 class RtcpByeTest : public test::SendTest {
1504 public:
1505 RtcpByeTest() : SendTest(kDefaultTimeoutMs), media_bytes_sent_(0) {}
1506
1507 private:
1508 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
1509 RTPHeader header;
1510 EXPECT_TRUE(parser_->Parse(packet, length, &header));
1511 media_bytes_sent_ += length - header.headerLength - header.paddingLength;
1512 return SEND_PACKET;
1513 }
1514
1515 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
1516 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1517 EXPECT_TRUE(parser.IsValid());
1518
1519 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1520 uint32_t sender_octet_count = 0;
1521 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1522 if (packet_type == RTCPUtility::kRtcpSrCode) {
1523 sender_octet_count = parser.Packet().SR.SenderOctetCount;
1524 EXPECT_EQ(sender_octet_count, media_bytes_sent_);
1525 if (sender_octet_count > 0)
1526 observation_complete_->Set();
1527 }
1528
1529 packet_type = parser.Iterate();
1530 }
1531
1532 return SEND_PACKET;
1533 }
1534
1535 virtual void PerformTest() OVERRIDE {
1536 EXPECT_EQ(kEventSignaled, Wait())
1537 << "Timed out while waiting for RTCP sender report.";
1538 }
1539
1540 size_t media_bytes_sent_;
1541 } test;
1542
1543 RunBaseTest(&test);
1544}
1545
pbos@webrtc.orgb7ed7792014-10-31 13:08:10 +00001546TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
1547 static const int kScreencastTargetBitrateKbps = 200;
1548 class ScreencastTargetBitrateTest : public test::SendTest,
1549 public test::FakeEncoder {
1550 public:
1551 ScreencastTargetBitrateTest()
1552 : SendTest(kDefaultTimeoutMs),
1553 test::FakeEncoder(Clock::GetRealTimeClock()) {}
1554
1555 private:
1556 virtual int32_t InitEncode(const VideoCodec* config,
1557 int32_t number_of_cores,
1558 uint32_t max_payload_size) {
1559 EXPECT_EQ(static_cast<unsigned int>(kScreencastTargetBitrateKbps),
1560 config->targetBitrate);
1561 observation_complete_->Set();
1562 return test::FakeEncoder::InitEncode(
1563 config, number_of_cores, max_payload_size);
1564 }
1565 virtual void ModifyConfigs(
1566 VideoSendStream::Config* send_config,
1567 std::vector<VideoReceiveStream::Config>* receive_configs,
1568 VideoEncoderConfig* encoder_config) OVERRIDE {
1569 send_config->encoder_settings.encoder = this;
1570 EXPECT_EQ(1u, encoder_config->streams.size());
1571 EXPECT_TRUE(
1572 encoder_config->streams[0].temporal_layer_thresholds_bps.empty());
1573 encoder_config->streams[0].temporal_layer_thresholds_bps.push_back(
1574 kScreencastTargetBitrateKbps * 1000);
1575 encoder_config->content_type = VideoEncoderConfig::kScreenshare;
1576 }
1577
1578 virtual void PerformTest() OVERRIDE {
1579 EXPECT_EQ(kEventSignaled, Wait())
1580 << "Timed out while waiting for the encoder to be initialized.";
1581 }
1582 } test;
1583
1584 RunBaseTest(&test);
1585}
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +00001586} // namespace webrtc