xref: /aosp_15_r20/external/webrtc/video/video_send_stream_tests.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker #include <algorithm>  // max
11*d9f75844SAndroid Build Coastguard Worker #include <memory>
12*d9f75844SAndroid Build Coastguard Worker #include <vector>
13*d9f75844SAndroid Build Coastguard Worker 
14*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
15*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/match.h"
16*d9f75844SAndroid Build Coastguard Worker #include "api/sequence_checker.h"
17*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/default_task_queue_factory.h"
18*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/task_queue_base.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/test/metrics/global_metrics_logger_and_exporter.h"
20*d9f75844SAndroid Build Coastguard Worker #include "api/test/metrics/metric.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/test/simulated_network.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/video/builtin_video_bitrate_allocator_factory.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/video/encoded_image.h"
24*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_bitrate_allocation.h"
25*d9f75844SAndroid Build Coastguard Worker #include "api/video_codecs/video_encoder.h"
26*d9f75844SAndroid Build Coastguard Worker #include "call/call.h"
27*d9f75844SAndroid Build Coastguard Worker #include "call/fake_network_pipe.h"
28*d9f75844SAndroid Build Coastguard Worker #include "call/rtp_transport_controller_send.h"
29*d9f75844SAndroid Build Coastguard Worker #include "call/simulated_network.h"
30*d9f75844SAndroid Build Coastguard Worker #include "call/video_send_stream.h"
31*d9f75844SAndroid Build Coastguard Worker #include "media/engine/internal_encoder_factory.h"
32*d9f75844SAndroid Build Coastguard Worker #include "media/engine/simulcast_encoder_adapter.h"
33*d9f75844SAndroid Build Coastguard Worker #include "media/engine/webrtc_video_engine.h"
34*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
35*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/create_video_rtp_depacketizer.h"
36*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtcp_sender.h"
37*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
38*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_packet.h"
39*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_rtcp_impl2.h"
40*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_util.h"
41*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.h"
42*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/codecs/interface/common_constants.h"
43*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/codecs/vp8/include/vp8.h"
44*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/codecs/vp9/include/vp9.h"
45*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/svc/create_scalability_structure.h"
46*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/svc/scalability_mode_util.h"
47*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/svc/scalable_video_controller.h"
48*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
49*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/event.h"
50*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/experiments/alr_experiment.h"
51*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
52*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/platform_thread.h"
53*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/rate_limiter.h"
54*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
55*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/synchronization/mutex.h"
56*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/task_queue_for_test.h"
57*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
58*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/unique_id_generator.h"
59*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/sleep.h"
60*d9f75844SAndroid Build Coastguard Worker #include "test/call_test.h"
61*d9f75844SAndroid Build Coastguard Worker #include "test/configurable_frame_size_encoder.h"
62*d9f75844SAndroid Build Coastguard Worker #include "test/fake_encoder.h"
63*d9f75844SAndroid Build Coastguard Worker #include "test/fake_texture_frame.h"
64*d9f75844SAndroid Build Coastguard Worker #include "test/frame_forwarder.h"
65*d9f75844SAndroid Build Coastguard Worker #include "test/frame_generator_capturer.h"
66*d9f75844SAndroid Build Coastguard Worker #include "test/frame_utils.h"
67*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
68*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
69*d9f75844SAndroid Build Coastguard Worker #include "test/null_transport.h"
70*d9f75844SAndroid Build Coastguard Worker #include "test/rtcp_packet_parser.h"
71*d9f75844SAndroid Build Coastguard Worker #include "test/video_encoder_proxy_factory.h"
72*d9f75844SAndroid Build Coastguard Worker #include "video/config/encoder_stream_factory.h"
73*d9f75844SAndroid Build Coastguard Worker #include "video/send_statistics_proxy.h"
74*d9f75844SAndroid Build Coastguard Worker #include "video/transport_adapter.h"
75*d9f75844SAndroid Build Coastguard Worker #include "video/video_send_stream.h"
76*d9f75844SAndroid Build Coastguard Worker 
77*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
78*d9f75844SAndroid Build Coastguard Worker namespace test {
79*d9f75844SAndroid Build Coastguard Worker class VideoSendStreamPeer {
80*d9f75844SAndroid Build Coastguard Worker  public:
VideoSendStreamPeer(webrtc::VideoSendStream * base_class_stream)81*d9f75844SAndroid Build Coastguard Worker   explicit VideoSendStreamPeer(webrtc::VideoSendStream* base_class_stream)
82*d9f75844SAndroid Build Coastguard Worker       : internal_stream_(
83*d9f75844SAndroid Build Coastguard Worker             static_cast<internal::VideoSendStream*>(base_class_stream)) {}
GetPacingFactorOverride() const84*d9f75844SAndroid Build Coastguard Worker   absl::optional<float> GetPacingFactorOverride() const {
85*d9f75844SAndroid Build Coastguard Worker     return internal_stream_->GetPacingFactorOverride();
86*d9f75844SAndroid Build Coastguard Worker   }
87*d9f75844SAndroid Build Coastguard Worker 
88*d9f75844SAndroid Build Coastguard Worker  private:
89*d9f75844SAndroid Build Coastguard Worker   internal::VideoSendStream const* const internal_stream_;
90*d9f75844SAndroid Build Coastguard Worker };
91*d9f75844SAndroid Build Coastguard Worker }  // namespace test
92*d9f75844SAndroid Build Coastguard Worker 
93*d9f75844SAndroid Build Coastguard Worker namespace {
94*d9f75844SAndroid Build Coastguard Worker enum : int {  // The first valid value is 1.
95*d9f75844SAndroid Build Coastguard Worker   kAbsSendTimeExtensionId = 1,
96*d9f75844SAndroid Build Coastguard Worker   kTimestampOffsetExtensionId,
97*d9f75844SAndroid Build Coastguard Worker   kTransportSequenceNumberExtensionId,
98*d9f75844SAndroid Build Coastguard Worker   kVideoContentTypeExtensionId,
99*d9f75844SAndroid Build Coastguard Worker   kVideoRotationExtensionId,
100*d9f75844SAndroid Build Coastguard Worker   kVideoTimingExtensionId,
101*d9f75844SAndroid Build Coastguard Worker };
102*d9f75844SAndroid Build Coastguard Worker 
103*d9f75844SAndroid Build Coastguard Worker // Readability convenience enum for `WaitBitrateChanged()`.
104*d9f75844SAndroid Build Coastguard Worker enum class WaitUntil : bool { kZero = false, kNonZero = true };
105*d9f75844SAndroid Build Coastguard Worker 
106*d9f75844SAndroid Build Coastguard Worker constexpr int64_t kRtcpIntervalMs = 1000;
107*d9f75844SAndroid Build Coastguard Worker 
108*d9f75844SAndroid Build Coastguard Worker enum VideoFormat {
109*d9f75844SAndroid Build Coastguard Worker   kGeneric,
110*d9f75844SAndroid Build Coastguard Worker   kVP8,
111*d9f75844SAndroid Build Coastguard Worker };
112*d9f75844SAndroid Build Coastguard Worker 
113*d9f75844SAndroid Build Coastguard Worker struct Vp9TestParams {
114*d9f75844SAndroid Build Coastguard Worker   std::string scalability_mode;
115*d9f75844SAndroid Build Coastguard Worker   uint8_t num_spatial_layers;
116*d9f75844SAndroid Build Coastguard Worker   uint8_t num_temporal_layers;
117*d9f75844SAndroid Build Coastguard Worker   InterLayerPredMode inter_layer_pred;
118*d9f75844SAndroid Build Coastguard Worker };
119*d9f75844SAndroid Build Coastguard Worker 
120*d9f75844SAndroid Build Coastguard Worker using ParameterizationType = std::tuple<Vp9TestParams, bool>;
121*d9f75844SAndroid Build Coastguard Worker 
ParamInfoToStr(const testing::TestParamInfo<ParameterizationType> & info)122*d9f75844SAndroid Build Coastguard Worker std::string ParamInfoToStr(
123*d9f75844SAndroid Build Coastguard Worker     const testing::TestParamInfo<ParameterizationType>& info) {
124*d9f75844SAndroid Build Coastguard Worker   rtc::StringBuilder sb;
125*d9f75844SAndroid Build Coastguard Worker   sb << std::get<0>(info.param).scalability_mode << "_"
126*d9f75844SAndroid Build Coastguard Worker      << (std::get<1>(info.param) ? "WithIdentifier" : "WithoutIdentifier");
127*d9f75844SAndroid Build Coastguard Worker   return sb.str();
128*d9f75844SAndroid Build Coastguard Worker }
129*d9f75844SAndroid Build Coastguard Worker 
130*d9f75844SAndroid Build Coastguard Worker }  // namespace
131*d9f75844SAndroid Build Coastguard Worker 
132*d9f75844SAndroid Build Coastguard Worker class VideoSendStreamTest : public test::CallTest {
133*d9f75844SAndroid Build Coastguard Worker  public:
VideoSendStreamTest()134*d9f75844SAndroid Build Coastguard Worker   VideoSendStreamTest() {
135*d9f75844SAndroid Build Coastguard Worker     RegisterRtpExtension(RtpExtension(RtpExtension::kTransportSequenceNumberUri,
136*d9f75844SAndroid Build Coastguard Worker                                       kTransportSequenceNumberExtensionId));
137*d9f75844SAndroid Build Coastguard Worker   }
138*d9f75844SAndroid Build Coastguard Worker 
139*d9f75844SAndroid Build Coastguard Worker  protected:
140*d9f75844SAndroid Build Coastguard Worker   void TestNackRetransmission(uint32_t retransmit_ssrc,
141*d9f75844SAndroid Build Coastguard Worker                               uint8_t retransmit_payload_type);
142*d9f75844SAndroid Build Coastguard Worker   void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
143*d9f75844SAndroid Build Coastguard Worker 
144*d9f75844SAndroid Build Coastguard Worker   void TestVp9NonFlexMode(const Vp9TestParams& params,
145*d9f75844SAndroid Build Coastguard Worker                           bool use_scalability_mode_identifier);
146*d9f75844SAndroid Build Coastguard Worker 
147*d9f75844SAndroid Build Coastguard Worker   void TestRequestSourceRotateVideo(bool support_orientation_ext);
148*d9f75844SAndroid Build Coastguard Worker 
149*d9f75844SAndroid Build Coastguard Worker   void TestTemporalLayers(VideoEncoderFactory* encoder_factory,
150*d9f75844SAndroid Build Coastguard Worker                           const std::string& payload_name,
151*d9f75844SAndroid Build Coastguard Worker                           const std::vector<int>& num_temporal_layers,
152*d9f75844SAndroid Build Coastguard Worker                           const std::vector<ScalabilityMode>& scalability_mode);
153*d9f75844SAndroid Build Coastguard Worker };
154*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,CanStartStartedStream)155*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, CanStartStartedStream) {
156*d9f75844SAndroid Build Coastguard Worker   SendTask(task_queue(), [this]() {
157*d9f75844SAndroid Build Coastguard Worker     CreateSenderCall();
158*d9f75844SAndroid Build Coastguard Worker 
159*d9f75844SAndroid Build Coastguard Worker     test::NullTransport transport;
160*d9f75844SAndroid Build Coastguard Worker     CreateSendConfig(1, 0, 0, &transport);
161*d9f75844SAndroid Build Coastguard Worker     CreateVideoStreams();
162*d9f75844SAndroid Build Coastguard Worker     GetVideoSendStream()->Start();
163*d9f75844SAndroid Build Coastguard Worker     GetVideoSendStream()->Start();
164*d9f75844SAndroid Build Coastguard Worker     DestroyStreams();
165*d9f75844SAndroid Build Coastguard Worker     DestroyCalls();
166*d9f75844SAndroid Build Coastguard Worker   });
167*d9f75844SAndroid Build Coastguard Worker }
168*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,CanStopStoppedStream)169*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
170*d9f75844SAndroid Build Coastguard Worker   SendTask(task_queue(), [this]() {
171*d9f75844SAndroid Build Coastguard Worker     CreateSenderCall();
172*d9f75844SAndroid Build Coastguard Worker 
173*d9f75844SAndroid Build Coastguard Worker     test::NullTransport transport;
174*d9f75844SAndroid Build Coastguard Worker     CreateSendConfig(1, 0, 0, &transport);
175*d9f75844SAndroid Build Coastguard Worker     CreateVideoStreams();
176*d9f75844SAndroid Build Coastguard Worker     GetVideoSendStream()->Stop();
177*d9f75844SAndroid Build Coastguard Worker     GetVideoSendStream()->Stop();
178*d9f75844SAndroid Build Coastguard Worker     DestroyStreams();
179*d9f75844SAndroid Build Coastguard Worker     DestroyCalls();
180*d9f75844SAndroid Build Coastguard Worker   });
181*d9f75844SAndroid Build Coastguard Worker }
182*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsCName)183*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsCName) {
184*d9f75844SAndroid Build Coastguard Worker   static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
185*d9f75844SAndroid Build Coastguard Worker   class CNameObserver : public test::SendTest {
186*d9f75844SAndroid Build Coastguard Worker    public:
187*d9f75844SAndroid Build Coastguard Worker     CNameObserver() : SendTest(kDefaultTimeout) {}
188*d9f75844SAndroid Build Coastguard Worker 
189*d9f75844SAndroid Build Coastguard Worker    private:
190*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtcp(const uint8_t* packet, size_t length) override {
191*d9f75844SAndroid Build Coastguard Worker       test::RtcpPacketParser parser;
192*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(parser.Parse(packet, length));
193*d9f75844SAndroid Build Coastguard Worker       if (parser.sdes()->num_packets() > 0) {
194*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(1u, parser.sdes()->chunks().size());
195*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(kCName, parser.sdes()->chunks()[0].cname);
196*d9f75844SAndroid Build Coastguard Worker 
197*d9f75844SAndroid Build Coastguard Worker         observation_complete_.Set();
198*d9f75844SAndroid Build Coastguard Worker       }
199*d9f75844SAndroid Build Coastguard Worker 
200*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
201*d9f75844SAndroid Build Coastguard Worker     }
202*d9f75844SAndroid Build Coastguard Worker 
203*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
204*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
205*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
206*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
207*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.c_name = kCName;
208*d9f75844SAndroid Build Coastguard Worker     }
209*d9f75844SAndroid Build Coastguard Worker 
210*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
211*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while waiting for RTCP with CNAME.";
212*d9f75844SAndroid Build Coastguard Worker     }
213*d9f75844SAndroid Build Coastguard Worker   } test;
214*d9f75844SAndroid Build Coastguard Worker 
215*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
216*d9f75844SAndroid Build Coastguard Worker }
217*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsAbsoluteSendTime)218*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
219*d9f75844SAndroid Build Coastguard Worker   class AbsoluteSendTimeObserver : public test::SendTest {
220*d9f75844SAndroid Build Coastguard Worker    public:
221*d9f75844SAndroid Build Coastguard Worker     AbsoluteSendTimeObserver() : SendTest(kDefaultTimeout) {
222*d9f75844SAndroid Build Coastguard Worker       extensions_.Register<AbsoluteSendTime>(kAbsSendTimeExtensionId);
223*d9f75844SAndroid Build Coastguard Worker     }
224*d9f75844SAndroid Build Coastguard Worker 
225*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
226*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet(&extensions_);
227*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.Parse(packet, length));
228*d9f75844SAndroid Build Coastguard Worker 
229*d9f75844SAndroid Build Coastguard Worker       uint32_t abs_send_time = 0;
230*d9f75844SAndroid Build Coastguard Worker       EXPECT_FALSE(rtp_packet.HasExtension<TransmissionOffset>());
231*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.GetExtension<AbsoluteSendTime>(&abs_send_time));
232*d9f75844SAndroid Build Coastguard Worker       if (abs_send_time != 0) {
233*d9f75844SAndroid Build Coastguard Worker         // Wait for at least one packet with a non-zero send time. The send time
234*d9f75844SAndroid Build Coastguard Worker         // is a 16-bit value derived from the system clock, and it is valid
235*d9f75844SAndroid Build Coastguard Worker         // for a packet to have a zero send time. To tell that from an
236*d9f75844SAndroid Build Coastguard Worker         // unpopulated value we'll wait for a packet with non-zero send time.
237*d9f75844SAndroid Build Coastguard Worker         observation_complete_.Set();
238*d9f75844SAndroid Build Coastguard Worker       } else {
239*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_WARNING)
240*d9f75844SAndroid Build Coastguard Worker             << "Got a packet with zero absoluteSendTime, waiting"
241*d9f75844SAndroid Build Coastguard Worker                " for another packet...";
242*d9f75844SAndroid Build Coastguard Worker       }
243*d9f75844SAndroid Build Coastguard Worker 
244*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
245*d9f75844SAndroid Build Coastguard Worker     }
246*d9f75844SAndroid Build Coastguard Worker 
247*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
248*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
249*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
250*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
251*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.clear();
252*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.push_back(
253*d9f75844SAndroid Build Coastguard Worker           RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeExtensionId));
254*d9f75844SAndroid Build Coastguard Worker     }
255*d9f75844SAndroid Build Coastguard Worker 
256*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
257*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while waiting for single RTP packet.";
258*d9f75844SAndroid Build Coastguard Worker     }
259*d9f75844SAndroid Build Coastguard Worker 
260*d9f75844SAndroid Build Coastguard Worker    private:
261*d9f75844SAndroid Build Coastguard Worker     RtpHeaderExtensionMap extensions_;
262*d9f75844SAndroid Build Coastguard Worker   } test;
263*d9f75844SAndroid Build Coastguard Worker 
264*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
265*d9f75844SAndroid Build Coastguard Worker }
266*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsTransmissionTimeOffset)267*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
268*d9f75844SAndroid Build Coastguard Worker   static const int kEncodeDelayMs = 5;
269*d9f75844SAndroid Build Coastguard Worker   class TransmissionTimeOffsetObserver : public test::SendTest {
270*d9f75844SAndroid Build Coastguard Worker    public:
271*d9f75844SAndroid Build Coastguard Worker     TransmissionTimeOffsetObserver()
272*d9f75844SAndroid Build Coastguard Worker         : SendTest(kDefaultTimeout), encoder_factory_([]() {
273*d9f75844SAndroid Build Coastguard Worker             return std::make_unique<test::DelayedEncoder>(
274*d9f75844SAndroid Build Coastguard Worker                 Clock::GetRealTimeClock(), kEncodeDelayMs);
275*d9f75844SAndroid Build Coastguard Worker           }) {
276*d9f75844SAndroid Build Coastguard Worker       extensions_.Register<TransmissionOffset>(kTimestampOffsetExtensionId);
277*d9f75844SAndroid Build Coastguard Worker     }
278*d9f75844SAndroid Build Coastguard Worker 
279*d9f75844SAndroid Build Coastguard Worker    private:
280*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
281*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet(&extensions_);
282*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.Parse(packet, length));
283*d9f75844SAndroid Build Coastguard Worker 
284*d9f75844SAndroid Build Coastguard Worker       int32_t toffset = 0;
285*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.GetExtension<TransmissionOffset>(&toffset));
286*d9f75844SAndroid Build Coastguard Worker       EXPECT_FALSE(rtp_packet.HasExtension<AbsoluteSendTime>());
287*d9f75844SAndroid Build Coastguard Worker       EXPECT_GT(toffset, 0);
288*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
289*d9f75844SAndroid Build Coastguard Worker 
290*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
291*d9f75844SAndroid Build Coastguard Worker     }
292*d9f75844SAndroid Build Coastguard Worker 
293*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
294*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
295*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
296*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
297*d9f75844SAndroid Build Coastguard Worker       send_config->encoder_settings.encoder_factory = &encoder_factory_;
298*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.clear();
299*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.push_back(RtpExtension(
300*d9f75844SAndroid Build Coastguard Worker           RtpExtension::kTimestampOffsetUri, kTimestampOffsetExtensionId));
301*d9f75844SAndroid Build Coastguard Worker     }
302*d9f75844SAndroid Build Coastguard Worker 
303*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
304*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
305*d9f75844SAndroid Build Coastguard Worker     }
306*d9f75844SAndroid Build Coastguard Worker 
307*d9f75844SAndroid Build Coastguard Worker     test::FunctionVideoEncoderFactory encoder_factory_;
308*d9f75844SAndroid Build Coastguard Worker     RtpHeaderExtensionMap extensions_;
309*d9f75844SAndroid Build Coastguard Worker   } test;
310*d9f75844SAndroid Build Coastguard Worker 
311*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
312*d9f75844SAndroid Build Coastguard Worker }
313*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsTransportWideSequenceNumbers)314*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsTransportWideSequenceNumbers) {
315*d9f75844SAndroid Build Coastguard Worker   static const uint8_t kExtensionId = kTransportSequenceNumberExtensionId;
316*d9f75844SAndroid Build Coastguard Worker   class TransportWideSequenceNumberObserver : public test::SendTest {
317*d9f75844SAndroid Build Coastguard Worker    public:
318*d9f75844SAndroid Build Coastguard Worker     TransportWideSequenceNumberObserver()
319*d9f75844SAndroid Build Coastguard Worker         : SendTest(kDefaultTimeout), encoder_factory_([]() {
320*d9f75844SAndroid Build Coastguard Worker             return std::make_unique<test::FakeEncoder>(
321*d9f75844SAndroid Build Coastguard Worker                 Clock::GetRealTimeClock());
322*d9f75844SAndroid Build Coastguard Worker           }) {
323*d9f75844SAndroid Build Coastguard Worker       extensions_.Register<TransportSequenceNumber>(kExtensionId);
324*d9f75844SAndroid Build Coastguard Worker     }
325*d9f75844SAndroid Build Coastguard Worker 
326*d9f75844SAndroid Build Coastguard Worker    private:
327*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
328*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet(&extensions_);
329*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.Parse(packet, length));
330*d9f75844SAndroid Build Coastguard Worker 
331*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.HasExtension<TransportSequenceNumber>());
332*d9f75844SAndroid Build Coastguard Worker       EXPECT_FALSE(rtp_packet.HasExtension<TransmissionOffset>());
333*d9f75844SAndroid Build Coastguard Worker       EXPECT_FALSE(rtp_packet.HasExtension<AbsoluteSendTime>());
334*d9f75844SAndroid Build Coastguard Worker 
335*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
336*d9f75844SAndroid Build Coastguard Worker 
337*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
338*d9f75844SAndroid Build Coastguard Worker     }
339*d9f75844SAndroid Build Coastguard Worker 
340*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
341*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
342*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
343*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
344*d9f75844SAndroid Build Coastguard Worker       send_config->encoder_settings.encoder_factory = &encoder_factory_;
345*d9f75844SAndroid Build Coastguard Worker     }
346*d9f75844SAndroid Build Coastguard Worker 
347*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
348*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
349*d9f75844SAndroid Build Coastguard Worker     }
350*d9f75844SAndroid Build Coastguard Worker 
351*d9f75844SAndroid Build Coastguard Worker     test::FunctionVideoEncoderFactory encoder_factory_;
352*d9f75844SAndroid Build Coastguard Worker     RtpHeaderExtensionMap extensions_;
353*d9f75844SAndroid Build Coastguard Worker   } test;
354*d9f75844SAndroid Build Coastguard Worker 
355*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
356*d9f75844SAndroid Build Coastguard Worker }
357*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsVideoRotation)358*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsVideoRotation) {
359*d9f75844SAndroid Build Coastguard Worker   class VideoRotationObserver : public test::SendTest {
360*d9f75844SAndroid Build Coastguard Worker    public:
361*d9f75844SAndroid Build Coastguard Worker     VideoRotationObserver() : SendTest(kDefaultTimeout) {
362*d9f75844SAndroid Build Coastguard Worker       extensions_.Register<VideoOrientation>(kVideoRotationExtensionId);
363*d9f75844SAndroid Build Coastguard Worker     }
364*d9f75844SAndroid Build Coastguard Worker 
365*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
366*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet(&extensions_);
367*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.Parse(packet, length));
368*d9f75844SAndroid Build Coastguard Worker       // Only the last packet of the frame is required to have the extension.
369*d9f75844SAndroid Build Coastguard Worker       if (!rtp_packet.Marker())
370*d9f75844SAndroid Build Coastguard Worker         return SEND_PACKET;
371*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(rtp_packet.GetExtension<VideoOrientation>(), kVideoRotation_90);
372*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
373*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
374*d9f75844SAndroid Build Coastguard Worker     }
375*d9f75844SAndroid Build Coastguard Worker 
376*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
377*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
378*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
379*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
380*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.clear();
381*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.push_back(RtpExtension(
382*d9f75844SAndroid Build Coastguard Worker           RtpExtension::kVideoRotationUri, kVideoRotationExtensionId));
383*d9f75844SAndroid Build Coastguard Worker     }
384*d9f75844SAndroid Build Coastguard Worker 
385*d9f75844SAndroid Build Coastguard Worker     void OnFrameGeneratorCapturerCreated(
386*d9f75844SAndroid Build Coastguard Worker         test::FrameGeneratorCapturer* frame_generator_capturer) override {
387*d9f75844SAndroid Build Coastguard Worker       frame_generator_capturer->SetFakeRotation(kVideoRotation_90);
388*d9f75844SAndroid Build Coastguard Worker     }
389*d9f75844SAndroid Build Coastguard Worker 
390*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
391*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while waiting for single RTP packet.";
392*d9f75844SAndroid Build Coastguard Worker     }
393*d9f75844SAndroid Build Coastguard Worker 
394*d9f75844SAndroid Build Coastguard Worker    private:
395*d9f75844SAndroid Build Coastguard Worker     RtpHeaderExtensionMap extensions_;
396*d9f75844SAndroid Build Coastguard Worker   } test;
397*d9f75844SAndroid Build Coastguard Worker 
398*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
399*d9f75844SAndroid Build Coastguard Worker }
400*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsVideoContentType)401*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsVideoContentType) {
402*d9f75844SAndroid Build Coastguard Worker   class VideoContentTypeObserver : public test::SendTest {
403*d9f75844SAndroid Build Coastguard Worker    public:
404*d9f75844SAndroid Build Coastguard Worker     VideoContentTypeObserver()
405*d9f75844SAndroid Build Coastguard Worker         : SendTest(kDefaultTimeout), first_frame_sent_(false) {
406*d9f75844SAndroid Build Coastguard Worker       extensions_.Register<VideoContentTypeExtension>(
407*d9f75844SAndroid Build Coastguard Worker           kVideoContentTypeExtensionId);
408*d9f75844SAndroid Build Coastguard Worker     }
409*d9f75844SAndroid Build Coastguard Worker 
410*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
411*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet(&extensions_);
412*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.Parse(packet, length));
413*d9f75844SAndroid Build Coastguard Worker       // Only the last packet of the key-frame must have extension.
414*d9f75844SAndroid Build Coastguard Worker       if (!rtp_packet.Marker() || first_frame_sent_)
415*d9f75844SAndroid Build Coastguard Worker         return SEND_PACKET;
416*d9f75844SAndroid Build Coastguard Worker       // First marker bit seen means that the first frame is sent.
417*d9f75844SAndroid Build Coastguard Worker       first_frame_sent_ = true;
418*d9f75844SAndroid Build Coastguard Worker       VideoContentType type;
419*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.GetExtension<VideoContentTypeExtension>(&type));
420*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(videocontenttypehelpers::IsScreenshare(type));
421*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
422*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
423*d9f75844SAndroid Build Coastguard Worker     }
424*d9f75844SAndroid Build Coastguard Worker 
425*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
426*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
427*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
428*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
429*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.clear();
430*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.push_back(RtpExtension(
431*d9f75844SAndroid Build Coastguard Worker           RtpExtension::kVideoContentTypeUri, kVideoContentTypeExtensionId));
432*d9f75844SAndroid Build Coastguard Worker       encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
433*d9f75844SAndroid Build Coastguard Worker     }
434*d9f75844SAndroid Build Coastguard Worker 
435*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
436*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while waiting for single RTP packet.";
437*d9f75844SAndroid Build Coastguard Worker     }
438*d9f75844SAndroid Build Coastguard Worker 
439*d9f75844SAndroid Build Coastguard Worker    private:
440*d9f75844SAndroid Build Coastguard Worker     bool first_frame_sent_;
441*d9f75844SAndroid Build Coastguard Worker     RtpHeaderExtensionMap extensions_;
442*d9f75844SAndroid Build Coastguard Worker   } test;
443*d9f75844SAndroid Build Coastguard Worker 
444*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
445*d9f75844SAndroid Build Coastguard Worker }
446*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsVideoTimingFrames)447*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsVideoTimingFrames) {
448*d9f75844SAndroid Build Coastguard Worker   class VideoTimingObserver : public test::SendTest {
449*d9f75844SAndroid Build Coastguard Worker    public:
450*d9f75844SAndroid Build Coastguard Worker     VideoTimingObserver()
451*d9f75844SAndroid Build Coastguard Worker         : SendTest(kDefaultTimeout), first_frame_sent_(false) {
452*d9f75844SAndroid Build Coastguard Worker       extensions_.Register<VideoTimingExtension>(kVideoTimingExtensionId);
453*d9f75844SAndroid Build Coastguard Worker     }
454*d9f75844SAndroid Build Coastguard Worker 
455*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
456*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet(&extensions_);
457*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.Parse(packet, length));
458*d9f75844SAndroid Build Coastguard Worker       // Only the last packet of the frame must have extension.
459*d9f75844SAndroid Build Coastguard Worker       // Also don't check packets of the second frame if they happen to get
460*d9f75844SAndroid Build Coastguard Worker       // through before the test terminates.
461*d9f75844SAndroid Build Coastguard Worker       if (!rtp_packet.Marker() || first_frame_sent_)
462*d9f75844SAndroid Build Coastguard Worker         return SEND_PACKET;
463*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.HasExtension<VideoTimingExtension>());
464*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
465*d9f75844SAndroid Build Coastguard Worker       first_frame_sent_ = true;
466*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
467*d9f75844SAndroid Build Coastguard Worker     }
468*d9f75844SAndroid Build Coastguard Worker 
469*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
470*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
471*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
472*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
473*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.clear();
474*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.push_back(
475*d9f75844SAndroid Build Coastguard Worker           RtpExtension(RtpExtension::kVideoTimingUri, kVideoTimingExtensionId));
476*d9f75844SAndroid Build Coastguard Worker     }
477*d9f75844SAndroid Build Coastguard Worker 
478*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
479*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while waiting for timing frames.";
480*d9f75844SAndroid Build Coastguard Worker     }
481*d9f75844SAndroid Build Coastguard Worker 
482*d9f75844SAndroid Build Coastguard Worker    private:
483*d9f75844SAndroid Build Coastguard Worker     RtpHeaderExtensionMap extensions_;
484*d9f75844SAndroid Build Coastguard Worker     bool first_frame_sent_;
485*d9f75844SAndroid Build Coastguard Worker   } test;
486*d9f75844SAndroid Build Coastguard Worker 
487*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
488*d9f75844SAndroid Build Coastguard Worker }
489*d9f75844SAndroid Build Coastguard Worker 
490*d9f75844SAndroid Build Coastguard Worker class FakeReceiveStatistics : public ReceiveStatisticsProvider {
491*d9f75844SAndroid Build Coastguard Worker  public:
FakeReceiveStatistics(uint32_t send_ssrc,uint32_t last_sequence_number,uint32_t cumulative_lost,uint8_t fraction_lost)492*d9f75844SAndroid Build Coastguard Worker   FakeReceiveStatistics(uint32_t send_ssrc,
493*d9f75844SAndroid Build Coastguard Worker                         uint32_t last_sequence_number,
494*d9f75844SAndroid Build Coastguard Worker                         uint32_t cumulative_lost,
495*d9f75844SAndroid Build Coastguard Worker                         uint8_t fraction_lost) {
496*d9f75844SAndroid Build Coastguard Worker     stat_.SetMediaSsrc(send_ssrc);
497*d9f75844SAndroid Build Coastguard Worker     stat_.SetExtHighestSeqNum(last_sequence_number);
498*d9f75844SAndroid Build Coastguard Worker     stat_.SetCumulativeLost(cumulative_lost);
499*d9f75844SAndroid Build Coastguard Worker     stat_.SetFractionLost(fraction_lost);
500*d9f75844SAndroid Build Coastguard Worker   }
501*d9f75844SAndroid Build Coastguard Worker 
RtcpReportBlocks(size_t max_blocks)502*d9f75844SAndroid Build Coastguard Worker   std::vector<rtcp::ReportBlock> RtcpReportBlocks(size_t max_blocks) override {
503*d9f75844SAndroid Build Coastguard Worker     EXPECT_GE(max_blocks, 1u);
504*d9f75844SAndroid Build Coastguard Worker     return {stat_};
505*d9f75844SAndroid Build Coastguard Worker   }
506*d9f75844SAndroid Build Coastguard Worker 
507*d9f75844SAndroid Build Coastguard Worker  private:
508*d9f75844SAndroid Build Coastguard Worker   rtcp::ReportBlock stat_;
509*d9f75844SAndroid Build Coastguard Worker };
510*d9f75844SAndroid Build Coastguard Worker 
511*d9f75844SAndroid Build Coastguard Worker class UlpfecObserver : public test::EndToEndTest {
512*d9f75844SAndroid Build Coastguard Worker  public:
513*d9f75844SAndroid Build Coastguard Worker   // Some of the test cases are expected to time out.
514*d9f75844SAndroid Build Coastguard Worker   // Use a shorter timeout window than the default one for those.
515*d9f75844SAndroid Build Coastguard Worker   static constexpr TimeDelta kReducedTimeout = TimeDelta::Seconds(10);
516*d9f75844SAndroid Build Coastguard Worker 
UlpfecObserver(bool header_extensions_enabled,bool use_nack,bool expect_red,bool expect_ulpfec,const std::string & codec,VideoEncoderFactory * encoder_factory)517*d9f75844SAndroid Build Coastguard Worker   UlpfecObserver(bool header_extensions_enabled,
518*d9f75844SAndroid Build Coastguard Worker                  bool use_nack,
519*d9f75844SAndroid Build Coastguard Worker                  bool expect_red,
520*d9f75844SAndroid Build Coastguard Worker                  bool expect_ulpfec,
521*d9f75844SAndroid Build Coastguard Worker                  const std::string& codec,
522*d9f75844SAndroid Build Coastguard Worker                  VideoEncoderFactory* encoder_factory)
523*d9f75844SAndroid Build Coastguard Worker       : EndToEndTest(expect_ulpfec ? VideoSendStreamTest::kDefaultTimeout
524*d9f75844SAndroid Build Coastguard Worker                                    : kReducedTimeout),
525*d9f75844SAndroid Build Coastguard Worker         encoder_factory_(encoder_factory),
526*d9f75844SAndroid Build Coastguard Worker         payload_name_(codec),
527*d9f75844SAndroid Build Coastguard Worker         use_nack_(use_nack),
528*d9f75844SAndroid Build Coastguard Worker         expect_red_(expect_red),
529*d9f75844SAndroid Build Coastguard Worker         expect_ulpfec_(expect_ulpfec),
530*d9f75844SAndroid Build Coastguard Worker         sent_media_(false),
531*d9f75844SAndroid Build Coastguard Worker         sent_ulpfec_(false),
532*d9f75844SAndroid Build Coastguard Worker         header_extensions_enabled_(header_extensions_enabled) {
533*d9f75844SAndroid Build Coastguard Worker     extensions_.Register<AbsoluteSendTime>(kAbsSendTimeExtensionId);
534*d9f75844SAndroid Build Coastguard Worker     extensions_.Register<TransportSequenceNumber>(
535*d9f75844SAndroid Build Coastguard Worker         kTransportSequenceNumberExtensionId);
536*d9f75844SAndroid Build Coastguard Worker   }
537*d9f75844SAndroid Build Coastguard Worker 
538*d9f75844SAndroid Build Coastguard Worker  private:
OnSendRtp(const uint8_t * packet,size_t length)539*d9f75844SAndroid Build Coastguard Worker   Action OnSendRtp(const uint8_t* packet, size_t length) override {
540*d9f75844SAndroid Build Coastguard Worker     RtpPacket rtp_packet(&extensions_);
541*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(rtp_packet.Parse(packet, length));
542*d9f75844SAndroid Build Coastguard Worker 
543*d9f75844SAndroid Build Coastguard Worker     int encapsulated_payload_type = -1;
544*d9f75844SAndroid Build Coastguard Worker     if (rtp_packet.PayloadType() == VideoSendStreamTest::kRedPayloadType) {
545*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(expect_red_);
546*d9f75844SAndroid Build Coastguard Worker       encapsulated_payload_type = rtp_packet.payload()[0];
547*d9f75844SAndroid Build Coastguard Worker       if (encapsulated_payload_type !=
548*d9f75844SAndroid Build Coastguard Worker           VideoSendStreamTest::kFakeVideoSendPayloadType) {
549*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(VideoSendStreamTest::kUlpfecPayloadType,
550*d9f75844SAndroid Build Coastguard Worker                   encapsulated_payload_type);
551*d9f75844SAndroid Build Coastguard Worker       }
552*d9f75844SAndroid Build Coastguard Worker     } else {
553*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType,
554*d9f75844SAndroid Build Coastguard Worker                 rtp_packet.PayloadType());
555*d9f75844SAndroid Build Coastguard Worker       if (rtp_packet.payload_size() > 0) {
556*d9f75844SAndroid Build Coastguard Worker         // Not padding-only, media received outside of RED.
557*d9f75844SAndroid Build Coastguard Worker         EXPECT_FALSE(expect_red_);
558*d9f75844SAndroid Build Coastguard Worker         sent_media_ = true;
559*d9f75844SAndroid Build Coastguard Worker       }
560*d9f75844SAndroid Build Coastguard Worker     }
561*d9f75844SAndroid Build Coastguard Worker 
562*d9f75844SAndroid Build Coastguard Worker     if (header_extensions_enabled_) {
563*d9f75844SAndroid Build Coastguard Worker       uint32_t abs_send_time;
564*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.GetExtension<AbsoluteSendTime>(&abs_send_time));
565*d9f75844SAndroid Build Coastguard Worker       uint16_t transport_seq_num;
566*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(
567*d9f75844SAndroid Build Coastguard Worker           rtp_packet.GetExtension<TransportSequenceNumber>(&transport_seq_num));
568*d9f75844SAndroid Build Coastguard Worker       if (!first_packet_) {
569*d9f75844SAndroid Build Coastguard Worker         uint32_t kHalf24BitsSpace = 0xFFFFFF / 2;
570*d9f75844SAndroid Build Coastguard Worker         if (abs_send_time <= kHalf24BitsSpace &&
571*d9f75844SAndroid Build Coastguard Worker             prev_abs_send_time_ > kHalf24BitsSpace) {
572*d9f75844SAndroid Build Coastguard Worker           // 24 bits wrap.
573*d9f75844SAndroid Build Coastguard Worker           EXPECT_GT(prev_abs_send_time_, abs_send_time);
574*d9f75844SAndroid Build Coastguard Worker         } else {
575*d9f75844SAndroid Build Coastguard Worker           EXPECT_GE(abs_send_time, prev_abs_send_time_);
576*d9f75844SAndroid Build Coastguard Worker         }
577*d9f75844SAndroid Build Coastguard Worker 
578*d9f75844SAndroid Build Coastguard Worker         uint16_t seq_num_diff = transport_seq_num - prev_transport_seq_num_;
579*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(1, seq_num_diff);
580*d9f75844SAndroid Build Coastguard Worker       }
581*d9f75844SAndroid Build Coastguard Worker       first_packet_ = false;
582*d9f75844SAndroid Build Coastguard Worker       prev_abs_send_time_ = abs_send_time;
583*d9f75844SAndroid Build Coastguard Worker       prev_transport_seq_num_ = transport_seq_num;
584*d9f75844SAndroid Build Coastguard Worker     }
585*d9f75844SAndroid Build Coastguard Worker 
586*d9f75844SAndroid Build Coastguard Worker     if (encapsulated_payload_type != -1) {
587*d9f75844SAndroid Build Coastguard Worker       if (encapsulated_payload_type ==
588*d9f75844SAndroid Build Coastguard Worker           VideoSendStreamTest::kUlpfecPayloadType) {
589*d9f75844SAndroid Build Coastguard Worker         EXPECT_TRUE(expect_ulpfec_);
590*d9f75844SAndroid Build Coastguard Worker         sent_ulpfec_ = true;
591*d9f75844SAndroid Build Coastguard Worker       } else {
592*d9f75844SAndroid Build Coastguard Worker         sent_media_ = true;
593*d9f75844SAndroid Build Coastguard Worker       }
594*d9f75844SAndroid Build Coastguard Worker     }
595*d9f75844SAndroid Build Coastguard Worker 
596*d9f75844SAndroid Build Coastguard Worker     if (sent_media_ && sent_ulpfec_) {
597*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
598*d9f75844SAndroid Build Coastguard Worker     }
599*d9f75844SAndroid Build Coastguard Worker 
600*d9f75844SAndroid Build Coastguard Worker     return SEND_PACKET;
601*d9f75844SAndroid Build Coastguard Worker   }
602*d9f75844SAndroid Build Coastguard Worker 
CreateSendTransport(TaskQueueBase * task_queue,Call * sender_call)603*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<test::PacketTransport> CreateSendTransport(
604*d9f75844SAndroid Build Coastguard Worker       TaskQueueBase* task_queue,
605*d9f75844SAndroid Build Coastguard Worker       Call* sender_call) override {
606*d9f75844SAndroid Build Coastguard Worker     // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
607*d9f75844SAndroid Build Coastguard Worker     // Configure some network delay.
608*d9f75844SAndroid Build Coastguard Worker     const int kNetworkDelayMs = 100;
609*d9f75844SAndroid Build Coastguard Worker     BuiltInNetworkBehaviorConfig config;
610*d9f75844SAndroid Build Coastguard Worker     config.loss_percent = 5;
611*d9f75844SAndroid Build Coastguard Worker     config.queue_delay_ms = kNetworkDelayMs;
612*d9f75844SAndroid Build Coastguard Worker     return std::make_unique<test::PacketTransport>(
613*d9f75844SAndroid Build Coastguard Worker         task_queue, sender_call, this, test::PacketTransport::kSender,
614*d9f75844SAndroid Build Coastguard Worker         VideoSendStreamTest::payload_type_map_,
615*d9f75844SAndroid Build Coastguard Worker         std::make_unique<FakeNetworkPipe>(
616*d9f75844SAndroid Build Coastguard Worker             Clock::GetRealTimeClock(),
617*d9f75844SAndroid Build Coastguard Worker             std::make_unique<SimulatedNetwork>(config)));
618*d9f75844SAndroid Build Coastguard Worker   }
619*d9f75844SAndroid Build Coastguard Worker 
ModifyVideoConfigs(VideoSendStream::Config * send_config,std::vector<VideoReceiveStreamInterface::Config> * receive_configs,VideoEncoderConfig * encoder_config)620*d9f75844SAndroid Build Coastguard Worker   void ModifyVideoConfigs(
621*d9f75844SAndroid Build Coastguard Worker       VideoSendStream::Config* send_config,
622*d9f75844SAndroid Build Coastguard Worker       std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
623*d9f75844SAndroid Build Coastguard Worker       VideoEncoderConfig* encoder_config) override {
624*d9f75844SAndroid Build Coastguard Worker     if (use_nack_) {
625*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.nack.rtp_history_ms =
626*d9f75844SAndroid Build Coastguard Worker           (*receive_configs)[0].rtp.nack.rtp_history_ms =
627*d9f75844SAndroid Build Coastguard Worker               VideoSendStreamTest::kNackRtpHistoryMs;
628*d9f75844SAndroid Build Coastguard Worker     }
629*d9f75844SAndroid Build Coastguard Worker     send_config->encoder_settings.encoder_factory = encoder_factory_;
630*d9f75844SAndroid Build Coastguard Worker     send_config->rtp.payload_name = payload_name_;
631*d9f75844SAndroid Build Coastguard Worker     send_config->rtp.ulpfec.red_payload_type =
632*d9f75844SAndroid Build Coastguard Worker         VideoSendStreamTest::kRedPayloadType;
633*d9f75844SAndroid Build Coastguard Worker     send_config->rtp.ulpfec.ulpfec_payload_type =
634*d9f75844SAndroid Build Coastguard Worker         VideoSendStreamTest::kUlpfecPayloadType;
635*d9f75844SAndroid Build Coastguard Worker     if (!header_extensions_enabled_) {
636*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.clear();
637*d9f75844SAndroid Build Coastguard Worker     } else {
638*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.push_back(
639*d9f75844SAndroid Build Coastguard Worker           RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeExtensionId));
640*d9f75844SAndroid Build Coastguard Worker     }
641*d9f75844SAndroid Build Coastguard Worker     (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
642*d9f75844SAndroid Build Coastguard Worker     encoder_config->codec_type = PayloadStringToCodecType(payload_name_);
643*d9f75844SAndroid Build Coastguard Worker     (*receive_configs)[0].rtp.red_payload_type =
644*d9f75844SAndroid Build Coastguard Worker         send_config->rtp.ulpfec.red_payload_type;
645*d9f75844SAndroid Build Coastguard Worker     (*receive_configs)[0].rtp.ulpfec_payload_type =
646*d9f75844SAndroid Build Coastguard Worker         send_config->rtp.ulpfec.ulpfec_payload_type;
647*d9f75844SAndroid Build Coastguard Worker   }
648*d9f75844SAndroid Build Coastguard Worker 
PerformTest()649*d9f75844SAndroid Build Coastguard Worker   void PerformTest() override {
650*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(expect_ulpfec_, Wait())
651*d9f75844SAndroid Build Coastguard Worker         << "Timed out waiting for ULPFEC and/or media packets.";
652*d9f75844SAndroid Build Coastguard Worker   }
653*d9f75844SAndroid Build Coastguard Worker 
654*d9f75844SAndroid Build Coastguard Worker   VideoEncoderFactory* encoder_factory_;
655*d9f75844SAndroid Build Coastguard Worker   RtpHeaderExtensionMap extensions_;
656*d9f75844SAndroid Build Coastguard Worker   const std::string payload_name_;
657*d9f75844SAndroid Build Coastguard Worker   const bool use_nack_;
658*d9f75844SAndroid Build Coastguard Worker   const bool expect_red_;
659*d9f75844SAndroid Build Coastguard Worker   const bool expect_ulpfec_;
660*d9f75844SAndroid Build Coastguard Worker   bool sent_media_;
661*d9f75844SAndroid Build Coastguard Worker   bool sent_ulpfec_;
662*d9f75844SAndroid Build Coastguard Worker   const bool header_extensions_enabled_;
663*d9f75844SAndroid Build Coastguard Worker   bool first_packet_ = true;
664*d9f75844SAndroid Build Coastguard Worker   uint32_t prev_abs_send_time_ = 0;
665*d9f75844SAndroid Build Coastguard Worker   uint16_t prev_transport_seq_num_ = 0;
666*d9f75844SAndroid Build Coastguard Worker };
667*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsUlpfecWithExtensions)668*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsUlpfecWithExtensions) {
669*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
670*d9f75844SAndroid Build Coastguard Worker       []() { return VP8Encoder::Create(); });
671*d9f75844SAndroid Build Coastguard Worker   UlpfecObserver test(true, false, true, true, "VP8", &encoder_factory);
672*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
673*d9f75844SAndroid Build Coastguard Worker }
674*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsUlpfecWithoutExtensions)675*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsUlpfecWithoutExtensions) {
676*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
677*d9f75844SAndroid Build Coastguard Worker       []() { return VP8Encoder::Create(); });
678*d9f75844SAndroid Build Coastguard Worker   UlpfecObserver test(false, false, true, true, "VP8", &encoder_factory);
679*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
680*d9f75844SAndroid Build Coastguard Worker }
681*d9f75844SAndroid Build Coastguard Worker 
682*d9f75844SAndroid Build Coastguard Worker class VideoSendStreamWithoutUlpfecTest : public test::CallTest {
683*d9f75844SAndroid Build Coastguard Worker  protected:
VideoSendStreamWithoutUlpfecTest()684*d9f75844SAndroid Build Coastguard Worker   VideoSendStreamWithoutUlpfecTest()
685*d9f75844SAndroid Build Coastguard Worker       : field_trial_(field_trials_, "WebRTC-DisableUlpFecExperiment/Enabled/") {
686*d9f75844SAndroid Build Coastguard Worker   }
687*d9f75844SAndroid Build Coastguard Worker 
688*d9f75844SAndroid Build Coastguard Worker   test::ScopedKeyValueConfig field_trial_;
689*d9f75844SAndroid Build Coastguard Worker };
690*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamWithoutUlpfecTest,NoUlpfecIfDisabledThroughFieldTrial)691*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamWithoutUlpfecTest, NoUlpfecIfDisabledThroughFieldTrial) {
692*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
693*d9f75844SAndroid Build Coastguard Worker       []() { return VP8Encoder::Create(); });
694*d9f75844SAndroid Build Coastguard Worker   UlpfecObserver test(false, false, false, false, "VP8", &encoder_factory);
695*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
696*d9f75844SAndroid Build Coastguard Worker }
697*d9f75844SAndroid Build Coastguard Worker 
698*d9f75844SAndroid Build Coastguard Worker // The FEC scheme used is not efficient for H264, so we should not use RED/FEC
699*d9f75844SAndroid Build Coastguard Worker // since we'll still have to re-request FEC packets, effectively wasting
700*d9f75844SAndroid Build Coastguard Worker // bandwidth since the receiver has to wait for FEC retransmissions to determine
701*d9f75844SAndroid Build Coastguard Worker // that the received state is actually decodable.
TEST_F(VideoSendStreamTest,DoesNotUtilizeUlpfecForH264WithNackEnabled)702*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, DoesNotUtilizeUlpfecForH264WithNackEnabled) {
703*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory([]() {
704*d9f75844SAndroid Build Coastguard Worker     return std::make_unique<test::FakeH264Encoder>(Clock::GetRealTimeClock());
705*d9f75844SAndroid Build Coastguard Worker   });
706*d9f75844SAndroid Build Coastguard Worker   UlpfecObserver test(false, true, false, false, "H264", &encoder_factory);
707*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
708*d9f75844SAndroid Build Coastguard Worker }
709*d9f75844SAndroid Build Coastguard Worker 
710*d9f75844SAndroid Build Coastguard Worker // Without retransmissions FEC for H264 is fine.
TEST_F(VideoSendStreamTest,DoesUtilizeUlpfecForH264WithoutNackEnabled)711*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, DoesUtilizeUlpfecForH264WithoutNackEnabled) {
712*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory([]() {
713*d9f75844SAndroid Build Coastguard Worker     return std::make_unique<test::FakeH264Encoder>(Clock::GetRealTimeClock());
714*d9f75844SAndroid Build Coastguard Worker   });
715*d9f75844SAndroid Build Coastguard Worker   UlpfecObserver test(false, false, true, true, "H264", &encoder_factory);
716*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
717*d9f75844SAndroid Build Coastguard Worker }
718*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,DoesUtilizeUlpfecForVp8WithNackEnabled)719*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, DoesUtilizeUlpfecForVp8WithNackEnabled) {
720*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
721*d9f75844SAndroid Build Coastguard Worker       []() { return VP8Encoder::Create(); });
722*d9f75844SAndroid Build Coastguard Worker   UlpfecObserver test(false, true, true, true, "VP8", &encoder_factory);
723*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
724*d9f75844SAndroid Build Coastguard Worker }
725*d9f75844SAndroid Build Coastguard Worker 
726*d9f75844SAndroid Build Coastguard Worker #if defined(RTC_ENABLE_VP9)
TEST_F(VideoSendStreamTest,DoesUtilizeUlpfecForVp9WithNackEnabled)727*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, DoesUtilizeUlpfecForVp9WithNackEnabled) {
728*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
729*d9f75844SAndroid Build Coastguard Worker       []() { return VP9Encoder::Create(); });
730*d9f75844SAndroid Build Coastguard Worker   UlpfecObserver test(false, true, true, true, "VP9", &encoder_factory);
731*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
732*d9f75844SAndroid Build Coastguard Worker }
733*d9f75844SAndroid Build Coastguard Worker #endif  // defined(RTC_ENABLE_VP9)
734*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsUlpfecWithMultithreadedH264)735*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsUlpfecWithMultithreadedH264) {
736*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<TaskQueueFactory> task_queue_factory =
737*d9f75844SAndroid Build Coastguard Worker       CreateDefaultTaskQueueFactory();
738*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory([&]() {
739*d9f75844SAndroid Build Coastguard Worker     return std::make_unique<test::MultithreadedFakeH264Encoder>(
740*d9f75844SAndroid Build Coastguard Worker         Clock::GetRealTimeClock(), task_queue_factory.get());
741*d9f75844SAndroid Build Coastguard Worker   });
742*d9f75844SAndroid Build Coastguard Worker   UlpfecObserver test(false, false, true, true, "H264", &encoder_factory);
743*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
744*d9f75844SAndroid Build Coastguard Worker }
745*d9f75844SAndroid Build Coastguard Worker 
746*d9f75844SAndroid Build Coastguard Worker // TODO(brandtr): Move these FlexFEC tests when we have created
747*d9f75844SAndroid Build Coastguard Worker // FlexfecSendStream.
748*d9f75844SAndroid Build Coastguard Worker class FlexfecObserver : public test::EndToEndTest {
749*d9f75844SAndroid Build Coastguard Worker  public:
FlexfecObserver(bool header_extensions_enabled,bool use_nack,const std::string & codec,VideoEncoderFactory * encoder_factory,size_t num_video_streams)750*d9f75844SAndroid Build Coastguard Worker   FlexfecObserver(bool header_extensions_enabled,
751*d9f75844SAndroid Build Coastguard Worker                   bool use_nack,
752*d9f75844SAndroid Build Coastguard Worker                   const std::string& codec,
753*d9f75844SAndroid Build Coastguard Worker                   VideoEncoderFactory* encoder_factory,
754*d9f75844SAndroid Build Coastguard Worker                   size_t num_video_streams)
755*d9f75844SAndroid Build Coastguard Worker       : EndToEndTest(VideoSendStreamTest::kDefaultTimeout),
756*d9f75844SAndroid Build Coastguard Worker         encoder_factory_(encoder_factory),
757*d9f75844SAndroid Build Coastguard Worker         payload_name_(codec),
758*d9f75844SAndroid Build Coastguard Worker         use_nack_(use_nack),
759*d9f75844SAndroid Build Coastguard Worker         sent_media_(false),
760*d9f75844SAndroid Build Coastguard Worker         sent_flexfec_(false),
761*d9f75844SAndroid Build Coastguard Worker         header_extensions_enabled_(header_extensions_enabled),
762*d9f75844SAndroid Build Coastguard Worker         num_video_streams_(num_video_streams) {
763*d9f75844SAndroid Build Coastguard Worker     extensions_.Register<AbsoluteSendTime>(kAbsSendTimeExtensionId);
764*d9f75844SAndroid Build Coastguard Worker     extensions_.Register<TransmissionOffset>(kTimestampOffsetExtensionId);
765*d9f75844SAndroid Build Coastguard Worker     extensions_.Register<TransportSequenceNumber>(
766*d9f75844SAndroid Build Coastguard Worker         kTransportSequenceNumberExtensionId);
767*d9f75844SAndroid Build Coastguard Worker   }
768*d9f75844SAndroid Build Coastguard Worker 
GetNumFlexfecStreams() const769*d9f75844SAndroid Build Coastguard Worker   size_t GetNumFlexfecStreams() const override { return 1; }
GetNumVideoStreams() const770*d9f75844SAndroid Build Coastguard Worker   size_t GetNumVideoStreams() const override { return num_video_streams_; }
771*d9f75844SAndroid Build Coastguard Worker 
772*d9f75844SAndroid Build Coastguard Worker  private:
OnSendRtp(const uint8_t * packet,size_t length)773*d9f75844SAndroid Build Coastguard Worker   Action OnSendRtp(const uint8_t* packet, size_t length) override {
774*d9f75844SAndroid Build Coastguard Worker     RtpPacket rtp_packet(&extensions_);
775*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(rtp_packet.Parse(packet, length));
776*d9f75844SAndroid Build Coastguard Worker 
777*d9f75844SAndroid Build Coastguard Worker     if (rtp_packet.PayloadType() == VideoSendStreamTest::kFlexfecPayloadType) {
778*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(VideoSendStreamTest::kFlexfecSendSsrc, rtp_packet.Ssrc());
779*d9f75844SAndroid Build Coastguard Worker       sent_flexfec_ = true;
780*d9f75844SAndroid Build Coastguard Worker     } else {
781*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType,
782*d9f75844SAndroid Build Coastguard Worker                 rtp_packet.PayloadType());
783*d9f75844SAndroid Build Coastguard Worker       EXPECT_THAT(::testing::make_tuple(VideoSendStreamTest::kVideoSendSsrcs,
784*d9f75844SAndroid Build Coastguard Worker                                         num_video_streams_),
785*d9f75844SAndroid Build Coastguard Worker                   ::testing::Contains(rtp_packet.Ssrc()));
786*d9f75844SAndroid Build Coastguard Worker       sent_media_ = true;
787*d9f75844SAndroid Build Coastguard Worker     }
788*d9f75844SAndroid Build Coastguard Worker 
789*d9f75844SAndroid Build Coastguard Worker     if (header_extensions_enabled_) {
790*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.HasExtension<AbsoluteSendTime>());
791*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.HasExtension<TransmissionOffset>());
792*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.HasExtension<TransportSequenceNumber>());
793*d9f75844SAndroid Build Coastguard Worker     }
794*d9f75844SAndroid Build Coastguard Worker 
795*d9f75844SAndroid Build Coastguard Worker     if (sent_media_ && sent_flexfec_) {
796*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
797*d9f75844SAndroid Build Coastguard Worker     }
798*d9f75844SAndroid Build Coastguard Worker 
799*d9f75844SAndroid Build Coastguard Worker     return SEND_PACKET;
800*d9f75844SAndroid Build Coastguard Worker   }
801*d9f75844SAndroid Build Coastguard Worker 
CreateSendTransport(TaskQueueBase * task_queue,Call * sender_call)802*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<test::PacketTransport> CreateSendTransport(
803*d9f75844SAndroid Build Coastguard Worker       TaskQueueBase* task_queue,
804*d9f75844SAndroid Build Coastguard Worker       Call* sender_call) override {
805*d9f75844SAndroid Build Coastguard Worker     // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
806*d9f75844SAndroid Build Coastguard Worker     // Therefore we need some network delay.
807*d9f75844SAndroid Build Coastguard Worker     const int kNetworkDelayMs = 100;
808*d9f75844SAndroid Build Coastguard Worker     BuiltInNetworkBehaviorConfig config;
809*d9f75844SAndroid Build Coastguard Worker     config.loss_percent = 5;
810*d9f75844SAndroid Build Coastguard Worker     config.queue_delay_ms = kNetworkDelayMs;
811*d9f75844SAndroid Build Coastguard Worker     return std::make_unique<test::PacketTransport>(
812*d9f75844SAndroid Build Coastguard Worker         task_queue, sender_call, this, test::PacketTransport::kSender,
813*d9f75844SAndroid Build Coastguard Worker         VideoSendStreamTest::payload_type_map_,
814*d9f75844SAndroid Build Coastguard Worker         std::make_unique<FakeNetworkPipe>(
815*d9f75844SAndroid Build Coastguard Worker             Clock::GetRealTimeClock(),
816*d9f75844SAndroid Build Coastguard Worker             std::make_unique<SimulatedNetwork>(config)));
817*d9f75844SAndroid Build Coastguard Worker   }
818*d9f75844SAndroid Build Coastguard Worker 
CreateReceiveTransport(TaskQueueBase * task_queue)819*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<test::PacketTransport> CreateReceiveTransport(
820*d9f75844SAndroid Build Coastguard Worker       TaskQueueBase* task_queue) override {
821*d9f75844SAndroid Build Coastguard Worker     // We need the RTT to be >200 ms to send FEC and the network delay for the
822*d9f75844SAndroid Build Coastguard Worker     // send transport is 100 ms, so add 100 ms (but no loss) on the return link.
823*d9f75844SAndroid Build Coastguard Worker     BuiltInNetworkBehaviorConfig config;
824*d9f75844SAndroid Build Coastguard Worker     config.loss_percent = 0;
825*d9f75844SAndroid Build Coastguard Worker     config.queue_delay_ms = 100;
826*d9f75844SAndroid Build Coastguard Worker     return std::make_unique<test::PacketTransport>(
827*d9f75844SAndroid Build Coastguard Worker         task_queue, nullptr, this, test::PacketTransport::kReceiver,
828*d9f75844SAndroid Build Coastguard Worker         VideoSendStreamTest::payload_type_map_,
829*d9f75844SAndroid Build Coastguard Worker         std::make_unique<FakeNetworkPipe>(
830*d9f75844SAndroid Build Coastguard Worker             Clock::GetRealTimeClock(),
831*d9f75844SAndroid Build Coastguard Worker             std::make_unique<SimulatedNetwork>(config)));
832*d9f75844SAndroid Build Coastguard Worker   }
833*d9f75844SAndroid Build Coastguard Worker 
ModifyVideoConfigs(VideoSendStream::Config * send_config,std::vector<VideoReceiveStreamInterface::Config> * receive_configs,VideoEncoderConfig * encoder_config)834*d9f75844SAndroid Build Coastguard Worker   void ModifyVideoConfigs(
835*d9f75844SAndroid Build Coastguard Worker       VideoSendStream::Config* send_config,
836*d9f75844SAndroid Build Coastguard Worker       std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
837*d9f75844SAndroid Build Coastguard Worker       VideoEncoderConfig* encoder_config) override {
838*d9f75844SAndroid Build Coastguard Worker     if (use_nack_) {
839*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.nack.rtp_history_ms =
840*d9f75844SAndroid Build Coastguard Worker           (*receive_configs)[0].rtp.nack.rtp_history_ms =
841*d9f75844SAndroid Build Coastguard Worker               VideoSendStreamTest::kNackRtpHistoryMs;
842*d9f75844SAndroid Build Coastguard Worker     }
843*d9f75844SAndroid Build Coastguard Worker     send_config->encoder_settings.encoder_factory = encoder_factory_;
844*d9f75844SAndroid Build Coastguard Worker     send_config->rtp.payload_name = payload_name_;
845*d9f75844SAndroid Build Coastguard Worker     if (header_extensions_enabled_) {
846*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.push_back(
847*d9f75844SAndroid Build Coastguard Worker           RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeExtensionId));
848*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.push_back(RtpExtension(
849*d9f75844SAndroid Build Coastguard Worker           RtpExtension::kTimestampOffsetUri, kTimestampOffsetExtensionId));
850*d9f75844SAndroid Build Coastguard Worker     } else {
851*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.clear();
852*d9f75844SAndroid Build Coastguard Worker     }
853*d9f75844SAndroid Build Coastguard Worker     (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
854*d9f75844SAndroid Build Coastguard Worker     encoder_config->codec_type = PayloadStringToCodecType(payload_name_);
855*d9f75844SAndroid Build Coastguard Worker   }
856*d9f75844SAndroid Build Coastguard Worker 
PerformTest()857*d9f75844SAndroid Build Coastguard Worker   void PerformTest() override {
858*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(Wait())
859*d9f75844SAndroid Build Coastguard Worker         << "Timed out waiting for FlexFEC and/or media packets.";
860*d9f75844SAndroid Build Coastguard Worker   }
861*d9f75844SAndroid Build Coastguard Worker 
862*d9f75844SAndroid Build Coastguard Worker   VideoEncoderFactory* encoder_factory_;
863*d9f75844SAndroid Build Coastguard Worker   RtpHeaderExtensionMap extensions_;
864*d9f75844SAndroid Build Coastguard Worker   const std::string payload_name_;
865*d9f75844SAndroid Build Coastguard Worker   const bool use_nack_;
866*d9f75844SAndroid Build Coastguard Worker   bool sent_media_;
867*d9f75844SAndroid Build Coastguard Worker   bool sent_flexfec_;
868*d9f75844SAndroid Build Coastguard Worker   const bool header_extensions_enabled_;
869*d9f75844SAndroid Build Coastguard Worker   const size_t num_video_streams_;
870*d9f75844SAndroid Build Coastguard Worker };
871*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsFlexfecVp8)872*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsFlexfecVp8) {
873*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
874*d9f75844SAndroid Build Coastguard Worker       []() { return VP8Encoder::Create(); });
875*d9f75844SAndroid Build Coastguard Worker   FlexfecObserver test(false, false, "VP8", &encoder_factory, 1);
876*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
877*d9f75844SAndroid Build Coastguard Worker }
878*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsFlexfecSimulcastVp8)879*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsFlexfecSimulcastVp8) {
880*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
881*d9f75844SAndroid Build Coastguard Worker       []() { return VP8Encoder::Create(); });
882*d9f75844SAndroid Build Coastguard Worker   FlexfecObserver test(false, false, "VP8", &encoder_factory, 2);
883*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
884*d9f75844SAndroid Build Coastguard Worker }
885*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsFlexfecWithNackVp8)886*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackVp8) {
887*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
888*d9f75844SAndroid Build Coastguard Worker       []() { return VP8Encoder::Create(); });
889*d9f75844SAndroid Build Coastguard Worker   FlexfecObserver test(false, true, "VP8", &encoder_factory, 1);
890*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
891*d9f75844SAndroid Build Coastguard Worker }
892*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsFlexfecWithRtpExtensionsVp8)893*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsFlexfecWithRtpExtensionsVp8) {
894*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
895*d9f75844SAndroid Build Coastguard Worker       []() { return VP8Encoder::Create(); });
896*d9f75844SAndroid Build Coastguard Worker   FlexfecObserver test(true, false, "VP8", &encoder_factory, 1);
897*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
898*d9f75844SAndroid Build Coastguard Worker }
899*d9f75844SAndroid Build Coastguard Worker 
900*d9f75844SAndroid Build Coastguard Worker #if defined(RTC_ENABLE_VP9)
TEST_F(VideoSendStreamTest,SupportsFlexfecVp9)901*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsFlexfecVp9) {
902*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
903*d9f75844SAndroid Build Coastguard Worker       []() { return VP9Encoder::Create(); });
904*d9f75844SAndroid Build Coastguard Worker   FlexfecObserver test(false, false, "VP9", &encoder_factory, 1);
905*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
906*d9f75844SAndroid Build Coastguard Worker }
907*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsFlexfecWithNackVp9)908*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackVp9) {
909*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
910*d9f75844SAndroid Build Coastguard Worker       []() { return VP9Encoder::Create(); });
911*d9f75844SAndroid Build Coastguard Worker   FlexfecObserver test(false, true, "VP9", &encoder_factory, 1);
912*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
913*d9f75844SAndroid Build Coastguard Worker }
914*d9f75844SAndroid Build Coastguard Worker #endif  // defined(RTC_ENABLE_VP9)
915*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsFlexfecH264)916*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsFlexfecH264) {
917*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory([]() {
918*d9f75844SAndroid Build Coastguard Worker     return std::make_unique<test::FakeH264Encoder>(Clock::GetRealTimeClock());
919*d9f75844SAndroid Build Coastguard Worker   });
920*d9f75844SAndroid Build Coastguard Worker   FlexfecObserver test(false, false, "H264", &encoder_factory, 1);
921*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
922*d9f75844SAndroid Build Coastguard Worker }
923*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsFlexfecWithNackH264)924*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackH264) {
925*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory([]() {
926*d9f75844SAndroid Build Coastguard Worker     return std::make_unique<test::FakeH264Encoder>(Clock::GetRealTimeClock());
927*d9f75844SAndroid Build Coastguard Worker   });
928*d9f75844SAndroid Build Coastguard Worker   FlexfecObserver test(false, true, "H264", &encoder_factory, 1);
929*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
930*d9f75844SAndroid Build Coastguard Worker }
931*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SupportsFlexfecWithMultithreadedH264)932*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SupportsFlexfecWithMultithreadedH264) {
933*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<TaskQueueFactory> task_queue_factory =
934*d9f75844SAndroid Build Coastguard Worker       CreateDefaultTaskQueueFactory();
935*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory([&]() {
936*d9f75844SAndroid Build Coastguard Worker     return std::make_unique<test::MultithreadedFakeH264Encoder>(
937*d9f75844SAndroid Build Coastguard Worker         Clock::GetRealTimeClock(), task_queue_factory.get());
938*d9f75844SAndroid Build Coastguard Worker   });
939*d9f75844SAndroid Build Coastguard Worker 
940*d9f75844SAndroid Build Coastguard Worker   FlexfecObserver test(false, false, "H264", &encoder_factory, 1);
941*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
942*d9f75844SAndroid Build Coastguard Worker }
943*d9f75844SAndroid Build Coastguard Worker 
TestNackRetransmission(uint32_t retransmit_ssrc,uint8_t retransmit_payload_type)944*d9f75844SAndroid Build Coastguard Worker void VideoSendStreamTest::TestNackRetransmission(
945*d9f75844SAndroid Build Coastguard Worker     uint32_t retransmit_ssrc,
946*d9f75844SAndroid Build Coastguard Worker     uint8_t retransmit_payload_type) {
947*d9f75844SAndroid Build Coastguard Worker   class NackObserver : public test::SendTest {
948*d9f75844SAndroid Build Coastguard Worker    public:
949*d9f75844SAndroid Build Coastguard Worker     explicit NackObserver(uint32_t retransmit_ssrc,
950*d9f75844SAndroid Build Coastguard Worker                           uint8_t retransmit_payload_type)
951*d9f75844SAndroid Build Coastguard Worker         : SendTest(kDefaultTimeout),
952*d9f75844SAndroid Build Coastguard Worker           send_count_(0),
953*d9f75844SAndroid Build Coastguard Worker           retransmit_count_(0),
954*d9f75844SAndroid Build Coastguard Worker           retransmit_ssrc_(retransmit_ssrc),
955*d9f75844SAndroid Build Coastguard Worker           retransmit_payload_type_(retransmit_payload_type) {}
956*d9f75844SAndroid Build Coastguard Worker 
957*d9f75844SAndroid Build Coastguard Worker    private:
958*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
959*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet;
960*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.Parse(packet, length));
961*d9f75844SAndroid Build Coastguard Worker 
962*d9f75844SAndroid Build Coastguard Worker       // NACK packets two times at some arbitrary points.
963*d9f75844SAndroid Build Coastguard Worker       const int kNackedPacketsAtOnceCount = 3;
964*d9f75844SAndroid Build Coastguard Worker       const int kRetransmitTarget = kNackedPacketsAtOnceCount * 2;
965*d9f75844SAndroid Build Coastguard Worker 
966*d9f75844SAndroid Build Coastguard Worker       // Skip padding packets because they will never be retransmitted.
967*d9f75844SAndroid Build Coastguard Worker       if (rtp_packet.payload_size() == 0) {
968*d9f75844SAndroid Build Coastguard Worker         return SEND_PACKET;
969*d9f75844SAndroid Build Coastguard Worker       }
970*d9f75844SAndroid Build Coastguard Worker 
971*d9f75844SAndroid Build Coastguard Worker       ++send_count_;
972*d9f75844SAndroid Build Coastguard Worker 
973*d9f75844SAndroid Build Coastguard Worker       // NACK packets at arbitrary points.
974*d9f75844SAndroid Build Coastguard Worker       if (send_count_ % 25 == 0) {
975*d9f75844SAndroid Build Coastguard Worker         RTCPSender::Configuration config;
976*d9f75844SAndroid Build Coastguard Worker         config.clock = Clock::GetRealTimeClock();
977*d9f75844SAndroid Build Coastguard Worker         config.outgoing_transport = transport_adapter_.get();
978*d9f75844SAndroid Build Coastguard Worker         config.rtcp_report_interval = TimeDelta::Millis(kRtcpIntervalMs);
979*d9f75844SAndroid Build Coastguard Worker         config.local_media_ssrc = kReceiverLocalVideoSsrc;
980*d9f75844SAndroid Build Coastguard Worker         RTCPSender rtcp_sender(config);
981*d9f75844SAndroid Build Coastguard Worker 
982*d9f75844SAndroid Build Coastguard Worker         rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
983*d9f75844SAndroid Build Coastguard Worker         rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
984*d9f75844SAndroid Build Coastguard Worker 
985*d9f75844SAndroid Build Coastguard Worker         RTCPSender::FeedbackState feedback_state;
986*d9f75844SAndroid Build Coastguard Worker         uint16_t nack_sequence_numbers[kNackedPacketsAtOnceCount];
987*d9f75844SAndroid Build Coastguard Worker         int nack_count = 0;
988*d9f75844SAndroid Build Coastguard Worker         for (uint16_t sequence_number :
989*d9f75844SAndroid Build Coastguard Worker              sequence_numbers_pending_retransmission_) {
990*d9f75844SAndroid Build Coastguard Worker           if (nack_count < kNackedPacketsAtOnceCount) {
991*d9f75844SAndroid Build Coastguard Worker             nack_sequence_numbers[nack_count++] = sequence_number;
992*d9f75844SAndroid Build Coastguard Worker           } else {
993*d9f75844SAndroid Build Coastguard Worker             break;
994*d9f75844SAndroid Build Coastguard Worker           }
995*d9f75844SAndroid Build Coastguard Worker         }
996*d9f75844SAndroid Build Coastguard Worker 
997*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpNack, nack_count,
998*d9f75844SAndroid Build Coastguard Worker                                           nack_sequence_numbers));
999*d9f75844SAndroid Build Coastguard Worker       }
1000*d9f75844SAndroid Build Coastguard Worker 
1001*d9f75844SAndroid Build Coastguard Worker       uint16_t sequence_number = rtp_packet.SequenceNumber();
1002*d9f75844SAndroid Build Coastguard Worker       if (rtp_packet.Ssrc() == retransmit_ssrc_ &&
1003*d9f75844SAndroid Build Coastguard Worker           retransmit_ssrc_ != kVideoSendSsrcs[0]) {
1004*d9f75844SAndroid Build Coastguard Worker         // Not kVideoSendSsrcs[0], assume correct RTX packet. Extract sequence
1005*d9f75844SAndroid Build Coastguard Worker         // number.
1006*d9f75844SAndroid Build Coastguard Worker         const uint8_t* rtx_header = rtp_packet.payload().data();
1007*d9f75844SAndroid Build Coastguard Worker         sequence_number = (rtx_header[0] << 8) + rtx_header[1];
1008*d9f75844SAndroid Build Coastguard Worker       }
1009*d9f75844SAndroid Build Coastguard Worker 
1010*d9f75844SAndroid Build Coastguard Worker       auto it = sequence_numbers_pending_retransmission_.find(sequence_number);
1011*d9f75844SAndroid Build Coastguard Worker       if (it == sequence_numbers_pending_retransmission_.end()) {
1012*d9f75844SAndroid Build Coastguard Worker         // Not currently pending retransmission. Add it to retransmission queue
1013*d9f75844SAndroid Build Coastguard Worker         // if media and limit not reached.
1014*d9f75844SAndroid Build Coastguard Worker         if (rtp_packet.Ssrc() == kVideoSendSsrcs[0] &&
1015*d9f75844SAndroid Build Coastguard Worker             rtp_packet.payload_size() > 0 &&
1016*d9f75844SAndroid Build Coastguard Worker             retransmit_count_ +
1017*d9f75844SAndroid Build Coastguard Worker                     sequence_numbers_pending_retransmission_.size() <
1018*d9f75844SAndroid Build Coastguard Worker                 kRetransmitTarget) {
1019*d9f75844SAndroid Build Coastguard Worker           sequence_numbers_pending_retransmission_.insert(sequence_number);
1020*d9f75844SAndroid Build Coastguard Worker         }
1021*d9f75844SAndroid Build Coastguard Worker       } else {
1022*d9f75844SAndroid Build Coastguard Worker         // Packet is a retransmission, remove it from queue and check if done.
1023*d9f75844SAndroid Build Coastguard Worker         sequence_numbers_pending_retransmission_.erase(it);
1024*d9f75844SAndroid Build Coastguard Worker         if (++retransmit_count_ == kRetransmitTarget) {
1025*d9f75844SAndroid Build Coastguard Worker           EXPECT_EQ(retransmit_ssrc_, rtp_packet.Ssrc());
1026*d9f75844SAndroid Build Coastguard Worker           EXPECT_EQ(retransmit_payload_type_, rtp_packet.PayloadType());
1027*d9f75844SAndroid Build Coastguard Worker           observation_complete_.Set();
1028*d9f75844SAndroid Build Coastguard Worker         }
1029*d9f75844SAndroid Build Coastguard Worker       }
1030*d9f75844SAndroid Build Coastguard Worker 
1031*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
1032*d9f75844SAndroid Build Coastguard Worker     }
1033*d9f75844SAndroid Build Coastguard Worker 
1034*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
1035*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
1036*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
1037*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
1038*d9f75844SAndroid Build Coastguard Worker       transport_adapter_.reset(
1039*d9f75844SAndroid Build Coastguard Worker           new internal::TransportAdapter(send_config->send_transport));
1040*d9f75844SAndroid Build Coastguard Worker       transport_adapter_->Enable();
1041*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1042*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.rtx.payload_type = retransmit_payload_type_;
1043*d9f75844SAndroid Build Coastguard Worker       if (retransmit_ssrc_ != kVideoSendSsrcs[0])
1044*d9f75844SAndroid Build Coastguard Worker         send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
1045*d9f75844SAndroid Build Coastguard Worker     }
1046*d9f75844SAndroid Build Coastguard Worker 
1047*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
1048*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while waiting for NACK retransmission.";
1049*d9f75844SAndroid Build Coastguard Worker     }
1050*d9f75844SAndroid Build Coastguard Worker 
1051*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<internal::TransportAdapter> transport_adapter_;
1052*d9f75844SAndroid Build Coastguard Worker     int send_count_;
1053*d9f75844SAndroid Build Coastguard Worker     int retransmit_count_;
1054*d9f75844SAndroid Build Coastguard Worker     const uint32_t retransmit_ssrc_;
1055*d9f75844SAndroid Build Coastguard Worker     const uint8_t retransmit_payload_type_;
1056*d9f75844SAndroid Build Coastguard Worker     std::set<uint16_t> sequence_numbers_pending_retransmission_;
1057*d9f75844SAndroid Build Coastguard Worker   } test(retransmit_ssrc, retransmit_payload_type);
1058*d9f75844SAndroid Build Coastguard Worker 
1059*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
1060*d9f75844SAndroid Build Coastguard Worker }
1061*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,RetransmitsNack)1062*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, RetransmitsNack) {
1063*d9f75844SAndroid Build Coastguard Worker   // Normal NACKs should use the send SSRC.
1064*d9f75844SAndroid Build Coastguard Worker   TestNackRetransmission(kVideoSendSsrcs[0], kFakeVideoSendPayloadType);
1065*d9f75844SAndroid Build Coastguard Worker }
1066*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,RetransmitsNackOverRtx)1067*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
1068*d9f75844SAndroid Build Coastguard Worker   // NACKs over RTX should use a separate SSRC.
1069*d9f75844SAndroid Build Coastguard Worker   TestNackRetransmission(kSendRtxSsrcs[0], kSendRtxPayloadType);
1070*d9f75844SAndroid Build Coastguard Worker }
1071*d9f75844SAndroid Build Coastguard Worker 
TestPacketFragmentationSize(VideoFormat format,bool with_fec)1072*d9f75844SAndroid Build Coastguard Worker void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
1073*d9f75844SAndroid Build Coastguard Worker                                                       bool with_fec) {
1074*d9f75844SAndroid Build Coastguard Worker   // Use a fake encoder to output a frame of every size in the range [90, 290],
1075*d9f75844SAndroid Build Coastguard Worker   // for each size making sure that the exact number of payload bytes received
1076*d9f75844SAndroid Build Coastguard Worker   // is correct and that packets are fragmented to respect max packet size.
1077*d9f75844SAndroid Build Coastguard Worker   static const size_t kMaxPacketSize = 128;
1078*d9f75844SAndroid Build Coastguard Worker   static const size_t start = 90;
1079*d9f75844SAndroid Build Coastguard Worker   static const size_t stop = 290;
1080*d9f75844SAndroid Build Coastguard Worker 
1081*d9f75844SAndroid Build Coastguard Worker   // Observer that verifies that the expected number of packets and bytes
1082*d9f75844SAndroid Build Coastguard Worker   // arrive for each frame size, from start_size to stop_size.
1083*d9f75844SAndroid Build Coastguard Worker   class FrameFragmentationTest : public test::SendTest {
1084*d9f75844SAndroid Build Coastguard Worker    public:
1085*d9f75844SAndroid Build Coastguard Worker     FrameFragmentationTest(size_t max_packet_size,
1086*d9f75844SAndroid Build Coastguard Worker                            size_t start_size,
1087*d9f75844SAndroid Build Coastguard Worker                            size_t stop_size,
1088*d9f75844SAndroid Build Coastguard Worker                            bool test_generic_packetization,
1089*d9f75844SAndroid Build Coastguard Worker                            bool use_fec)
1090*d9f75844SAndroid Build Coastguard Worker         : SendTest(kLongTimeout),
1091*d9f75844SAndroid Build Coastguard Worker           encoder_(stop),
1092*d9f75844SAndroid Build Coastguard Worker           encoder_factory_(&encoder_),
1093*d9f75844SAndroid Build Coastguard Worker           max_packet_size_(max_packet_size),
1094*d9f75844SAndroid Build Coastguard Worker           stop_size_(stop_size),
1095*d9f75844SAndroid Build Coastguard Worker           test_generic_packetization_(test_generic_packetization),
1096*d9f75844SAndroid Build Coastguard Worker           use_fec_(use_fec),
1097*d9f75844SAndroid Build Coastguard Worker           packet_count_(0),
1098*d9f75844SAndroid Build Coastguard Worker           packets_lost_(0),
1099*d9f75844SAndroid Build Coastguard Worker           last_packet_count_(0),
1100*d9f75844SAndroid Build Coastguard Worker           last_packets_lost_(0),
1101*d9f75844SAndroid Build Coastguard Worker           accumulated_size_(0),
1102*d9f75844SAndroid Build Coastguard Worker           accumulated_payload_(0),
1103*d9f75844SAndroid Build Coastguard Worker           fec_packet_received_(false),
1104*d9f75844SAndroid Build Coastguard Worker           current_size_rtp_(start_size),
1105*d9f75844SAndroid Build Coastguard Worker           current_size_frame_(static_cast<int>(start_size)) {
1106*d9f75844SAndroid Build Coastguard Worker       // Fragmentation required, this test doesn't make sense without it.
1107*d9f75844SAndroid Build Coastguard Worker       encoder_.SetFrameSize(start_size);
1108*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_GT(stop_size, max_packet_size);
1109*d9f75844SAndroid Build Coastguard Worker       if (!test_generic_packetization_)
1110*d9f75844SAndroid Build Coastguard Worker         encoder_.SetCodecType(kVideoCodecVP8);
1111*d9f75844SAndroid Build Coastguard Worker     }
1112*d9f75844SAndroid Build Coastguard Worker 
1113*d9f75844SAndroid Build Coastguard Worker    private:
1114*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t size) override {
1115*d9f75844SAndroid Build Coastguard Worker       size_t length = size;
1116*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet;
1117*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.Parse(packet, length));
1118*d9f75844SAndroid Build Coastguard Worker 
1119*d9f75844SAndroid Build Coastguard Worker       EXPECT_LE(length, max_packet_size_);
1120*d9f75844SAndroid Build Coastguard Worker 
1121*d9f75844SAndroid Build Coastguard Worker       if (use_fec_ && rtp_packet.payload_size() > 0) {
1122*d9f75844SAndroid Build Coastguard Worker         uint8_t payload_type = rtp_packet.payload()[0];
1123*d9f75844SAndroid Build Coastguard Worker         bool is_fec = rtp_packet.PayloadType() == kRedPayloadType &&
1124*d9f75844SAndroid Build Coastguard Worker                       payload_type == kUlpfecPayloadType;
1125*d9f75844SAndroid Build Coastguard Worker         if (is_fec) {
1126*d9f75844SAndroid Build Coastguard Worker           fec_packet_received_ = true;
1127*d9f75844SAndroid Build Coastguard Worker           return SEND_PACKET;
1128*d9f75844SAndroid Build Coastguard Worker         }
1129*d9f75844SAndroid Build Coastguard Worker       }
1130*d9f75844SAndroid Build Coastguard Worker 
1131*d9f75844SAndroid Build Coastguard Worker       accumulated_size_ += length;
1132*d9f75844SAndroid Build Coastguard Worker 
1133*d9f75844SAndroid Build Coastguard Worker       if (use_fec_)
1134*d9f75844SAndroid Build Coastguard Worker         TriggerLossReport(rtp_packet);
1135*d9f75844SAndroid Build Coastguard Worker 
1136*d9f75844SAndroid Build Coastguard Worker       if (test_generic_packetization_) {
1137*d9f75844SAndroid Build Coastguard Worker         size_t overhead = rtp_packet.headers_size() + rtp_packet.padding_size();
1138*d9f75844SAndroid Build Coastguard Worker         // Only remove payload header and RED header if the packet actually
1139*d9f75844SAndroid Build Coastguard Worker         // contains payload.
1140*d9f75844SAndroid Build Coastguard Worker         if (length > overhead) {
1141*d9f75844SAndroid Build Coastguard Worker           overhead += (1 /* Generic header */);
1142*d9f75844SAndroid Build Coastguard Worker           if (use_fec_)
1143*d9f75844SAndroid Build Coastguard Worker             overhead += 1;  // RED for FEC header.
1144*d9f75844SAndroid Build Coastguard Worker         }
1145*d9f75844SAndroid Build Coastguard Worker         EXPECT_GE(length, overhead);
1146*d9f75844SAndroid Build Coastguard Worker         accumulated_payload_ += length - overhead;
1147*d9f75844SAndroid Build Coastguard Worker       }
1148*d9f75844SAndroid Build Coastguard Worker 
1149*d9f75844SAndroid Build Coastguard Worker       // Marker bit set indicates last packet of a frame.
1150*d9f75844SAndroid Build Coastguard Worker       if (rtp_packet.Marker()) {
1151*d9f75844SAndroid Build Coastguard Worker         if (use_fec_ && accumulated_payload_ == current_size_rtp_ - 1) {
1152*d9f75844SAndroid Build Coastguard Worker           // With FEC enabled, frame size is incremented asynchronously, so
1153*d9f75844SAndroid Build Coastguard Worker           // "old" frames one byte too small may arrive. Accept, but don't
1154*d9f75844SAndroid Build Coastguard Worker           // increase expected frame size.
1155*d9f75844SAndroid Build Coastguard Worker           accumulated_size_ = 0;
1156*d9f75844SAndroid Build Coastguard Worker           accumulated_payload_ = 0;
1157*d9f75844SAndroid Build Coastguard Worker           return SEND_PACKET;
1158*d9f75844SAndroid Build Coastguard Worker         }
1159*d9f75844SAndroid Build Coastguard Worker 
1160*d9f75844SAndroid Build Coastguard Worker         EXPECT_GE(accumulated_size_, current_size_rtp_);
1161*d9f75844SAndroid Build Coastguard Worker         if (test_generic_packetization_) {
1162*d9f75844SAndroid Build Coastguard Worker           EXPECT_EQ(current_size_rtp_, accumulated_payload_);
1163*d9f75844SAndroid Build Coastguard Worker         }
1164*d9f75844SAndroid Build Coastguard Worker 
1165*d9f75844SAndroid Build Coastguard Worker         // Last packet of frame; reset counters.
1166*d9f75844SAndroid Build Coastguard Worker         accumulated_size_ = 0;
1167*d9f75844SAndroid Build Coastguard Worker         accumulated_payload_ = 0;
1168*d9f75844SAndroid Build Coastguard Worker         if (current_size_rtp_ == stop_size_) {
1169*d9f75844SAndroid Build Coastguard Worker           // Done! (Don't increase size again, might arrive more @ stop_size).
1170*d9f75844SAndroid Build Coastguard Worker           observation_complete_.Set();
1171*d9f75844SAndroid Build Coastguard Worker         } else {
1172*d9f75844SAndroid Build Coastguard Worker           // Increase next expected frame size. If testing with FEC, make sure
1173*d9f75844SAndroid Build Coastguard Worker           // a FEC packet has been received for this frame size before
1174*d9f75844SAndroid Build Coastguard Worker           // proceeding, to make sure that redundancy packets don't exceed
1175*d9f75844SAndroid Build Coastguard Worker           // size limit.
1176*d9f75844SAndroid Build Coastguard Worker           if (!use_fec_) {
1177*d9f75844SAndroid Build Coastguard Worker             ++current_size_rtp_;
1178*d9f75844SAndroid Build Coastguard Worker           } else if (fec_packet_received_) {
1179*d9f75844SAndroid Build Coastguard Worker             fec_packet_received_ = false;
1180*d9f75844SAndroid Build Coastguard Worker             ++current_size_rtp_;
1181*d9f75844SAndroid Build Coastguard Worker 
1182*d9f75844SAndroid Build Coastguard Worker             MutexLock lock(&mutex_);
1183*d9f75844SAndroid Build Coastguard Worker             ++current_size_frame_;
1184*d9f75844SAndroid Build Coastguard Worker           }
1185*d9f75844SAndroid Build Coastguard Worker         }
1186*d9f75844SAndroid Build Coastguard Worker       }
1187*d9f75844SAndroid Build Coastguard Worker 
1188*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
1189*d9f75844SAndroid Build Coastguard Worker     }
1190*d9f75844SAndroid Build Coastguard Worker 
1191*d9f75844SAndroid Build Coastguard Worker     void TriggerLossReport(const RtpPacket& rtp_packet) {
1192*d9f75844SAndroid Build Coastguard Worker       // Send lossy receive reports to trigger FEC enabling.
1193*d9f75844SAndroid Build Coastguard Worker       const int kLossPercent = 5;
1194*d9f75844SAndroid Build Coastguard Worker       if (++packet_count_ % (100 / kLossPercent) == 0) {
1195*d9f75844SAndroid Build Coastguard Worker         packets_lost_++;
1196*d9f75844SAndroid Build Coastguard Worker         int loss_delta = packets_lost_ - last_packets_lost_;
1197*d9f75844SAndroid Build Coastguard Worker         int packets_delta = packet_count_ - last_packet_count_;
1198*d9f75844SAndroid Build Coastguard Worker         last_packet_count_ = packet_count_;
1199*d9f75844SAndroid Build Coastguard Worker         last_packets_lost_ = packets_lost_;
1200*d9f75844SAndroid Build Coastguard Worker         uint8_t loss_ratio =
1201*d9f75844SAndroid Build Coastguard Worker             static_cast<uint8_t>(loss_delta * 255 / packets_delta);
1202*d9f75844SAndroid Build Coastguard Worker         FakeReceiveStatistics lossy_receive_stats(
1203*d9f75844SAndroid Build Coastguard Worker             kVideoSendSsrcs[0], rtp_packet.SequenceNumber(),
1204*d9f75844SAndroid Build Coastguard Worker             packets_lost_,  // Cumulative lost.
1205*d9f75844SAndroid Build Coastguard Worker             loss_ratio);    // Loss percent.
1206*d9f75844SAndroid Build Coastguard Worker         RTCPSender::Configuration config;
1207*d9f75844SAndroid Build Coastguard Worker         config.clock = Clock::GetRealTimeClock();
1208*d9f75844SAndroid Build Coastguard Worker         config.receive_statistics = &lossy_receive_stats;
1209*d9f75844SAndroid Build Coastguard Worker         config.outgoing_transport = transport_adapter_.get();
1210*d9f75844SAndroid Build Coastguard Worker         config.rtcp_report_interval = TimeDelta::Millis(kRtcpIntervalMs);
1211*d9f75844SAndroid Build Coastguard Worker         config.local_media_ssrc = kVideoSendSsrcs[0];
1212*d9f75844SAndroid Build Coastguard Worker         RTCPSender rtcp_sender(config);
1213*d9f75844SAndroid Build Coastguard Worker 
1214*d9f75844SAndroid Build Coastguard Worker         rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
1215*d9f75844SAndroid Build Coastguard Worker         rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
1216*d9f75844SAndroid Build Coastguard Worker 
1217*d9f75844SAndroid Build Coastguard Worker         RTCPSender::FeedbackState feedback_state;
1218*d9f75844SAndroid Build Coastguard Worker 
1219*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
1220*d9f75844SAndroid Build Coastguard Worker       }
1221*d9f75844SAndroid Build Coastguard Worker     }
1222*d9f75844SAndroid Build Coastguard Worker 
1223*d9f75844SAndroid Build Coastguard Worker     void UpdateConfiguration() {
1224*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
1225*d9f75844SAndroid Build Coastguard Worker       // Increase frame size for next encoded frame, in the context of the
1226*d9f75844SAndroid Build Coastguard Worker       // encoder thread.
1227*d9f75844SAndroid Build Coastguard Worker       if (!use_fec_ && current_size_frame_ < static_cast<int32_t>(stop_size_)) {
1228*d9f75844SAndroid Build Coastguard Worker         ++current_size_frame_;
1229*d9f75844SAndroid Build Coastguard Worker       }
1230*d9f75844SAndroid Build Coastguard Worker       encoder_.SetFrameSize(static_cast<size_t>(current_size_frame_));
1231*d9f75844SAndroid Build Coastguard Worker     }
1232*d9f75844SAndroid Build Coastguard Worker     void ModifySenderBitrateConfig(
1233*d9f75844SAndroid Build Coastguard Worker         BitrateConstraints* bitrate_config) override {
1234*d9f75844SAndroid Build Coastguard Worker       const int kMinBitrateBps = 300000;
1235*d9f75844SAndroid Build Coastguard Worker       bitrate_config->min_bitrate_bps = kMinBitrateBps;
1236*d9f75844SAndroid Build Coastguard Worker     }
1237*d9f75844SAndroid Build Coastguard Worker 
1238*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
1239*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
1240*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
1241*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
1242*d9f75844SAndroid Build Coastguard Worker       transport_adapter_.reset(
1243*d9f75844SAndroid Build Coastguard Worker           new internal::TransportAdapter(send_config->send_transport));
1244*d9f75844SAndroid Build Coastguard Worker       transport_adapter_->Enable();
1245*d9f75844SAndroid Build Coastguard Worker       if (use_fec_) {
1246*d9f75844SAndroid Build Coastguard Worker         send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
1247*d9f75844SAndroid Build Coastguard Worker         send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
1248*d9f75844SAndroid Build Coastguard Worker       }
1249*d9f75844SAndroid Build Coastguard Worker 
1250*d9f75844SAndroid Build Coastguard Worker       if (!test_generic_packetization_)
1251*d9f75844SAndroid Build Coastguard Worker         send_config->rtp.payload_name = "VP8";
1252*d9f75844SAndroid Build Coastguard Worker 
1253*d9f75844SAndroid Build Coastguard Worker       send_config->encoder_settings.encoder_factory = &encoder_factory_;
1254*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.max_packet_size = kMaxPacketSize;
1255*d9f75844SAndroid Build Coastguard Worker       encoder_.RegisterPostEncodeCallback([this]() { UpdateConfiguration(); });
1256*d9f75844SAndroid Build Coastguard Worker 
1257*d9f75844SAndroid Build Coastguard Worker       // Make sure there is at least one extension header, to make the RTP
1258*d9f75844SAndroid Build Coastguard Worker       // header larger than the base length of 12 bytes.
1259*d9f75844SAndroid Build Coastguard Worker       EXPECT_FALSE(send_config->rtp.extensions.empty());
1260*d9f75844SAndroid Build Coastguard Worker 
1261*d9f75844SAndroid Build Coastguard Worker       // Setup screen content disables frame dropping which makes this easier.
1262*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(1u, encoder_config->simulcast_layers.size());
1263*d9f75844SAndroid Build Coastguard Worker       encoder_config->simulcast_layers[0].num_temporal_layers = 2;
1264*d9f75844SAndroid Build Coastguard Worker       encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
1265*d9f75844SAndroid Build Coastguard Worker     }
1266*d9f75844SAndroid Build Coastguard Worker 
1267*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
1268*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while observing incoming RTP packets.";
1269*d9f75844SAndroid Build Coastguard Worker     }
1270*d9f75844SAndroid Build Coastguard Worker 
1271*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<internal::TransportAdapter> transport_adapter_;
1272*d9f75844SAndroid Build Coastguard Worker     test::ConfigurableFrameSizeEncoder encoder_;
1273*d9f75844SAndroid Build Coastguard Worker     test::VideoEncoderProxyFactory encoder_factory_;
1274*d9f75844SAndroid Build Coastguard Worker 
1275*d9f75844SAndroid Build Coastguard Worker     const size_t max_packet_size_;
1276*d9f75844SAndroid Build Coastguard Worker     const size_t stop_size_;
1277*d9f75844SAndroid Build Coastguard Worker     const bool test_generic_packetization_;
1278*d9f75844SAndroid Build Coastguard Worker     const bool use_fec_;
1279*d9f75844SAndroid Build Coastguard Worker 
1280*d9f75844SAndroid Build Coastguard Worker     uint32_t packet_count_;
1281*d9f75844SAndroid Build Coastguard Worker     uint32_t packets_lost_;
1282*d9f75844SAndroid Build Coastguard Worker     uint32_t last_packet_count_;
1283*d9f75844SAndroid Build Coastguard Worker     uint32_t last_packets_lost_;
1284*d9f75844SAndroid Build Coastguard Worker     size_t accumulated_size_;
1285*d9f75844SAndroid Build Coastguard Worker     size_t accumulated_payload_;
1286*d9f75844SAndroid Build Coastguard Worker     bool fec_packet_received_;
1287*d9f75844SAndroid Build Coastguard Worker 
1288*d9f75844SAndroid Build Coastguard Worker     size_t current_size_rtp_;
1289*d9f75844SAndroid Build Coastguard Worker     Mutex mutex_;
1290*d9f75844SAndroid Build Coastguard Worker     int current_size_frame_ RTC_GUARDED_BY(mutex_);
1291*d9f75844SAndroid Build Coastguard Worker   };
1292*d9f75844SAndroid Build Coastguard Worker 
1293*d9f75844SAndroid Build Coastguard Worker   // Don't auto increment if FEC is used; continue sending frame size until
1294*d9f75844SAndroid Build Coastguard Worker   // a FEC packet has been received.
1295*d9f75844SAndroid Build Coastguard Worker   FrameFragmentationTest test(kMaxPacketSize, start, stop, format == kGeneric,
1296*d9f75844SAndroid Build Coastguard Worker                               with_fec);
1297*d9f75844SAndroid Build Coastguard Worker 
1298*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
1299*d9f75844SAndroid Build Coastguard Worker }
1300*d9f75844SAndroid Build Coastguard Worker 
1301*d9f75844SAndroid Build Coastguard Worker // TODO(sprang): Is there any way of speeding up these tests?
TEST_F(VideoSendStreamTest,FragmentsGenericAccordingToMaxPacketSize)1302*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSize) {
1303*d9f75844SAndroid Build Coastguard Worker   TestPacketFragmentationSize(kGeneric, false);
1304*d9f75844SAndroid Build Coastguard Worker }
1305*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,FragmentsGenericAccordingToMaxPacketSizeWithFec)1306*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, FragmentsGenericAccordingToMaxPacketSizeWithFec) {
1307*d9f75844SAndroid Build Coastguard Worker   TestPacketFragmentationSize(kGeneric, true);
1308*d9f75844SAndroid Build Coastguard Worker }
1309*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,FragmentsVp8AccordingToMaxPacketSize)1310*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSize) {
1311*d9f75844SAndroid Build Coastguard Worker   TestPacketFragmentationSize(kVP8, false);
1312*d9f75844SAndroid Build Coastguard Worker }
1313*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,FragmentsVp8AccordingToMaxPacketSizeWithFec)1314*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSizeWithFec) {
1315*d9f75844SAndroid Build Coastguard Worker   TestPacketFragmentationSize(kVP8, true);
1316*d9f75844SAndroid Build Coastguard Worker }
1317*d9f75844SAndroid Build Coastguard Worker 
1318*d9f75844SAndroid Build Coastguard Worker // This test that padding stops being send after a while if the Camera stops
1319*d9f75844SAndroid Build Coastguard Worker // producing video frames and that padding resumes if the camera restarts.
TEST_F(VideoSendStreamTest,NoPaddingWhenVideoIsMuted)1320*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
1321*d9f75844SAndroid Build Coastguard Worker   class NoPaddingWhenVideoIsMuted : public test::SendTest {
1322*d9f75844SAndroid Build Coastguard Worker    public:
1323*d9f75844SAndroid Build Coastguard Worker     NoPaddingWhenVideoIsMuted()
1324*d9f75844SAndroid Build Coastguard Worker         : SendTest(kDefaultTimeout),
1325*d9f75844SAndroid Build Coastguard Worker           clock_(Clock::GetRealTimeClock()),
1326*d9f75844SAndroid Build Coastguard Worker           capturer_(nullptr) {}
1327*d9f75844SAndroid Build Coastguard Worker 
1328*d9f75844SAndroid Build Coastguard Worker    private:
1329*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
1330*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
1331*d9f75844SAndroid Build Coastguard Worker       last_packet_time_ms_ = clock_->TimeInMilliseconds();
1332*d9f75844SAndroid Build Coastguard Worker 
1333*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet;
1334*d9f75844SAndroid Build Coastguard Worker       rtp_packet.Parse(packet, length);
1335*d9f75844SAndroid Build Coastguard Worker       const bool only_padding = rtp_packet.payload_size() == 0;
1336*d9f75844SAndroid Build Coastguard Worker 
1337*d9f75844SAndroid Build Coastguard Worker       if (test_state_ == kBeforeStopCapture) {
1338*d9f75844SAndroid Build Coastguard Worker         // Packets are flowing, stop camera.
1339*d9f75844SAndroid Build Coastguard Worker         capturer_->Stop();
1340*d9f75844SAndroid Build Coastguard Worker         test_state_ = kWaitingForPadding;
1341*d9f75844SAndroid Build Coastguard Worker       } else if (test_state_ == kWaitingForPadding && only_padding) {
1342*d9f75844SAndroid Build Coastguard Worker         // We're still getting padding, after stopping camera.
1343*d9f75844SAndroid Build Coastguard Worker         test_state_ = kWaitingForNoPackets;
1344*d9f75844SAndroid Build Coastguard Worker       } else if (test_state_ == kWaitingForMediaAfterCameraRestart &&
1345*d9f75844SAndroid Build Coastguard Worker                  !only_padding) {
1346*d9f75844SAndroid Build Coastguard Worker         // Media packets are flowing again, stop camera a second time.
1347*d9f75844SAndroid Build Coastguard Worker         capturer_->Stop();
1348*d9f75844SAndroid Build Coastguard Worker         test_state_ = kWaitingForPaddingAfterCameraStopsAgain;
1349*d9f75844SAndroid Build Coastguard Worker       } else if (test_state_ == kWaitingForPaddingAfterCameraStopsAgain &&
1350*d9f75844SAndroid Build Coastguard Worker                  only_padding) {
1351*d9f75844SAndroid Build Coastguard Worker         // Padding is still flowing, test ok.
1352*d9f75844SAndroid Build Coastguard Worker         observation_complete_.Set();
1353*d9f75844SAndroid Build Coastguard Worker       }
1354*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
1355*d9f75844SAndroid Build Coastguard Worker     }
1356*d9f75844SAndroid Build Coastguard Worker 
1357*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtcp(const uint8_t* packet, size_t length) override {
1358*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
1359*d9f75844SAndroid Build Coastguard Worker       const int kNoPacketsThresholdMs = 2000;
1360*d9f75844SAndroid Build Coastguard Worker       if (test_state_ == kWaitingForNoPackets &&
1361*d9f75844SAndroid Build Coastguard Worker           (last_packet_time_ms_ &&
1362*d9f75844SAndroid Build Coastguard Worker            clock_->TimeInMilliseconds() - last_packet_time_ms_.value() >
1363*d9f75844SAndroid Build Coastguard Worker                kNoPacketsThresholdMs)) {
1364*d9f75844SAndroid Build Coastguard Worker         // No packets seen for `kNoPacketsThresholdMs`, restart camera.
1365*d9f75844SAndroid Build Coastguard Worker         capturer_->Start();
1366*d9f75844SAndroid Build Coastguard Worker         test_state_ = kWaitingForMediaAfterCameraRestart;
1367*d9f75844SAndroid Build Coastguard Worker       }
1368*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
1369*d9f75844SAndroid Build Coastguard Worker     }
1370*d9f75844SAndroid Build Coastguard Worker 
1371*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
1372*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
1373*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
1374*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
1375*d9f75844SAndroid Build Coastguard Worker       // Make sure padding is sent if encoder is not producing media.
1376*d9f75844SAndroid Build Coastguard Worker       encoder_config->min_transmit_bitrate_bps = 50000;
1377*d9f75844SAndroid Build Coastguard Worker     }
1378*d9f75844SAndroid Build Coastguard Worker 
1379*d9f75844SAndroid Build Coastguard Worker     void OnFrameGeneratorCapturerCreated(
1380*d9f75844SAndroid Build Coastguard Worker         test::FrameGeneratorCapturer* frame_generator_capturer) override {
1381*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
1382*d9f75844SAndroid Build Coastguard Worker       capturer_ = frame_generator_capturer;
1383*d9f75844SAndroid Build Coastguard Worker     }
1384*d9f75844SAndroid Build Coastguard Worker 
1385*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
1386*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait())
1387*d9f75844SAndroid Build Coastguard Worker           << "Timed out while waiting for RTP packets to stop being sent.";
1388*d9f75844SAndroid Build Coastguard Worker     }
1389*d9f75844SAndroid Build Coastguard Worker 
1390*d9f75844SAndroid Build Coastguard Worker     enum TestState {
1391*d9f75844SAndroid Build Coastguard Worker       kBeforeStopCapture,
1392*d9f75844SAndroid Build Coastguard Worker       kWaitingForPadding,
1393*d9f75844SAndroid Build Coastguard Worker       kWaitingForNoPackets,
1394*d9f75844SAndroid Build Coastguard Worker       kWaitingForMediaAfterCameraRestart,
1395*d9f75844SAndroid Build Coastguard Worker       kWaitingForPaddingAfterCameraStopsAgain
1396*d9f75844SAndroid Build Coastguard Worker     };
1397*d9f75844SAndroid Build Coastguard Worker 
1398*d9f75844SAndroid Build Coastguard Worker     TestState test_state_ = kBeforeStopCapture;
1399*d9f75844SAndroid Build Coastguard Worker     Clock* const clock_;
1400*d9f75844SAndroid Build Coastguard Worker     Mutex mutex_;
1401*d9f75844SAndroid Build Coastguard Worker     absl::optional<int64_t> last_packet_time_ms_ RTC_GUARDED_BY(mutex_);
1402*d9f75844SAndroid Build Coastguard Worker     test::FrameGeneratorCapturer* capturer_ RTC_GUARDED_BY(mutex_);
1403*d9f75844SAndroid Build Coastguard Worker   } test;
1404*d9f75844SAndroid Build Coastguard Worker 
1405*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
1406*d9f75844SAndroid Build Coastguard Worker }
1407*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,PaddingIsPrimarilyRetransmissions)1408*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, PaddingIsPrimarilyRetransmissions) {
1409*d9f75844SAndroid Build Coastguard Worker   const int kCapacityKbps = 10000;  // 10 Mbps
1410*d9f75844SAndroid Build Coastguard Worker   class PaddingIsPrimarilyRetransmissions : public test::EndToEndTest {
1411*d9f75844SAndroid Build Coastguard Worker    public:
1412*d9f75844SAndroid Build Coastguard Worker     PaddingIsPrimarilyRetransmissions()
1413*d9f75844SAndroid Build Coastguard Worker         : EndToEndTest(kDefaultTimeout),
1414*d9f75844SAndroid Build Coastguard Worker           clock_(Clock::GetRealTimeClock()),
1415*d9f75844SAndroid Build Coastguard Worker           padding_length_(0),
1416*d9f75844SAndroid Build Coastguard Worker           total_length_(0),
1417*d9f75844SAndroid Build Coastguard Worker           call_(nullptr) {}
1418*d9f75844SAndroid Build Coastguard Worker 
1419*d9f75844SAndroid Build Coastguard Worker    private:
1420*d9f75844SAndroid Build Coastguard Worker     void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1421*d9f75844SAndroid Build Coastguard Worker       call_ = sender_call;
1422*d9f75844SAndroid Build Coastguard Worker     }
1423*d9f75844SAndroid Build Coastguard Worker 
1424*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
1425*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
1426*d9f75844SAndroid Build Coastguard Worker 
1427*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet;
1428*d9f75844SAndroid Build Coastguard Worker       rtp_packet.Parse(packet, length);
1429*d9f75844SAndroid Build Coastguard Worker       padding_length_ += rtp_packet.padding_size();
1430*d9f75844SAndroid Build Coastguard Worker       total_length_ += length;
1431*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
1432*d9f75844SAndroid Build Coastguard Worker     }
1433*d9f75844SAndroid Build Coastguard Worker 
1434*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<test::PacketTransport> CreateSendTransport(
1435*d9f75844SAndroid Build Coastguard Worker         TaskQueueBase* task_queue,
1436*d9f75844SAndroid Build Coastguard Worker         Call* sender_call) override {
1437*d9f75844SAndroid Build Coastguard Worker       const int kNetworkDelayMs = 50;
1438*d9f75844SAndroid Build Coastguard Worker       BuiltInNetworkBehaviorConfig config;
1439*d9f75844SAndroid Build Coastguard Worker       config.loss_percent = 10;
1440*d9f75844SAndroid Build Coastguard Worker       config.link_capacity_kbps = kCapacityKbps;
1441*d9f75844SAndroid Build Coastguard Worker       config.queue_delay_ms = kNetworkDelayMs;
1442*d9f75844SAndroid Build Coastguard Worker       return std::make_unique<test::PacketTransport>(
1443*d9f75844SAndroid Build Coastguard Worker           task_queue, sender_call, this, test::PacketTransport::kSender,
1444*d9f75844SAndroid Build Coastguard Worker           payload_type_map_,
1445*d9f75844SAndroid Build Coastguard Worker           std::make_unique<FakeNetworkPipe>(
1446*d9f75844SAndroid Build Coastguard Worker               Clock::GetRealTimeClock(),
1447*d9f75844SAndroid Build Coastguard Worker               std::make_unique<SimulatedNetwork>(config)));
1448*d9f75844SAndroid Build Coastguard Worker     }
1449*d9f75844SAndroid Build Coastguard Worker 
1450*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
1451*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
1452*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
1453*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
1454*d9f75844SAndroid Build Coastguard Worker       // Turn on RTX.
1455*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.rtx.payload_type = kFakeVideoSendPayloadType;
1456*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
1457*d9f75844SAndroid Build Coastguard Worker     }
1458*d9f75844SAndroid Build Coastguard Worker 
1459*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
1460*d9f75844SAndroid Build Coastguard Worker       // TODO(isheriff): Some platforms do not ramp up as expected to full
1461*d9f75844SAndroid Build Coastguard Worker       // capacity due to packet scheduling delays. Fix that before getting
1462*d9f75844SAndroid Build Coastguard Worker       // rid of this.
1463*d9f75844SAndroid Build Coastguard Worker       SleepMs(5000);
1464*d9f75844SAndroid Build Coastguard Worker       {
1465*d9f75844SAndroid Build Coastguard Worker         MutexLock lock(&mutex_);
1466*d9f75844SAndroid Build Coastguard Worker         // Expect padding to be a small percentage of total bytes sent.
1467*d9f75844SAndroid Build Coastguard Worker         EXPECT_LT(padding_length_, .1 * total_length_);
1468*d9f75844SAndroid Build Coastguard Worker       }
1469*d9f75844SAndroid Build Coastguard Worker     }
1470*d9f75844SAndroid Build Coastguard Worker 
1471*d9f75844SAndroid Build Coastguard Worker     Mutex mutex_;
1472*d9f75844SAndroid Build Coastguard Worker     Clock* const clock_;
1473*d9f75844SAndroid Build Coastguard Worker     size_t padding_length_ RTC_GUARDED_BY(mutex_);
1474*d9f75844SAndroid Build Coastguard Worker     size_t total_length_ RTC_GUARDED_BY(mutex_);
1475*d9f75844SAndroid Build Coastguard Worker     Call* call_;
1476*d9f75844SAndroid Build Coastguard Worker   } test;
1477*d9f75844SAndroid Build Coastguard Worker 
1478*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
1479*d9f75844SAndroid Build Coastguard Worker }
1480*d9f75844SAndroid Build Coastguard Worker 
1481*d9f75844SAndroid Build Coastguard Worker // This test first observes "high" bitrate use at which point it sends a REMB to
1482*d9f75844SAndroid Build Coastguard Worker // indicate that it should be lowered significantly. The test then observes that
1483*d9f75844SAndroid Build Coastguard Worker // the bitrate observed is sinking well below the min-transmit-bitrate threshold
1484*d9f75844SAndroid Build Coastguard Worker // to verify that the min-transmit bitrate respects incoming REMB.
1485*d9f75844SAndroid Build Coastguard Worker //
1486*d9f75844SAndroid Build Coastguard Worker // Note that the test starts at "high" bitrate and does not ramp up to "higher"
1487*d9f75844SAndroid Build Coastguard Worker // bitrate since no receiver block or remb is sent in the initial phase.
TEST_F(VideoSendStreamTest,MinTransmitBitrateRespectsRemb)1488*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
1489*d9f75844SAndroid Build Coastguard Worker   static const int kMinTransmitBitrateBps = 400000;
1490*d9f75844SAndroid Build Coastguard Worker   static const int kHighBitrateBps = 150000;
1491*d9f75844SAndroid Build Coastguard Worker   static const int kRembBitrateBps = 80000;
1492*d9f75844SAndroid Build Coastguard Worker   static const int kRembRespectedBitrateBps = 100000;
1493*d9f75844SAndroid Build Coastguard Worker   class BitrateObserver : public test::SendTest {
1494*d9f75844SAndroid Build Coastguard Worker    public:
1495*d9f75844SAndroid Build Coastguard Worker     explicit BitrateObserver(TaskQueueBase* task_queue)
1496*d9f75844SAndroid Build Coastguard Worker         : SendTest(kDefaultTimeout),
1497*d9f75844SAndroid Build Coastguard Worker           task_queue_(task_queue),
1498*d9f75844SAndroid Build Coastguard Worker           retranmission_rate_limiter_(Clock::GetRealTimeClock(), 1000),
1499*d9f75844SAndroid Build Coastguard Worker           stream_(nullptr),
1500*d9f75844SAndroid Build Coastguard Worker           bitrate_capped_(false),
1501*d9f75844SAndroid Build Coastguard Worker           task_safety_flag_(PendingTaskSafetyFlag::CreateDetached()) {}
1502*d9f75844SAndroid Build Coastguard Worker 
1503*d9f75844SAndroid Build Coastguard Worker    private:
1504*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
1505*d9f75844SAndroid Build Coastguard Worker       if (IsRtcpPacket(rtc::MakeArrayView(packet, length)))
1506*d9f75844SAndroid Build Coastguard Worker         return DROP_PACKET;
1507*d9f75844SAndroid Build Coastguard Worker 
1508*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet;
1509*d9f75844SAndroid Build Coastguard Worker       RTC_CHECK(rtp_packet.Parse(packet, length));
1510*d9f75844SAndroid Build Coastguard Worker       const uint32_t ssrc = rtp_packet.Ssrc();
1511*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK(stream_);
1512*d9f75844SAndroid Build Coastguard Worker 
1513*d9f75844SAndroid Build Coastguard Worker       task_queue_->PostTask(SafeTask(task_safety_flag_, [this, ssrc]() {
1514*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Stats stats = stream_->GetStats();
1515*d9f75844SAndroid Build Coastguard Worker         if (!stats.substreams.empty()) {
1516*d9f75844SAndroid Build Coastguard Worker           EXPECT_EQ(1u, stats.substreams.size());
1517*d9f75844SAndroid Build Coastguard Worker           int total_bitrate_bps =
1518*d9f75844SAndroid Build Coastguard Worker               stats.substreams.begin()->second.total_bitrate_bps;
1519*d9f75844SAndroid Build Coastguard Worker           test::GetGlobalMetricsLogger()->LogSingleValueMetric(
1520*d9f75844SAndroid Build Coastguard Worker               "bitrate_stats_min_transmit_bitrate_low_remb", "bitrate_bps",
1521*d9f75844SAndroid Build Coastguard Worker               static_cast<size_t>(total_bitrate_bps) / 1000.0,
1522*d9f75844SAndroid Build Coastguard Worker               test::Unit::kKilobitsPerSecond,
1523*d9f75844SAndroid Build Coastguard Worker               test::ImprovementDirection::kNeitherIsBetter);
1524*d9f75844SAndroid Build Coastguard Worker           if (total_bitrate_bps > kHighBitrateBps) {
1525*d9f75844SAndroid Build Coastguard Worker             rtp_rtcp_->SetRemb(kRembBitrateBps, {ssrc});
1526*d9f75844SAndroid Build Coastguard Worker             bitrate_capped_ = true;
1527*d9f75844SAndroid Build Coastguard Worker           } else if (bitrate_capped_ &&
1528*d9f75844SAndroid Build Coastguard Worker                      total_bitrate_bps < kRembRespectedBitrateBps) {
1529*d9f75844SAndroid Build Coastguard Worker             observation_complete_.Set();
1530*d9f75844SAndroid Build Coastguard Worker           }
1531*d9f75844SAndroid Build Coastguard Worker         }
1532*d9f75844SAndroid Build Coastguard Worker       }));
1533*d9f75844SAndroid Build Coastguard Worker 
1534*d9f75844SAndroid Build Coastguard Worker       // Packets don't have to be delivered since the test is the receiver.
1535*d9f75844SAndroid Build Coastguard Worker       return DROP_PACKET;
1536*d9f75844SAndroid Build Coastguard Worker     }
1537*d9f75844SAndroid Build Coastguard Worker 
1538*d9f75844SAndroid Build Coastguard Worker     void OnVideoStreamsCreated(VideoSendStream* send_stream,
1539*d9f75844SAndroid Build Coastguard Worker                                const std::vector<VideoReceiveStreamInterface*>&
1540*d9f75844SAndroid Build Coastguard Worker                                    receive_streams) override {
1541*d9f75844SAndroid Build Coastguard Worker       stream_ = send_stream;
1542*d9f75844SAndroid Build Coastguard Worker       RtpRtcpInterface::Configuration config;
1543*d9f75844SAndroid Build Coastguard Worker       config.clock = Clock::GetRealTimeClock();
1544*d9f75844SAndroid Build Coastguard Worker       config.outgoing_transport = feedback_transport_.get();
1545*d9f75844SAndroid Build Coastguard Worker       config.retransmission_rate_limiter = &retranmission_rate_limiter_;
1546*d9f75844SAndroid Build Coastguard Worker       rtp_rtcp_ = ModuleRtpRtcpImpl2::Create(config);
1547*d9f75844SAndroid Build Coastguard Worker       rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
1548*d9f75844SAndroid Build Coastguard Worker     }
1549*d9f75844SAndroid Build Coastguard Worker 
1550*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
1551*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
1552*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
1553*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
1554*d9f75844SAndroid Build Coastguard Worker       feedback_transport_.reset(
1555*d9f75844SAndroid Build Coastguard Worker           new internal::TransportAdapter(send_config->send_transport));
1556*d9f75844SAndroid Build Coastguard Worker       feedback_transport_->Enable();
1557*d9f75844SAndroid Build Coastguard Worker       encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
1558*d9f75844SAndroid Build Coastguard Worker     }
1559*d9f75844SAndroid Build Coastguard Worker 
1560*d9f75844SAndroid Build Coastguard Worker     void OnStreamsStopped() override {
1561*d9f75844SAndroid Build Coastguard Worker       task_safety_flag_->SetNotAlive();
1562*d9f75844SAndroid Build Coastguard Worker       rtp_rtcp_.reset();
1563*d9f75844SAndroid Build Coastguard Worker     }
1564*d9f75844SAndroid Build Coastguard Worker 
1565*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
1566*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait())
1567*d9f75844SAndroid Build Coastguard Worker           << "Timeout while waiting for low bitrate stats after REMB.";
1568*d9f75844SAndroid Build Coastguard Worker     }
1569*d9f75844SAndroid Build Coastguard Worker 
1570*d9f75844SAndroid Build Coastguard Worker     TaskQueueBase* const task_queue_;
1571*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<ModuleRtpRtcpImpl2> rtp_rtcp_;
1572*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<internal::TransportAdapter> feedback_transport_;
1573*d9f75844SAndroid Build Coastguard Worker     RateLimiter retranmission_rate_limiter_;
1574*d9f75844SAndroid Build Coastguard Worker     VideoSendStream* stream_;
1575*d9f75844SAndroid Build Coastguard Worker     bool bitrate_capped_;
1576*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<PendingTaskSafetyFlag> task_safety_flag_;
1577*d9f75844SAndroid Build Coastguard Worker   } test(task_queue());
1578*d9f75844SAndroid Build Coastguard Worker 
1579*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
1580*d9f75844SAndroid Build Coastguard Worker }
1581*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,ChangingNetworkRoute)1582*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, ChangingNetworkRoute) {
1583*d9f75844SAndroid Build Coastguard Worker   static const int kStartBitrateBps = 300000;
1584*d9f75844SAndroid Build Coastguard Worker   static const int kNewMaxBitrateBps = 1234567;
1585*d9f75844SAndroid Build Coastguard Worker   static const uint8_t kExtensionId = kTransportSequenceNumberExtensionId;
1586*d9f75844SAndroid Build Coastguard Worker   class ChangingNetworkRouteTest : public test::EndToEndTest {
1587*d9f75844SAndroid Build Coastguard Worker    public:
1588*d9f75844SAndroid Build Coastguard Worker     explicit ChangingNetworkRouteTest(TaskQueueBase* task_queue)
1589*d9f75844SAndroid Build Coastguard Worker         : EndToEndTest(test::CallTest::kDefaultTimeout),
1590*d9f75844SAndroid Build Coastguard Worker           task_queue_(task_queue),
1591*d9f75844SAndroid Build Coastguard Worker           call_(nullptr) {
1592*d9f75844SAndroid Build Coastguard Worker       module_process_thread_.Detach();
1593*d9f75844SAndroid Build Coastguard Worker       task_queue_thread_.Detach();
1594*d9f75844SAndroid Build Coastguard Worker       extensions_.Register<TransportSequenceNumber>(kExtensionId);
1595*d9f75844SAndroid Build Coastguard Worker     }
1596*d9f75844SAndroid Build Coastguard Worker 
1597*d9f75844SAndroid Build Coastguard Worker     ~ChangingNetworkRouteTest() {
1598*d9f75844SAndroid Build Coastguard Worker       // Block until all already posted tasks run to avoid 'use after free'
1599*d9f75844SAndroid Build Coastguard Worker       // when such task accesses `this`.
1600*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_, [] {});
1601*d9f75844SAndroid Build Coastguard Worker     }
1602*d9f75844SAndroid Build Coastguard Worker 
1603*d9f75844SAndroid Build Coastguard Worker     void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1604*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_RUN_ON(&task_queue_thread_);
1605*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK(!call_);
1606*d9f75844SAndroid Build Coastguard Worker       call_ = sender_call;
1607*d9f75844SAndroid Build Coastguard Worker     }
1608*d9f75844SAndroid Build Coastguard Worker 
1609*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
1610*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
1611*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
1612*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
1613*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_RUN_ON(&task_queue_thread_);
1614*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.clear();
1615*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.push_back(RtpExtension(
1616*d9f75844SAndroid Build Coastguard Worker           RtpExtension::kTransportSequenceNumberUri, kExtensionId));
1617*d9f75844SAndroid Build Coastguard Worker       (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1618*d9f75844SAndroid Build Coastguard Worker       (*receive_configs)[0].rtp.transport_cc = true;
1619*d9f75844SAndroid Build Coastguard Worker     }
1620*d9f75844SAndroid Build Coastguard Worker 
1621*d9f75844SAndroid Build Coastguard Worker     void ModifyAudioConfigs(AudioSendStream::Config* send_config,
1622*d9f75844SAndroid Build Coastguard Worker                             std::vector<AudioReceiveStreamInterface::Config>*
1623*d9f75844SAndroid Build Coastguard Worker                                 receive_configs) override {
1624*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_RUN_ON(&task_queue_thread_);
1625*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.clear();
1626*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.push_back(RtpExtension(
1627*d9f75844SAndroid Build Coastguard Worker           RtpExtension::kTransportSequenceNumberUri, kExtensionId));
1628*d9f75844SAndroid Build Coastguard Worker       (*receive_configs)[0].rtp.extensions.clear();
1629*d9f75844SAndroid Build Coastguard Worker       (*receive_configs)[0].rtp.extensions = send_config->rtp.extensions;
1630*d9f75844SAndroid Build Coastguard Worker       (*receive_configs)[0].rtp.transport_cc = true;
1631*d9f75844SAndroid Build Coastguard Worker     }
1632*d9f75844SAndroid Build Coastguard Worker 
1633*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
1634*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_RUN_ON(&module_process_thread_);
1635*d9f75844SAndroid Build Coastguard Worker       task_queue_->PostTask([this]() {
1636*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK_RUN_ON(&task_queue_thread_);
1637*d9f75844SAndroid Build Coastguard Worker         if (!call_)
1638*d9f75844SAndroid Build Coastguard Worker           return;
1639*d9f75844SAndroid Build Coastguard Worker         Call::Stats stats = call_->GetStats();
1640*d9f75844SAndroid Build Coastguard Worker         if (stats.send_bandwidth_bps > kStartBitrateBps)
1641*d9f75844SAndroid Build Coastguard Worker           observation_complete_.Set();
1642*d9f75844SAndroid Build Coastguard Worker       });
1643*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
1644*d9f75844SAndroid Build Coastguard Worker     }
1645*d9f75844SAndroid Build Coastguard Worker 
1646*d9f75844SAndroid Build Coastguard Worker     void OnStreamsStopped() override {
1647*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_RUN_ON(&task_queue_thread_);
1648*d9f75844SAndroid Build Coastguard Worker       call_ = nullptr;
1649*d9f75844SAndroid Build Coastguard Worker     }
1650*d9f75844SAndroid Build Coastguard Worker 
1651*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
1652*d9f75844SAndroid Build Coastguard Worker       rtc::NetworkRoute new_route;
1653*d9f75844SAndroid Build Coastguard Worker       new_route.connected = true;
1654*d9f75844SAndroid Build Coastguard Worker       new_route.local = rtc::RouteEndpoint::CreateWithNetworkId(10);
1655*d9f75844SAndroid Build Coastguard Worker       new_route.remote = rtc::RouteEndpoint::CreateWithNetworkId(20);
1656*d9f75844SAndroid Build Coastguard Worker       BitrateConstraints bitrate_config;
1657*d9f75844SAndroid Build Coastguard Worker 
1658*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_,
1659*d9f75844SAndroid Build Coastguard Worker                [this, &new_route, &bitrate_config]() {
1660*d9f75844SAndroid Build Coastguard Worker                  RTC_DCHECK_RUN_ON(&task_queue_thread_);
1661*d9f75844SAndroid Build Coastguard Worker                  call_->GetTransportControllerSend()->OnNetworkRouteChanged(
1662*d9f75844SAndroid Build Coastguard Worker                      "transport", new_route);
1663*d9f75844SAndroid Build Coastguard Worker                  bitrate_config.start_bitrate_bps = kStartBitrateBps;
1664*d9f75844SAndroid Build Coastguard Worker                  call_->GetTransportControllerSend()->SetSdpBitrateParameters(
1665*d9f75844SAndroid Build Coastguard Worker                      bitrate_config);
1666*d9f75844SAndroid Build Coastguard Worker                });
1667*d9f75844SAndroid Build Coastguard Worker 
1668*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait())
1669*d9f75844SAndroid Build Coastguard Worker           << "Timed out while waiting for start bitrate to be exceeded.";
1670*d9f75844SAndroid Build Coastguard Worker 
1671*d9f75844SAndroid Build Coastguard Worker       SendTask(
1672*d9f75844SAndroid Build Coastguard Worker           task_queue_, [this, &new_route, &bitrate_config]() {
1673*d9f75844SAndroid Build Coastguard Worker             RTC_DCHECK_RUN_ON(&task_queue_thread_);
1674*d9f75844SAndroid Build Coastguard Worker             bitrate_config.start_bitrate_bps = -1;
1675*d9f75844SAndroid Build Coastguard Worker             bitrate_config.max_bitrate_bps = kNewMaxBitrateBps;
1676*d9f75844SAndroid Build Coastguard Worker             call_->GetTransportControllerSend()->SetSdpBitrateParameters(
1677*d9f75844SAndroid Build Coastguard Worker                 bitrate_config);
1678*d9f75844SAndroid Build Coastguard Worker             // TODO(holmer): We should set the last sent packet id here and
1679*d9f75844SAndroid Build Coastguard Worker             // verify that we correctly ignore any packet loss reported prior to
1680*d9f75844SAndroid Build Coastguard Worker             // that id.
1681*d9f75844SAndroid Build Coastguard Worker             new_route.local = rtc::RouteEndpoint::CreateWithNetworkId(
1682*d9f75844SAndroid Build Coastguard Worker                 new_route.local.network_id() + 1);
1683*d9f75844SAndroid Build Coastguard Worker             call_->GetTransportControllerSend()->OnNetworkRouteChanged(
1684*d9f75844SAndroid Build Coastguard Worker                 "transport", new_route);
1685*d9f75844SAndroid Build Coastguard Worker             EXPECT_GE(call_->GetStats().send_bandwidth_bps, kStartBitrateBps);
1686*d9f75844SAndroid Build Coastguard Worker           });
1687*d9f75844SAndroid Build Coastguard Worker     }
1688*d9f75844SAndroid Build Coastguard Worker 
1689*d9f75844SAndroid Build Coastguard Worker    private:
1690*d9f75844SAndroid Build Coastguard Worker     webrtc::SequenceChecker module_process_thread_;
1691*d9f75844SAndroid Build Coastguard Worker     webrtc::SequenceChecker task_queue_thread_;
1692*d9f75844SAndroid Build Coastguard Worker     TaskQueueBase* const task_queue_;
1693*d9f75844SAndroid Build Coastguard Worker     RtpHeaderExtensionMap extensions_;
1694*d9f75844SAndroid Build Coastguard Worker     Call* call_ RTC_GUARDED_BY(task_queue_thread_);
1695*d9f75844SAndroid Build Coastguard Worker   } test(task_queue());
1696*d9f75844SAndroid Build Coastguard Worker 
1697*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
1698*d9f75844SAndroid Build Coastguard Worker }
1699*d9f75844SAndroid Build Coastguard Worker 
1700*d9f75844SAndroid Build Coastguard Worker // Test that if specified, relay cap is lifted on transition to direct
1701*d9f75844SAndroid Build Coastguard Worker // connection.
1702*d9f75844SAndroid Build Coastguard Worker // TODO(https://bugs.webrtc.org/13353): Test disabled  due to flakiness.
TEST_F(VideoSendStreamTest,DISABLED_RelayToDirectRoute)1703*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, DISABLED_RelayToDirectRoute) {
1704*d9f75844SAndroid Build Coastguard Worker   static const int kStartBitrateBps = 300000;
1705*d9f75844SAndroid Build Coastguard Worker   static const int kRelayBandwidthCapBps = 800000;
1706*d9f75844SAndroid Build Coastguard Worker   static const int kMinPacketsToSend = 100;
1707*d9f75844SAndroid Build Coastguard Worker   webrtc::test::ScopedKeyValueConfig field_trials(
1708*d9f75844SAndroid Build Coastguard Worker       field_trials_, "WebRTC-Bwe-NetworkRouteConstraints/relay_cap:" +
1709*d9f75844SAndroid Build Coastguard Worker                          std::to_string(kRelayBandwidthCapBps) + "bps/");
1710*d9f75844SAndroid Build Coastguard Worker 
1711*d9f75844SAndroid Build Coastguard Worker   class RelayToDirectRouteTest : public test::EndToEndTest {
1712*d9f75844SAndroid Build Coastguard Worker    public:
1713*d9f75844SAndroid Build Coastguard Worker     explicit RelayToDirectRouteTest(TaskQueueBase* task_queue)
1714*d9f75844SAndroid Build Coastguard Worker         : EndToEndTest(test::CallTest::kDefaultTimeout),
1715*d9f75844SAndroid Build Coastguard Worker           task_queue_(task_queue),
1716*d9f75844SAndroid Build Coastguard Worker           call_(nullptr),
1717*d9f75844SAndroid Build Coastguard Worker           packets_sent_(0),
1718*d9f75844SAndroid Build Coastguard Worker           relayed_phase_(true) {
1719*d9f75844SAndroid Build Coastguard Worker       module_process_thread_.Detach();
1720*d9f75844SAndroid Build Coastguard Worker       task_queue_thread_.Detach();
1721*d9f75844SAndroid Build Coastguard Worker     }
1722*d9f75844SAndroid Build Coastguard Worker 
1723*d9f75844SAndroid Build Coastguard Worker     ~RelayToDirectRouteTest() {
1724*d9f75844SAndroid Build Coastguard Worker       // Block until all already posted tasks run to avoid 'use after free'
1725*d9f75844SAndroid Build Coastguard Worker       // when such task accesses `this`.
1726*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_, [] {});
1727*d9f75844SAndroid Build Coastguard Worker     }
1728*d9f75844SAndroid Build Coastguard Worker 
1729*d9f75844SAndroid Build Coastguard Worker     void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1730*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_RUN_ON(&task_queue_thread_);
1731*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK(!call_);
1732*d9f75844SAndroid Build Coastguard Worker       call_ = sender_call;
1733*d9f75844SAndroid Build Coastguard Worker     }
1734*d9f75844SAndroid Build Coastguard Worker 
1735*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
1736*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_RUN_ON(&module_process_thread_);
1737*d9f75844SAndroid Build Coastguard Worker       task_queue_->PostTask([this]() {
1738*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK_RUN_ON(&task_queue_thread_);
1739*d9f75844SAndroid Build Coastguard Worker         if (!call_)
1740*d9f75844SAndroid Build Coastguard Worker           return;
1741*d9f75844SAndroid Build Coastguard Worker         bool had_time_to_exceed_cap_in_relayed_phase =
1742*d9f75844SAndroid Build Coastguard Worker             relayed_phase_ && ++packets_sent_ > kMinPacketsToSend;
1743*d9f75844SAndroid Build Coastguard Worker         bool did_exceed_cap =
1744*d9f75844SAndroid Build Coastguard Worker             call_->GetStats().send_bandwidth_bps > kRelayBandwidthCapBps;
1745*d9f75844SAndroid Build Coastguard Worker         if (did_exceed_cap || had_time_to_exceed_cap_in_relayed_phase)
1746*d9f75844SAndroid Build Coastguard Worker           observation_complete_.Set();
1747*d9f75844SAndroid Build Coastguard Worker       });
1748*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
1749*d9f75844SAndroid Build Coastguard Worker     }
1750*d9f75844SAndroid Build Coastguard Worker 
1751*d9f75844SAndroid Build Coastguard Worker     void OnStreamsStopped() override {
1752*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_RUN_ON(&task_queue_thread_);
1753*d9f75844SAndroid Build Coastguard Worker       call_ = nullptr;
1754*d9f75844SAndroid Build Coastguard Worker     }
1755*d9f75844SAndroid Build Coastguard Worker 
1756*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
1757*d9f75844SAndroid Build Coastguard Worker       rtc::NetworkRoute route;
1758*d9f75844SAndroid Build Coastguard Worker       route.connected = true;
1759*d9f75844SAndroid Build Coastguard Worker       route.local = rtc::RouteEndpoint::CreateWithNetworkId(10);
1760*d9f75844SAndroid Build Coastguard Worker       route.remote = rtc::RouteEndpoint::CreateWithNetworkId(20);
1761*d9f75844SAndroid Build Coastguard Worker 
1762*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_, [this, &route]() {
1763*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK_RUN_ON(&task_queue_thread_);
1764*d9f75844SAndroid Build Coastguard Worker         relayed_phase_ = true;
1765*d9f75844SAndroid Build Coastguard Worker         route.remote = route.remote.CreateWithTurn(true);
1766*d9f75844SAndroid Build Coastguard Worker         call_->GetTransportControllerSend()->OnNetworkRouteChanged("transport",
1767*d9f75844SAndroid Build Coastguard Worker                                                                    route);
1768*d9f75844SAndroid Build Coastguard Worker         BitrateConstraints bitrate_config;
1769*d9f75844SAndroid Build Coastguard Worker         bitrate_config.start_bitrate_bps = kStartBitrateBps;
1770*d9f75844SAndroid Build Coastguard Worker 
1771*d9f75844SAndroid Build Coastguard Worker         call_->GetTransportControllerSend()->SetSdpBitrateParameters(
1772*d9f75844SAndroid Build Coastguard Worker             bitrate_config);
1773*d9f75844SAndroid Build Coastguard Worker       });
1774*d9f75844SAndroid Build Coastguard Worker 
1775*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait())
1776*d9f75844SAndroid Build Coastguard Worker           << "Timeout waiting for sufficient packets sent count.";
1777*d9f75844SAndroid Build Coastguard Worker 
1778*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_, [this, &route]() {
1779*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK_RUN_ON(&task_queue_thread_);
1780*d9f75844SAndroid Build Coastguard Worker         EXPECT_LE(call_->GetStats().send_bandwidth_bps, kRelayBandwidthCapBps);
1781*d9f75844SAndroid Build Coastguard Worker 
1782*d9f75844SAndroid Build Coastguard Worker         route.remote = route.remote.CreateWithTurn(false);
1783*d9f75844SAndroid Build Coastguard Worker         call_->GetTransportControllerSend()->OnNetworkRouteChanged("transport",
1784*d9f75844SAndroid Build Coastguard Worker                                                                    route);
1785*d9f75844SAndroid Build Coastguard Worker         relayed_phase_ = false;
1786*d9f75844SAndroid Build Coastguard Worker         observation_complete_.Reset();
1787*d9f75844SAndroid Build Coastguard Worker       });
1788*d9f75844SAndroid Build Coastguard Worker 
1789*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait())
1790*d9f75844SAndroid Build Coastguard Worker           << "Timeout while waiting for bandwidth to outgrow relay cap.";
1791*d9f75844SAndroid Build Coastguard Worker     }
1792*d9f75844SAndroid Build Coastguard Worker 
1793*d9f75844SAndroid Build Coastguard Worker    private:
1794*d9f75844SAndroid Build Coastguard Worker     webrtc::SequenceChecker module_process_thread_;
1795*d9f75844SAndroid Build Coastguard Worker     webrtc::SequenceChecker task_queue_thread_;
1796*d9f75844SAndroid Build Coastguard Worker     TaskQueueBase* const task_queue_;
1797*d9f75844SAndroid Build Coastguard Worker     Call* call_ RTC_GUARDED_BY(task_queue_thread_);
1798*d9f75844SAndroid Build Coastguard Worker     int packets_sent_ RTC_GUARDED_BY(task_queue_thread_);
1799*d9f75844SAndroid Build Coastguard Worker     bool relayed_phase_ RTC_GUARDED_BY(task_queue_thread_);
1800*d9f75844SAndroid Build Coastguard Worker   } test(task_queue());
1801*d9f75844SAndroid Build Coastguard Worker 
1802*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
1803*d9f75844SAndroid Build Coastguard Worker }
1804*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,ChangingTransportOverhead)1805*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, ChangingTransportOverhead) {
1806*d9f75844SAndroid Build Coastguard Worker   class ChangingTransportOverheadTest : public test::EndToEndTest {
1807*d9f75844SAndroid Build Coastguard Worker    public:
1808*d9f75844SAndroid Build Coastguard Worker     explicit ChangingTransportOverheadTest(TaskQueueBase* task_queue)
1809*d9f75844SAndroid Build Coastguard Worker         : EndToEndTest(test::CallTest::kDefaultTimeout),
1810*d9f75844SAndroid Build Coastguard Worker           task_queue_(task_queue),
1811*d9f75844SAndroid Build Coastguard Worker           call_(nullptr),
1812*d9f75844SAndroid Build Coastguard Worker           packets_sent_(0),
1813*d9f75844SAndroid Build Coastguard Worker           transport_overhead_(0) {}
1814*d9f75844SAndroid Build Coastguard Worker 
1815*d9f75844SAndroid Build Coastguard Worker     void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1816*d9f75844SAndroid Build Coastguard Worker       call_ = sender_call;
1817*d9f75844SAndroid Build Coastguard Worker     }
1818*d9f75844SAndroid Build Coastguard Worker 
1819*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
1820*d9f75844SAndroid Build Coastguard Worker       EXPECT_LE(length, kMaxRtpPacketSize);
1821*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&lock_);
1822*d9f75844SAndroid Build Coastguard Worker       if (++packets_sent_ < 100)
1823*d9f75844SAndroid Build Coastguard Worker         return SEND_PACKET;
1824*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
1825*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
1826*d9f75844SAndroid Build Coastguard Worker     }
1827*d9f75844SAndroid Build Coastguard Worker 
1828*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
1829*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
1830*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
1831*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
1832*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.max_packet_size = kMaxRtpPacketSize;
1833*d9f75844SAndroid Build Coastguard Worker     }
1834*d9f75844SAndroid Build Coastguard Worker 
1835*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
1836*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_, [this]() {
1837*d9f75844SAndroid Build Coastguard Worker         transport_overhead_ = 100;
1838*d9f75844SAndroid Build Coastguard Worker         call_->GetTransportControllerSend()->OnTransportOverheadChanged(
1839*d9f75844SAndroid Build Coastguard Worker             transport_overhead_);
1840*d9f75844SAndroid Build Coastguard Worker       });
1841*d9f75844SAndroid Build Coastguard Worker 
1842*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait());
1843*d9f75844SAndroid Build Coastguard Worker 
1844*d9f75844SAndroid Build Coastguard Worker       {
1845*d9f75844SAndroid Build Coastguard Worker         MutexLock lock(&lock_);
1846*d9f75844SAndroid Build Coastguard Worker         packets_sent_ = 0;
1847*d9f75844SAndroid Build Coastguard Worker       }
1848*d9f75844SAndroid Build Coastguard Worker 
1849*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_, [this]() {
1850*d9f75844SAndroid Build Coastguard Worker         transport_overhead_ = 500;
1851*d9f75844SAndroid Build Coastguard Worker         call_->GetTransportControllerSend()->OnTransportOverheadChanged(
1852*d9f75844SAndroid Build Coastguard Worker             transport_overhead_);
1853*d9f75844SAndroid Build Coastguard Worker       });
1854*d9f75844SAndroid Build Coastguard Worker 
1855*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait());
1856*d9f75844SAndroid Build Coastguard Worker     }
1857*d9f75844SAndroid Build Coastguard Worker 
1858*d9f75844SAndroid Build Coastguard Worker    private:
1859*d9f75844SAndroid Build Coastguard Worker     TaskQueueBase* const task_queue_;
1860*d9f75844SAndroid Build Coastguard Worker     Call* call_;
1861*d9f75844SAndroid Build Coastguard Worker     Mutex lock_;
1862*d9f75844SAndroid Build Coastguard Worker     int packets_sent_ RTC_GUARDED_BY(lock_);
1863*d9f75844SAndroid Build Coastguard Worker     int transport_overhead_;
1864*d9f75844SAndroid Build Coastguard Worker     const size_t kMaxRtpPacketSize = 1000;
1865*d9f75844SAndroid Build Coastguard Worker   } test(task_queue());
1866*d9f75844SAndroid Build Coastguard Worker 
1867*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
1868*d9f75844SAndroid Build Coastguard Worker }
1869*d9f75844SAndroid Build Coastguard Worker 
1870*d9f75844SAndroid Build Coastguard Worker // Test class takes takes as argument a switch selecting if type switch should
1871*d9f75844SAndroid Build Coastguard Worker // occur and a function pointer to reset the send stream. This is necessary
1872*d9f75844SAndroid Build Coastguard Worker // since you cannot change the content type of a VideoSendStream, you need to
1873*d9f75844SAndroid Build Coastguard Worker // recreate it. Stopping and recreating the stream can only be done on the main
1874*d9f75844SAndroid Build Coastguard Worker // thread and in the context of VideoSendStreamTest (not BaseTest).
1875*d9f75844SAndroid Build Coastguard Worker template <typename T>
1876*d9f75844SAndroid Build Coastguard Worker class MaxPaddingSetTest : public test::SendTest {
1877*d9f75844SAndroid Build Coastguard Worker  public:
1878*d9f75844SAndroid Build Coastguard Worker   static const uint32_t kMinTransmitBitrateBps = 400000;
1879*d9f75844SAndroid Build Coastguard Worker   static const uint32_t kActualEncodeBitrateBps = 40000;
1880*d9f75844SAndroid Build Coastguard Worker   static const uint32_t kMinPacketsToSend = 50;
1881*d9f75844SAndroid Build Coastguard Worker 
MaxPaddingSetTest(bool test_switch_content_type,T * stream_reset_fun,TaskQueueBase * task_queue)1882*d9f75844SAndroid Build Coastguard Worker   MaxPaddingSetTest(bool test_switch_content_type,
1883*d9f75844SAndroid Build Coastguard Worker                     T* stream_reset_fun,
1884*d9f75844SAndroid Build Coastguard Worker                     TaskQueueBase* task_queue)
1885*d9f75844SAndroid Build Coastguard Worker       : SendTest(test::CallTest::kDefaultTimeout),
1886*d9f75844SAndroid Build Coastguard Worker         running_without_padding_(test_switch_content_type),
1887*d9f75844SAndroid Build Coastguard Worker         stream_resetter_(stream_reset_fun),
1888*d9f75844SAndroid Build Coastguard Worker         task_queue_(task_queue) {
1889*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(stream_resetter_);
1890*d9f75844SAndroid Build Coastguard Worker     module_process_thread_.Detach();
1891*d9f75844SAndroid Build Coastguard Worker     task_queue_thread_.Detach();
1892*d9f75844SAndroid Build Coastguard Worker   }
1893*d9f75844SAndroid Build Coastguard Worker 
~MaxPaddingSetTest()1894*d9f75844SAndroid Build Coastguard Worker   ~MaxPaddingSetTest() {
1895*d9f75844SAndroid Build Coastguard Worker     // Block until all already posted tasks run to avoid 'use after free'
1896*d9f75844SAndroid Build Coastguard Worker     // when such task accesses `this`.
1897*d9f75844SAndroid Build Coastguard Worker     SendTask(task_queue_, [] {});
1898*d9f75844SAndroid Build Coastguard Worker   }
1899*d9f75844SAndroid Build Coastguard Worker 
ModifyVideoConfigs(VideoSendStream::Config * send_config,std::vector<VideoReceiveStreamInterface::Config> * receive_configs,VideoEncoderConfig * encoder_config)1900*d9f75844SAndroid Build Coastguard Worker   void ModifyVideoConfigs(
1901*d9f75844SAndroid Build Coastguard Worker       VideoSendStream::Config* send_config,
1902*d9f75844SAndroid Build Coastguard Worker       std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
1903*d9f75844SAndroid Build Coastguard Worker       VideoEncoderConfig* encoder_config) override {
1904*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_RUN_ON(&task_queue_thread_);
1905*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
1906*d9f75844SAndroid Build Coastguard Worker     if (running_without_padding_) {
1907*d9f75844SAndroid Build Coastguard Worker       encoder_config->min_transmit_bitrate_bps = 0;
1908*d9f75844SAndroid Build Coastguard Worker       encoder_config->content_type =
1909*d9f75844SAndroid Build Coastguard Worker           VideoEncoderConfig::ContentType::kRealtimeVideo;
1910*d9f75844SAndroid Build Coastguard Worker     } else {
1911*d9f75844SAndroid Build Coastguard Worker       encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps;
1912*d9f75844SAndroid Build Coastguard Worker       encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
1913*d9f75844SAndroid Build Coastguard Worker     }
1914*d9f75844SAndroid Build Coastguard Worker     send_stream_config_ = send_config->Copy();
1915*d9f75844SAndroid Build Coastguard Worker     encoder_config_ = encoder_config->Copy();
1916*d9f75844SAndroid Build Coastguard Worker   }
1917*d9f75844SAndroid Build Coastguard Worker 
OnCallsCreated(Call * sender_call,Call * receiver_call)1918*d9f75844SAndroid Build Coastguard Worker   void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1919*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_RUN_ON(&task_queue_thread_);
1920*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(task_queue_->IsCurrent());
1921*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(!call_);
1922*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(sender_call);
1923*d9f75844SAndroid Build Coastguard Worker     call_ = sender_call;
1924*d9f75844SAndroid Build Coastguard Worker   }
1925*d9f75844SAndroid Build Coastguard Worker 
1926*d9f75844SAndroid Build Coastguard Worker   // Called on the pacer thread.
OnSendRtp(const uint8_t * packet,size_t length)1927*d9f75844SAndroid Build Coastguard Worker   Action OnSendRtp(const uint8_t* packet, size_t length) override {
1928*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_RUN_ON(&module_process_thread_);
1929*d9f75844SAndroid Build Coastguard Worker 
1930*d9f75844SAndroid Build Coastguard Worker     // Check the stats on the correct thread and signal the 'complete' flag
1931*d9f75844SAndroid Build Coastguard Worker     // once we detect that we're done.
1932*d9f75844SAndroid Build Coastguard Worker 
1933*d9f75844SAndroid Build Coastguard Worker     task_queue_->PostTask([this]() {
1934*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_RUN_ON(&task_queue_thread_);
1935*d9f75844SAndroid Build Coastguard Worker       // In case we get a callback during teardown.
1936*d9f75844SAndroid Build Coastguard Worker       // When this happens, OnStreamsStopped() has been called already,
1937*d9f75844SAndroid Build Coastguard Worker       // `call_` is null and the streams are being torn down.
1938*d9f75844SAndroid Build Coastguard Worker       if (!call_)
1939*d9f75844SAndroid Build Coastguard Worker         return;
1940*d9f75844SAndroid Build Coastguard Worker 
1941*d9f75844SAndroid Build Coastguard Worker       ++packets_sent_;
1942*d9f75844SAndroid Build Coastguard Worker 
1943*d9f75844SAndroid Build Coastguard Worker       Call::Stats stats = call_->GetStats();
1944*d9f75844SAndroid Build Coastguard Worker       if (running_without_padding_) {
1945*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(0, stats.max_padding_bitrate_bps);
1946*d9f75844SAndroid Build Coastguard Worker 
1947*d9f75844SAndroid Build Coastguard Worker         // Wait until at least kMinPacketsToSend frames have been encoded, so
1948*d9f75844SAndroid Build Coastguard Worker         // that we have reliable data.
1949*d9f75844SAndroid Build Coastguard Worker         if (packets_sent_ < kMinPacketsToSend)
1950*d9f75844SAndroid Build Coastguard Worker           return;
1951*d9f75844SAndroid Build Coastguard Worker 
1952*d9f75844SAndroid Build Coastguard Worker         // We've sent kMinPacketsToSend packets with default configuration,
1953*d9f75844SAndroid Build Coastguard Worker         // switch to enabling screen content and setting min transmit bitrate.
1954*d9f75844SAndroid Build Coastguard Worker         // Note that we need to recreate the stream if changing content type.
1955*d9f75844SAndroid Build Coastguard Worker         packets_sent_ = 0;
1956*d9f75844SAndroid Build Coastguard Worker 
1957*d9f75844SAndroid Build Coastguard Worker         encoder_config_.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
1958*d9f75844SAndroid Build Coastguard Worker         encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
1959*d9f75844SAndroid Build Coastguard Worker 
1960*d9f75844SAndroid Build Coastguard Worker         running_without_padding_ = false;
1961*d9f75844SAndroid Build Coastguard Worker         (*stream_resetter_)(send_stream_config_, encoder_config_);
1962*d9f75844SAndroid Build Coastguard Worker       } else {
1963*d9f75844SAndroid Build Coastguard Worker         // Make sure the pacer has been configured with a min transmit bitrate.
1964*d9f75844SAndroid Build Coastguard Worker         if (stats.max_padding_bitrate_bps > 0) {
1965*d9f75844SAndroid Build Coastguard Worker           observation_complete_.Set();
1966*d9f75844SAndroid Build Coastguard Worker         }
1967*d9f75844SAndroid Build Coastguard Worker       }
1968*d9f75844SAndroid Build Coastguard Worker     });
1969*d9f75844SAndroid Build Coastguard Worker 
1970*d9f75844SAndroid Build Coastguard Worker     return SEND_PACKET;
1971*d9f75844SAndroid Build Coastguard Worker   }
1972*d9f75844SAndroid Build Coastguard Worker 
1973*d9f75844SAndroid Build Coastguard Worker   // Called on `task_queue_`
OnStreamsStopped()1974*d9f75844SAndroid Build Coastguard Worker   void OnStreamsStopped() override {
1975*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_RUN_ON(&task_queue_thread_);
1976*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(task_queue_->IsCurrent());
1977*d9f75844SAndroid Build Coastguard Worker     call_ = nullptr;
1978*d9f75844SAndroid Build Coastguard Worker   }
1979*d9f75844SAndroid Build Coastguard Worker 
PerformTest()1980*d9f75844SAndroid Build Coastguard Worker   void PerformTest() override {
1981*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(Wait()) << "Timed out waiting for a valid padding bitrate.";
1982*d9f75844SAndroid Build Coastguard Worker   }
1983*d9f75844SAndroid Build Coastguard Worker 
1984*d9f75844SAndroid Build Coastguard Worker  private:
1985*d9f75844SAndroid Build Coastguard Worker   webrtc::SequenceChecker task_queue_thread_;
1986*d9f75844SAndroid Build Coastguard Worker   Call* call_ RTC_GUARDED_BY(task_queue_thread_) = nullptr;
1987*d9f75844SAndroid Build Coastguard Worker   VideoSendStream::Config send_stream_config_{nullptr};
1988*d9f75844SAndroid Build Coastguard Worker   VideoEncoderConfig encoder_config_;
1989*d9f75844SAndroid Build Coastguard Worker   webrtc::SequenceChecker module_process_thread_;
1990*d9f75844SAndroid Build Coastguard Worker   uint32_t packets_sent_ RTC_GUARDED_BY(task_queue_thread_) = 0;
1991*d9f75844SAndroid Build Coastguard Worker   bool running_without_padding_ RTC_GUARDED_BY(task_queue_thread_);
1992*d9f75844SAndroid Build Coastguard Worker   T* const stream_resetter_;
1993*d9f75844SAndroid Build Coastguard Worker   TaskQueueBase* const task_queue_;
1994*d9f75844SAndroid Build Coastguard Worker };
1995*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,RespectsMinTransmitBitrate)1996*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, RespectsMinTransmitBitrate) {
1997*d9f75844SAndroid Build Coastguard Worker   auto reset_fun = [](const VideoSendStream::Config& send_stream_config,
1998*d9f75844SAndroid Build Coastguard Worker                       const VideoEncoderConfig& encoder_config) {};
1999*d9f75844SAndroid Build Coastguard Worker   MaxPaddingSetTest<decltype(reset_fun)> test(false, &reset_fun, task_queue());
2000*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
2001*d9f75844SAndroid Build Coastguard Worker }
2002*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,RespectsMinTransmitBitrateAfterContentSwitch)2003*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, RespectsMinTransmitBitrateAfterContentSwitch) {
2004*d9f75844SAndroid Build Coastguard Worker   // Function for removing and recreating the send stream with a new config.
2005*d9f75844SAndroid Build Coastguard Worker   auto reset_fun = [this](const VideoSendStream::Config& send_stream_config,
2006*d9f75844SAndroid Build Coastguard Worker                           const VideoEncoderConfig& encoder_config) {
2007*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(task_queue()->IsCurrent());
2008*d9f75844SAndroid Build Coastguard Worker     Stop();
2009*d9f75844SAndroid Build Coastguard Worker     DestroyVideoSendStreams();
2010*d9f75844SAndroid Build Coastguard Worker     SetVideoSendConfig(send_stream_config);
2011*d9f75844SAndroid Build Coastguard Worker     SetVideoEncoderConfig(encoder_config);
2012*d9f75844SAndroid Build Coastguard Worker     CreateVideoSendStreams();
2013*d9f75844SAndroid Build Coastguard Worker     SetVideoDegradation(DegradationPreference::MAINTAIN_RESOLUTION);
2014*d9f75844SAndroid Build Coastguard Worker     Start();
2015*d9f75844SAndroid Build Coastguard Worker   };
2016*d9f75844SAndroid Build Coastguard Worker   MaxPaddingSetTest<decltype(reset_fun)> test(true, &reset_fun, task_queue());
2017*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
2018*d9f75844SAndroid Build Coastguard Worker }
2019*d9f75844SAndroid Build Coastguard Worker 
2020*d9f75844SAndroid Build Coastguard Worker // This test verifies that new frame sizes reconfigures encoders even though not
2021*d9f75844SAndroid Build Coastguard Worker // (yet) sending. The purpose of this is to permit encoding as quickly as
2022*d9f75844SAndroid Build Coastguard Worker // possible once we start sending. Likely the frames being input are from the
2023*d9f75844SAndroid Build Coastguard Worker // same source that will be sent later, which just means that we're ready
2024*d9f75844SAndroid Build Coastguard Worker // earlier.
TEST_F(VideoSendStreamTest,EncoderReconfigureOnResolutionChangeWhenNotSending)2025*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest,
2026*d9f75844SAndroid Build Coastguard Worker        EncoderReconfigureOnResolutionChangeWhenNotSending) {
2027*d9f75844SAndroid Build Coastguard Worker   class EncoderObserver : public test::FakeEncoder {
2028*d9f75844SAndroid Build Coastguard Worker    public:
2029*d9f75844SAndroid Build Coastguard Worker     EncoderObserver()
2030*d9f75844SAndroid Build Coastguard Worker         : FakeEncoder(Clock::GetRealTimeClock()),
2031*d9f75844SAndroid Build Coastguard Worker           last_initialized_frame_width_(0),
2032*d9f75844SAndroid Build Coastguard Worker           last_initialized_frame_height_(0) {}
2033*d9f75844SAndroid Build Coastguard Worker 
2034*d9f75844SAndroid Build Coastguard Worker     void WaitForResolution(int width, int height) {
2035*d9f75844SAndroid Build Coastguard Worker       {
2036*d9f75844SAndroid Build Coastguard Worker         MutexLock lock(&mutex_);
2037*d9f75844SAndroid Build Coastguard Worker         if (last_initialized_frame_width_ == width &&
2038*d9f75844SAndroid Build Coastguard Worker             last_initialized_frame_height_ == height) {
2039*d9f75844SAndroid Build Coastguard Worker           return;
2040*d9f75844SAndroid Build Coastguard Worker         }
2041*d9f75844SAndroid Build Coastguard Worker       }
2042*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(
2043*d9f75844SAndroid Build Coastguard Worker           init_encode_called_.Wait(VideoSendStreamTest::kDefaultTimeout));
2044*d9f75844SAndroid Build Coastguard Worker       {
2045*d9f75844SAndroid Build Coastguard Worker         MutexLock lock(&mutex_);
2046*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(width, last_initialized_frame_width_);
2047*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(height, last_initialized_frame_height_);
2048*d9f75844SAndroid Build Coastguard Worker       }
2049*d9f75844SAndroid Build Coastguard Worker     }
2050*d9f75844SAndroid Build Coastguard Worker 
2051*d9f75844SAndroid Build Coastguard Worker    private:
2052*d9f75844SAndroid Build Coastguard Worker     int32_t InitEncode(const VideoCodec* config,
2053*d9f75844SAndroid Build Coastguard Worker                        const Settings& settings) override {
2054*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2055*d9f75844SAndroid Build Coastguard Worker       last_initialized_frame_width_ = config->width;
2056*d9f75844SAndroid Build Coastguard Worker       last_initialized_frame_height_ = config->height;
2057*d9f75844SAndroid Build Coastguard Worker       init_encode_called_.Set();
2058*d9f75844SAndroid Build Coastguard Worker       return FakeEncoder::InitEncode(config, settings);
2059*d9f75844SAndroid Build Coastguard Worker     }
2060*d9f75844SAndroid Build Coastguard Worker 
2061*d9f75844SAndroid Build Coastguard Worker     int32_t Encode(const VideoFrame& input_image,
2062*d9f75844SAndroid Build Coastguard Worker                    const std::vector<VideoFrameType>* frame_types) override {
2063*d9f75844SAndroid Build Coastguard Worker       ADD_FAILURE()
2064*d9f75844SAndroid Build Coastguard Worker           << "Unexpected Encode call since the send stream is not started";
2065*d9f75844SAndroid Build Coastguard Worker       return 0;
2066*d9f75844SAndroid Build Coastguard Worker     }
2067*d9f75844SAndroid Build Coastguard Worker 
2068*d9f75844SAndroid Build Coastguard Worker     Mutex mutex_;
2069*d9f75844SAndroid Build Coastguard Worker     rtc::Event init_encode_called_;
2070*d9f75844SAndroid Build Coastguard Worker     int last_initialized_frame_width_ RTC_GUARDED_BY(&mutex_);
2071*d9f75844SAndroid Build Coastguard Worker     int last_initialized_frame_height_ RTC_GUARDED_BY(&mutex_);
2072*d9f75844SAndroid Build Coastguard Worker   };
2073*d9f75844SAndroid Build Coastguard Worker 
2074*d9f75844SAndroid Build Coastguard Worker   test::NullTransport transport;
2075*d9f75844SAndroid Build Coastguard Worker   EncoderObserver encoder;
2076*d9f75844SAndroid Build Coastguard Worker   test::VideoEncoderProxyFactory encoder_factory(&encoder);
2077*d9f75844SAndroid Build Coastguard Worker 
2078*d9f75844SAndroid Build Coastguard Worker   SendTask(task_queue(), [this, &transport, &encoder_factory]() {
2079*d9f75844SAndroid Build Coastguard Worker     CreateSenderCall();
2080*d9f75844SAndroid Build Coastguard Worker     CreateSendConfig(1, 0, 0, &transport);
2081*d9f75844SAndroid Build Coastguard Worker     GetVideoSendConfig()->encoder_settings.encoder_factory = &encoder_factory;
2082*d9f75844SAndroid Build Coastguard Worker     CreateVideoStreams();
2083*d9f75844SAndroid Build Coastguard Worker     CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
2084*d9f75844SAndroid Build Coastguard Worker                                  kDefaultHeight);
2085*d9f75844SAndroid Build Coastguard Worker     frame_generator_capturer_->Start();
2086*d9f75844SAndroid Build Coastguard Worker   });
2087*d9f75844SAndroid Build Coastguard Worker 
2088*d9f75844SAndroid Build Coastguard Worker   encoder.WaitForResolution(kDefaultWidth, kDefaultHeight);
2089*d9f75844SAndroid Build Coastguard Worker 
2090*d9f75844SAndroid Build Coastguard Worker   SendTask(task_queue(), [this]() {
2091*d9f75844SAndroid Build Coastguard Worker     frame_generator_capturer_->ChangeResolution(kDefaultWidth * 2,
2092*d9f75844SAndroid Build Coastguard Worker                                                 kDefaultHeight * 2);
2093*d9f75844SAndroid Build Coastguard Worker   });
2094*d9f75844SAndroid Build Coastguard Worker 
2095*d9f75844SAndroid Build Coastguard Worker   encoder.WaitForResolution(kDefaultWidth * 2, kDefaultHeight * 2);
2096*d9f75844SAndroid Build Coastguard Worker 
2097*d9f75844SAndroid Build Coastguard Worker   SendTask(task_queue(), [this]() {
2098*d9f75844SAndroid Build Coastguard Worker     DestroyStreams();
2099*d9f75844SAndroid Build Coastguard Worker     DestroyCalls();
2100*d9f75844SAndroid Build Coastguard Worker   });
2101*d9f75844SAndroid Build Coastguard Worker }
2102*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,CanReconfigureToUseStartBitrateAbovePreviousMax)2103*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) {
2104*d9f75844SAndroid Build Coastguard Worker   class StartBitrateObserver : public test::FakeEncoder {
2105*d9f75844SAndroid Build Coastguard Worker    public:
2106*d9f75844SAndroid Build Coastguard Worker     StartBitrateObserver()
2107*d9f75844SAndroid Build Coastguard Worker         : FakeEncoder(Clock::GetRealTimeClock()), start_bitrate_kbps_(0) {}
2108*d9f75844SAndroid Build Coastguard Worker     int32_t InitEncode(const VideoCodec* config,
2109*d9f75844SAndroid Build Coastguard Worker                        const Settings& settings) override {
2110*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2111*d9f75844SAndroid Build Coastguard Worker       start_bitrate_kbps_ = config->startBitrate;
2112*d9f75844SAndroid Build Coastguard Worker       start_bitrate_changed_.Set();
2113*d9f75844SAndroid Build Coastguard Worker       return FakeEncoder::InitEncode(config, settings);
2114*d9f75844SAndroid Build Coastguard Worker     }
2115*d9f75844SAndroid Build Coastguard Worker 
2116*d9f75844SAndroid Build Coastguard Worker     void SetRates(const RateControlParameters& parameters) override {
2117*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2118*d9f75844SAndroid Build Coastguard Worker       start_bitrate_kbps_ = parameters.bitrate.get_sum_kbps();
2119*d9f75844SAndroid Build Coastguard Worker       start_bitrate_changed_.Set();
2120*d9f75844SAndroid Build Coastguard Worker       FakeEncoder::SetRates(parameters);
2121*d9f75844SAndroid Build Coastguard Worker     }
2122*d9f75844SAndroid Build Coastguard Worker 
2123*d9f75844SAndroid Build Coastguard Worker     int GetStartBitrateKbps() const {
2124*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2125*d9f75844SAndroid Build Coastguard Worker       return start_bitrate_kbps_;
2126*d9f75844SAndroid Build Coastguard Worker     }
2127*d9f75844SAndroid Build Coastguard Worker 
2128*d9f75844SAndroid Build Coastguard Worker     bool WaitForStartBitrate() {
2129*d9f75844SAndroid Build Coastguard Worker       return start_bitrate_changed_.Wait(VideoSendStreamTest::kDefaultTimeout);
2130*d9f75844SAndroid Build Coastguard Worker     }
2131*d9f75844SAndroid Build Coastguard Worker 
2132*d9f75844SAndroid Build Coastguard Worker    private:
2133*d9f75844SAndroid Build Coastguard Worker     mutable Mutex mutex_;
2134*d9f75844SAndroid Build Coastguard Worker     rtc::Event start_bitrate_changed_;
2135*d9f75844SAndroid Build Coastguard Worker     int start_bitrate_kbps_ RTC_GUARDED_BY(mutex_);
2136*d9f75844SAndroid Build Coastguard Worker   };
2137*d9f75844SAndroid Build Coastguard Worker 
2138*d9f75844SAndroid Build Coastguard Worker   CreateSenderCall();
2139*d9f75844SAndroid Build Coastguard Worker 
2140*d9f75844SAndroid Build Coastguard Worker   test::NullTransport transport;
2141*d9f75844SAndroid Build Coastguard Worker   CreateSendConfig(1, 0, 0, &transport);
2142*d9f75844SAndroid Build Coastguard Worker 
2143*d9f75844SAndroid Build Coastguard Worker   BitrateConstraints bitrate_config;
2144*d9f75844SAndroid Build Coastguard Worker   bitrate_config.start_bitrate_bps =
2145*d9f75844SAndroid Build Coastguard Worker       2 * GetVideoEncoderConfig()->max_bitrate_bps;
2146*d9f75844SAndroid Build Coastguard Worker   sender_call_->GetTransportControllerSend()->SetSdpBitrateParameters(
2147*d9f75844SAndroid Build Coastguard Worker       bitrate_config);
2148*d9f75844SAndroid Build Coastguard Worker 
2149*d9f75844SAndroid Build Coastguard Worker   StartBitrateObserver encoder;
2150*d9f75844SAndroid Build Coastguard Worker   test::VideoEncoderProxyFactory encoder_factory(&encoder);
2151*d9f75844SAndroid Build Coastguard Worker   GetVideoSendConfig()->encoder_settings.encoder_factory = &encoder_factory;
2152*d9f75844SAndroid Build Coastguard Worker 
2153*d9f75844SAndroid Build Coastguard Worker   CreateVideoStreams();
2154*d9f75844SAndroid Build Coastguard Worker 
2155*d9f75844SAndroid Build Coastguard Worker   // Start capturing and encoding frames to force encoder reconfiguration.
2156*d9f75844SAndroid Build Coastguard Worker   CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
2157*d9f75844SAndroid Build Coastguard Worker                                kDefaultHeight);
2158*d9f75844SAndroid Build Coastguard Worker   frame_generator_capturer_->Start();
2159*d9f75844SAndroid Build Coastguard Worker   // TODO(crbug/1255737): Added manual current thread message processing because
2160*d9f75844SAndroid Build Coastguard Worker   // the test code context is interpreted as the worker thread and we assume
2161*d9f75844SAndroid Build Coastguard Worker   // progress on it. The test should probably be ported to use simulated time
2162*d9f75844SAndroid Build Coastguard Worker   // instead (ported to a scenario test perhaps?).
2163*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::Current()->ProcessMessages(5000);
2164*d9f75844SAndroid Build Coastguard Worker 
2165*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(encoder.WaitForStartBitrate());
2166*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(GetVideoEncoderConfig()->max_bitrate_bps / 1000,
2167*d9f75844SAndroid Build Coastguard Worker             encoder.GetStartBitrateKbps());
2168*d9f75844SAndroid Build Coastguard Worker 
2169*d9f75844SAndroid Build Coastguard Worker   GetVideoEncoderConfig()->max_bitrate_bps =
2170*d9f75844SAndroid Build Coastguard Worker       2 * bitrate_config.start_bitrate_bps;
2171*d9f75844SAndroid Build Coastguard Worker   GetVideoSendStream()->ReconfigureVideoEncoder(
2172*d9f75844SAndroid Build Coastguard Worker       GetVideoEncoderConfig()->Copy());
2173*d9f75844SAndroid Build Coastguard Worker   // TODO(crbug/1255737): Added manual current thread message processing because
2174*d9f75844SAndroid Build Coastguard Worker   // the test code context is interpreted as the worker thread and we assume
2175*d9f75844SAndroid Build Coastguard Worker   // progress on it. The test should probably be ported to use simulated time
2176*d9f75844SAndroid Build Coastguard Worker   // instead (ported to a scenario test perhaps?).
2177*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::Current()->ProcessMessages(5000);
2178*d9f75844SAndroid Build Coastguard Worker 
2179*d9f75844SAndroid Build Coastguard Worker   // New bitrate should be reconfigured above the previous max. As there's no
2180*d9f75844SAndroid Build Coastguard Worker   // network connection this shouldn't be flaky, as no bitrate should've been
2181*d9f75844SAndroid Build Coastguard Worker   // reported in between.
2182*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(encoder.WaitForStartBitrate());
2183*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(bitrate_config.start_bitrate_bps / 1000,
2184*d9f75844SAndroid Build Coastguard Worker             encoder.GetStartBitrateKbps());
2185*d9f75844SAndroid Build Coastguard Worker 
2186*d9f75844SAndroid Build Coastguard Worker   DestroyStreams();
2187*d9f75844SAndroid Build Coastguard Worker }
2188*d9f75844SAndroid Build Coastguard Worker 
2189*d9f75844SAndroid Build Coastguard Worker class StartStopBitrateObserver : public test::FakeEncoder {
2190*d9f75844SAndroid Build Coastguard Worker  public:
StartStopBitrateObserver()2191*d9f75844SAndroid Build Coastguard Worker   StartStopBitrateObserver() : FakeEncoder(Clock::GetRealTimeClock()) {}
InitEncode(const VideoCodec * config,const Settings & settings)2192*d9f75844SAndroid Build Coastguard Worker   int32_t InitEncode(const VideoCodec* config,
2193*d9f75844SAndroid Build Coastguard Worker                      const Settings& settings) override {
2194*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&mutex_);
2195*d9f75844SAndroid Build Coastguard Worker     encoder_init_.Set();
2196*d9f75844SAndroid Build Coastguard Worker     return FakeEncoder::InitEncode(config, settings);
2197*d9f75844SAndroid Build Coastguard Worker   }
2198*d9f75844SAndroid Build Coastguard Worker 
SetRates(const RateControlParameters & parameters)2199*d9f75844SAndroid Build Coastguard Worker   void SetRates(const RateControlParameters& parameters) override {
2200*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&mutex_);
2201*d9f75844SAndroid Build Coastguard Worker     bitrate_kbps_ = parameters.bitrate.get_sum_kbps();
2202*d9f75844SAndroid Build Coastguard Worker     bitrate_changed_.Set();
2203*d9f75844SAndroid Build Coastguard Worker     FakeEncoder::SetRates(parameters);
2204*d9f75844SAndroid Build Coastguard Worker   }
2205*d9f75844SAndroid Build Coastguard Worker 
WaitForEncoderInit()2206*d9f75844SAndroid Build Coastguard Worker   bool WaitForEncoderInit() {
2207*d9f75844SAndroid Build Coastguard Worker     return encoder_init_.Wait(VideoSendStreamTest::kDefaultTimeout);
2208*d9f75844SAndroid Build Coastguard Worker   }
2209*d9f75844SAndroid Build Coastguard Worker 
WaitBitrateChanged(WaitUntil until)2210*d9f75844SAndroid Build Coastguard Worker   bool WaitBitrateChanged(WaitUntil until) {
2211*d9f75844SAndroid Build Coastguard Worker     do {
2212*d9f75844SAndroid Build Coastguard Worker       absl::optional<int> bitrate_kbps;
2213*d9f75844SAndroid Build Coastguard Worker       {
2214*d9f75844SAndroid Build Coastguard Worker         MutexLock lock(&mutex_);
2215*d9f75844SAndroid Build Coastguard Worker         bitrate_kbps = bitrate_kbps_;
2216*d9f75844SAndroid Build Coastguard Worker       }
2217*d9f75844SAndroid Build Coastguard Worker       if (!bitrate_kbps)
2218*d9f75844SAndroid Build Coastguard Worker         continue;
2219*d9f75844SAndroid Build Coastguard Worker 
2220*d9f75844SAndroid Build Coastguard Worker       if ((until == WaitUntil::kNonZero && *bitrate_kbps > 0) ||
2221*d9f75844SAndroid Build Coastguard Worker           (until == WaitUntil::kZero && *bitrate_kbps == 0)) {
2222*d9f75844SAndroid Build Coastguard Worker         return true;
2223*d9f75844SAndroid Build Coastguard Worker       }
2224*d9f75844SAndroid Build Coastguard Worker     } while (bitrate_changed_.Wait(VideoSendStreamTest::kDefaultTimeout));
2225*d9f75844SAndroid Build Coastguard Worker     return false;
2226*d9f75844SAndroid Build Coastguard Worker   }
2227*d9f75844SAndroid Build Coastguard Worker 
2228*d9f75844SAndroid Build Coastguard Worker  private:
2229*d9f75844SAndroid Build Coastguard Worker   Mutex mutex_;
2230*d9f75844SAndroid Build Coastguard Worker   rtc::Event encoder_init_;
2231*d9f75844SAndroid Build Coastguard Worker   rtc::Event bitrate_changed_;
2232*d9f75844SAndroid Build Coastguard Worker   absl::optional<int> bitrate_kbps_ RTC_GUARDED_BY(mutex_);
2233*d9f75844SAndroid Build Coastguard Worker };
2234*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,EncoderIsProperlyInitializedAndDestroyed)2235*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
2236*d9f75844SAndroid Build Coastguard Worker   class EncoderStateObserver : public test::SendTest, public VideoEncoder {
2237*d9f75844SAndroid Build Coastguard Worker    public:
2238*d9f75844SAndroid Build Coastguard Worker     explicit EncoderStateObserver(TaskQueueBase* task_queue)
2239*d9f75844SAndroid Build Coastguard Worker         : SendTest(kDefaultTimeout),
2240*d9f75844SAndroid Build Coastguard Worker           task_queue_(task_queue),
2241*d9f75844SAndroid Build Coastguard Worker           stream_(nullptr),
2242*d9f75844SAndroid Build Coastguard Worker           initialized_(false),
2243*d9f75844SAndroid Build Coastguard Worker           callback_registered_(false),
2244*d9f75844SAndroid Build Coastguard Worker           num_releases_(0),
2245*d9f75844SAndroid Build Coastguard Worker           released_(false),
2246*d9f75844SAndroid Build Coastguard Worker           encoder_factory_(this) {}
2247*d9f75844SAndroid Build Coastguard Worker 
2248*d9f75844SAndroid Build Coastguard Worker     bool IsReleased() RTC_LOCKS_EXCLUDED(mutex_) {
2249*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2250*d9f75844SAndroid Build Coastguard Worker       return released_;
2251*d9f75844SAndroid Build Coastguard Worker     }
2252*d9f75844SAndroid Build Coastguard Worker 
2253*d9f75844SAndroid Build Coastguard Worker     bool IsReadyForEncode() RTC_LOCKS_EXCLUDED(mutex_) {
2254*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2255*d9f75844SAndroid Build Coastguard Worker       return IsReadyForEncodeLocked();
2256*d9f75844SAndroid Build Coastguard Worker     }
2257*d9f75844SAndroid Build Coastguard Worker 
2258*d9f75844SAndroid Build Coastguard Worker     size_t num_releases() RTC_LOCKS_EXCLUDED(mutex_) {
2259*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2260*d9f75844SAndroid Build Coastguard Worker       return num_releases_;
2261*d9f75844SAndroid Build Coastguard Worker     }
2262*d9f75844SAndroid Build Coastguard Worker 
2263*d9f75844SAndroid Build Coastguard Worker    private:
2264*d9f75844SAndroid Build Coastguard Worker     bool IsReadyForEncodeLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
2265*d9f75844SAndroid Build Coastguard Worker       return initialized_ && callback_registered_;
2266*d9f75844SAndroid Build Coastguard Worker     }
2267*d9f75844SAndroid Build Coastguard Worker 
2268*d9f75844SAndroid Build Coastguard Worker     void SetFecControllerOverride(
2269*d9f75844SAndroid Build Coastguard Worker         FecControllerOverride* fec_controller_override) override {
2270*d9f75844SAndroid Build Coastguard Worker       // Ignored.
2271*d9f75844SAndroid Build Coastguard Worker     }
2272*d9f75844SAndroid Build Coastguard Worker 
2273*d9f75844SAndroid Build Coastguard Worker     int32_t InitEncode(const VideoCodec* codecSettings,
2274*d9f75844SAndroid Build Coastguard Worker                        const Settings& settings) override
2275*d9f75844SAndroid Build Coastguard Worker         RTC_LOCKS_EXCLUDED(mutex_) {
2276*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2277*d9f75844SAndroid Build Coastguard Worker       EXPECT_FALSE(initialized_);
2278*d9f75844SAndroid Build Coastguard Worker       initialized_ = true;
2279*d9f75844SAndroid Build Coastguard Worker       released_ = false;
2280*d9f75844SAndroid Build Coastguard Worker       return 0;
2281*d9f75844SAndroid Build Coastguard Worker     }
2282*d9f75844SAndroid Build Coastguard Worker 
2283*d9f75844SAndroid Build Coastguard Worker     int32_t Encode(const VideoFrame& inputImage,
2284*d9f75844SAndroid Build Coastguard Worker                    const std::vector<VideoFrameType>* frame_types) override {
2285*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(IsReadyForEncode());
2286*d9f75844SAndroid Build Coastguard Worker 
2287*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
2288*d9f75844SAndroid Build Coastguard Worker       return 0;
2289*d9f75844SAndroid Build Coastguard Worker     }
2290*d9f75844SAndroid Build Coastguard Worker 
2291*d9f75844SAndroid Build Coastguard Worker     int32_t RegisterEncodeCompleteCallback(
2292*d9f75844SAndroid Build Coastguard Worker         EncodedImageCallback* callback) override RTC_LOCKS_EXCLUDED(mutex_) {
2293*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2294*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(initialized_);
2295*d9f75844SAndroid Build Coastguard Worker       callback_registered_ = true;
2296*d9f75844SAndroid Build Coastguard Worker       return 0;
2297*d9f75844SAndroid Build Coastguard Worker     }
2298*d9f75844SAndroid Build Coastguard Worker 
2299*d9f75844SAndroid Build Coastguard Worker     int32_t Release() override RTC_LOCKS_EXCLUDED(mutex_) {
2300*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2301*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(IsReadyForEncodeLocked());
2302*d9f75844SAndroid Build Coastguard Worker       EXPECT_FALSE(released_);
2303*d9f75844SAndroid Build Coastguard Worker       initialized_ = false;
2304*d9f75844SAndroid Build Coastguard Worker       callback_registered_ = false;
2305*d9f75844SAndroid Build Coastguard Worker       released_ = true;
2306*d9f75844SAndroid Build Coastguard Worker       ++num_releases_;
2307*d9f75844SAndroid Build Coastguard Worker       return 0;
2308*d9f75844SAndroid Build Coastguard Worker     }
2309*d9f75844SAndroid Build Coastguard Worker 
2310*d9f75844SAndroid Build Coastguard Worker     void SetRates(const RateControlParameters& parameters) override {
2311*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(IsReadyForEncode());
2312*d9f75844SAndroid Build Coastguard Worker     }
2313*d9f75844SAndroid Build Coastguard Worker 
2314*d9f75844SAndroid Build Coastguard Worker     void OnVideoStreamsCreated(VideoSendStream* send_stream,
2315*d9f75844SAndroid Build Coastguard Worker                                const std::vector<VideoReceiveStreamInterface*>&
2316*d9f75844SAndroid Build Coastguard Worker                                    receive_streams) override {
2317*d9f75844SAndroid Build Coastguard Worker       stream_ = send_stream;
2318*d9f75844SAndroid Build Coastguard Worker     }
2319*d9f75844SAndroid Build Coastguard Worker 
2320*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
2321*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
2322*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
2323*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
2324*d9f75844SAndroid Build Coastguard Worker       send_config->encoder_settings.encoder_factory = &encoder_factory_;
2325*d9f75844SAndroid Build Coastguard Worker       encoder_config_ = encoder_config->Copy();
2326*d9f75844SAndroid Build Coastguard Worker     }
2327*d9f75844SAndroid Build Coastguard Worker 
2328*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
2329*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
2330*d9f75844SAndroid Build Coastguard Worker 
2331*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_, [this]() {
2332*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(0u, num_releases());
2333*d9f75844SAndroid Build Coastguard Worker         stream_->ReconfigureVideoEncoder(std::move(encoder_config_));
2334*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(0u, num_releases());
2335*d9f75844SAndroid Build Coastguard Worker         stream_->Stop();
2336*d9f75844SAndroid Build Coastguard Worker         // Encoder should not be released before destroying the VideoSendStream.
2337*d9f75844SAndroid Build Coastguard Worker         EXPECT_FALSE(IsReleased());
2338*d9f75844SAndroid Build Coastguard Worker         EXPECT_TRUE(IsReadyForEncode());
2339*d9f75844SAndroid Build Coastguard Worker         stream_->Start();
2340*d9f75844SAndroid Build Coastguard Worker       });
2341*d9f75844SAndroid Build Coastguard Worker 
2342*d9f75844SAndroid Build Coastguard Worker       // Sanity check, make sure we still encode frames with this encoder.
2343*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while waiting for Encode.";
2344*d9f75844SAndroid Build Coastguard Worker     }
2345*d9f75844SAndroid Build Coastguard Worker 
2346*d9f75844SAndroid Build Coastguard Worker     TaskQueueBase* const task_queue_;
2347*d9f75844SAndroid Build Coastguard Worker     Mutex mutex_;
2348*d9f75844SAndroid Build Coastguard Worker     VideoSendStream* stream_;
2349*d9f75844SAndroid Build Coastguard Worker     bool initialized_ RTC_GUARDED_BY(mutex_);
2350*d9f75844SAndroid Build Coastguard Worker     bool callback_registered_ RTC_GUARDED_BY(mutex_);
2351*d9f75844SAndroid Build Coastguard Worker     size_t num_releases_ RTC_GUARDED_BY(mutex_);
2352*d9f75844SAndroid Build Coastguard Worker     bool released_ RTC_GUARDED_BY(mutex_);
2353*d9f75844SAndroid Build Coastguard Worker     test::VideoEncoderProxyFactory encoder_factory_;
2354*d9f75844SAndroid Build Coastguard Worker     VideoEncoderConfig encoder_config_;
2355*d9f75844SAndroid Build Coastguard Worker   } test_encoder(task_queue());
2356*d9f75844SAndroid Build Coastguard Worker 
2357*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test_encoder);
2358*d9f75844SAndroid Build Coastguard Worker 
2359*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(test_encoder.IsReleased());
2360*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, test_encoder.num_releases());
2361*d9f75844SAndroid Build Coastguard Worker }
2362*d9f75844SAndroid Build Coastguard Worker 
2363*d9f75844SAndroid Build Coastguard Worker static const size_t kVideoCodecConfigObserverNumberOfTemporalLayers = 3;
2364*d9f75844SAndroid Build Coastguard Worker template <typename T>
2365*d9f75844SAndroid Build Coastguard Worker class VideoCodecConfigObserver : public test::SendTest,
2366*d9f75844SAndroid Build Coastguard Worker                                  public test::FakeEncoder {
2367*d9f75844SAndroid Build Coastguard Worker  public:
VideoCodecConfigObserver(VideoCodecType video_codec_type,TaskQueueBase * task_queue)2368*d9f75844SAndroid Build Coastguard Worker   VideoCodecConfigObserver(VideoCodecType video_codec_type,
2369*d9f75844SAndroid Build Coastguard Worker                            TaskQueueBase* task_queue)
2370*d9f75844SAndroid Build Coastguard Worker       : SendTest(VideoSendStreamTest::kDefaultTimeout),
2371*d9f75844SAndroid Build Coastguard Worker         FakeEncoder(Clock::GetRealTimeClock()),
2372*d9f75844SAndroid Build Coastguard Worker         video_codec_type_(video_codec_type),
2373*d9f75844SAndroid Build Coastguard Worker         stream_(nullptr),
2374*d9f75844SAndroid Build Coastguard Worker         encoder_factory_(this),
2375*d9f75844SAndroid Build Coastguard Worker         task_queue_(task_queue) {
2376*d9f75844SAndroid Build Coastguard Worker     InitCodecSpecifics();
2377*d9f75844SAndroid Build Coastguard Worker   }
2378*d9f75844SAndroid Build Coastguard Worker 
2379*d9f75844SAndroid Build Coastguard Worker  private:
ModifyVideoConfigs(VideoSendStream::Config * send_config,std::vector<VideoReceiveStreamInterface::Config> * receive_configs,VideoEncoderConfig * encoder_config)2380*d9f75844SAndroid Build Coastguard Worker   void ModifyVideoConfigs(
2381*d9f75844SAndroid Build Coastguard Worker       VideoSendStream::Config* send_config,
2382*d9f75844SAndroid Build Coastguard Worker       std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
2383*d9f75844SAndroid Build Coastguard Worker       VideoEncoderConfig* encoder_config) override {
2384*d9f75844SAndroid Build Coastguard Worker     send_config->encoder_settings.encoder_factory = &encoder_factory_;
2385*d9f75844SAndroid Build Coastguard Worker     send_config->rtp.payload_name = CodecTypeToPayloadString(video_codec_type_);
2386*d9f75844SAndroid Build Coastguard Worker 
2387*d9f75844SAndroid Build Coastguard Worker     encoder_config->codec_type = video_codec_type_;
2388*d9f75844SAndroid Build Coastguard Worker     encoder_config->encoder_specific_settings = GetEncoderSpecificSettings();
2389*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(1u, encoder_config->simulcast_layers.size());
2390*d9f75844SAndroid Build Coastguard Worker     encoder_config->simulcast_layers[0].num_temporal_layers =
2391*d9f75844SAndroid Build Coastguard Worker         kVideoCodecConfigObserverNumberOfTemporalLayers;
2392*d9f75844SAndroid Build Coastguard Worker     encoder_config_ = encoder_config->Copy();
2393*d9f75844SAndroid Build Coastguard Worker   }
2394*d9f75844SAndroid Build Coastguard Worker 
OnVideoStreamsCreated(VideoSendStream * send_stream,const std::vector<VideoReceiveStreamInterface * > & receive_streams)2395*d9f75844SAndroid Build Coastguard Worker   void OnVideoStreamsCreated(VideoSendStream* send_stream,
2396*d9f75844SAndroid Build Coastguard Worker                              const std::vector<VideoReceiveStreamInterface*>&
2397*d9f75844SAndroid Build Coastguard Worker                                  receive_streams) override {
2398*d9f75844SAndroid Build Coastguard Worker     stream_ = send_stream;
2399*d9f75844SAndroid Build Coastguard Worker   }
2400*d9f75844SAndroid Build Coastguard Worker 
InitEncode(const VideoCodec * config,const Settings & settings)2401*d9f75844SAndroid Build Coastguard Worker   int32_t InitEncode(const VideoCodec* config,
2402*d9f75844SAndroid Build Coastguard Worker                      const Settings& settings) override {
2403*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(video_codec_type_, config->codecType);
2404*d9f75844SAndroid Build Coastguard Worker     VerifyCodecSpecifics(*config);
2405*d9f75844SAndroid Build Coastguard Worker     int ret = FakeEncoder::InitEncode(config, settings);
2406*d9f75844SAndroid Build Coastguard Worker     init_encode_event_.Set();
2407*d9f75844SAndroid Build Coastguard Worker     return ret;
2408*d9f75844SAndroid Build Coastguard Worker   }
2409*d9f75844SAndroid Build Coastguard Worker 
2410*d9f75844SAndroid Build Coastguard Worker   void InitCodecSpecifics();
2411*d9f75844SAndroid Build Coastguard Worker   void VerifyCodecSpecifics(const VideoCodec& config) const;
2412*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
2413*d9f75844SAndroid Build Coastguard Worker   GetEncoderSpecificSettings() const;
2414*d9f75844SAndroid Build Coastguard Worker 
PerformTest()2415*d9f75844SAndroid Build Coastguard Worker   void PerformTest() override {
2416*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeout));
2417*d9f75844SAndroid Build Coastguard Worker     ASSERT_EQ(1, FakeEncoder::GetNumInitializations())
2418*d9f75844SAndroid Build Coastguard Worker         << "VideoEncoder not initialized.";
2419*d9f75844SAndroid Build Coastguard Worker 
2420*d9f75844SAndroid Build Coastguard Worker     // Change encoder settings to actually trigger reconfiguration.
2421*d9f75844SAndroid Build Coastguard Worker     encoder_config_.frame_drop_enabled = !encoder_config_.frame_drop_enabled;
2422*d9f75844SAndroid Build Coastguard Worker     encoder_config_.encoder_specific_settings = GetEncoderSpecificSettings();
2423*d9f75844SAndroid Build Coastguard Worker     SendTask(task_queue_, [&]() {
2424*d9f75844SAndroid Build Coastguard Worker       stream_->ReconfigureVideoEncoder(std::move(encoder_config_));
2425*d9f75844SAndroid Build Coastguard Worker     });
2426*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeout));
2427*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(2, FakeEncoder::GetNumInitializations())
2428*d9f75844SAndroid Build Coastguard Worker         << "ReconfigureVideoEncoder did not reinitialize the encoder with "
2429*d9f75844SAndroid Build Coastguard Worker            "new encoder settings.";
2430*d9f75844SAndroid Build Coastguard Worker   }
2431*d9f75844SAndroid Build Coastguard Worker 
Encode(const VideoFrame & input_image,const std::vector<VideoFrameType> * frame_types)2432*d9f75844SAndroid Build Coastguard Worker   int32_t Encode(const VideoFrame& input_image,
2433*d9f75844SAndroid Build Coastguard Worker                  const std::vector<VideoFrameType>* frame_types) override {
2434*d9f75844SAndroid Build Coastguard Worker     // Silently skip the encode, FakeEncoder::Encode doesn't produce VP8.
2435*d9f75844SAndroid Build Coastguard Worker     return 0;
2436*d9f75844SAndroid Build Coastguard Worker   }
2437*d9f75844SAndroid Build Coastguard Worker 
2438*d9f75844SAndroid Build Coastguard Worker   T encoder_settings_;
2439*d9f75844SAndroid Build Coastguard Worker   const VideoCodecType video_codec_type_;
2440*d9f75844SAndroid Build Coastguard Worker   rtc::Event init_encode_event_;
2441*d9f75844SAndroid Build Coastguard Worker   VideoSendStream* stream_;
2442*d9f75844SAndroid Build Coastguard Worker   test::VideoEncoderProxyFactory encoder_factory_;
2443*d9f75844SAndroid Build Coastguard Worker   VideoEncoderConfig encoder_config_;
2444*d9f75844SAndroid Build Coastguard Worker   TaskQueueBase* task_queue_;
2445*d9f75844SAndroid Build Coastguard Worker };
2446*d9f75844SAndroid Build Coastguard Worker 
2447*d9f75844SAndroid Build Coastguard Worker template <>
InitCodecSpecifics()2448*d9f75844SAndroid Build Coastguard Worker void VideoCodecConfigObserver<VideoCodecH264>::InitCodecSpecifics() {}
2449*d9f75844SAndroid Build Coastguard Worker 
2450*d9f75844SAndroid Build Coastguard Worker template <>
VerifyCodecSpecifics(const VideoCodec & config) const2451*d9f75844SAndroid Build Coastguard Worker void VideoCodecConfigObserver<VideoCodecH264>::VerifyCodecSpecifics(
2452*d9f75844SAndroid Build Coastguard Worker     const VideoCodec& config) const {
2453*d9f75844SAndroid Build Coastguard Worker   // Check that the number of temporal layers has propagated properly to
2454*d9f75844SAndroid Build Coastguard Worker   // VideoCodec.
2455*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
2456*d9f75844SAndroid Build Coastguard Worker             config.H264().numberOfTemporalLayers);
2457*d9f75844SAndroid Build Coastguard Worker 
2458*d9f75844SAndroid Build Coastguard Worker   for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
2459*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
2460*d9f75844SAndroid Build Coastguard Worker               config.simulcastStream[i].numberOfTemporalLayers);
2461*d9f75844SAndroid Build Coastguard Worker   }
2462*d9f75844SAndroid Build Coastguard Worker 
2463*d9f75844SAndroid Build Coastguard Worker   // Set expected temporal layers as they should have been set when
2464*d9f75844SAndroid Build Coastguard Worker   // reconfiguring the encoder and not match the set config.
2465*d9f75844SAndroid Build Coastguard Worker   VideoCodecH264 encoder_settings = VideoEncoder::GetDefaultH264Settings();
2466*d9f75844SAndroid Build Coastguard Worker   encoder_settings.numberOfTemporalLayers =
2467*d9f75844SAndroid Build Coastguard Worker       kVideoCodecConfigObserverNumberOfTemporalLayers;
2468*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(config.H264(), encoder_settings);
2469*d9f75844SAndroid Build Coastguard Worker }
2470*d9f75844SAndroid Build Coastguard Worker 
2471*d9f75844SAndroid Build Coastguard Worker template <>
2472*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
GetEncoderSpecificSettings() const2473*d9f75844SAndroid Build Coastguard Worker VideoCodecConfigObserver<VideoCodecH264>::GetEncoderSpecificSettings() const {
2474*d9f75844SAndroid Build Coastguard Worker   return nullptr;
2475*d9f75844SAndroid Build Coastguard Worker }
2476*d9f75844SAndroid Build Coastguard Worker 
2477*d9f75844SAndroid Build Coastguard Worker template <>
InitCodecSpecifics()2478*d9f75844SAndroid Build Coastguard Worker void VideoCodecConfigObserver<VideoCodecVP8>::InitCodecSpecifics() {
2479*d9f75844SAndroid Build Coastguard Worker   encoder_settings_ = VideoEncoder::GetDefaultVp8Settings();
2480*d9f75844SAndroid Build Coastguard Worker }
2481*d9f75844SAndroid Build Coastguard Worker 
2482*d9f75844SAndroid Build Coastguard Worker template <>
VerifyCodecSpecifics(const VideoCodec & config) const2483*d9f75844SAndroid Build Coastguard Worker void VideoCodecConfigObserver<VideoCodecVP8>::VerifyCodecSpecifics(
2484*d9f75844SAndroid Build Coastguard Worker     const VideoCodec& config) const {
2485*d9f75844SAndroid Build Coastguard Worker   // Check that the number of temporal layers has propagated properly to
2486*d9f75844SAndroid Build Coastguard Worker   // VideoCodec.
2487*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
2488*d9f75844SAndroid Build Coastguard Worker             config.VP8().numberOfTemporalLayers);
2489*d9f75844SAndroid Build Coastguard Worker 
2490*d9f75844SAndroid Build Coastguard Worker   for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
2491*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
2492*d9f75844SAndroid Build Coastguard Worker               config.simulcastStream[i].numberOfTemporalLayers);
2493*d9f75844SAndroid Build Coastguard Worker   }
2494*d9f75844SAndroid Build Coastguard Worker 
2495*d9f75844SAndroid Build Coastguard Worker   // Set expected temporal layers as they should have been set when
2496*d9f75844SAndroid Build Coastguard Worker   // reconfiguring the encoder and not match the set config.
2497*d9f75844SAndroid Build Coastguard Worker   VideoCodecVP8 encoder_settings = encoder_settings_;
2498*d9f75844SAndroid Build Coastguard Worker   encoder_settings.numberOfTemporalLayers =
2499*d9f75844SAndroid Build Coastguard Worker       kVideoCodecConfigObserverNumberOfTemporalLayers;
2500*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(
2501*d9f75844SAndroid Build Coastguard Worker       0, memcmp(&config.VP8(), &encoder_settings, sizeof(encoder_settings_)));
2502*d9f75844SAndroid Build Coastguard Worker }
2503*d9f75844SAndroid Build Coastguard Worker 
2504*d9f75844SAndroid Build Coastguard Worker template <>
2505*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
GetEncoderSpecificSettings() const2506*d9f75844SAndroid Build Coastguard Worker VideoCodecConfigObserver<VideoCodecVP8>::GetEncoderSpecificSettings() const {
2507*d9f75844SAndroid Build Coastguard Worker   return rtc::make_ref_counted<VideoEncoderConfig::Vp8EncoderSpecificSettings>(
2508*d9f75844SAndroid Build Coastguard Worker       encoder_settings_);
2509*d9f75844SAndroid Build Coastguard Worker }
2510*d9f75844SAndroid Build Coastguard Worker 
2511*d9f75844SAndroid Build Coastguard Worker template <>
InitCodecSpecifics()2512*d9f75844SAndroid Build Coastguard Worker void VideoCodecConfigObserver<VideoCodecVP9>::InitCodecSpecifics() {
2513*d9f75844SAndroid Build Coastguard Worker   encoder_settings_ = VideoEncoder::GetDefaultVp9Settings();
2514*d9f75844SAndroid Build Coastguard Worker }
2515*d9f75844SAndroid Build Coastguard Worker 
2516*d9f75844SAndroid Build Coastguard Worker template <>
VerifyCodecSpecifics(const VideoCodec & config) const2517*d9f75844SAndroid Build Coastguard Worker void VideoCodecConfigObserver<VideoCodecVP9>::VerifyCodecSpecifics(
2518*d9f75844SAndroid Build Coastguard Worker     const VideoCodec& config) const {
2519*d9f75844SAndroid Build Coastguard Worker   // Check that the number of temporal layers has propagated properly to
2520*d9f75844SAndroid Build Coastguard Worker   // VideoCodec.
2521*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
2522*d9f75844SAndroid Build Coastguard Worker             config.VP9().numberOfTemporalLayers);
2523*d9f75844SAndroid Build Coastguard Worker 
2524*d9f75844SAndroid Build Coastguard Worker   for (unsigned char i = 0; i < config.numberOfSimulcastStreams; ++i) {
2525*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(kVideoCodecConfigObserverNumberOfTemporalLayers,
2526*d9f75844SAndroid Build Coastguard Worker               config.simulcastStream[i].numberOfTemporalLayers);
2527*d9f75844SAndroid Build Coastguard Worker   }
2528*d9f75844SAndroid Build Coastguard Worker 
2529*d9f75844SAndroid Build Coastguard Worker   // Set expected temporal layers as they should have been set when
2530*d9f75844SAndroid Build Coastguard Worker   // reconfiguring the encoder and not match the set config.
2531*d9f75844SAndroid Build Coastguard Worker   VideoCodecVP9 encoder_settings = encoder_settings_;
2532*d9f75844SAndroid Build Coastguard Worker   encoder_settings.numberOfTemporalLayers =
2533*d9f75844SAndroid Build Coastguard Worker       kVideoCodecConfigObserverNumberOfTemporalLayers;
2534*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(
2535*d9f75844SAndroid Build Coastguard Worker       0, memcmp(&(config.VP9()), &encoder_settings, sizeof(encoder_settings_)));
2536*d9f75844SAndroid Build Coastguard Worker }
2537*d9f75844SAndroid Build Coastguard Worker 
2538*d9f75844SAndroid Build Coastguard Worker template <>
2539*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<VideoEncoderConfig::EncoderSpecificSettings>
GetEncoderSpecificSettings() const2540*d9f75844SAndroid Build Coastguard Worker VideoCodecConfigObserver<VideoCodecVP9>::GetEncoderSpecificSettings() const {
2541*d9f75844SAndroid Build Coastguard Worker   return rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
2542*d9f75844SAndroid Build Coastguard Worker       encoder_settings_);
2543*d9f75844SAndroid Build Coastguard Worker }
2544*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,EncoderSetupPropagatesVp8Config)2545*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp8Config) {
2546*d9f75844SAndroid Build Coastguard Worker   VideoCodecConfigObserver<VideoCodecVP8> test(kVideoCodecVP8, task_queue());
2547*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
2548*d9f75844SAndroid Build Coastguard Worker }
2549*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,EncoderSetupPropagatesVp9Config)2550*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, EncoderSetupPropagatesVp9Config) {
2551*d9f75844SAndroid Build Coastguard Worker   VideoCodecConfigObserver<VideoCodecVP9> test(kVideoCodecVP9, task_queue());
2552*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
2553*d9f75844SAndroid Build Coastguard Worker }
2554*d9f75844SAndroid Build Coastguard Worker 
2555*d9f75844SAndroid Build Coastguard Worker // Fails on MSAN: https://bugs.chromium.org/p/webrtc/issues/detail?id=11376.
2556*d9f75844SAndroid Build Coastguard Worker #if defined(MEMORY_SANITIZER)
2557*d9f75844SAndroid Build Coastguard Worker #define MAYBE_EncoderSetupPropagatesH264Config \
2558*d9f75844SAndroid Build Coastguard Worker   DISABLED_EncoderSetupPropagatesH264Config
2559*d9f75844SAndroid Build Coastguard Worker #else
2560*d9f75844SAndroid Build Coastguard Worker #define MAYBE_EncoderSetupPropagatesH264Config EncoderSetupPropagatesH264Config
2561*d9f75844SAndroid Build Coastguard Worker #endif
TEST_F(VideoSendStreamTest,MAYBE_EncoderSetupPropagatesH264Config)2562*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, MAYBE_EncoderSetupPropagatesH264Config) {
2563*d9f75844SAndroid Build Coastguard Worker   VideoCodecConfigObserver<VideoCodecH264> test(kVideoCodecH264, task_queue());
2564*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
2565*d9f75844SAndroid Build Coastguard Worker }
2566*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,RtcpSenderReportContainsMediaBytesSent)2567*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, RtcpSenderReportContainsMediaBytesSent) {
2568*d9f75844SAndroid Build Coastguard Worker   class RtcpSenderReportTest : public test::SendTest {
2569*d9f75844SAndroid Build Coastguard Worker    public:
2570*d9f75844SAndroid Build Coastguard Worker     RtcpSenderReportTest()
2571*d9f75844SAndroid Build Coastguard Worker         : SendTest(kDefaultTimeout),
2572*d9f75844SAndroid Build Coastguard Worker           rtp_packets_sent_(0),
2573*d9f75844SAndroid Build Coastguard Worker           media_bytes_sent_(0) {}
2574*d9f75844SAndroid Build Coastguard Worker 
2575*d9f75844SAndroid Build Coastguard Worker    private:
2576*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
2577*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2578*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet;
2579*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.Parse(packet, length));
2580*d9f75844SAndroid Build Coastguard Worker       ++rtp_packets_sent_;
2581*d9f75844SAndroid Build Coastguard Worker       media_bytes_sent_ += rtp_packet.payload_size();
2582*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
2583*d9f75844SAndroid Build Coastguard Worker     }
2584*d9f75844SAndroid Build Coastguard Worker 
2585*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtcp(const uint8_t* packet, size_t length) override {
2586*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2587*d9f75844SAndroid Build Coastguard Worker       test::RtcpPacketParser parser;
2588*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(parser.Parse(packet, length));
2589*d9f75844SAndroid Build Coastguard Worker 
2590*d9f75844SAndroid Build Coastguard Worker       if (parser.sender_report()->num_packets() > 0) {
2591*d9f75844SAndroid Build Coastguard Worker         // Only compare sent media bytes if SenderPacketCount matches the
2592*d9f75844SAndroid Build Coastguard Worker         // number of sent rtp packets (a new rtp packet could be sent before
2593*d9f75844SAndroid Build Coastguard Worker         // the rtcp packet).
2594*d9f75844SAndroid Build Coastguard Worker         if (parser.sender_report()->sender_octet_count() > 0 &&
2595*d9f75844SAndroid Build Coastguard Worker             parser.sender_report()->sender_packet_count() ==
2596*d9f75844SAndroid Build Coastguard Worker                 rtp_packets_sent_) {
2597*d9f75844SAndroid Build Coastguard Worker           EXPECT_EQ(media_bytes_sent_,
2598*d9f75844SAndroid Build Coastguard Worker                     parser.sender_report()->sender_octet_count());
2599*d9f75844SAndroid Build Coastguard Worker           observation_complete_.Set();
2600*d9f75844SAndroid Build Coastguard Worker         }
2601*d9f75844SAndroid Build Coastguard Worker       }
2602*d9f75844SAndroid Build Coastguard Worker 
2603*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
2604*d9f75844SAndroid Build Coastguard Worker     }
2605*d9f75844SAndroid Build Coastguard Worker 
2606*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
2607*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while waiting for RTCP sender report.";
2608*d9f75844SAndroid Build Coastguard Worker     }
2609*d9f75844SAndroid Build Coastguard Worker 
2610*d9f75844SAndroid Build Coastguard Worker     Mutex mutex_;
2611*d9f75844SAndroid Build Coastguard Worker     size_t rtp_packets_sent_ RTC_GUARDED_BY(&mutex_);
2612*d9f75844SAndroid Build Coastguard Worker     size_t media_bytes_sent_ RTC_GUARDED_BY(&mutex_);
2613*d9f75844SAndroid Build Coastguard Worker   } test;
2614*d9f75844SAndroid Build Coastguard Worker 
2615*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
2616*d9f75844SAndroid Build Coastguard Worker }
2617*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,TranslatesTwoLayerScreencastToTargetBitrate)2618*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
2619*d9f75844SAndroid Build Coastguard Worker   static const int kScreencastMaxTargetBitrateDeltaKbps = 1;
2620*d9f75844SAndroid Build Coastguard Worker 
2621*d9f75844SAndroid Build Coastguard Worker   class VideoStreamFactory
2622*d9f75844SAndroid Build Coastguard Worker       : public VideoEncoderConfig::VideoStreamFactoryInterface {
2623*d9f75844SAndroid Build Coastguard Worker    public:
2624*d9f75844SAndroid Build Coastguard Worker     VideoStreamFactory() {}
2625*d9f75844SAndroid Build Coastguard Worker 
2626*d9f75844SAndroid Build Coastguard Worker    private:
2627*d9f75844SAndroid Build Coastguard Worker     std::vector<VideoStream> CreateEncoderStreams(
2628*d9f75844SAndroid Build Coastguard Worker         int frame_width,
2629*d9f75844SAndroid Build Coastguard Worker         int frame_height,
2630*d9f75844SAndroid Build Coastguard Worker         const VideoEncoderConfig& encoder_config) override {
2631*d9f75844SAndroid Build Coastguard Worker       std::vector<VideoStream> streams =
2632*d9f75844SAndroid Build Coastguard Worker           test::CreateVideoStreams(frame_width, frame_height, encoder_config);
2633*d9f75844SAndroid Build Coastguard Worker       RTC_CHECK_GT(streams[0].max_bitrate_bps,
2634*d9f75844SAndroid Build Coastguard Worker                    kScreencastMaxTargetBitrateDeltaKbps);
2635*d9f75844SAndroid Build Coastguard Worker       streams[0].target_bitrate_bps =
2636*d9f75844SAndroid Build Coastguard Worker           streams[0].max_bitrate_bps -
2637*d9f75844SAndroid Build Coastguard Worker           kScreencastMaxTargetBitrateDeltaKbps * 1000;
2638*d9f75844SAndroid Build Coastguard Worker       return streams;
2639*d9f75844SAndroid Build Coastguard Worker     }
2640*d9f75844SAndroid Build Coastguard Worker   };
2641*d9f75844SAndroid Build Coastguard Worker 
2642*d9f75844SAndroid Build Coastguard Worker   class ScreencastTargetBitrateTest : public test::SendTest,
2643*d9f75844SAndroid Build Coastguard Worker                                       public test::FakeEncoder {
2644*d9f75844SAndroid Build Coastguard Worker    public:
2645*d9f75844SAndroid Build Coastguard Worker     ScreencastTargetBitrateTest()
2646*d9f75844SAndroid Build Coastguard Worker         : SendTest(kDefaultTimeout),
2647*d9f75844SAndroid Build Coastguard Worker           test::FakeEncoder(Clock::GetRealTimeClock()),
2648*d9f75844SAndroid Build Coastguard Worker           encoder_factory_(this) {}
2649*d9f75844SAndroid Build Coastguard Worker 
2650*d9f75844SAndroid Build Coastguard Worker    private:
2651*d9f75844SAndroid Build Coastguard Worker     int32_t InitEncode(const VideoCodec* config,
2652*d9f75844SAndroid Build Coastguard Worker                        const Settings& settings) override {
2653*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(config->numberOfSimulcastStreams, 1);
2654*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(static_cast<unsigned int>(kScreencastMaxTargetBitrateDeltaKbps),
2655*d9f75844SAndroid Build Coastguard Worker                 config->simulcastStream[0].maxBitrate -
2656*d9f75844SAndroid Build Coastguard Worker                     config->simulcastStream[0].targetBitrate);
2657*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
2658*d9f75844SAndroid Build Coastguard Worker       return test::FakeEncoder::InitEncode(config, settings);
2659*d9f75844SAndroid Build Coastguard Worker     }
2660*d9f75844SAndroid Build Coastguard Worker 
2661*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
2662*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
2663*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
2664*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
2665*d9f75844SAndroid Build Coastguard Worker       send_config->encoder_settings.encoder_factory = &encoder_factory_;
2666*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(1u, encoder_config->number_of_streams);
2667*d9f75844SAndroid Build Coastguard Worker       encoder_config->video_stream_factory =
2668*d9f75844SAndroid Build Coastguard Worker           rtc::make_ref_counted<VideoStreamFactory>();
2669*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(1u, encoder_config->simulcast_layers.size());
2670*d9f75844SAndroid Build Coastguard Worker       encoder_config->simulcast_layers[0].num_temporal_layers = 2;
2671*d9f75844SAndroid Build Coastguard Worker       encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
2672*d9f75844SAndroid Build Coastguard Worker     }
2673*d9f75844SAndroid Build Coastguard Worker 
2674*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
2675*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait())
2676*d9f75844SAndroid Build Coastguard Worker           << "Timed out while waiting for the encoder to be initialized.";
2677*d9f75844SAndroid Build Coastguard Worker     }
2678*d9f75844SAndroid Build Coastguard Worker     test::VideoEncoderProxyFactory encoder_factory_;
2679*d9f75844SAndroid Build Coastguard Worker   } test;
2680*d9f75844SAndroid Build Coastguard Worker 
2681*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
2682*d9f75844SAndroid Build Coastguard Worker }
2683*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,ReconfigureBitratesSetsEncoderBitratesCorrectly)2684*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) {
2685*d9f75844SAndroid Build Coastguard Worker   // These are chosen to be "kind of odd" to not be accidentally checked against
2686*d9f75844SAndroid Build Coastguard Worker   // default values.
2687*d9f75844SAndroid Build Coastguard Worker   static const int kMinBitrateKbps = 137;
2688*d9f75844SAndroid Build Coastguard Worker   static const int kStartBitrateKbps = 345;
2689*d9f75844SAndroid Build Coastguard Worker   static const int kLowerMaxBitrateKbps = 312;
2690*d9f75844SAndroid Build Coastguard Worker   static const int kMaxBitrateKbps = 413;
2691*d9f75844SAndroid Build Coastguard Worker   static const int kIncreasedStartBitrateKbps = 451;
2692*d9f75844SAndroid Build Coastguard Worker   static const int kIncreasedMaxBitrateKbps = 597;
2693*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/12058): If these fields trial are on, we get lower
2694*d9f75844SAndroid Build Coastguard Worker   // bitrates than expected by this test, due to encoder pushback and subtracted
2695*d9f75844SAndroid Build Coastguard Worker   // overhead.
2696*d9f75844SAndroid Build Coastguard Worker   webrtc::test::ScopedKeyValueConfig field_trials(
2697*d9f75844SAndroid Build Coastguard Worker       field_trials_, "WebRTC-VideoRateControl/bitrate_adjuster:false/");
2698*d9f75844SAndroid Build Coastguard Worker 
2699*d9f75844SAndroid Build Coastguard Worker   class EncoderBitrateThresholdObserver : public test::SendTest,
2700*d9f75844SAndroid Build Coastguard Worker                                           public VideoBitrateAllocatorFactory,
2701*d9f75844SAndroid Build Coastguard Worker                                           public test::FakeEncoder {
2702*d9f75844SAndroid Build Coastguard Worker    public:
2703*d9f75844SAndroid Build Coastguard Worker     explicit EncoderBitrateThresholdObserver(TaskQueueBase* task_queue)
2704*d9f75844SAndroid Build Coastguard Worker         : SendTest(kDefaultTimeout),
2705*d9f75844SAndroid Build Coastguard Worker           FakeEncoder(Clock::GetRealTimeClock()),
2706*d9f75844SAndroid Build Coastguard Worker           task_queue_(task_queue),
2707*d9f75844SAndroid Build Coastguard Worker           target_bitrate_(0),
2708*d9f75844SAndroid Build Coastguard Worker           num_rate_allocator_creations_(0),
2709*d9f75844SAndroid Build Coastguard Worker           num_encoder_initializations_(0),
2710*d9f75844SAndroid Build Coastguard Worker           call_(nullptr),
2711*d9f75844SAndroid Build Coastguard Worker           send_stream_(nullptr),
2712*d9f75844SAndroid Build Coastguard Worker           encoder_factory_(this),
2713*d9f75844SAndroid Build Coastguard Worker           bitrate_allocator_factory_(
2714*d9f75844SAndroid Build Coastguard Worker               CreateBuiltinVideoBitrateAllocatorFactory()) {}
2715*d9f75844SAndroid Build Coastguard Worker 
2716*d9f75844SAndroid Build Coastguard Worker    private:
2717*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<VideoBitrateAllocator> CreateVideoBitrateAllocator(
2718*d9f75844SAndroid Build Coastguard Worker         const VideoCodec& codec) override {
2719*d9f75844SAndroid Build Coastguard Worker       EXPECT_GE(codec.startBitrate, codec.minBitrate);
2720*d9f75844SAndroid Build Coastguard Worker       EXPECT_LE(codec.startBitrate, codec.maxBitrate);
2721*d9f75844SAndroid Build Coastguard Worker       if (num_rate_allocator_creations_ == 0) {
2722*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(static_cast<unsigned int>(kMinBitrateKbps), codec.minBitrate);
2723*d9f75844SAndroid Build Coastguard Worker         EXPECT_NEAR(static_cast<unsigned int>(kStartBitrateKbps),
2724*d9f75844SAndroid Build Coastguard Worker                     codec.startBitrate, 10);
2725*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(static_cast<unsigned int>(kMaxBitrateKbps), codec.maxBitrate);
2726*d9f75844SAndroid Build Coastguard Worker       } else if (num_rate_allocator_creations_ == 1) {
2727*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(static_cast<unsigned int>(kLowerMaxBitrateKbps),
2728*d9f75844SAndroid Build Coastguard Worker                   codec.maxBitrate);
2729*d9f75844SAndroid Build Coastguard Worker         // The start bitrate should be kept (-1) and capped to the max bitrate.
2730*d9f75844SAndroid Build Coastguard Worker         // Since this is not an end-to-end call no receiver should have been
2731*d9f75844SAndroid Build Coastguard Worker         // returning a REMB that could lower this estimate.
2732*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(codec.startBitrate, codec.maxBitrate);
2733*d9f75844SAndroid Build Coastguard Worker       } else if (num_rate_allocator_creations_ == 2) {
2734*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(static_cast<unsigned int>(kIncreasedMaxBitrateKbps),
2735*d9f75844SAndroid Build Coastguard Worker                   codec.maxBitrate);
2736*d9f75844SAndroid Build Coastguard Worker         // The start bitrate will be whatever the rate BitRateController has
2737*d9f75844SAndroid Build Coastguard Worker         // currently configured but in the span of the set max and min bitrate.
2738*d9f75844SAndroid Build Coastguard Worker       }
2739*d9f75844SAndroid Build Coastguard Worker       ++num_rate_allocator_creations_;
2740*d9f75844SAndroid Build Coastguard Worker       create_rate_allocator_event_.Set();
2741*d9f75844SAndroid Build Coastguard Worker 
2742*d9f75844SAndroid Build Coastguard Worker       return bitrate_allocator_factory_->CreateVideoBitrateAllocator(codec);
2743*d9f75844SAndroid Build Coastguard Worker     }
2744*d9f75844SAndroid Build Coastguard Worker 
2745*d9f75844SAndroid Build Coastguard Worker     int32_t InitEncode(const VideoCodec* codecSettings,
2746*d9f75844SAndroid Build Coastguard Worker                        const Settings& settings) override {
2747*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(0, num_encoder_initializations_);
2748*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(static_cast<unsigned int>(kMinBitrateKbps),
2749*d9f75844SAndroid Build Coastguard Worker                 codecSettings->minBitrate);
2750*d9f75844SAndroid Build Coastguard Worker       EXPECT_NEAR(static_cast<unsigned int>(kStartBitrateKbps),
2751*d9f75844SAndroid Build Coastguard Worker                   codecSettings->startBitrate, 10);
2752*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(static_cast<unsigned int>(kMaxBitrateKbps),
2753*d9f75844SAndroid Build Coastguard Worker                 codecSettings->maxBitrate);
2754*d9f75844SAndroid Build Coastguard Worker 
2755*d9f75844SAndroid Build Coastguard Worker       ++num_encoder_initializations_;
2756*d9f75844SAndroid Build Coastguard Worker 
2757*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
2758*d9f75844SAndroid Build Coastguard Worker       init_encode_event_.Set();
2759*d9f75844SAndroid Build Coastguard Worker 
2760*d9f75844SAndroid Build Coastguard Worker       return FakeEncoder::InitEncode(codecSettings, settings);
2761*d9f75844SAndroid Build Coastguard Worker     }
2762*d9f75844SAndroid Build Coastguard Worker 
2763*d9f75844SAndroid Build Coastguard Worker     void SetRates(const RateControlParameters& parameters) override {
2764*d9f75844SAndroid Build Coastguard Worker       {
2765*d9f75844SAndroid Build Coastguard Worker         MutexLock lock(&mutex_);
2766*d9f75844SAndroid Build Coastguard Worker         if (target_bitrate_ == parameters.bitrate.get_sum_kbps()) {
2767*d9f75844SAndroid Build Coastguard Worker           FakeEncoder::SetRates(parameters);
2768*d9f75844SAndroid Build Coastguard Worker           return;
2769*d9f75844SAndroid Build Coastguard Worker         }
2770*d9f75844SAndroid Build Coastguard Worker         target_bitrate_ = parameters.bitrate.get_sum_kbps();
2771*d9f75844SAndroid Build Coastguard Worker       }
2772*d9f75844SAndroid Build Coastguard Worker       bitrate_changed_event_.Set();
2773*d9f75844SAndroid Build Coastguard Worker       FakeEncoder::SetRates(parameters);
2774*d9f75844SAndroid Build Coastguard Worker     }
2775*d9f75844SAndroid Build Coastguard Worker 
2776*d9f75844SAndroid Build Coastguard Worker     void WaitForSetRates(uint32_t expected_bitrate, int abs_error) {
2777*d9f75844SAndroid Build Coastguard Worker       // Wait for the expected rate to be set. In some cases there can be
2778*d9f75844SAndroid Build Coastguard Worker       // more than one update pending, in which case we keep waiting
2779*d9f75844SAndroid Build Coastguard Worker       // until the correct value has been observed.
2780*d9f75844SAndroid Build Coastguard Worker       // The target_bitrate_ is reduced by the calculated packet overhead.
2781*d9f75844SAndroid Build Coastguard Worker       const int64_t start_time = rtc::TimeMillis();
2782*d9f75844SAndroid Build Coastguard Worker       do {
2783*d9f75844SAndroid Build Coastguard Worker         MutexLock lock(&mutex_);
2784*d9f75844SAndroid Build Coastguard Worker 
2785*d9f75844SAndroid Build Coastguard Worker         int error = target_bitrate_ - expected_bitrate;
2786*d9f75844SAndroid Build Coastguard Worker         if ((error < 0 && error >= -abs_error) ||
2787*d9f75844SAndroid Build Coastguard Worker             (error >= 0 && error <= abs_error)) {
2788*d9f75844SAndroid Build Coastguard Worker           return;
2789*d9f75844SAndroid Build Coastguard Worker         }
2790*d9f75844SAndroid Build Coastguard Worker       } while (bitrate_changed_event_.Wait(
2791*d9f75844SAndroid Build Coastguard Worker           std::max(TimeDelta::Millis(1),
2792*d9f75844SAndroid Build Coastguard Worker                    VideoSendStreamTest::kDefaultTimeout -
2793*d9f75844SAndroid Build Coastguard Worker                        TimeDelta::Millis(rtc::TimeMillis() - start_time))));
2794*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
2795*d9f75844SAndroid Build Coastguard Worker       EXPECT_NEAR(target_bitrate_, expected_bitrate, abs_error)
2796*d9f75844SAndroid Build Coastguard Worker           << "Timed out while waiting encoder rate to be set.";
2797*d9f75844SAndroid Build Coastguard Worker     }
2798*d9f75844SAndroid Build Coastguard Worker 
2799*d9f75844SAndroid Build Coastguard Worker     void ModifySenderBitrateConfig(
2800*d9f75844SAndroid Build Coastguard Worker         BitrateConstraints* bitrate_config) override {
2801*d9f75844SAndroid Build Coastguard Worker       bitrate_config->min_bitrate_bps = kMinBitrateKbps * 1000;
2802*d9f75844SAndroid Build Coastguard Worker       bitrate_config->start_bitrate_bps = kStartBitrateKbps * 1000;
2803*d9f75844SAndroid Build Coastguard Worker       bitrate_config->max_bitrate_bps = kMaxBitrateKbps * 1000;
2804*d9f75844SAndroid Build Coastguard Worker     }
2805*d9f75844SAndroid Build Coastguard Worker 
2806*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
2807*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
2808*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
2809*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
2810*d9f75844SAndroid Build Coastguard Worker       send_config->encoder_settings.encoder_factory = &encoder_factory_;
2811*d9f75844SAndroid Build Coastguard Worker       send_config->encoder_settings.bitrate_allocator_factory = this;
2812*d9f75844SAndroid Build Coastguard Worker       // Set bitrates lower/higher than min/max to make sure they are properly
2813*d9f75844SAndroid Build Coastguard Worker       // capped.
2814*d9f75844SAndroid Build Coastguard Worker       encoder_config->max_bitrate_bps = kMaxBitrateKbps * 1000;
2815*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(1u, encoder_config->simulcast_layers.size());
2816*d9f75844SAndroid Build Coastguard Worker       encoder_config->simulcast_layers[0].min_bitrate_bps =
2817*d9f75844SAndroid Build Coastguard Worker           kMinBitrateKbps * 1000;
2818*d9f75844SAndroid Build Coastguard Worker       encoder_config_ = encoder_config->Copy();
2819*d9f75844SAndroid Build Coastguard Worker     }
2820*d9f75844SAndroid Build Coastguard Worker 
2821*d9f75844SAndroid Build Coastguard Worker     void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
2822*d9f75844SAndroid Build Coastguard Worker       call_ = sender_call;
2823*d9f75844SAndroid Build Coastguard Worker     }
2824*d9f75844SAndroid Build Coastguard Worker 
2825*d9f75844SAndroid Build Coastguard Worker     void OnVideoStreamsCreated(VideoSendStream* send_stream,
2826*d9f75844SAndroid Build Coastguard Worker                                const std::vector<VideoReceiveStreamInterface*>&
2827*d9f75844SAndroid Build Coastguard Worker                                    receive_streams) override {
2828*d9f75844SAndroid Build Coastguard Worker       send_stream_ = send_stream;
2829*d9f75844SAndroid Build Coastguard Worker     }
2830*d9f75844SAndroid Build Coastguard Worker 
2831*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
2832*d9f75844SAndroid Build Coastguard Worker       ASSERT_TRUE(create_rate_allocator_event_.Wait(
2833*d9f75844SAndroid Build Coastguard Worker           VideoSendStreamTest::kDefaultTimeout))
2834*d9f75844SAndroid Build Coastguard Worker           << "Timed out while waiting for rate allocator to be created.";
2835*d9f75844SAndroid Build Coastguard Worker       ASSERT_TRUE(init_encode_event_.Wait(VideoSendStreamTest::kDefaultTimeout))
2836*d9f75844SAndroid Build Coastguard Worker           << "Timed out while waiting for encoder to be configured.";
2837*d9f75844SAndroid Build Coastguard Worker       WaitForSetRates(kStartBitrateKbps, 80);
2838*d9f75844SAndroid Build Coastguard Worker       BitrateConstraints bitrate_config;
2839*d9f75844SAndroid Build Coastguard Worker       bitrate_config.start_bitrate_bps = kIncreasedStartBitrateKbps * 1000;
2840*d9f75844SAndroid Build Coastguard Worker       bitrate_config.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000;
2841*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_, [this, &bitrate_config]() {
2842*d9f75844SAndroid Build Coastguard Worker         call_->GetTransportControllerSend()->SetSdpBitrateParameters(
2843*d9f75844SAndroid Build Coastguard Worker             bitrate_config);
2844*d9f75844SAndroid Build Coastguard Worker       });
2845*d9f75844SAndroid Build Coastguard Worker       // Encoder rate is capped by EncoderConfig max_bitrate_bps.
2846*d9f75844SAndroid Build Coastguard Worker       WaitForSetRates(kMaxBitrateKbps, 10);
2847*d9f75844SAndroid Build Coastguard Worker       encoder_config_.max_bitrate_bps = kLowerMaxBitrateKbps * 1000;
2848*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_, [&]() {
2849*d9f75844SAndroid Build Coastguard Worker         send_stream_->ReconfigureVideoEncoder(encoder_config_.Copy());
2850*d9f75844SAndroid Build Coastguard Worker       });
2851*d9f75844SAndroid Build Coastguard Worker       ASSERT_TRUE(create_rate_allocator_event_.Wait(
2852*d9f75844SAndroid Build Coastguard Worker           VideoSendStreamTest::kDefaultTimeout));
2853*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(2, num_rate_allocator_creations_)
2854*d9f75844SAndroid Build Coastguard Worker           << "Rate allocator should have been recreated.";
2855*d9f75844SAndroid Build Coastguard Worker 
2856*d9f75844SAndroid Build Coastguard Worker       WaitForSetRates(kLowerMaxBitrateKbps, 10);
2857*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(1, num_encoder_initializations_);
2858*d9f75844SAndroid Build Coastguard Worker 
2859*d9f75844SAndroid Build Coastguard Worker       encoder_config_.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000;
2860*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_, [&]() {
2861*d9f75844SAndroid Build Coastguard Worker         send_stream_->ReconfigureVideoEncoder(encoder_config_.Copy());
2862*d9f75844SAndroid Build Coastguard Worker       });
2863*d9f75844SAndroid Build Coastguard Worker       ASSERT_TRUE(create_rate_allocator_event_.Wait(
2864*d9f75844SAndroid Build Coastguard Worker           VideoSendStreamTest::kDefaultTimeout));
2865*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(3, num_rate_allocator_creations_)
2866*d9f75844SAndroid Build Coastguard Worker           << "Rate allocator should have been recreated.";
2867*d9f75844SAndroid Build Coastguard Worker 
2868*d9f75844SAndroid Build Coastguard Worker       // Expected target bitrate is the start bitrate set in the call to
2869*d9f75844SAndroid Build Coastguard Worker       // call_->GetTransportControllerSend()->SetSdpBitrateParameters.
2870*d9f75844SAndroid Build Coastguard Worker       WaitForSetRates(kIncreasedStartBitrateKbps, 10);
2871*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(1, num_encoder_initializations_);
2872*d9f75844SAndroid Build Coastguard Worker     }
2873*d9f75844SAndroid Build Coastguard Worker 
2874*d9f75844SAndroid Build Coastguard Worker     TaskQueueBase* const task_queue_;
2875*d9f75844SAndroid Build Coastguard Worker     rtc::Event create_rate_allocator_event_;
2876*d9f75844SAndroid Build Coastguard Worker     rtc::Event init_encode_event_;
2877*d9f75844SAndroid Build Coastguard Worker     rtc::Event bitrate_changed_event_;
2878*d9f75844SAndroid Build Coastguard Worker     Mutex mutex_;
2879*d9f75844SAndroid Build Coastguard Worker     uint32_t target_bitrate_ RTC_GUARDED_BY(&mutex_);
2880*d9f75844SAndroid Build Coastguard Worker 
2881*d9f75844SAndroid Build Coastguard Worker     int num_rate_allocator_creations_;
2882*d9f75844SAndroid Build Coastguard Worker     int num_encoder_initializations_;
2883*d9f75844SAndroid Build Coastguard Worker     webrtc::Call* call_;
2884*d9f75844SAndroid Build Coastguard Worker     webrtc::VideoSendStream* send_stream_;
2885*d9f75844SAndroid Build Coastguard Worker     test::VideoEncoderProxyFactory encoder_factory_;
2886*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<VideoBitrateAllocatorFactory> bitrate_allocator_factory_;
2887*d9f75844SAndroid Build Coastguard Worker     webrtc::VideoEncoderConfig encoder_config_;
2888*d9f75844SAndroid Build Coastguard Worker   } test(task_queue());
2889*d9f75844SAndroid Build Coastguard Worker 
2890*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
2891*d9f75844SAndroid Build Coastguard Worker }
2892*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,ReportsSentResolution)2893*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, ReportsSentResolution) {
2894*d9f75844SAndroid Build Coastguard Worker   static const size_t kNumStreams = 3;
2895*d9f75844SAndroid Build Coastguard Worker   // Unusual resolutions to make sure that they are the ones being reported.
2896*d9f75844SAndroid Build Coastguard Worker   static const struct {
2897*d9f75844SAndroid Build Coastguard Worker     int width;
2898*d9f75844SAndroid Build Coastguard Worker     int height;
2899*d9f75844SAndroid Build Coastguard Worker   } kEncodedResolution[kNumStreams] = {{241, 181}, {300, 121}, {121, 221}};
2900*d9f75844SAndroid Build Coastguard Worker   class ScreencastTargetBitrateTest : public test::SendTest,
2901*d9f75844SAndroid Build Coastguard Worker                                       public test::FakeEncoder {
2902*d9f75844SAndroid Build Coastguard Worker    public:
2903*d9f75844SAndroid Build Coastguard Worker     explicit ScreencastTargetBitrateTest(TaskQueueBase* task_queue)
2904*d9f75844SAndroid Build Coastguard Worker         : SendTest(kDefaultTimeout),
2905*d9f75844SAndroid Build Coastguard Worker           test::FakeEncoder(Clock::GetRealTimeClock()),
2906*d9f75844SAndroid Build Coastguard Worker           send_stream_(nullptr),
2907*d9f75844SAndroid Build Coastguard Worker           encoder_factory_(this),
2908*d9f75844SAndroid Build Coastguard Worker           task_queue_(task_queue) {}
2909*d9f75844SAndroid Build Coastguard Worker 
2910*d9f75844SAndroid Build Coastguard Worker    private:
2911*d9f75844SAndroid Build Coastguard Worker     int32_t Encode(const VideoFrame& input_image,
2912*d9f75844SAndroid Build Coastguard Worker                    const std::vector<VideoFrameType>* frame_types) override {
2913*d9f75844SAndroid Build Coastguard Worker       CodecSpecificInfo specifics;
2914*d9f75844SAndroid Build Coastguard Worker       specifics.codecType = kVideoCodecGeneric;
2915*d9f75844SAndroid Build Coastguard Worker 
2916*d9f75844SAndroid Build Coastguard Worker       EncodedImage encoded;
2917*d9f75844SAndroid Build Coastguard Worker       auto buffer = EncodedImageBuffer::Create(16);
2918*d9f75844SAndroid Build Coastguard Worker       memset(buffer->data(), 0, 16);
2919*d9f75844SAndroid Build Coastguard Worker       encoded.SetEncodedData(buffer);
2920*d9f75844SAndroid Build Coastguard Worker       encoded.SetTimestamp(input_image.timestamp());
2921*d9f75844SAndroid Build Coastguard Worker       encoded.capture_time_ms_ = input_image.render_time_ms();
2922*d9f75844SAndroid Build Coastguard Worker 
2923*d9f75844SAndroid Build Coastguard Worker       for (size_t i = 0; i < kNumStreams; ++i) {
2924*d9f75844SAndroid Build Coastguard Worker         encoded._frameType = (*frame_types)[i];
2925*d9f75844SAndroid Build Coastguard Worker         encoded._encodedWidth = kEncodedResolution[i].width;
2926*d9f75844SAndroid Build Coastguard Worker         encoded._encodedHeight = kEncodedResolution[i].height;
2927*d9f75844SAndroid Build Coastguard Worker         encoded.SetSpatialIndex(i);
2928*d9f75844SAndroid Build Coastguard Worker         EncodedImageCallback* callback;
2929*d9f75844SAndroid Build Coastguard Worker         {
2930*d9f75844SAndroid Build Coastguard Worker           MutexLock lock(&mutex_);
2931*d9f75844SAndroid Build Coastguard Worker           callback = callback_;
2932*d9f75844SAndroid Build Coastguard Worker         }
2933*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK(callback);
2934*d9f75844SAndroid Build Coastguard Worker         if (callback->OnEncodedImage(encoded, &specifics).error !=
2935*d9f75844SAndroid Build Coastguard Worker             EncodedImageCallback::Result::OK) {
2936*d9f75844SAndroid Build Coastguard Worker           return -1;
2937*d9f75844SAndroid Build Coastguard Worker         }
2938*d9f75844SAndroid Build Coastguard Worker       }
2939*d9f75844SAndroid Build Coastguard Worker 
2940*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
2941*d9f75844SAndroid Build Coastguard Worker       return 0;
2942*d9f75844SAndroid Build Coastguard Worker     }
2943*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
2944*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
2945*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
2946*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
2947*d9f75844SAndroid Build Coastguard Worker       send_config->encoder_settings.encoder_factory = &encoder_factory_;
2948*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(kNumStreams, encoder_config->number_of_streams);
2949*d9f75844SAndroid Build Coastguard Worker     }
2950*d9f75844SAndroid Build Coastguard Worker 
2951*d9f75844SAndroid Build Coastguard Worker     size_t GetNumVideoStreams() const override { return kNumStreams; }
2952*d9f75844SAndroid Build Coastguard Worker 
2953*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
2954*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait())
2955*d9f75844SAndroid Build Coastguard Worker           << "Timed out while waiting for the encoder to send one frame.";
2956*d9f75844SAndroid Build Coastguard Worker       VideoSendStream::Stats stats;
2957*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_, [&]() { stats = send_stream_->GetStats(); });
2958*d9f75844SAndroid Build Coastguard Worker 
2959*d9f75844SAndroid Build Coastguard Worker       for (size_t i = 0; i < kNumStreams; ++i) {
2960*d9f75844SAndroid Build Coastguard Worker         ASSERT_TRUE(stats.substreams.find(kVideoSendSsrcs[i]) !=
2961*d9f75844SAndroid Build Coastguard Worker                     stats.substreams.end())
2962*d9f75844SAndroid Build Coastguard Worker             << "No stats for SSRC: " << kVideoSendSsrcs[i]
2963*d9f75844SAndroid Build Coastguard Worker             << ", stats should exist as soon as frames have been encoded.";
2964*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::StreamStats ssrc_stats =
2965*d9f75844SAndroid Build Coastguard Worker             stats.substreams[kVideoSendSsrcs[i]];
2966*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(kEncodedResolution[i].width, ssrc_stats.width);
2967*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(kEncodedResolution[i].height, ssrc_stats.height);
2968*d9f75844SAndroid Build Coastguard Worker       }
2969*d9f75844SAndroid Build Coastguard Worker     }
2970*d9f75844SAndroid Build Coastguard Worker 
2971*d9f75844SAndroid Build Coastguard Worker     void OnVideoStreamsCreated(VideoSendStream* send_stream,
2972*d9f75844SAndroid Build Coastguard Worker                                const std::vector<VideoReceiveStreamInterface*>&
2973*d9f75844SAndroid Build Coastguard Worker                                    receive_streams) override {
2974*d9f75844SAndroid Build Coastguard Worker       send_stream_ = send_stream;
2975*d9f75844SAndroid Build Coastguard Worker     }
2976*d9f75844SAndroid Build Coastguard Worker 
2977*d9f75844SAndroid Build Coastguard Worker     VideoSendStream* send_stream_;
2978*d9f75844SAndroid Build Coastguard Worker     test::VideoEncoderProxyFactory encoder_factory_;
2979*d9f75844SAndroid Build Coastguard Worker     TaskQueueBase* const task_queue_;
2980*d9f75844SAndroid Build Coastguard Worker   } test(task_queue());
2981*d9f75844SAndroid Build Coastguard Worker 
2982*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
2983*d9f75844SAndroid Build Coastguard Worker }
2984*d9f75844SAndroid Build Coastguard Worker 
2985*d9f75844SAndroid Build Coastguard Worker #if defined(RTC_ENABLE_VP9)
2986*d9f75844SAndroid Build Coastguard Worker class Vp9HeaderObserver : public test::SendTest {
2987*d9f75844SAndroid Build Coastguard Worker  public:
Vp9HeaderObserver(const Vp9TestParams & params)2988*d9f75844SAndroid Build Coastguard Worker   explicit Vp9HeaderObserver(const Vp9TestParams& params)
2989*d9f75844SAndroid Build Coastguard Worker       : SendTest(VideoSendStreamTest::kLongTimeout),
2990*d9f75844SAndroid Build Coastguard Worker         encoder_factory_([]() { return VP9Encoder::Create(); }),
2991*d9f75844SAndroid Build Coastguard Worker         params_(params),
2992*d9f75844SAndroid Build Coastguard Worker         vp9_settings_(VideoEncoder::GetDefaultVp9Settings()) {}
2993*d9f75844SAndroid Build Coastguard Worker 
ModifyVideoConfigsHook(VideoSendStream::Config * send_config,std::vector<VideoReceiveStreamInterface::Config> * receive_configs,VideoEncoderConfig * encoder_config)2994*d9f75844SAndroid Build Coastguard Worker   virtual void ModifyVideoConfigsHook(
2995*d9f75844SAndroid Build Coastguard Worker       VideoSendStream::Config* send_config,
2996*d9f75844SAndroid Build Coastguard Worker       std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
2997*d9f75844SAndroid Build Coastguard Worker       VideoEncoderConfig* encoder_config) {}
2998*d9f75844SAndroid Build Coastguard Worker 
2999*d9f75844SAndroid Build Coastguard Worker   virtual void InspectHeader(const RTPVideoHeaderVP9& vp9) = 0;
3000*d9f75844SAndroid Build Coastguard Worker 
3001*d9f75844SAndroid Build Coastguard Worker  private:
3002*d9f75844SAndroid Build Coastguard Worker   const int kVp9PayloadType = test::CallTest::kVideoSendPayloadType;
3003*d9f75844SAndroid Build Coastguard Worker 
ModifyVideoConfigs(VideoSendStream::Config * send_config,std::vector<VideoReceiveStreamInterface::Config> * receive_configs,VideoEncoderConfig * encoder_config)3004*d9f75844SAndroid Build Coastguard Worker   void ModifyVideoConfigs(
3005*d9f75844SAndroid Build Coastguard Worker       VideoSendStream::Config* send_config,
3006*d9f75844SAndroid Build Coastguard Worker       std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
3007*d9f75844SAndroid Build Coastguard Worker       VideoEncoderConfig* encoder_config) override {
3008*d9f75844SAndroid Build Coastguard Worker     send_config->encoder_settings.encoder_factory = &encoder_factory_;
3009*d9f75844SAndroid Build Coastguard Worker     send_config->rtp.payload_name = "VP9";
3010*d9f75844SAndroid Build Coastguard Worker     send_config->rtp.payload_type = kVp9PayloadType;
3011*d9f75844SAndroid Build Coastguard Worker     ModifyVideoConfigsHook(send_config, receive_configs, encoder_config);
3012*d9f75844SAndroid Build Coastguard Worker     encoder_config->encoder_specific_settings =
3013*d9f75844SAndroid Build Coastguard Worker         rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
3014*d9f75844SAndroid Build Coastguard Worker             vp9_settings_);
3015*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(1u, encoder_config->number_of_streams);
3016*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(1u, encoder_config->simulcast_layers.size());
3017*d9f75844SAndroid Build Coastguard Worker     encoder_config_ = encoder_config->Copy();
3018*d9f75844SAndroid Build Coastguard Worker   }
3019*d9f75844SAndroid Build Coastguard Worker 
ModifyVideoCaptureStartResolution(int * width,int * height,int * frame_rate)3020*d9f75844SAndroid Build Coastguard Worker   void ModifyVideoCaptureStartResolution(int* width,
3021*d9f75844SAndroid Build Coastguard Worker                                          int* height,
3022*d9f75844SAndroid Build Coastguard Worker                                          int* frame_rate) override {
3023*d9f75844SAndroid Build Coastguard Worker     expected_width_ = *width;
3024*d9f75844SAndroid Build Coastguard Worker     expected_height_ = *height;
3025*d9f75844SAndroid Build Coastguard Worker   }
3026*d9f75844SAndroid Build Coastguard Worker 
PerformTest()3027*d9f75844SAndroid Build Coastguard Worker   void PerformTest() override {
3028*d9f75844SAndroid Build Coastguard Worker     bool wait = Wait();
3029*d9f75844SAndroid Build Coastguard Worker     {
3030*d9f75844SAndroid Build Coastguard Worker       // In case of time out, OnSendRtp might still access frames_sent_;
3031*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
3032*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(wait) << "Test timed out waiting for VP9 packet, num frames "
3033*d9f75844SAndroid Build Coastguard Worker                         << frames_sent_;
3034*d9f75844SAndroid Build Coastguard Worker     }
3035*d9f75844SAndroid Build Coastguard Worker   }
3036*d9f75844SAndroid Build Coastguard Worker 
OnSendRtp(const uint8_t * packet,size_t length)3037*d9f75844SAndroid Build Coastguard Worker   Action OnSendRtp(const uint8_t* packet, size_t length) override {
3038*d9f75844SAndroid Build Coastguard Worker     RtpPacket rtp_packet;
3039*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(rtp_packet.Parse(packet, length));
3040*d9f75844SAndroid Build Coastguard Worker 
3041*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(kVp9PayloadType, rtp_packet.PayloadType());
3042*d9f75844SAndroid Build Coastguard Worker     rtc::ArrayView<const uint8_t> rtp_payload = rtp_packet.payload();
3043*d9f75844SAndroid Build Coastguard Worker 
3044*d9f75844SAndroid Build Coastguard Worker     bool new_packet = !last_packet_sequence_number_.has_value() ||
3045*d9f75844SAndroid Build Coastguard Worker                       IsNewerSequenceNumber(rtp_packet.SequenceNumber(),
3046*d9f75844SAndroid Build Coastguard Worker                                             *last_packet_sequence_number_);
3047*d9f75844SAndroid Build Coastguard Worker     if (!rtp_payload.empty() && new_packet) {
3048*d9f75844SAndroid Build Coastguard Worker       RTPVideoHeader video_header;
3049*d9f75844SAndroid Build Coastguard Worker       EXPECT_NE(
3050*d9f75844SAndroid Build Coastguard Worker           VideoRtpDepacketizerVp9::ParseRtpPayload(rtp_payload, &video_header),
3051*d9f75844SAndroid Build Coastguard Worker           0);
3052*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(VideoCodecType::kVideoCodecVP9, video_header.codec);
3053*d9f75844SAndroid Build Coastguard Worker       // Verify common fields for all configurations.
3054*d9f75844SAndroid Build Coastguard Worker       const auto& vp9_header =
3055*d9f75844SAndroid Build Coastguard Worker           absl::get<RTPVideoHeaderVP9>(video_header.video_type_header);
3056*d9f75844SAndroid Build Coastguard Worker       VerifyCommonHeader(vp9_header);
3057*d9f75844SAndroid Build Coastguard Worker       CompareConsecutiveFrames(rtp_packet, video_header);
3058*d9f75844SAndroid Build Coastguard Worker       // Verify configuration specific settings.
3059*d9f75844SAndroid Build Coastguard Worker       InspectHeader(vp9_header);
3060*d9f75844SAndroid Build Coastguard Worker 
3061*d9f75844SAndroid Build Coastguard Worker       if (rtp_packet.Marker()) {
3062*d9f75844SAndroid Build Coastguard Worker         MutexLock lock(&mutex_);
3063*d9f75844SAndroid Build Coastguard Worker         ++frames_sent_;
3064*d9f75844SAndroid Build Coastguard Worker       }
3065*d9f75844SAndroid Build Coastguard Worker       last_packet_marker_ = rtp_packet.Marker();
3066*d9f75844SAndroid Build Coastguard Worker       last_packet_sequence_number_ = rtp_packet.SequenceNumber();
3067*d9f75844SAndroid Build Coastguard Worker       last_packet_timestamp_ = rtp_packet.Timestamp();
3068*d9f75844SAndroid Build Coastguard Worker       last_vp9_ = vp9_header;
3069*d9f75844SAndroid Build Coastguard Worker       last_temporal_idx_by_spatial_idx_[vp9_header.spatial_idx] =
3070*d9f75844SAndroid Build Coastguard Worker           vp9_header.temporal_idx;
3071*d9f75844SAndroid Build Coastguard Worker     }
3072*d9f75844SAndroid Build Coastguard Worker     return SEND_PACKET;
3073*d9f75844SAndroid Build Coastguard Worker   }
3074*d9f75844SAndroid Build Coastguard Worker 
3075*d9f75844SAndroid Build Coastguard Worker  protected:
ContinuousPictureId(const RTPVideoHeaderVP9 & vp9) const3076*d9f75844SAndroid Build Coastguard Worker   bool ContinuousPictureId(const RTPVideoHeaderVP9& vp9) const {
3077*d9f75844SAndroid Build Coastguard Worker     if (last_vp9_.picture_id > vp9.picture_id) {
3078*d9f75844SAndroid Build Coastguard Worker       return vp9.picture_id == 0;  // Wrap.
3079*d9f75844SAndroid Build Coastguard Worker     } else {
3080*d9f75844SAndroid Build Coastguard Worker       return vp9.picture_id == last_vp9_.picture_id + 1;
3081*d9f75844SAndroid Build Coastguard Worker     }
3082*d9f75844SAndroid Build Coastguard Worker   }
3083*d9f75844SAndroid Build Coastguard Worker 
IsTemporalShiftEnabled() const3084*d9f75844SAndroid Build Coastguard Worker   bool IsTemporalShiftEnabled() const {
3085*d9f75844SAndroid Build Coastguard Worker     return params_.scalability_mode.find("_SHIFT") != std::string::npos;
3086*d9f75844SAndroid Build Coastguard Worker   }
3087*d9f75844SAndroid Build Coastguard Worker 
VerifySpatialIdxWithinFrame(const RTPVideoHeaderVP9 & vp9) const3088*d9f75844SAndroid Build Coastguard Worker   void VerifySpatialIdxWithinFrame(const RTPVideoHeaderVP9& vp9) const {
3089*d9f75844SAndroid Build Coastguard Worker     bool new_layer = vp9.spatial_idx != last_vp9_.spatial_idx;
3090*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(new_layer, vp9.beginning_of_frame);
3091*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(new_layer, last_vp9_.end_of_frame);
3092*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(new_layer ? last_vp9_.spatial_idx + 1 : last_vp9_.spatial_idx,
3093*d9f75844SAndroid Build Coastguard Worker               vp9.spatial_idx);
3094*d9f75844SAndroid Build Coastguard Worker   }
3095*d9f75844SAndroid Build Coastguard Worker 
VerifyTemporalIdxWithinFrame(const RTPVideoHeaderVP9 & vp9) const3096*d9f75844SAndroid Build Coastguard Worker   void VerifyTemporalIdxWithinFrame(const RTPVideoHeaderVP9& vp9) const {
3097*d9f75844SAndroid Build Coastguard Worker     if (!IsTemporalShiftEnabled()) {
3098*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(vp9.temporal_idx, last_vp9_.temporal_idx);
3099*d9f75844SAndroid Build Coastguard Worker       return;
3100*d9f75844SAndroid Build Coastguard Worker     }
3101*d9f75844SAndroid Build Coastguard Worker     // Temporal shift.
3102*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(params_.num_temporal_layers, 2);
3103*d9f75844SAndroid Build Coastguard Worker     if (vp9.spatial_idx == params_.num_spatial_layers - 1) {
3104*d9f75844SAndroid Build Coastguard Worker       // Lower spatial layers should be shifted.
3105*d9f75844SAndroid Build Coastguard Worker       int expected_tid =
3106*d9f75844SAndroid Build Coastguard Worker           (!vp9.inter_pic_predicted || vp9.temporal_idx == 1) ? 0 : 1;
3107*d9f75844SAndroid Build Coastguard Worker       for (int i = 0; i < vp9.spatial_idx; ++i) {
3108*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(last_temporal_idx_by_spatial_idx_.at(i), expected_tid);
3109*d9f75844SAndroid Build Coastguard Worker       }
3110*d9f75844SAndroid Build Coastguard Worker     }
3111*d9f75844SAndroid Build Coastguard Worker     // Same within spatial layer.
3112*d9f75844SAndroid Build Coastguard Worker     bool new_layer = vp9.spatial_idx != last_vp9_.spatial_idx;
3113*d9f75844SAndroid Build Coastguard Worker     if (!new_layer) {
3114*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(vp9.temporal_idx, last_vp9_.temporal_idx);
3115*d9f75844SAndroid Build Coastguard Worker     }
3116*d9f75844SAndroid Build Coastguard Worker   }
3117*d9f75844SAndroid Build Coastguard Worker 
VerifyFixedTemporalLayerStructure(const RTPVideoHeaderVP9 & vp9,uint8_t num_layers) const3118*d9f75844SAndroid Build Coastguard Worker   void VerifyFixedTemporalLayerStructure(const RTPVideoHeaderVP9& vp9,
3119*d9f75844SAndroid Build Coastguard Worker                                          uint8_t num_layers) const {
3120*d9f75844SAndroid Build Coastguard Worker     switch (num_layers) {
3121*d9f75844SAndroid Build Coastguard Worker       case 0:
3122*d9f75844SAndroid Build Coastguard Worker         VerifyTemporalLayerStructure0(vp9);
3123*d9f75844SAndroid Build Coastguard Worker         break;
3124*d9f75844SAndroid Build Coastguard Worker       case 1:
3125*d9f75844SAndroid Build Coastguard Worker         VerifyTemporalLayerStructure1(vp9);
3126*d9f75844SAndroid Build Coastguard Worker         break;
3127*d9f75844SAndroid Build Coastguard Worker       case 2:
3128*d9f75844SAndroid Build Coastguard Worker         VerifyTemporalLayerStructure2(vp9);
3129*d9f75844SAndroid Build Coastguard Worker         break;
3130*d9f75844SAndroid Build Coastguard Worker       case 3:
3131*d9f75844SAndroid Build Coastguard Worker         VerifyTemporalLayerStructure3(vp9);
3132*d9f75844SAndroid Build Coastguard Worker         break;
3133*d9f75844SAndroid Build Coastguard Worker       default:
3134*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK_NOTREACHED();
3135*d9f75844SAndroid Build Coastguard Worker     }
3136*d9f75844SAndroid Build Coastguard Worker   }
3137*d9f75844SAndroid Build Coastguard Worker 
VerifyTemporalLayerStructure0(const RTPVideoHeaderVP9 & vp9) const3138*d9f75844SAndroid Build Coastguard Worker   void VerifyTemporalLayerStructure0(const RTPVideoHeaderVP9& vp9) const {
3139*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(kNoTl0PicIdx, vp9.tl0_pic_idx);
3140*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(kNoTemporalIdx, vp9.temporal_idx);  // no tid
3141*d9f75844SAndroid Build Coastguard Worker     // Technically true, but layer indices not available.
3142*d9f75844SAndroid Build Coastguard Worker     EXPECT_FALSE(vp9.temporal_up_switch);
3143*d9f75844SAndroid Build Coastguard Worker   }
3144*d9f75844SAndroid Build Coastguard Worker 
VerifyTemporalLayerStructure1(const RTPVideoHeaderVP9 & vp9) const3145*d9f75844SAndroid Build Coastguard Worker   void VerifyTemporalLayerStructure1(const RTPVideoHeaderVP9& vp9) const {
3146*d9f75844SAndroid Build Coastguard Worker     EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
3147*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(0, vp9.temporal_idx);  // 0,0,0,...
3148*d9f75844SAndroid Build Coastguard Worker   }
3149*d9f75844SAndroid Build Coastguard Worker 
VerifyTemporalLayerStructure2(const RTPVideoHeaderVP9 & vp9) const3150*d9f75844SAndroid Build Coastguard Worker   void VerifyTemporalLayerStructure2(const RTPVideoHeaderVP9& vp9) const {
3151*d9f75844SAndroid Build Coastguard Worker     EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
3152*d9f75844SAndroid Build Coastguard Worker     EXPECT_GE(vp9.temporal_idx, 0);  // 0,1,0,1,... (tid reset on I-frames).
3153*d9f75844SAndroid Build Coastguard Worker     EXPECT_LE(vp9.temporal_idx, 1);
3154*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(vp9.temporal_up_switch);
3155*d9f75844SAndroid Build Coastguard Worker     // Verify temporal structure for the highest spatial layer (the structure
3156*d9f75844SAndroid Build Coastguard Worker     // may be shifted for lower spatial layer if temporal shift is configured).
3157*d9f75844SAndroid Build Coastguard Worker     if (IsHighestSpatialLayer(vp9) && vp9.beginning_of_frame) {
3158*d9f75844SAndroid Build Coastguard Worker       int expected_tid =
3159*d9f75844SAndroid Build Coastguard Worker           (!vp9.inter_pic_predicted ||
3160*d9f75844SAndroid Build Coastguard Worker            last_temporal_idx_by_spatial_idx_.at(vp9.spatial_idx) == 1)
3161*d9f75844SAndroid Build Coastguard Worker               ? 0
3162*d9f75844SAndroid Build Coastguard Worker               : 1;
3163*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(vp9.temporal_idx, expected_tid);
3164*d9f75844SAndroid Build Coastguard Worker     }
3165*d9f75844SAndroid Build Coastguard Worker   }
3166*d9f75844SAndroid Build Coastguard Worker 
VerifyTemporalLayerStructure3(const RTPVideoHeaderVP9 & vp9) const3167*d9f75844SAndroid Build Coastguard Worker   void VerifyTemporalLayerStructure3(const RTPVideoHeaderVP9& vp9) const {
3168*d9f75844SAndroid Build Coastguard Worker     EXPECT_NE(kNoTl0PicIdx, vp9.tl0_pic_idx);
3169*d9f75844SAndroid Build Coastguard Worker     EXPECT_GE(vp9.temporal_idx, 0);  // 0,2,1,2,... (tid reset on I-frames).
3170*d9f75844SAndroid Build Coastguard Worker     EXPECT_LE(vp9.temporal_idx, 2);
3171*d9f75844SAndroid Build Coastguard Worker     if (IsNewPictureId(vp9) && vp9.inter_pic_predicted) {
3172*d9f75844SAndroid Build Coastguard Worker       EXPECT_NE(vp9.temporal_idx, last_vp9_.temporal_idx);
3173*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(vp9.temporal_up_switch);
3174*d9f75844SAndroid Build Coastguard Worker       switch (vp9.temporal_idx) {
3175*d9f75844SAndroid Build Coastguard Worker         case 0:
3176*d9f75844SAndroid Build Coastguard Worker           EXPECT_EQ(last_vp9_.temporal_idx, 2);
3177*d9f75844SAndroid Build Coastguard Worker           break;
3178*d9f75844SAndroid Build Coastguard Worker         case 1:
3179*d9f75844SAndroid Build Coastguard Worker           EXPECT_EQ(last_vp9_.temporal_idx, 2);
3180*d9f75844SAndroid Build Coastguard Worker           break;
3181*d9f75844SAndroid Build Coastguard Worker         case 2:
3182*d9f75844SAndroid Build Coastguard Worker           EXPECT_LT(last_vp9_.temporal_idx, 2);
3183*d9f75844SAndroid Build Coastguard Worker           break;
3184*d9f75844SAndroid Build Coastguard Worker       }
3185*d9f75844SAndroid Build Coastguard Worker     }
3186*d9f75844SAndroid Build Coastguard Worker   }
3187*d9f75844SAndroid Build Coastguard Worker 
VerifyTl0Idx(const RTPVideoHeaderVP9 & vp9) const3188*d9f75844SAndroid Build Coastguard Worker   void VerifyTl0Idx(const RTPVideoHeaderVP9& vp9) const {
3189*d9f75844SAndroid Build Coastguard Worker     if (vp9.tl0_pic_idx == kNoTl0PicIdx)
3190*d9f75844SAndroid Build Coastguard Worker       return;
3191*d9f75844SAndroid Build Coastguard Worker 
3192*d9f75844SAndroid Build Coastguard Worker     uint8_t expected_tl0_idx = last_vp9_.tl0_pic_idx;
3193*d9f75844SAndroid Build Coastguard Worker     if (vp9.temporal_idx == 0)
3194*d9f75844SAndroid Build Coastguard Worker       ++expected_tl0_idx;
3195*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(expected_tl0_idx, vp9.tl0_pic_idx);
3196*d9f75844SAndroid Build Coastguard Worker   }
3197*d9f75844SAndroid Build Coastguard Worker 
IsNewPictureId(const RTPVideoHeaderVP9 & vp9) const3198*d9f75844SAndroid Build Coastguard Worker   bool IsNewPictureId(const RTPVideoHeaderVP9& vp9) const {
3199*d9f75844SAndroid Build Coastguard Worker     return frames_sent_ > 0 && (vp9.picture_id != last_vp9_.picture_id);
3200*d9f75844SAndroid Build Coastguard Worker   }
3201*d9f75844SAndroid Build Coastguard Worker 
IsHighestSpatialLayer(const RTPVideoHeaderVP9 & vp9) const3202*d9f75844SAndroid Build Coastguard Worker   bool IsHighestSpatialLayer(const RTPVideoHeaderVP9& vp9) const {
3203*d9f75844SAndroid Build Coastguard Worker     return vp9.spatial_idx == params_.num_spatial_layers - 1 ||
3204*d9f75844SAndroid Build Coastguard Worker            vp9.spatial_idx == kNoSpatialIdx;
3205*d9f75844SAndroid Build Coastguard Worker   }
3206*d9f75844SAndroid Build Coastguard Worker 
3207*d9f75844SAndroid Build Coastguard Worker   // Flexible mode (F=1):    Non-flexible mode (F=0):
3208*d9f75844SAndroid Build Coastguard Worker   //
3209*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+
3210*d9f75844SAndroid Build Coastguard Worker   //      |I|P|L|F|B|E|V|-|     |I|P|L|F|B|E|V|-|
3211*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+
3212*d9f75844SAndroid Build Coastguard Worker   // I:   |M| PICTURE ID  |  I: |M| PICTURE ID  |
3213*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+
3214*d9f75844SAndroid Build Coastguard Worker   // M:   | EXTENDED PID  |  M: | EXTENDED PID  |
3215*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+
3216*d9f75844SAndroid Build Coastguard Worker   // L:   |  T  |U|  S  |D|  L: |  T  |U|  S  |D|
3217*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+
3218*d9f75844SAndroid Build Coastguard Worker   // P,F: | P_DIFF    |X|N|     |   TL0PICIDX   |
3219*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+
3220*d9f75844SAndroid Build Coastguard Worker   // X:   |EXTENDED P_DIFF|  V: | SS  ..        |
3221*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+
3222*d9f75844SAndroid Build Coastguard Worker   // V:   | SS  ..        |
3223*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+
VerifyCommonHeader(const RTPVideoHeaderVP9 & vp9) const3224*d9f75844SAndroid Build Coastguard Worker   void VerifyCommonHeader(const RTPVideoHeaderVP9& vp9) const {
3225*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(kMaxTwoBytePictureId, vp9.max_picture_id);       // M:1
3226*d9f75844SAndroid Build Coastguard Worker     EXPECT_NE(kNoPictureId, vp9.picture_id);                   // I:1
3227*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(vp9_settings_.flexibleMode, vp9.flexible_mode);  // F
3228*d9f75844SAndroid Build Coastguard Worker 
3229*d9f75844SAndroid Build Coastguard Worker     if (params_.num_spatial_layers > 1) {
3230*d9f75844SAndroid Build Coastguard Worker       EXPECT_LT(vp9.spatial_idx, params_.num_spatial_layers);
3231*d9f75844SAndroid Build Coastguard Worker     } else if (params_.num_temporal_layers > 1) {
3232*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(vp9.spatial_idx, 0);
3233*d9f75844SAndroid Build Coastguard Worker     } else {
3234*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(vp9.spatial_idx, kNoSpatialIdx);
3235*d9f75844SAndroid Build Coastguard Worker     }
3236*d9f75844SAndroid Build Coastguard Worker 
3237*d9f75844SAndroid Build Coastguard Worker     if (params_.num_temporal_layers > 1) {
3238*d9f75844SAndroid Build Coastguard Worker       EXPECT_LT(vp9.temporal_idx, params_.num_temporal_layers);
3239*d9f75844SAndroid Build Coastguard Worker     } else if (params_.num_spatial_layers > 1) {
3240*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(vp9.temporal_idx, 0);
3241*d9f75844SAndroid Build Coastguard Worker     } else {
3242*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(vp9.temporal_idx, kNoTemporalIdx);
3243*d9f75844SAndroid Build Coastguard Worker     }
3244*d9f75844SAndroid Build Coastguard Worker 
3245*d9f75844SAndroid Build Coastguard Worker     if (vp9.ss_data_available)  // V
3246*d9f75844SAndroid Build Coastguard Worker       VerifySsData(vp9);
3247*d9f75844SAndroid Build Coastguard Worker 
3248*d9f75844SAndroid Build Coastguard Worker     if (frames_sent_ == 0)
3249*d9f75844SAndroid Build Coastguard Worker       EXPECT_FALSE(vp9.inter_pic_predicted);  // P
3250*d9f75844SAndroid Build Coastguard Worker 
3251*d9f75844SAndroid Build Coastguard Worker     if (!vp9.inter_pic_predicted) {
3252*d9f75844SAndroid Build Coastguard Worker       if (vp9.temporal_idx == kNoTemporalIdx) {
3253*d9f75844SAndroid Build Coastguard Worker         EXPECT_FALSE(vp9.temporal_up_switch);
3254*d9f75844SAndroid Build Coastguard Worker       } else {
3255*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(vp9.temporal_idx, 0);
3256*d9f75844SAndroid Build Coastguard Worker         EXPECT_TRUE(vp9.temporal_up_switch);
3257*d9f75844SAndroid Build Coastguard Worker       }
3258*d9f75844SAndroid Build Coastguard Worker     }
3259*d9f75844SAndroid Build Coastguard Worker   }
3260*d9f75844SAndroid Build Coastguard Worker 
3261*d9f75844SAndroid Build Coastguard Worker   // Scalability structure (SS).
3262*d9f75844SAndroid Build Coastguard Worker   //
3263*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+
3264*d9f75844SAndroid Build Coastguard Worker   // V:   | N_S |Y|G|-|-|-|
3265*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+
3266*d9f75844SAndroid Build Coastguard Worker   // Y:   |    WIDTH      |  N_S + 1 times
3267*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+
3268*d9f75844SAndroid Build Coastguard Worker   //      |    HEIGHT     |
3269*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+
3270*d9f75844SAndroid Build Coastguard Worker   // G:   |      N_G      |
3271*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+
3272*d9f75844SAndroid Build Coastguard Worker   // N_G: |  T  |U| R |-|-|  N_G times
3273*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+
3274*d9f75844SAndroid Build Coastguard Worker   //      |    P_DIFF     |  R times
3275*d9f75844SAndroid Build Coastguard Worker   //      +-+-+-+-+-+-+-+-+
VerifySsData(const RTPVideoHeaderVP9 & vp9) const3276*d9f75844SAndroid Build Coastguard Worker   void VerifySsData(const RTPVideoHeaderVP9& vp9) const {
3277*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(vp9.ss_data_available);             // V
3278*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(params_.num_spatial_layers,           // N_S + 1
3279*d9f75844SAndroid Build Coastguard Worker               vp9.num_spatial_layers);
3280*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(vp9.spatial_layer_resolution_present);  // Y:1
3281*d9f75844SAndroid Build Coastguard Worker 
3282*d9f75844SAndroid Build Coastguard Worker     ScalableVideoController::StreamLayersConfig config = GetScalabilityConfig();
3283*d9f75844SAndroid Build Coastguard Worker     for (int i = config.num_spatial_layers - 1; i >= 0; --i) {
3284*d9f75844SAndroid Build Coastguard Worker       double ratio = static_cast<double>(config.scaling_factor_num[i]) /
3285*d9f75844SAndroid Build Coastguard Worker                      config.scaling_factor_den[i];
3286*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(expected_width_ * ratio, vp9.width[i]);    // WIDTH
3287*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(expected_height_ * ratio, vp9.height[i]);  // HEIGHT
3288*d9f75844SAndroid Build Coastguard Worker     }
3289*d9f75844SAndroid Build Coastguard Worker   }
3290*d9f75844SAndroid Build Coastguard Worker 
CompareConsecutiveFrames(const RtpPacket & rtp_packet,const RTPVideoHeader & video) const3291*d9f75844SAndroid Build Coastguard Worker   void CompareConsecutiveFrames(const RtpPacket& rtp_packet,
3292*d9f75844SAndroid Build Coastguard Worker                                 const RTPVideoHeader& video) const {
3293*d9f75844SAndroid Build Coastguard Worker     const auto& vp9_header =
3294*d9f75844SAndroid Build Coastguard Worker         absl::get<RTPVideoHeaderVP9>(video.video_type_header);
3295*d9f75844SAndroid Build Coastguard Worker 
3296*d9f75844SAndroid Build Coastguard Worker     const bool new_temporal_unit =
3297*d9f75844SAndroid Build Coastguard Worker         !last_packet_timestamp_.has_value() ||
3298*d9f75844SAndroid Build Coastguard Worker         IsNewerTimestamp(rtp_packet.Timestamp(), *last_packet_timestamp_);
3299*d9f75844SAndroid Build Coastguard Worker     const bool new_frame =
3300*d9f75844SAndroid Build Coastguard Worker         new_temporal_unit || last_vp9_.spatial_idx != vp9_header.spatial_idx;
3301*d9f75844SAndroid Build Coastguard Worker 
3302*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(new_frame, video.is_first_packet_in_frame);
3303*d9f75844SAndroid Build Coastguard Worker     if (!new_temporal_unit) {
3304*d9f75844SAndroid Build Coastguard Worker       EXPECT_FALSE(last_packet_marker_);
3305*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(*last_packet_timestamp_, rtp_packet.Timestamp());
3306*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(last_vp9_.picture_id, vp9_header.picture_id);
3307*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(last_vp9_.tl0_pic_idx, vp9_header.tl0_pic_idx);
3308*d9f75844SAndroid Build Coastguard Worker       VerifySpatialIdxWithinFrame(vp9_header);
3309*d9f75844SAndroid Build Coastguard Worker       VerifyTemporalIdxWithinFrame(vp9_header);
3310*d9f75844SAndroid Build Coastguard Worker       return;
3311*d9f75844SAndroid Build Coastguard Worker     }
3312*d9f75844SAndroid Build Coastguard Worker     // New frame.
3313*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(vp9_header.beginning_of_frame);
3314*d9f75844SAndroid Build Coastguard Worker 
3315*d9f75844SAndroid Build Coastguard Worker     // Compare with last packet in previous frame.
3316*d9f75844SAndroid Build Coastguard Worker     if (frames_sent_ == 0)
3317*d9f75844SAndroid Build Coastguard Worker       return;
3318*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(last_vp9_.end_of_frame);
3319*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(last_packet_marker_);
3320*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(ContinuousPictureId(vp9_header));
3321*d9f75844SAndroid Build Coastguard Worker     VerifyTl0Idx(vp9_header);
3322*d9f75844SAndroid Build Coastguard Worker   }
3323*d9f75844SAndroid Build Coastguard Worker 
GetScalabilityConfig() const3324*d9f75844SAndroid Build Coastguard Worker   ScalableVideoController::StreamLayersConfig GetScalabilityConfig() const {
3325*d9f75844SAndroid Build Coastguard Worker     absl::optional<ScalabilityMode> scalability_mode =
3326*d9f75844SAndroid Build Coastguard Worker         ScalabilityModeFromString(params_.scalability_mode);
3327*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(scalability_mode.has_value());
3328*d9f75844SAndroid Build Coastguard Worker     absl::optional<ScalableVideoController::StreamLayersConfig> config =
3329*d9f75844SAndroid Build Coastguard Worker         ScalabilityStructureConfig(*scalability_mode);
3330*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(config.has_value());
3331*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(config->num_spatial_layers, params_.num_spatial_layers);
3332*d9f75844SAndroid Build Coastguard Worker     return *config;
3333*d9f75844SAndroid Build Coastguard Worker   }
3334*d9f75844SAndroid Build Coastguard Worker 
3335*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory_;
3336*d9f75844SAndroid Build Coastguard Worker   const Vp9TestParams params_;
3337*d9f75844SAndroid Build Coastguard Worker   VideoCodecVP9 vp9_settings_;
3338*d9f75844SAndroid Build Coastguard Worker   webrtc::VideoEncoderConfig encoder_config_;
3339*d9f75844SAndroid Build Coastguard Worker   bool last_packet_marker_ = false;
3340*d9f75844SAndroid Build Coastguard Worker   absl::optional<uint16_t> last_packet_sequence_number_;
3341*d9f75844SAndroid Build Coastguard Worker   absl::optional<uint32_t> last_packet_timestamp_;
3342*d9f75844SAndroid Build Coastguard Worker   RTPVideoHeaderVP9 last_vp9_;
3343*d9f75844SAndroid Build Coastguard Worker   std::map<int, int> last_temporal_idx_by_spatial_idx_;
3344*d9f75844SAndroid Build Coastguard Worker   Mutex mutex_;
3345*d9f75844SAndroid Build Coastguard Worker   size_t frames_sent_ = 0;
3346*d9f75844SAndroid Build Coastguard Worker   int expected_width_ = 0;
3347*d9f75844SAndroid Build Coastguard Worker   int expected_height_ = 0;
3348*d9f75844SAndroid Build Coastguard Worker };
3349*d9f75844SAndroid Build Coastguard Worker 
3350*d9f75844SAndroid Build Coastguard Worker class Vp9Test : public VideoSendStreamTest,
3351*d9f75844SAndroid Build Coastguard Worker                 public ::testing::WithParamInterface<ParameterizationType> {
3352*d9f75844SAndroid Build Coastguard Worker  public:
Vp9Test()3353*d9f75844SAndroid Build Coastguard Worker   Vp9Test()
3354*d9f75844SAndroid Build Coastguard Worker       : params_(::testing::get<Vp9TestParams>(GetParam())),
3355*d9f75844SAndroid Build Coastguard Worker         use_scalability_mode_identifier_(::testing::get<bool>(GetParam())) {}
3356*d9f75844SAndroid Build Coastguard Worker 
3357*d9f75844SAndroid Build Coastguard Worker  protected:
3358*d9f75844SAndroid Build Coastguard Worker   const Vp9TestParams params_;
3359*d9f75844SAndroid Build Coastguard Worker   const bool use_scalability_mode_identifier_;
3360*d9f75844SAndroid Build Coastguard Worker };
3361*d9f75844SAndroid Build Coastguard Worker 
3362*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
3363*d9f75844SAndroid Build Coastguard Worker     ScalabilityMode,
3364*d9f75844SAndroid Build Coastguard Worker     Vp9Test,
3365*d9f75844SAndroid Build Coastguard Worker     ::testing::Combine(
3366*d9f75844SAndroid Build Coastguard Worker         ::testing::ValuesIn<Vp9TestParams>(
3367*d9f75844SAndroid Build Coastguard Worker             {{"L1T1", 1, 1, InterLayerPredMode::kOn},
3368*d9f75844SAndroid Build Coastguard Worker              {"L1T2", 1, 2, InterLayerPredMode::kOn},
3369*d9f75844SAndroid Build Coastguard Worker              {"L1T3", 1, 3, InterLayerPredMode::kOn},
3370*d9f75844SAndroid Build Coastguard Worker              {"L2T1", 2, 1, InterLayerPredMode::kOn},
3371*d9f75844SAndroid Build Coastguard Worker              {"L2T1_KEY", 2, 1, InterLayerPredMode::kOnKeyPic},
3372*d9f75844SAndroid Build Coastguard Worker              {"L2T2", 2, 2, InterLayerPredMode::kOn},
3373*d9f75844SAndroid Build Coastguard Worker              {"L2T2_KEY", 2, 2, InterLayerPredMode::kOnKeyPic},
3374*d9f75844SAndroid Build Coastguard Worker              {"L2T3", 2, 3, InterLayerPredMode::kOn},
3375*d9f75844SAndroid Build Coastguard Worker              {"L2T3_KEY", 2, 3, InterLayerPredMode::kOnKeyPic},
3376*d9f75844SAndroid Build Coastguard Worker              {"L3T1", 3, 1, InterLayerPredMode::kOn},
3377*d9f75844SAndroid Build Coastguard Worker              {"L3T1_KEY", 3, 1, InterLayerPredMode::kOnKeyPic},
3378*d9f75844SAndroid Build Coastguard Worker              {"L3T2", 3, 2, InterLayerPredMode::kOn},
3379*d9f75844SAndroid Build Coastguard Worker              {"L3T2_KEY", 3, 2, InterLayerPredMode::kOnKeyPic},
3380*d9f75844SAndroid Build Coastguard Worker              {"L3T3", 3, 3, InterLayerPredMode::kOn},
3381*d9f75844SAndroid Build Coastguard Worker              {"L3T3_KEY", 3, 3, InterLayerPredMode::kOnKeyPic},
3382*d9f75844SAndroid Build Coastguard Worker              {"S2T1", 2, 1, InterLayerPredMode::kOff},
3383*d9f75844SAndroid Build Coastguard Worker              {"S2T2", 2, 2, InterLayerPredMode::kOff},
3384*d9f75844SAndroid Build Coastguard Worker              {"S2T3", 2, 3, InterLayerPredMode::kOff},
3385*d9f75844SAndroid Build Coastguard Worker              {"S3T1", 3, 1, InterLayerPredMode::kOff},
3386*d9f75844SAndroid Build Coastguard Worker              {"S3T2", 3, 2, InterLayerPredMode::kOff},
3387*d9f75844SAndroid Build Coastguard Worker              {"S3T3", 3, 3, InterLayerPredMode::kOff}}),
3388*d9f75844SAndroid Build Coastguard Worker         ::testing::Values(false, true)),  // use_scalability_mode_identifier
3389*d9f75844SAndroid Build Coastguard Worker     ParamInfoToStr);
3390*d9f75844SAndroid Build Coastguard Worker 
3391*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
3392*d9f75844SAndroid Build Coastguard Worker     ScalabilityModeOn,
3393*d9f75844SAndroid Build Coastguard Worker     Vp9Test,
3394*d9f75844SAndroid Build Coastguard Worker     ::testing::Combine(
3395*d9f75844SAndroid Build Coastguard Worker         ::testing::ValuesIn<Vp9TestParams>(
3396*d9f75844SAndroid Build Coastguard Worker             {{"L2T1h", 2, 1, InterLayerPredMode::kOn},
3397*d9f75844SAndroid Build Coastguard Worker              {"L2T2h", 2, 2, InterLayerPredMode::kOn},
3398*d9f75844SAndroid Build Coastguard Worker              {"L2T3h", 2, 3, InterLayerPredMode::kOn},
3399*d9f75844SAndroid Build Coastguard Worker              {"L2T2_KEY_SHIFT", 2, 2, InterLayerPredMode::kOnKeyPic},
3400*d9f75844SAndroid Build Coastguard Worker              {"L3T1h", 3, 1, InterLayerPredMode::kOn},
3401*d9f75844SAndroid Build Coastguard Worker              {"L3T2h", 3, 2, InterLayerPredMode::kOn},
3402*d9f75844SAndroid Build Coastguard Worker              {"L3T3h", 3, 3, InterLayerPredMode::kOn},
3403*d9f75844SAndroid Build Coastguard Worker              {"S2T1h", 2, 1, InterLayerPredMode::kOff},
3404*d9f75844SAndroid Build Coastguard Worker              {"S2T2h", 2, 2, InterLayerPredMode::kOff},
3405*d9f75844SAndroid Build Coastguard Worker              {"S2T3h", 2, 3, InterLayerPredMode::kOff},
3406*d9f75844SAndroid Build Coastguard Worker              {"S3T1h", 3, 1, InterLayerPredMode::kOff},
3407*d9f75844SAndroid Build Coastguard Worker              {"S3T2h", 3, 2, InterLayerPredMode::kOff},
3408*d9f75844SAndroid Build Coastguard Worker              {"S3T3h", 3, 3, InterLayerPredMode::kOff}}),
3409*d9f75844SAndroid Build Coastguard Worker         ::testing::Values(true)),  // use_scalability_mode_identifier
3410*d9f75844SAndroid Build Coastguard Worker     ParamInfoToStr);
3411*d9f75844SAndroid Build Coastguard Worker 
TEST_P(Vp9Test,NonFlexMode)3412*d9f75844SAndroid Build Coastguard Worker TEST_P(Vp9Test, NonFlexMode) {
3413*d9f75844SAndroid Build Coastguard Worker   TestVp9NonFlexMode(params_, use_scalability_mode_identifier_);
3414*d9f75844SAndroid Build Coastguard Worker }
3415*d9f75844SAndroid Build Coastguard Worker 
TestVp9NonFlexMode(const Vp9TestParams & params,bool use_scalability_mode_identifier)3416*d9f75844SAndroid Build Coastguard Worker void VideoSendStreamTest::TestVp9NonFlexMode(
3417*d9f75844SAndroid Build Coastguard Worker     const Vp9TestParams& params,
3418*d9f75844SAndroid Build Coastguard Worker     bool use_scalability_mode_identifier) {
3419*d9f75844SAndroid Build Coastguard Worker   static const size_t kNumFramesToSend = 100;
3420*d9f75844SAndroid Build Coastguard Worker   // Set to < kNumFramesToSend and coprime to length of temporal layer
3421*d9f75844SAndroid Build Coastguard Worker   // structures to verify temporal id reset on key frame.
3422*d9f75844SAndroid Build Coastguard Worker   static const int kKeyFrameInterval = 31;
3423*d9f75844SAndroid Build Coastguard Worker 
3424*d9f75844SAndroid Build Coastguard Worker   static const int kWidth = kMinVp9SpatialLayerLongSideLength;
3425*d9f75844SAndroid Build Coastguard Worker   static const int kHeight = kMinVp9SpatialLayerShortSideLength;
3426*d9f75844SAndroid Build Coastguard Worker   static const float kGoodBitsPerPixel = 0.1f;
3427*d9f75844SAndroid Build Coastguard Worker   class NonFlexibleMode : public Vp9HeaderObserver {
3428*d9f75844SAndroid Build Coastguard Worker    public:
3429*d9f75844SAndroid Build Coastguard Worker     NonFlexibleMode(const Vp9TestParams& params,
3430*d9f75844SAndroid Build Coastguard Worker                     bool use_scalability_mode_identifier)
3431*d9f75844SAndroid Build Coastguard Worker         : Vp9HeaderObserver(params),
3432*d9f75844SAndroid Build Coastguard Worker           use_scalability_mode_identifier_(use_scalability_mode_identifier),
3433*d9f75844SAndroid Build Coastguard Worker           l_field_(params.num_temporal_layers > 1 ||
3434*d9f75844SAndroid Build Coastguard Worker                    params.num_spatial_layers > 1) {}
3435*d9f75844SAndroid Build Coastguard Worker 
3436*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigsHook(
3437*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
3438*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
3439*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
3440*d9f75844SAndroid Build Coastguard Worker       encoder_config->codec_type = kVideoCodecVP9;
3441*d9f75844SAndroid Build Coastguard Worker       int bitrate_bps = 0;
3442*d9f75844SAndroid Build Coastguard Worker       for (int sl_idx = 0; sl_idx < params_.num_spatial_layers; ++sl_idx) {
3443*d9f75844SAndroid Build Coastguard Worker         const int width = kWidth << sl_idx;
3444*d9f75844SAndroid Build Coastguard Worker         const int height = kHeight << sl_idx;
3445*d9f75844SAndroid Build Coastguard Worker         const float bpp = kGoodBitsPerPixel / (1 << sl_idx);
3446*d9f75844SAndroid Build Coastguard Worker         bitrate_bps += static_cast<int>(width * height * bpp * 30);
3447*d9f75844SAndroid Build Coastguard Worker       }
3448*d9f75844SAndroid Build Coastguard Worker       encoder_config->max_bitrate_bps = bitrate_bps * 2;
3449*d9f75844SAndroid Build Coastguard Worker 
3450*d9f75844SAndroid Build Coastguard Worker       encoder_config->frame_drop_enabled = false;
3451*d9f75844SAndroid Build Coastguard Worker 
3452*d9f75844SAndroid Build Coastguard Worker       vp9_settings_.flexibleMode = false;
3453*d9f75844SAndroid Build Coastguard Worker       vp9_settings_.automaticResizeOn = false;
3454*d9f75844SAndroid Build Coastguard Worker       vp9_settings_.keyFrameInterval = kKeyFrameInterval;
3455*d9f75844SAndroid Build Coastguard Worker       if (!use_scalability_mode_identifier_) {
3456*d9f75844SAndroid Build Coastguard Worker         vp9_settings_.numberOfTemporalLayers = params_.num_temporal_layers;
3457*d9f75844SAndroid Build Coastguard Worker         vp9_settings_.numberOfSpatialLayers = params_.num_spatial_layers;
3458*d9f75844SAndroid Build Coastguard Worker         vp9_settings_.interLayerPred = params_.inter_layer_pred;
3459*d9f75844SAndroid Build Coastguard Worker       } else {
3460*d9f75844SAndroid Build Coastguard Worker         absl::optional<ScalabilityMode> mode =
3461*d9f75844SAndroid Build Coastguard Worker             ScalabilityModeFromString(params_.scalability_mode);
3462*d9f75844SAndroid Build Coastguard Worker         encoder_config->simulcast_layers[0].scalability_mode = mode;
3463*d9f75844SAndroid Build Coastguard Worker         EXPECT_TRUE(mode.has_value());
3464*d9f75844SAndroid Build Coastguard Worker       }
3465*d9f75844SAndroid Build Coastguard Worker     }
3466*d9f75844SAndroid Build Coastguard Worker 
3467*d9f75844SAndroid Build Coastguard Worker     int GetRequiredDivisibility() const {
3468*d9f75844SAndroid Build Coastguard Worker       ScalableVideoController::StreamLayersConfig config =
3469*d9f75844SAndroid Build Coastguard Worker           GetScalabilityConfig();
3470*d9f75844SAndroid Build Coastguard Worker       int required_divisibility = 1;
3471*d9f75844SAndroid Build Coastguard Worker       for (int sl_idx = 0; sl_idx < config.num_spatial_layers; ++sl_idx) {
3472*d9f75844SAndroid Build Coastguard Worker         required_divisibility = cricket::LeastCommonMultiple(
3473*d9f75844SAndroid Build Coastguard Worker             required_divisibility, config.scaling_factor_den[sl_idx]);
3474*d9f75844SAndroid Build Coastguard Worker       }
3475*d9f75844SAndroid Build Coastguard Worker       return required_divisibility;
3476*d9f75844SAndroid Build Coastguard Worker     }
3477*d9f75844SAndroid Build Coastguard Worker 
3478*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoCaptureStartResolution(int* width,
3479*d9f75844SAndroid Build Coastguard Worker                                            int* height,
3480*d9f75844SAndroid Build Coastguard Worker                                            int* frame_rate) override {
3481*d9f75844SAndroid Build Coastguard Worker       expected_width_ = kWidth << (params_.num_spatial_layers - 1);
3482*d9f75844SAndroid Build Coastguard Worker       expected_height_ = kHeight << (params_.num_spatial_layers - 1);
3483*d9f75844SAndroid Build Coastguard Worker       *width = expected_width_;
3484*d9f75844SAndroid Build Coastguard Worker       *height = expected_height_;
3485*d9f75844SAndroid Build Coastguard Worker       // Top layer may be adjusted to ensure evenly divided layers.
3486*d9f75844SAndroid Build Coastguard Worker       int divisibility = GetRequiredDivisibility();
3487*d9f75844SAndroid Build Coastguard Worker       expected_width_ -= (expected_width_ % divisibility);
3488*d9f75844SAndroid Build Coastguard Worker       expected_height_ -= (expected_height_ % divisibility);
3489*d9f75844SAndroid Build Coastguard Worker     }
3490*d9f75844SAndroid Build Coastguard Worker 
3491*d9f75844SAndroid Build Coastguard Worker     void InspectHeader(const RTPVideoHeaderVP9& vp9) override {
3492*d9f75844SAndroid Build Coastguard Worker       bool ss_data_expected = !vp9.inter_pic_predicted &&
3493*d9f75844SAndroid Build Coastguard Worker                               vp9.beginning_of_frame &&
3494*d9f75844SAndroid Build Coastguard Worker                               !vp9.inter_layer_predicted;
3495*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(ss_data_expected, vp9.ss_data_available);
3496*d9f75844SAndroid Build Coastguard Worker 
3497*d9f75844SAndroid Build Coastguard Worker       bool is_key_frame = frames_sent_ % kKeyFrameInterval == 0;
3498*d9f75844SAndroid Build Coastguard Worker       if (params_.num_spatial_layers > 1) {
3499*d9f75844SAndroid Build Coastguard Worker         switch (params_.inter_layer_pred) {
3500*d9f75844SAndroid Build Coastguard Worker           case InterLayerPredMode::kOff:
3501*d9f75844SAndroid Build Coastguard Worker             EXPECT_FALSE(vp9.inter_layer_predicted);
3502*d9f75844SAndroid Build Coastguard Worker             break;
3503*d9f75844SAndroid Build Coastguard Worker           case InterLayerPredMode::kOn:
3504*d9f75844SAndroid Build Coastguard Worker             EXPECT_EQ(vp9.spatial_idx > 0, vp9.inter_layer_predicted);
3505*d9f75844SAndroid Build Coastguard Worker             break;
3506*d9f75844SAndroid Build Coastguard Worker           case InterLayerPredMode::kOnKeyPic:
3507*d9f75844SAndroid Build Coastguard Worker             EXPECT_EQ(is_key_frame && vp9.spatial_idx > 0,
3508*d9f75844SAndroid Build Coastguard Worker                       vp9.inter_layer_predicted);
3509*d9f75844SAndroid Build Coastguard Worker             break;
3510*d9f75844SAndroid Build Coastguard Worker         }
3511*d9f75844SAndroid Build Coastguard Worker       } else {
3512*d9f75844SAndroid Build Coastguard Worker         EXPECT_FALSE(vp9.inter_layer_predicted);
3513*d9f75844SAndroid Build Coastguard Worker       }
3514*d9f75844SAndroid Build Coastguard Worker 
3515*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(is_key_frame, !vp9.inter_pic_predicted);
3516*d9f75844SAndroid Build Coastguard Worker 
3517*d9f75844SAndroid Build Coastguard Worker       if (IsNewPictureId(vp9)) {
3518*d9f75844SAndroid Build Coastguard Worker         if (params_.num_temporal_layers == 1 &&
3519*d9f75844SAndroid Build Coastguard Worker             params_.num_spatial_layers == 1) {
3520*d9f75844SAndroid Build Coastguard Worker           EXPECT_EQ(kNoSpatialIdx, vp9.spatial_idx);
3521*d9f75844SAndroid Build Coastguard Worker         } else {
3522*d9f75844SAndroid Build Coastguard Worker           EXPECT_EQ(0, vp9.spatial_idx);
3523*d9f75844SAndroid Build Coastguard Worker         }
3524*d9f75844SAndroid Build Coastguard Worker         if (params_.num_spatial_layers > 1)
3525*d9f75844SAndroid Build Coastguard Worker           EXPECT_EQ(params_.num_spatial_layers - 1, last_vp9_.spatial_idx);
3526*d9f75844SAndroid Build Coastguard Worker       }
3527*d9f75844SAndroid Build Coastguard Worker 
3528*d9f75844SAndroid Build Coastguard Worker       VerifyFixedTemporalLayerStructure(
3529*d9f75844SAndroid Build Coastguard Worker           vp9, l_field_ ? params_.num_temporal_layers : 0);
3530*d9f75844SAndroid Build Coastguard Worker 
3531*d9f75844SAndroid Build Coastguard Worker       if (frames_sent_ > kNumFramesToSend)
3532*d9f75844SAndroid Build Coastguard Worker         observation_complete_.Set();
3533*d9f75844SAndroid Build Coastguard Worker     }
3534*d9f75844SAndroid Build Coastguard Worker     const bool use_scalability_mode_identifier_;
3535*d9f75844SAndroid Build Coastguard Worker     const bool l_field_;
3536*d9f75844SAndroid Build Coastguard Worker 
3537*d9f75844SAndroid Build Coastguard Worker    private:
3538*d9f75844SAndroid Build Coastguard Worker     void ModifySenderBitrateConfig(
3539*d9f75844SAndroid Build Coastguard Worker         BitrateConstraints* bitrate_config) override {
3540*d9f75844SAndroid Build Coastguard Worker       const int kBitrateBps = 800000;
3541*d9f75844SAndroid Build Coastguard Worker       bitrate_config->min_bitrate_bps = kBitrateBps;
3542*d9f75844SAndroid Build Coastguard Worker       bitrate_config->start_bitrate_bps = kBitrateBps;
3543*d9f75844SAndroid Build Coastguard Worker     }
3544*d9f75844SAndroid Build Coastguard Worker   } test(params, use_scalability_mode_identifier);
3545*d9f75844SAndroid Build Coastguard Worker 
3546*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
3547*d9f75844SAndroid Build Coastguard Worker }
3548*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,Vp9NonFlexModeSmallResolution)3549*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, Vp9NonFlexModeSmallResolution) {
3550*d9f75844SAndroid Build Coastguard Worker   static const size_t kNumFramesToSend = 50;
3551*d9f75844SAndroid Build Coastguard Worker   static const int kWidth = 4;
3552*d9f75844SAndroid Build Coastguard Worker   static const int kHeight = 4;
3553*d9f75844SAndroid Build Coastguard Worker   class NonFlexibleModeResolution : public Vp9HeaderObserver {
3554*d9f75844SAndroid Build Coastguard Worker    public:
3555*d9f75844SAndroid Build Coastguard Worker     explicit NonFlexibleModeResolution(const Vp9TestParams& params)
3556*d9f75844SAndroid Build Coastguard Worker         : Vp9HeaderObserver(params) {}
3557*d9f75844SAndroid Build Coastguard Worker 
3558*d9f75844SAndroid Build Coastguard Worker    private:
3559*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigsHook(
3560*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
3561*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
3562*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
3563*d9f75844SAndroid Build Coastguard Worker       encoder_config->codec_type = kVideoCodecVP9;
3564*d9f75844SAndroid Build Coastguard Worker       vp9_settings_.flexibleMode = false;
3565*d9f75844SAndroid Build Coastguard Worker       vp9_settings_.numberOfTemporalLayers = params_.num_temporal_layers;
3566*d9f75844SAndroid Build Coastguard Worker       vp9_settings_.numberOfSpatialLayers = params_.num_spatial_layers;
3567*d9f75844SAndroid Build Coastguard Worker       vp9_settings_.interLayerPred = params_.inter_layer_pred;
3568*d9f75844SAndroid Build Coastguard Worker     }
3569*d9f75844SAndroid Build Coastguard Worker 
3570*d9f75844SAndroid Build Coastguard Worker     void InspectHeader(const RTPVideoHeaderVP9& vp9_header) override {
3571*d9f75844SAndroid Build Coastguard Worker       if (frames_sent_ > kNumFramesToSend)
3572*d9f75844SAndroid Build Coastguard Worker         observation_complete_.Set();
3573*d9f75844SAndroid Build Coastguard Worker     }
3574*d9f75844SAndroid Build Coastguard Worker 
3575*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoCaptureStartResolution(int* width,
3576*d9f75844SAndroid Build Coastguard Worker                                            int* height,
3577*d9f75844SAndroid Build Coastguard Worker                                            int* frame_rate) override {
3578*d9f75844SAndroid Build Coastguard Worker       expected_width_ = kWidth;
3579*d9f75844SAndroid Build Coastguard Worker       expected_height_ = kHeight;
3580*d9f75844SAndroid Build Coastguard Worker       *width = kWidth;
3581*d9f75844SAndroid Build Coastguard Worker       *height = kHeight;
3582*d9f75844SAndroid Build Coastguard Worker     }
3583*d9f75844SAndroid Build Coastguard Worker   };
3584*d9f75844SAndroid Build Coastguard Worker 
3585*d9f75844SAndroid Build Coastguard Worker   Vp9TestParams params{"L1T1", 1, 1, InterLayerPredMode::kOn};
3586*d9f75844SAndroid Build Coastguard Worker   NonFlexibleModeResolution test(params);
3587*d9f75844SAndroid Build Coastguard Worker 
3588*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
3589*d9f75844SAndroid Build Coastguard Worker }
3590*d9f75844SAndroid Build Coastguard Worker 
3591*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_ANDROID)
3592*d9f75844SAndroid Build Coastguard Worker // Crashes on Android; bugs.webrtc.org/7401
3593*d9f75844SAndroid Build Coastguard Worker #define MAYBE_Vp9FlexModeRefCount DISABLED_Vp9FlexModeRefCount
3594*d9f75844SAndroid Build Coastguard Worker #else
3595*d9f75844SAndroid Build Coastguard Worker // TODO(webrtc:9270): Support of flexible mode is temporarily disabled. Enable
3596*d9f75844SAndroid Build Coastguard Worker // the test after webrtc:9270 is implemented.
3597*d9f75844SAndroid Build Coastguard Worker #define MAYBE_Vp9FlexModeRefCount DISABLED_Vp9FlexModeRefCount
3598*d9f75844SAndroid Build Coastguard Worker // #define MAYBE_Vp9FlexModeRefCount Vp9FlexModeRefCount
3599*d9f75844SAndroid Build Coastguard Worker #endif
TEST_F(VideoSendStreamTest,MAYBE_Vp9FlexModeRefCount)3600*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, MAYBE_Vp9FlexModeRefCount) {
3601*d9f75844SAndroid Build Coastguard Worker   class FlexibleMode : public Vp9HeaderObserver {
3602*d9f75844SAndroid Build Coastguard Worker    public:
3603*d9f75844SAndroid Build Coastguard Worker     explicit FlexibleMode(const Vp9TestParams& params)
3604*d9f75844SAndroid Build Coastguard Worker         : Vp9HeaderObserver(params) {}
3605*d9f75844SAndroid Build Coastguard Worker 
3606*d9f75844SAndroid Build Coastguard Worker    private:
3607*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigsHook(
3608*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
3609*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
3610*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
3611*d9f75844SAndroid Build Coastguard Worker       encoder_config->codec_type = kVideoCodecVP9;
3612*d9f75844SAndroid Build Coastguard Worker       encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3613*d9f75844SAndroid Build Coastguard Worker       vp9_settings_.flexibleMode = true;
3614*d9f75844SAndroid Build Coastguard Worker       vp9_settings_.numberOfTemporalLayers = params_.num_temporal_layers;
3615*d9f75844SAndroid Build Coastguard Worker       vp9_settings_.numberOfSpatialLayers = params_.num_spatial_layers;
3616*d9f75844SAndroid Build Coastguard Worker       vp9_settings_.interLayerPred = params_.inter_layer_pred;
3617*d9f75844SAndroid Build Coastguard Worker     }
3618*d9f75844SAndroid Build Coastguard Worker 
3619*d9f75844SAndroid Build Coastguard Worker     void InspectHeader(const RTPVideoHeaderVP9& vp9_header) override {
3620*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(vp9_header.flexible_mode);
3621*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(kNoTl0PicIdx, vp9_header.tl0_pic_idx);
3622*d9f75844SAndroid Build Coastguard Worker       if (vp9_header.inter_pic_predicted) {
3623*d9f75844SAndroid Build Coastguard Worker         EXPECT_GT(vp9_header.num_ref_pics, 0u);
3624*d9f75844SAndroid Build Coastguard Worker         observation_complete_.Set();
3625*d9f75844SAndroid Build Coastguard Worker       }
3626*d9f75844SAndroid Build Coastguard Worker     }
3627*d9f75844SAndroid Build Coastguard Worker   };
3628*d9f75844SAndroid Build Coastguard Worker 
3629*d9f75844SAndroid Build Coastguard Worker   Vp9TestParams params{"L2T1", 2, 1, InterLayerPredMode::kOn};
3630*d9f75844SAndroid Build Coastguard Worker   FlexibleMode test(params);
3631*d9f75844SAndroid Build Coastguard Worker 
3632*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
3633*d9f75844SAndroid Build Coastguard Worker }
3634*d9f75844SAndroid Build Coastguard Worker #endif  // defined(RTC_ENABLE_VP9)
3635*d9f75844SAndroid Build Coastguard Worker 
TestRequestSourceRotateVideo(bool support_orientation_ext)3636*d9f75844SAndroid Build Coastguard Worker void VideoSendStreamTest::TestRequestSourceRotateVideo(
3637*d9f75844SAndroid Build Coastguard Worker     bool support_orientation_ext) {
3638*d9f75844SAndroid Build Coastguard Worker   CreateSenderCall();
3639*d9f75844SAndroid Build Coastguard Worker 
3640*d9f75844SAndroid Build Coastguard Worker   test::NullTransport transport;
3641*d9f75844SAndroid Build Coastguard Worker   CreateSendConfig(1, 0, 0, &transport);
3642*d9f75844SAndroid Build Coastguard Worker   GetVideoSendConfig()->rtp.extensions.clear();
3643*d9f75844SAndroid Build Coastguard Worker   if (support_orientation_ext) {
3644*d9f75844SAndroid Build Coastguard Worker     GetVideoSendConfig()->rtp.extensions.push_back(
3645*d9f75844SAndroid Build Coastguard Worker         RtpExtension(RtpExtension::kVideoRotationUri, 1));
3646*d9f75844SAndroid Build Coastguard Worker   }
3647*d9f75844SAndroid Build Coastguard Worker 
3648*d9f75844SAndroid Build Coastguard Worker   CreateVideoStreams();
3649*d9f75844SAndroid Build Coastguard Worker   test::FrameForwarder forwarder;
3650*d9f75844SAndroid Build Coastguard Worker   GetVideoSendStream()->SetSource(&forwarder,
3651*d9f75844SAndroid Build Coastguard Worker                                   DegradationPreference::MAINTAIN_FRAMERATE);
3652*d9f75844SAndroid Build Coastguard Worker 
3653*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(forwarder.sink_wants().rotation_applied !=
3654*d9f75844SAndroid Build Coastguard Worker               support_orientation_ext);
3655*d9f75844SAndroid Build Coastguard Worker 
3656*d9f75844SAndroid Build Coastguard Worker   DestroyStreams();
3657*d9f75844SAndroid Build Coastguard Worker }
3658*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,RequestSourceRotateIfVideoOrientationExtensionNotSupported)3659*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest,
3660*d9f75844SAndroid Build Coastguard Worker        RequestSourceRotateIfVideoOrientationExtensionNotSupported) {
3661*d9f75844SAndroid Build Coastguard Worker   TestRequestSourceRotateVideo(false);
3662*d9f75844SAndroid Build Coastguard Worker }
3663*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,DoNotRequestsRotationIfVideoOrientationExtensionSupported)3664*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest,
3665*d9f75844SAndroid Build Coastguard Worker        DoNotRequestsRotationIfVideoOrientationExtensionSupported) {
3666*d9f75844SAndroid Build Coastguard Worker   TestRequestSourceRotateVideo(true);
3667*d9f75844SAndroid Build Coastguard Worker }
3668*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,EncoderConfigMaxFramerateReportedToSource)3669*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, EncoderConfigMaxFramerateReportedToSource) {
3670*d9f75844SAndroid Build Coastguard Worker   static const int kMaxFps = 22;
3671*d9f75844SAndroid Build Coastguard Worker   class FpsObserver : public test::SendTest,
3672*d9f75844SAndroid Build Coastguard Worker                       public test::FrameGeneratorCapturer::SinkWantsObserver {
3673*d9f75844SAndroid Build Coastguard Worker    public:
3674*d9f75844SAndroid Build Coastguard Worker     FpsObserver() : SendTest(kDefaultTimeout) {}
3675*d9f75844SAndroid Build Coastguard Worker 
3676*d9f75844SAndroid Build Coastguard Worker     void OnFrameGeneratorCapturerCreated(
3677*d9f75844SAndroid Build Coastguard Worker         test::FrameGeneratorCapturer* frame_generator_capturer) override {
3678*d9f75844SAndroid Build Coastguard Worker       frame_generator_capturer->SetSinkWantsObserver(this);
3679*d9f75844SAndroid Build Coastguard Worker     }
3680*d9f75844SAndroid Build Coastguard Worker 
3681*d9f75844SAndroid Build Coastguard Worker     void OnSinkWantsChanged(rtc::VideoSinkInterface<VideoFrame>* sink,
3682*d9f75844SAndroid Build Coastguard Worker                             const rtc::VideoSinkWants& wants) override {
3683*d9f75844SAndroid Build Coastguard Worker       if (wants.max_framerate_fps == kMaxFps)
3684*d9f75844SAndroid Build Coastguard Worker         observation_complete_.Set();
3685*d9f75844SAndroid Build Coastguard Worker     }
3686*d9f75844SAndroid Build Coastguard Worker 
3687*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
3688*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
3689*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
3690*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
3691*d9f75844SAndroid Build Coastguard Worker       encoder_config->simulcast_layers[0].max_framerate = kMaxFps;
3692*d9f75844SAndroid Build Coastguard Worker     }
3693*d9f75844SAndroid Build Coastguard Worker 
3694*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
3695*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(Wait()) << "Timed out while waiting for fps to be reported.";
3696*d9f75844SAndroid Build Coastguard Worker     }
3697*d9f75844SAndroid Build Coastguard Worker   } test;
3698*d9f75844SAndroid Build Coastguard Worker 
3699*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
3700*d9f75844SAndroid Build Coastguard Worker }
3701*d9f75844SAndroid Build Coastguard Worker 
3702*d9f75844SAndroid Build Coastguard Worker // This test verifies that overhead is removed from the bandwidth estimate by
3703*d9f75844SAndroid Build Coastguard Worker // testing that the maximum possible target payload rate is smaller than the
3704*d9f75844SAndroid Build Coastguard Worker // maximum bandwidth estimate by the overhead rate.
TEST_F(VideoSendStreamTest,RemoveOverheadFromBandwidth)3705*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, RemoveOverheadFromBandwidth) {
3706*d9f75844SAndroid Build Coastguard Worker   class RemoveOverheadFromBandwidthTest : public test::EndToEndTest,
3707*d9f75844SAndroid Build Coastguard Worker                                           public test::FakeEncoder {
3708*d9f75844SAndroid Build Coastguard Worker    public:
3709*d9f75844SAndroid Build Coastguard Worker     explicit RemoveOverheadFromBandwidthTest(TaskQueueBase* task_queue)
3710*d9f75844SAndroid Build Coastguard Worker         : EndToEndTest(test::CallTest::kDefaultTimeout),
3711*d9f75844SAndroid Build Coastguard Worker           FakeEncoder(Clock::GetRealTimeClock()),
3712*d9f75844SAndroid Build Coastguard Worker           task_queue_(task_queue),
3713*d9f75844SAndroid Build Coastguard Worker           encoder_factory_(this),
3714*d9f75844SAndroid Build Coastguard Worker           call_(nullptr),
3715*d9f75844SAndroid Build Coastguard Worker           max_bitrate_bps_(0),
3716*d9f75844SAndroid Build Coastguard Worker           first_packet_sent_(false) {}
3717*d9f75844SAndroid Build Coastguard Worker 
3718*d9f75844SAndroid Build Coastguard Worker     void SetRates(const RateControlParameters& parameters) override {
3719*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
3720*d9f75844SAndroid Build Coastguard Worker       // Wait for the first sent packet so that videosendstream knows
3721*d9f75844SAndroid Build Coastguard Worker       // rtp_overhead.
3722*d9f75844SAndroid Build Coastguard Worker       if (first_packet_sent_) {
3723*d9f75844SAndroid Build Coastguard Worker         max_bitrate_bps_ = parameters.bitrate.get_sum_bps();
3724*d9f75844SAndroid Build Coastguard Worker         bitrate_changed_event_.Set();
3725*d9f75844SAndroid Build Coastguard Worker       }
3726*d9f75844SAndroid Build Coastguard Worker       return FakeEncoder::SetRates(parameters);
3727*d9f75844SAndroid Build Coastguard Worker     }
3728*d9f75844SAndroid Build Coastguard Worker 
3729*d9f75844SAndroid Build Coastguard Worker     void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
3730*d9f75844SAndroid Build Coastguard Worker       call_ = sender_call;
3731*d9f75844SAndroid Build Coastguard Worker     }
3732*d9f75844SAndroid Build Coastguard Worker 
3733*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
3734*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
3735*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
3736*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
3737*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.max_packet_size = 1200;
3738*d9f75844SAndroid Build Coastguard Worker       send_config->encoder_settings.encoder_factory = &encoder_factory_;
3739*d9f75844SAndroid Build Coastguard Worker       EXPECT_FALSE(send_config->rtp.extensions.empty());
3740*d9f75844SAndroid Build Coastguard Worker     }
3741*d9f75844SAndroid Build Coastguard Worker 
3742*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
3743*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
3744*d9f75844SAndroid Build Coastguard Worker       first_packet_sent_ = true;
3745*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
3746*d9f75844SAndroid Build Coastguard Worker     }
3747*d9f75844SAndroid Build Coastguard Worker 
3748*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override {
3749*d9f75844SAndroid Build Coastguard Worker       BitrateConstraints bitrate_config;
3750*d9f75844SAndroid Build Coastguard Worker       constexpr int kStartBitrateBps = 60000;
3751*d9f75844SAndroid Build Coastguard Worker       constexpr int kMaxBitrateBps = 60000;
3752*d9f75844SAndroid Build Coastguard Worker       constexpr int kMinBitrateBps = 10000;
3753*d9f75844SAndroid Build Coastguard Worker       bitrate_config.start_bitrate_bps = kStartBitrateBps;
3754*d9f75844SAndroid Build Coastguard Worker       bitrate_config.max_bitrate_bps = kMaxBitrateBps;
3755*d9f75844SAndroid Build Coastguard Worker       bitrate_config.min_bitrate_bps = kMinBitrateBps;
3756*d9f75844SAndroid Build Coastguard Worker       SendTask(task_queue_, [this, &bitrate_config]() {
3757*d9f75844SAndroid Build Coastguard Worker         call_->GetTransportControllerSend()->SetSdpBitrateParameters(
3758*d9f75844SAndroid Build Coastguard Worker             bitrate_config);
3759*d9f75844SAndroid Build Coastguard Worker         call_->GetTransportControllerSend()->OnTransportOverheadChanged(40);
3760*d9f75844SAndroid Build Coastguard Worker       });
3761*d9f75844SAndroid Build Coastguard Worker 
3762*d9f75844SAndroid Build Coastguard Worker       // At a bitrate of 60kbps with a packet size of 1200B video and an
3763*d9f75844SAndroid Build Coastguard Worker       // overhead of 40B per packet video produces 2240bps overhead.
3764*d9f75844SAndroid Build Coastguard Worker       // So the encoder BW should be set to 57760bps.
3765*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(
3766*d9f75844SAndroid Build Coastguard Worker           bitrate_changed_event_.Wait(VideoSendStreamTest::kDefaultTimeout));
3767*d9f75844SAndroid Build Coastguard Worker       {
3768*d9f75844SAndroid Build Coastguard Worker         MutexLock lock(&mutex_);
3769*d9f75844SAndroid Build Coastguard Worker         EXPECT_LE(max_bitrate_bps_, 57760u);
3770*d9f75844SAndroid Build Coastguard Worker       }
3771*d9f75844SAndroid Build Coastguard Worker     }
3772*d9f75844SAndroid Build Coastguard Worker 
3773*d9f75844SAndroid Build Coastguard Worker    private:
3774*d9f75844SAndroid Build Coastguard Worker     TaskQueueBase* const task_queue_;
3775*d9f75844SAndroid Build Coastguard Worker     test::VideoEncoderProxyFactory encoder_factory_;
3776*d9f75844SAndroid Build Coastguard Worker     Call* call_;
3777*d9f75844SAndroid Build Coastguard Worker     Mutex mutex_;
3778*d9f75844SAndroid Build Coastguard Worker     uint32_t max_bitrate_bps_ RTC_GUARDED_BY(&mutex_);
3779*d9f75844SAndroid Build Coastguard Worker     bool first_packet_sent_ RTC_GUARDED_BY(&mutex_);
3780*d9f75844SAndroid Build Coastguard Worker     rtc::Event bitrate_changed_event_;
3781*d9f75844SAndroid Build Coastguard Worker   } test(task_queue());
3782*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
3783*d9f75844SAndroid Build Coastguard Worker }
3784*d9f75844SAndroid Build Coastguard Worker 
3785*d9f75844SAndroid Build Coastguard Worker class PacingFactorObserver : public test::SendTest {
3786*d9f75844SAndroid Build Coastguard Worker  public:
PacingFactorObserver(bool configure_send_side,absl::optional<float> expected_pacing_factor)3787*d9f75844SAndroid Build Coastguard Worker   PacingFactorObserver(bool configure_send_side,
3788*d9f75844SAndroid Build Coastguard Worker                        absl::optional<float> expected_pacing_factor)
3789*d9f75844SAndroid Build Coastguard Worker       : test::SendTest(VideoSendStreamTest::kDefaultTimeout),
3790*d9f75844SAndroid Build Coastguard Worker         configure_send_side_(configure_send_side),
3791*d9f75844SAndroid Build Coastguard Worker         expected_pacing_factor_(expected_pacing_factor) {}
3792*d9f75844SAndroid Build Coastguard Worker 
ModifyVideoConfigs(VideoSendStream::Config * send_config,std::vector<VideoReceiveStreamInterface::Config> * receive_configs,VideoEncoderConfig * encoder_config)3793*d9f75844SAndroid Build Coastguard Worker   void ModifyVideoConfigs(
3794*d9f75844SAndroid Build Coastguard Worker       VideoSendStream::Config* send_config,
3795*d9f75844SAndroid Build Coastguard Worker       std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
3796*d9f75844SAndroid Build Coastguard Worker       VideoEncoderConfig* encoder_config) override {
3797*d9f75844SAndroid Build Coastguard Worker     // Check if send-side bwe extension is already present, and remove it if
3798*d9f75844SAndroid Build Coastguard Worker     // it is not desired.
3799*d9f75844SAndroid Build Coastguard Worker     bool has_send_side = false;
3800*d9f75844SAndroid Build Coastguard Worker     for (auto it = send_config->rtp.extensions.begin();
3801*d9f75844SAndroid Build Coastguard Worker          it != send_config->rtp.extensions.end(); ++it) {
3802*d9f75844SAndroid Build Coastguard Worker       if (it->uri == RtpExtension::kTransportSequenceNumberUri) {
3803*d9f75844SAndroid Build Coastguard Worker         if (configure_send_side_) {
3804*d9f75844SAndroid Build Coastguard Worker           has_send_side = true;
3805*d9f75844SAndroid Build Coastguard Worker         } else {
3806*d9f75844SAndroid Build Coastguard Worker           send_config->rtp.extensions.erase(it);
3807*d9f75844SAndroid Build Coastguard Worker         }
3808*d9f75844SAndroid Build Coastguard Worker         break;
3809*d9f75844SAndroid Build Coastguard Worker       }
3810*d9f75844SAndroid Build Coastguard Worker     }
3811*d9f75844SAndroid Build Coastguard Worker 
3812*d9f75844SAndroid Build Coastguard Worker     if (configure_send_side_ && !has_send_side) {
3813*d9f75844SAndroid Build Coastguard Worker       rtc::UniqueNumberGenerator<int> unique_id_generator;
3814*d9f75844SAndroid Build Coastguard Worker       unique_id_generator.AddKnownId(0);  // First valid RTP extension ID is 1.
3815*d9f75844SAndroid Build Coastguard Worker       for (const RtpExtension& extension : send_config->rtp.extensions) {
3816*d9f75844SAndroid Build Coastguard Worker         unique_id_generator.AddKnownId(extension.id);
3817*d9f75844SAndroid Build Coastguard Worker       }
3818*d9f75844SAndroid Build Coastguard Worker       // Want send side, not present by default, so add it.
3819*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.extensions.emplace_back(
3820*d9f75844SAndroid Build Coastguard Worker           RtpExtension::kTransportSequenceNumberUri, unique_id_generator());
3821*d9f75844SAndroid Build Coastguard Worker     }
3822*d9f75844SAndroid Build Coastguard Worker 
3823*d9f75844SAndroid Build Coastguard Worker     // ALR only enabled for screenshare.
3824*d9f75844SAndroid Build Coastguard Worker     encoder_config->content_type = VideoEncoderConfig::ContentType::kScreen;
3825*d9f75844SAndroid Build Coastguard Worker   }
3826*d9f75844SAndroid Build Coastguard Worker 
OnVideoStreamsCreated(VideoSendStream * send_stream,const std::vector<VideoReceiveStreamInterface * > & receive_streams)3827*d9f75844SAndroid Build Coastguard Worker   void OnVideoStreamsCreated(VideoSendStream* send_stream,
3828*d9f75844SAndroid Build Coastguard Worker                              const std::vector<VideoReceiveStreamInterface*>&
3829*d9f75844SAndroid Build Coastguard Worker                                  receive_streams) override {
3830*d9f75844SAndroid Build Coastguard Worker     auto internal_send_peer = test::VideoSendStreamPeer(send_stream);
3831*d9f75844SAndroid Build Coastguard Worker     // Video streams created, check that pacing factor is correctly configured.
3832*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(expected_pacing_factor_,
3833*d9f75844SAndroid Build Coastguard Worker               internal_send_peer.GetPacingFactorOverride());
3834*d9f75844SAndroid Build Coastguard Worker     observation_complete_.Set();
3835*d9f75844SAndroid Build Coastguard Worker   }
3836*d9f75844SAndroid Build Coastguard Worker 
PerformTest()3837*d9f75844SAndroid Build Coastguard Worker   void PerformTest() override {
3838*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(Wait()) << "Timed out while waiting for stream creation.";
3839*d9f75844SAndroid Build Coastguard Worker   }
3840*d9f75844SAndroid Build Coastguard Worker 
3841*d9f75844SAndroid Build Coastguard Worker  private:
3842*d9f75844SAndroid Build Coastguard Worker   const bool configure_send_side_;
3843*d9f75844SAndroid Build Coastguard Worker   const absl::optional<float> expected_pacing_factor_;
3844*d9f75844SAndroid Build Coastguard Worker };
3845*d9f75844SAndroid Build Coastguard Worker 
GetAlrProbingExperimentString()3846*d9f75844SAndroid Build Coastguard Worker std::string GetAlrProbingExperimentString() {
3847*d9f75844SAndroid Build Coastguard Worker   return std::string(
3848*d9f75844SAndroid Build Coastguard Worker              AlrExperimentSettings::kScreenshareProbingBweExperimentName) +
3849*d9f75844SAndroid Build Coastguard Worker          "/1.0,2875,80,40,-60,3/";
3850*d9f75844SAndroid Build Coastguard Worker }
3851*d9f75844SAndroid Build Coastguard Worker const float kAlrProbingExperimentPaceMultiplier = 1.0f;
3852*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,AlrConfiguredWhenSendSideOn)3853*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, AlrConfiguredWhenSendSideOn) {
3854*d9f75844SAndroid Build Coastguard Worker   test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString());
3855*d9f75844SAndroid Build Coastguard Worker   // Send-side bwe on, use pacing factor from `kAlrProbingExperiment` above.
3856*d9f75844SAndroid Build Coastguard Worker   PacingFactorObserver test_with_send_side(true,
3857*d9f75844SAndroid Build Coastguard Worker                                            kAlrProbingExperimentPaceMultiplier);
3858*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test_with_send_side);
3859*d9f75844SAndroid Build Coastguard Worker }
3860*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,AlrNotConfiguredWhenSendSideOff)3861*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, AlrNotConfiguredWhenSendSideOff) {
3862*d9f75844SAndroid Build Coastguard Worker   test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString());
3863*d9f75844SAndroid Build Coastguard Worker   // Send-side bwe off, use configuration should not be overridden.
3864*d9f75844SAndroid Build Coastguard Worker   PacingFactorObserver test_without_send_side(false, absl::nullopt);
3865*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test_without_send_side);
3866*d9f75844SAndroid Build Coastguard Worker }
3867*d9f75844SAndroid Build Coastguard Worker 
3868*d9f75844SAndroid Build Coastguard Worker // Test class takes as argument a function pointer to reset the send
3869*d9f75844SAndroid Build Coastguard Worker // stream and call OnVideoStreamsCreated. This is necessary since you cannot
3870*d9f75844SAndroid Build Coastguard Worker // change the content type of a VideoSendStream, you need to recreate it.
3871*d9f75844SAndroid Build Coastguard Worker // Stopping and recreating the stream can only be done on the main thread and in
3872*d9f75844SAndroid Build Coastguard Worker // the context of VideoSendStreamTest (not BaseTest). The test switches from
3873*d9f75844SAndroid Build Coastguard Worker // realtime to screenshare and back.
3874*d9f75844SAndroid Build Coastguard Worker template <typename T>
3875*d9f75844SAndroid Build Coastguard Worker class ContentSwitchTest : public test::SendTest {
3876*d9f75844SAndroid Build Coastguard Worker  public:
3877*d9f75844SAndroid Build Coastguard Worker   enum class StreamState {
3878*d9f75844SAndroid Build Coastguard Worker     kBeforeSwitch = 0,
3879*d9f75844SAndroid Build Coastguard Worker     kInScreenshare = 1,
3880*d9f75844SAndroid Build Coastguard Worker     kAfterSwitchBack = 2,
3881*d9f75844SAndroid Build Coastguard Worker   };
3882*d9f75844SAndroid Build Coastguard Worker   static const uint32_t kMinPacketsToSend = 50;
3883*d9f75844SAndroid Build Coastguard Worker 
ContentSwitchTest(T * stream_reset_fun,TaskQueueBase * task_queue)3884*d9f75844SAndroid Build Coastguard Worker   explicit ContentSwitchTest(T* stream_reset_fun, TaskQueueBase* task_queue)
3885*d9f75844SAndroid Build Coastguard Worker       : SendTest(test::CallTest::kDefaultTimeout),
3886*d9f75844SAndroid Build Coastguard Worker         call_(nullptr),
3887*d9f75844SAndroid Build Coastguard Worker         state_(StreamState::kBeforeSwitch),
3888*d9f75844SAndroid Build Coastguard Worker         send_stream_(nullptr),
3889*d9f75844SAndroid Build Coastguard Worker         send_stream_config_(nullptr),
3890*d9f75844SAndroid Build Coastguard Worker         packets_sent_(0),
3891*d9f75844SAndroid Build Coastguard Worker         stream_resetter_(stream_reset_fun),
3892*d9f75844SAndroid Build Coastguard Worker         task_queue_(task_queue) {
3893*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(stream_resetter_);
3894*d9f75844SAndroid Build Coastguard Worker   }
3895*d9f75844SAndroid Build Coastguard Worker 
OnVideoStreamsCreated(VideoSendStream * send_stream,const std::vector<VideoReceiveStreamInterface * > & receive_streams)3896*d9f75844SAndroid Build Coastguard Worker   void OnVideoStreamsCreated(VideoSendStream* send_stream,
3897*d9f75844SAndroid Build Coastguard Worker                              const std::vector<VideoReceiveStreamInterface*>&
3898*d9f75844SAndroid Build Coastguard Worker                                  receive_streams) override {
3899*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&mutex_);
3900*d9f75844SAndroid Build Coastguard Worker     send_stream_ = send_stream;
3901*d9f75844SAndroid Build Coastguard Worker   }
3902*d9f75844SAndroid Build Coastguard Worker 
ModifyVideoConfigs(VideoSendStream::Config * send_config,std::vector<VideoReceiveStreamInterface::Config> * receive_configs,VideoEncoderConfig * encoder_config)3903*d9f75844SAndroid Build Coastguard Worker   void ModifyVideoConfigs(
3904*d9f75844SAndroid Build Coastguard Worker       VideoSendStream::Config* send_config,
3905*d9f75844SAndroid Build Coastguard Worker       std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
3906*d9f75844SAndroid Build Coastguard Worker       VideoEncoderConfig* encoder_config) override {
3907*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
3908*d9f75844SAndroid Build Coastguard Worker     encoder_config->min_transmit_bitrate_bps = 0;
3909*d9f75844SAndroid Build Coastguard Worker     encoder_config->content_type =
3910*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig::ContentType::kRealtimeVideo;
3911*d9f75844SAndroid Build Coastguard Worker     send_stream_config_ = send_config->Copy();
3912*d9f75844SAndroid Build Coastguard Worker     encoder_config_ = encoder_config->Copy();
3913*d9f75844SAndroid Build Coastguard Worker   }
3914*d9f75844SAndroid Build Coastguard Worker 
OnCallsCreated(Call * sender_call,Call * receiver_call)3915*d9f75844SAndroid Build Coastguard Worker   void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
3916*d9f75844SAndroid Build Coastguard Worker     call_ = sender_call;
3917*d9f75844SAndroid Build Coastguard Worker   }
3918*d9f75844SAndroid Build Coastguard Worker 
OnStreamsStopped()3919*d9f75844SAndroid Build Coastguard Worker   void OnStreamsStopped() override {
3920*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&mutex_);
3921*d9f75844SAndroid Build Coastguard Worker     done_ = true;
3922*d9f75844SAndroid Build Coastguard Worker   }
3923*d9f75844SAndroid Build Coastguard Worker 
OnSendRtp(const uint8_t * packet,size_t length)3924*d9f75844SAndroid Build Coastguard Worker   Action OnSendRtp(const uint8_t* packet, size_t length) override {
3925*d9f75844SAndroid Build Coastguard Worker     task_queue_->PostTask([this]() {
3926*d9f75844SAndroid Build Coastguard Worker       MutexLock lock(&mutex_);
3927*d9f75844SAndroid Build Coastguard Worker       if (done_)
3928*d9f75844SAndroid Build Coastguard Worker         return;
3929*d9f75844SAndroid Build Coastguard Worker 
3930*d9f75844SAndroid Build Coastguard Worker       auto internal_send_peer = test::VideoSendStreamPeer(send_stream_);
3931*d9f75844SAndroid Build Coastguard Worker       float pacing_factor =
3932*d9f75844SAndroid Build Coastguard Worker           internal_send_peer.GetPacingFactorOverride().value_or(0.0f);
3933*d9f75844SAndroid Build Coastguard Worker       float expected_pacing_factor = 1.1;  // Strict pacing factor.
3934*d9f75844SAndroid Build Coastguard Worker       VideoSendStream::Stats stats = send_stream_->GetStats();
3935*d9f75844SAndroid Build Coastguard Worker       if (stats.content_type == webrtc::VideoContentType::SCREENSHARE) {
3936*d9f75844SAndroid Build Coastguard Worker         expected_pacing_factor = 1.0f;  // Currently used pacing factor in ALR.
3937*d9f75844SAndroid Build Coastguard Worker       }
3938*d9f75844SAndroid Build Coastguard Worker 
3939*d9f75844SAndroid Build Coastguard Worker       EXPECT_NEAR(expected_pacing_factor, pacing_factor, 1e-6);
3940*d9f75844SAndroid Build Coastguard Worker 
3941*d9f75844SAndroid Build Coastguard Worker       // Wait until at least kMinPacketsToSend packets to be sent, so that
3942*d9f75844SAndroid Build Coastguard Worker       // some frames would be encoded.
3943*d9f75844SAndroid Build Coastguard Worker       if (++packets_sent_ < kMinPacketsToSend)
3944*d9f75844SAndroid Build Coastguard Worker         return;
3945*d9f75844SAndroid Build Coastguard Worker 
3946*d9f75844SAndroid Build Coastguard Worker       if (state_ != StreamState::kAfterSwitchBack) {
3947*d9f75844SAndroid Build Coastguard Worker         // We've sent kMinPacketsToSend packets, switch the content type and
3948*d9f75844SAndroid Build Coastguard Worker         // move move to the next state. Note that we need to recreate the stream
3949*d9f75844SAndroid Build Coastguard Worker         // if changing content type.
3950*d9f75844SAndroid Build Coastguard Worker         packets_sent_ = 0;
3951*d9f75844SAndroid Build Coastguard Worker         if (encoder_config_.content_type ==
3952*d9f75844SAndroid Build Coastguard Worker             VideoEncoderConfig::ContentType::kRealtimeVideo) {
3953*d9f75844SAndroid Build Coastguard Worker           encoder_config_.content_type =
3954*d9f75844SAndroid Build Coastguard Worker               VideoEncoderConfig::ContentType::kScreen;
3955*d9f75844SAndroid Build Coastguard Worker         } else {
3956*d9f75844SAndroid Build Coastguard Worker           encoder_config_.content_type =
3957*d9f75844SAndroid Build Coastguard Worker               VideoEncoderConfig::ContentType::kRealtimeVideo;
3958*d9f75844SAndroid Build Coastguard Worker         }
3959*d9f75844SAndroid Build Coastguard Worker         switch (state_) {
3960*d9f75844SAndroid Build Coastguard Worker           case StreamState::kBeforeSwitch:
3961*d9f75844SAndroid Build Coastguard Worker             state_ = StreamState::kInScreenshare;
3962*d9f75844SAndroid Build Coastguard Worker             break;
3963*d9f75844SAndroid Build Coastguard Worker           case StreamState::kInScreenshare:
3964*d9f75844SAndroid Build Coastguard Worker             state_ = StreamState::kAfterSwitchBack;
3965*d9f75844SAndroid Build Coastguard Worker             break;
3966*d9f75844SAndroid Build Coastguard Worker           case StreamState::kAfterSwitchBack:
3967*d9f75844SAndroid Build Coastguard Worker             RTC_DCHECK_NOTREACHED();
3968*d9f75844SAndroid Build Coastguard Worker             break;
3969*d9f75844SAndroid Build Coastguard Worker         }
3970*d9f75844SAndroid Build Coastguard Worker         content_switch_event_.Set();
3971*d9f75844SAndroid Build Coastguard Worker         return;
3972*d9f75844SAndroid Build Coastguard Worker       }
3973*d9f75844SAndroid Build Coastguard Worker       observation_complete_.Set();
3974*d9f75844SAndroid Build Coastguard Worker     });
3975*d9f75844SAndroid Build Coastguard Worker 
3976*d9f75844SAndroid Build Coastguard Worker     return SEND_PACKET;
3977*d9f75844SAndroid Build Coastguard Worker   }
3978*d9f75844SAndroid Build Coastguard Worker 
PerformTest()3979*d9f75844SAndroid Build Coastguard Worker   void PerformTest() override {
3980*d9f75844SAndroid Build Coastguard Worker     while (GetStreamState() != StreamState::kAfterSwitchBack) {
3981*d9f75844SAndroid Build Coastguard Worker       ASSERT_TRUE(content_switch_event_.Wait(test::CallTest::kDefaultTimeout));
3982*d9f75844SAndroid Build Coastguard Worker       (*stream_resetter_)(send_stream_config_, encoder_config_, this);
3983*d9f75844SAndroid Build Coastguard Worker     }
3984*d9f75844SAndroid Build Coastguard Worker 
3985*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(Wait())
3986*d9f75844SAndroid Build Coastguard Worker         << "Timed out waiting for a frame sent after switch back";
3987*d9f75844SAndroid Build Coastguard Worker   }
3988*d9f75844SAndroid Build Coastguard Worker 
3989*d9f75844SAndroid Build Coastguard Worker  private:
GetStreamState()3990*d9f75844SAndroid Build Coastguard Worker   StreamState GetStreamState() {
3991*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&mutex_);
3992*d9f75844SAndroid Build Coastguard Worker     return state_;
3993*d9f75844SAndroid Build Coastguard Worker   }
3994*d9f75844SAndroid Build Coastguard Worker 
3995*d9f75844SAndroid Build Coastguard Worker   Mutex mutex_;
3996*d9f75844SAndroid Build Coastguard Worker   rtc::Event content_switch_event_;
3997*d9f75844SAndroid Build Coastguard Worker   Call* call_;
3998*d9f75844SAndroid Build Coastguard Worker   bool done_ RTC_GUARDED_BY(mutex_) = false;
3999*d9f75844SAndroid Build Coastguard Worker   StreamState state_ RTC_GUARDED_BY(mutex_);
4000*d9f75844SAndroid Build Coastguard Worker   VideoSendStream* send_stream_ RTC_GUARDED_BY(mutex_);
4001*d9f75844SAndroid Build Coastguard Worker   VideoSendStream::Config send_stream_config_;
4002*d9f75844SAndroid Build Coastguard Worker   VideoEncoderConfig encoder_config_;
4003*d9f75844SAndroid Build Coastguard Worker   uint32_t packets_sent_ RTC_GUARDED_BY(mutex_);
4004*d9f75844SAndroid Build Coastguard Worker   T* stream_resetter_;
4005*d9f75844SAndroid Build Coastguard Worker   TaskQueueBase* task_queue_;
4006*d9f75844SAndroid Build Coastguard Worker };
4007*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,SwitchesToScreenshareAndBack)4008*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, SwitchesToScreenshareAndBack) {
4009*d9f75844SAndroid Build Coastguard Worker   auto reset_fun = [this](const VideoSendStream::Config& send_stream_config,
4010*d9f75844SAndroid Build Coastguard Worker                           const VideoEncoderConfig& encoder_config,
4011*d9f75844SAndroid Build Coastguard Worker                           test::BaseTest* test) {
4012*d9f75844SAndroid Build Coastguard Worker     SendTask(task_queue(),
4013*d9f75844SAndroid Build Coastguard Worker              [this, &send_stream_config, &encoder_config, &test]() {
4014*d9f75844SAndroid Build Coastguard Worker                Stop();
4015*d9f75844SAndroid Build Coastguard Worker                DestroyVideoSendStreams();
4016*d9f75844SAndroid Build Coastguard Worker                SetVideoSendConfig(send_stream_config);
4017*d9f75844SAndroid Build Coastguard Worker                SetVideoEncoderConfig(encoder_config);
4018*d9f75844SAndroid Build Coastguard Worker                CreateVideoSendStreams();
4019*d9f75844SAndroid Build Coastguard Worker                SetVideoDegradation(DegradationPreference::MAINTAIN_RESOLUTION);
4020*d9f75844SAndroid Build Coastguard Worker                test->OnVideoStreamsCreated(GetVideoSendStream(),
4021*d9f75844SAndroid Build Coastguard Worker                                            video_receive_streams_);
4022*d9f75844SAndroid Build Coastguard Worker                Start();
4023*d9f75844SAndroid Build Coastguard Worker              });
4024*d9f75844SAndroid Build Coastguard Worker   };
4025*d9f75844SAndroid Build Coastguard Worker   ContentSwitchTest<decltype(reset_fun)> test(&reset_fun, task_queue());
4026*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
4027*d9f75844SAndroid Build Coastguard Worker }
4028*d9f75844SAndroid Build Coastguard Worker 
TestTemporalLayers(VideoEncoderFactory * encoder_factory,const std::string & payload_name,const std::vector<int> & num_temporal_layers,const std::vector<ScalabilityMode> & scalability_mode)4029*d9f75844SAndroid Build Coastguard Worker void VideoSendStreamTest::TestTemporalLayers(
4030*d9f75844SAndroid Build Coastguard Worker     VideoEncoderFactory* encoder_factory,
4031*d9f75844SAndroid Build Coastguard Worker     const std::string& payload_name,
4032*d9f75844SAndroid Build Coastguard Worker     const std::vector<int>& num_temporal_layers,
4033*d9f75844SAndroid Build Coastguard Worker     const std::vector<ScalabilityMode>& scalability_mode) {
4034*d9f75844SAndroid Build Coastguard Worker   static constexpr int kMaxBitrateBps = 1000000;
4035*d9f75844SAndroid Build Coastguard Worker   static constexpr int kMinFramesToObservePerStream = 8;
4036*d9f75844SAndroid Build Coastguard Worker 
4037*d9f75844SAndroid Build Coastguard Worker   class TemporalLayerObserver
4038*d9f75844SAndroid Build Coastguard Worker       : public test::EndToEndTest,
4039*d9f75844SAndroid Build Coastguard Worker         public test::FrameGeneratorCapturer::SinkWantsObserver {
4040*d9f75844SAndroid Build Coastguard Worker    public:
4041*d9f75844SAndroid Build Coastguard Worker     TemporalLayerObserver(VideoEncoderFactory* encoder_factory,
4042*d9f75844SAndroid Build Coastguard Worker                           const std::string& payload_name,
4043*d9f75844SAndroid Build Coastguard Worker                           const std::vector<int>& num_temporal_layers,
4044*d9f75844SAndroid Build Coastguard Worker                           const std::vector<ScalabilityMode>& scalability_mode)
4045*d9f75844SAndroid Build Coastguard Worker         : EndToEndTest(kDefaultTimeout),
4046*d9f75844SAndroid Build Coastguard Worker           encoder_factory_(encoder_factory),
4047*d9f75844SAndroid Build Coastguard Worker           payload_name_(payload_name),
4048*d9f75844SAndroid Build Coastguard Worker           num_temporal_layers_(num_temporal_layers),
4049*d9f75844SAndroid Build Coastguard Worker           scalability_mode_(scalability_mode),
4050*d9f75844SAndroid Build Coastguard Worker           depacketizer_(CreateVideoRtpDepacketizer(
4051*d9f75844SAndroid Build Coastguard Worker               PayloadStringToCodecType(payload_name))) {}
4052*d9f75844SAndroid Build Coastguard Worker 
4053*d9f75844SAndroid Build Coastguard Worker    private:
4054*d9f75844SAndroid Build Coastguard Worker     void OnFrameGeneratorCapturerCreated(
4055*d9f75844SAndroid Build Coastguard Worker         test::FrameGeneratorCapturer* frame_generator_capturer) override {
4056*d9f75844SAndroid Build Coastguard Worker       frame_generator_capturer->ChangeResolution(640, 360);
4057*d9f75844SAndroid Build Coastguard Worker     }
4058*d9f75844SAndroid Build Coastguard Worker 
4059*d9f75844SAndroid Build Coastguard Worker     void OnSinkWantsChanged(rtc::VideoSinkInterface<VideoFrame>* sink,
4060*d9f75844SAndroid Build Coastguard Worker                             const rtc::VideoSinkWants& wants) override {}
4061*d9f75844SAndroid Build Coastguard Worker 
4062*d9f75844SAndroid Build Coastguard Worker     void ModifySenderBitrateConfig(
4063*d9f75844SAndroid Build Coastguard Worker         BitrateConstraints* bitrate_config) override {
4064*d9f75844SAndroid Build Coastguard Worker       bitrate_config->start_bitrate_bps = kMaxBitrateBps / 2;
4065*d9f75844SAndroid Build Coastguard Worker     }
4066*d9f75844SAndroid Build Coastguard Worker 
4067*d9f75844SAndroid Build Coastguard Worker     size_t GetNumVideoStreams() const override {
4068*d9f75844SAndroid Build Coastguard Worker       if (scalability_mode_.empty()) {
4069*d9f75844SAndroid Build Coastguard Worker         return num_temporal_layers_.size();
4070*d9f75844SAndroid Build Coastguard Worker       } else {
4071*d9f75844SAndroid Build Coastguard Worker         return scalability_mode_.size();
4072*d9f75844SAndroid Build Coastguard Worker       }
4073*d9f75844SAndroid Build Coastguard Worker     }
4074*d9f75844SAndroid Build Coastguard Worker 
4075*d9f75844SAndroid Build Coastguard Worker     void ModifyVideoConfigs(
4076*d9f75844SAndroid Build Coastguard Worker         VideoSendStream::Config* send_config,
4077*d9f75844SAndroid Build Coastguard Worker         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
4078*d9f75844SAndroid Build Coastguard Worker         VideoEncoderConfig* encoder_config) override {
4079*d9f75844SAndroid Build Coastguard Worker       webrtc::VideoEncoder::EncoderInfo encoder_info;
4080*d9f75844SAndroid Build Coastguard Worker       send_config->encoder_settings.encoder_factory = encoder_factory_;
4081*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.payload_name = payload_name_;
4082*d9f75844SAndroid Build Coastguard Worker       send_config->rtp.payload_type = test::CallTest::kVideoSendPayloadType;
4083*d9f75844SAndroid Build Coastguard Worker       encoder_config->video_format.name = payload_name_;
4084*d9f75844SAndroid Build Coastguard Worker       encoder_config->codec_type = PayloadStringToCodecType(payload_name_);
4085*d9f75844SAndroid Build Coastguard Worker       encoder_config->video_stream_factory =
4086*d9f75844SAndroid Build Coastguard Worker           rtc::make_ref_counted<cricket::EncoderStreamFactory>(
4087*d9f75844SAndroid Build Coastguard Worker               payload_name_, /*max_qp=*/56, /*is_screenshare=*/false,
4088*d9f75844SAndroid Build Coastguard Worker               /*conference_mode=*/false, encoder_info);
4089*d9f75844SAndroid Build Coastguard Worker       encoder_config->max_bitrate_bps = kMaxBitrateBps;
4090*d9f75844SAndroid Build Coastguard Worker       if (absl::EqualsIgnoreCase(payload_name_, "VP9")) {
4091*d9f75844SAndroid Build Coastguard Worker         encoder_config->encoder_specific_settings = rtc::make_ref_counted<
4092*d9f75844SAndroid Build Coastguard Worker             VideoEncoderConfig::Vp9EncoderSpecificSettings>(
4093*d9f75844SAndroid Build Coastguard Worker             VideoEncoder::GetDefaultVp9Settings());
4094*d9f75844SAndroid Build Coastguard Worker       }
4095*d9f75844SAndroid Build Coastguard Worker       if (scalability_mode_.empty()) {
4096*d9f75844SAndroid Build Coastguard Worker         for (size_t i = 0; i < num_temporal_layers_.size(); ++i) {
4097*d9f75844SAndroid Build Coastguard Worker           VideoStream& stream = encoder_config->simulcast_layers[i];
4098*d9f75844SAndroid Build Coastguard Worker           stream.num_temporal_layers = num_temporal_layers_[i];
4099*d9f75844SAndroid Build Coastguard Worker           configured_num_temporal_layers_[send_config->rtp.ssrcs[i]] =
4100*d9f75844SAndroid Build Coastguard Worker               num_temporal_layers_[i];
4101*d9f75844SAndroid Build Coastguard Worker         }
4102*d9f75844SAndroid Build Coastguard Worker       } else {
4103*d9f75844SAndroid Build Coastguard Worker         for (size_t i = 0; i < scalability_mode_.size(); ++i) {
4104*d9f75844SAndroid Build Coastguard Worker           VideoStream& stream = encoder_config->simulcast_layers[i];
4105*d9f75844SAndroid Build Coastguard Worker           stream.scalability_mode = scalability_mode_[i];
4106*d9f75844SAndroid Build Coastguard Worker 
4107*d9f75844SAndroid Build Coastguard Worker           configured_num_temporal_layers_[send_config->rtp.ssrcs[i]] =
4108*d9f75844SAndroid Build Coastguard Worker               ScalabilityModeToNumTemporalLayers(scalability_mode_[i]);
4109*d9f75844SAndroid Build Coastguard Worker         }
4110*d9f75844SAndroid Build Coastguard Worker       }
4111*d9f75844SAndroid Build Coastguard Worker     }
4112*d9f75844SAndroid Build Coastguard Worker 
4113*d9f75844SAndroid Build Coastguard Worker     struct ParsedPacket {
4114*d9f75844SAndroid Build Coastguard Worker       uint32_t timestamp;
4115*d9f75844SAndroid Build Coastguard Worker       uint32_t ssrc;
4116*d9f75844SAndroid Build Coastguard Worker       int temporal_idx;
4117*d9f75844SAndroid Build Coastguard Worker     };
4118*d9f75844SAndroid Build Coastguard Worker 
4119*d9f75844SAndroid Build Coastguard Worker     bool ParsePayload(const uint8_t* packet,
4120*d9f75844SAndroid Build Coastguard Worker                       size_t length,
4121*d9f75844SAndroid Build Coastguard Worker                       ParsedPacket& parsed) const {
4122*d9f75844SAndroid Build Coastguard Worker       RtpPacket rtp_packet;
4123*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(rtp_packet.Parse(packet, length));
4124*d9f75844SAndroid Build Coastguard Worker 
4125*d9f75844SAndroid Build Coastguard Worker       if (rtp_packet.payload_size() == 0) {
4126*d9f75844SAndroid Build Coastguard Worker         return false;  // Padding packet.
4127*d9f75844SAndroid Build Coastguard Worker       }
4128*d9f75844SAndroid Build Coastguard Worker       parsed.timestamp = rtp_packet.Timestamp();
4129*d9f75844SAndroid Build Coastguard Worker       parsed.ssrc = rtp_packet.Ssrc();
4130*d9f75844SAndroid Build Coastguard Worker 
4131*d9f75844SAndroid Build Coastguard Worker       absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed_payload =
4132*d9f75844SAndroid Build Coastguard Worker           depacketizer_->Parse(rtp_packet.PayloadBuffer());
4133*d9f75844SAndroid Build Coastguard Worker       EXPECT_TRUE(parsed_payload);
4134*d9f75844SAndroid Build Coastguard Worker 
4135*d9f75844SAndroid Build Coastguard Worker       if (const auto* vp8_header = absl::get_if<RTPVideoHeaderVP8>(
4136*d9f75844SAndroid Build Coastguard Worker               &parsed_payload->video_header.video_type_header)) {
4137*d9f75844SAndroid Build Coastguard Worker         parsed.temporal_idx = vp8_header->temporalIdx;
4138*d9f75844SAndroid Build Coastguard Worker       } else if (const auto* vp9_header = absl::get_if<RTPVideoHeaderVP9>(
4139*d9f75844SAndroid Build Coastguard Worker                      &parsed_payload->video_header.video_type_header)) {
4140*d9f75844SAndroid Build Coastguard Worker         parsed.temporal_idx = vp9_header->temporal_idx;
4141*d9f75844SAndroid Build Coastguard Worker       } else {
4142*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK_NOTREACHED();
4143*d9f75844SAndroid Build Coastguard Worker       }
4144*d9f75844SAndroid Build Coastguard Worker       return true;
4145*d9f75844SAndroid Build Coastguard Worker     }
4146*d9f75844SAndroid Build Coastguard Worker 
4147*d9f75844SAndroid Build Coastguard Worker     Action OnSendRtp(const uint8_t* packet, size_t length) override {
4148*d9f75844SAndroid Build Coastguard Worker       ParsedPacket parsed;
4149*d9f75844SAndroid Build Coastguard Worker       if (!ParsePayload(packet, length, parsed))
4150*d9f75844SAndroid Build Coastguard Worker         return SEND_PACKET;
4151*d9f75844SAndroid Build Coastguard Worker 
4152*d9f75844SAndroid Build Coastguard Worker       uint32_t ssrc = parsed.ssrc;
4153*d9f75844SAndroid Build Coastguard Worker       int temporal_idx =
4154*d9f75844SAndroid Build Coastguard Worker           parsed.temporal_idx == kNoTemporalIdx ? 0 : parsed.temporal_idx;
4155*d9f75844SAndroid Build Coastguard Worker       max_observed_tl_idxs_[ssrc] =
4156*d9f75844SAndroid Build Coastguard Worker           std::max(temporal_idx, max_observed_tl_idxs_[ssrc]);
4157*d9f75844SAndroid Build Coastguard Worker 
4158*d9f75844SAndroid Build Coastguard Worker       if (last_observed_packet_.count(ssrc) == 0 ||
4159*d9f75844SAndroid Build Coastguard Worker           parsed.timestamp != last_observed_packet_[ssrc].timestamp) {
4160*d9f75844SAndroid Build Coastguard Worker         num_observed_frames_[ssrc]++;
4161*d9f75844SAndroid Build Coastguard Worker       }
4162*d9f75844SAndroid Build Coastguard Worker       last_observed_packet_[ssrc] = parsed;
4163*d9f75844SAndroid Build Coastguard Worker 
4164*d9f75844SAndroid Build Coastguard Worker       if (HighestTemporalLayerSentPerStream())
4165*d9f75844SAndroid Build Coastguard Worker         observation_complete_.Set();
4166*d9f75844SAndroid Build Coastguard Worker 
4167*d9f75844SAndroid Build Coastguard Worker       return SEND_PACKET;
4168*d9f75844SAndroid Build Coastguard Worker     }
4169*d9f75844SAndroid Build Coastguard Worker 
4170*d9f75844SAndroid Build Coastguard Worker     bool HighestTemporalLayerSentPerStream() const {
4171*d9f75844SAndroid Build Coastguard Worker       if (num_observed_frames_.size() !=
4172*d9f75844SAndroid Build Coastguard Worker           configured_num_temporal_layers_.size()) {
4173*d9f75844SAndroid Build Coastguard Worker         return false;
4174*d9f75844SAndroid Build Coastguard Worker       }
4175*d9f75844SAndroid Build Coastguard Worker       for (const auto& num_frames : num_observed_frames_) {
4176*d9f75844SAndroid Build Coastguard Worker         if (num_frames.second < kMinFramesToObservePerStream) {
4177*d9f75844SAndroid Build Coastguard Worker           return false;
4178*d9f75844SAndroid Build Coastguard Worker         }
4179*d9f75844SAndroid Build Coastguard Worker       }
4180*d9f75844SAndroid Build Coastguard Worker       if (max_observed_tl_idxs_.size() !=
4181*d9f75844SAndroid Build Coastguard Worker           configured_num_temporal_layers_.size()) {
4182*d9f75844SAndroid Build Coastguard Worker         return false;
4183*d9f75844SAndroid Build Coastguard Worker       }
4184*d9f75844SAndroid Build Coastguard Worker       for (const auto& max_tl_idx : max_observed_tl_idxs_) {
4185*d9f75844SAndroid Build Coastguard Worker         uint32_t ssrc = max_tl_idx.first;
4186*d9f75844SAndroid Build Coastguard Worker         int configured_num_tls =
4187*d9f75844SAndroid Build Coastguard Worker             configured_num_temporal_layers_.find(ssrc)->second;
4188*d9f75844SAndroid Build Coastguard Worker         if (max_tl_idx.second != configured_num_tls - 1)
4189*d9f75844SAndroid Build Coastguard Worker           return false;
4190*d9f75844SAndroid Build Coastguard Worker       }
4191*d9f75844SAndroid Build Coastguard Worker       return true;
4192*d9f75844SAndroid Build Coastguard Worker     }
4193*d9f75844SAndroid Build Coastguard Worker 
4194*d9f75844SAndroid Build Coastguard Worker     void PerformTest() override { EXPECT_TRUE(Wait()); }
4195*d9f75844SAndroid Build Coastguard Worker 
4196*d9f75844SAndroid Build Coastguard Worker     VideoEncoderFactory* const encoder_factory_;
4197*d9f75844SAndroid Build Coastguard Worker     const std::string payload_name_;
4198*d9f75844SAndroid Build Coastguard Worker     const std::vector<int> num_temporal_layers_;
4199*d9f75844SAndroid Build Coastguard Worker     const std::vector<ScalabilityMode> scalability_mode_;
4200*d9f75844SAndroid Build Coastguard Worker     const std::unique_ptr<VideoRtpDepacketizer> depacketizer_;
4201*d9f75844SAndroid Build Coastguard Worker     // Mapped by SSRC.
4202*d9f75844SAndroid Build Coastguard Worker     std::map<uint32_t, int> configured_num_temporal_layers_;
4203*d9f75844SAndroid Build Coastguard Worker     std::map<uint32_t, int> max_observed_tl_idxs_;
4204*d9f75844SAndroid Build Coastguard Worker     std::map<uint32_t, int> num_observed_frames_;
4205*d9f75844SAndroid Build Coastguard Worker     std::map<uint32_t, ParsedPacket> last_observed_packet_;
4206*d9f75844SAndroid Build Coastguard Worker   } test(encoder_factory, payload_name, num_temporal_layers, scalability_mode);
4207*d9f75844SAndroid Build Coastguard Worker 
4208*d9f75844SAndroid Build Coastguard Worker   RunBaseTest(&test);
4209*d9f75844SAndroid Build Coastguard Worker }
4210*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,TestTemporalLayersVp8)4211*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, TestTemporalLayersVp8) {
4212*d9f75844SAndroid Build Coastguard Worker   InternalEncoderFactory internal_encoder_factory;
4213*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
4214*d9f75844SAndroid Build Coastguard Worker       [&internal_encoder_factory]() {
4215*d9f75844SAndroid Build Coastguard Worker         return std::make_unique<SimulcastEncoderAdapter>(
4216*d9f75844SAndroid Build Coastguard Worker             &internal_encoder_factory, SdpVideoFormat("VP8"));
4217*d9f75844SAndroid Build Coastguard Worker       });
4218*d9f75844SAndroid Build Coastguard Worker 
4219*d9f75844SAndroid Build Coastguard Worker   TestTemporalLayers(&encoder_factory, "VP8",
4220*d9f75844SAndroid Build Coastguard Worker                      /*num_temporal_layers=*/{2},
4221*d9f75844SAndroid Build Coastguard Worker                      /*scalability_mode=*/{});
4222*d9f75844SAndroid Build Coastguard Worker }
4223*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,TestTemporalLayersVp8Simulcast)4224*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, TestTemporalLayersVp8Simulcast) {
4225*d9f75844SAndroid Build Coastguard Worker   InternalEncoderFactory internal_encoder_factory;
4226*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
4227*d9f75844SAndroid Build Coastguard Worker       [&internal_encoder_factory]() {
4228*d9f75844SAndroid Build Coastguard Worker         return std::make_unique<SimulcastEncoderAdapter>(
4229*d9f75844SAndroid Build Coastguard Worker             &internal_encoder_factory, SdpVideoFormat("VP8"));
4230*d9f75844SAndroid Build Coastguard Worker       });
4231*d9f75844SAndroid Build Coastguard Worker 
4232*d9f75844SAndroid Build Coastguard Worker   TestTemporalLayers(&encoder_factory, "VP8",
4233*d9f75844SAndroid Build Coastguard Worker                      /*num_temporal_layers=*/{2, 2},
4234*d9f75844SAndroid Build Coastguard Worker                      /*scalability_mode=*/{});
4235*d9f75844SAndroid Build Coastguard Worker }
4236*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,TestTemporalLayersVp8SimulcastWithDifferentNumTls)4237*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, TestTemporalLayersVp8SimulcastWithDifferentNumTls) {
4238*d9f75844SAndroid Build Coastguard Worker   InternalEncoderFactory internal_encoder_factory;
4239*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
4240*d9f75844SAndroid Build Coastguard Worker       [&internal_encoder_factory]() {
4241*d9f75844SAndroid Build Coastguard Worker         return std::make_unique<SimulcastEncoderAdapter>(
4242*d9f75844SAndroid Build Coastguard Worker             &internal_encoder_factory, SdpVideoFormat("VP8"));
4243*d9f75844SAndroid Build Coastguard Worker       });
4244*d9f75844SAndroid Build Coastguard Worker 
4245*d9f75844SAndroid Build Coastguard Worker   TestTemporalLayers(&encoder_factory, "VP8",
4246*d9f75844SAndroid Build Coastguard Worker                      /*num_temporal_layers=*/{3, 1},
4247*d9f75844SAndroid Build Coastguard Worker                      /*scalability_mode=*/{});
4248*d9f75844SAndroid Build Coastguard Worker }
4249*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,TestTemporalLayersVp8SimulcastWithoutSimAdapter)4250*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, TestTemporalLayersVp8SimulcastWithoutSimAdapter) {
4251*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
4252*d9f75844SAndroid Build Coastguard Worker       []() { return VP8Encoder::Create(); });
4253*d9f75844SAndroid Build Coastguard Worker 
4254*d9f75844SAndroid Build Coastguard Worker   TestTemporalLayers(&encoder_factory, "VP8",
4255*d9f75844SAndroid Build Coastguard Worker                      /*num_temporal_layers=*/{2, 2},
4256*d9f75844SAndroid Build Coastguard Worker                      /*scalability_mode=*/{});
4257*d9f75844SAndroid Build Coastguard Worker }
4258*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,TestScalabilityModeVp8L1T2)4259*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, TestScalabilityModeVp8L1T2) {
4260*d9f75844SAndroid Build Coastguard Worker   InternalEncoderFactory internal_encoder_factory;
4261*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
4262*d9f75844SAndroid Build Coastguard Worker       [&internal_encoder_factory]() {
4263*d9f75844SAndroid Build Coastguard Worker         return std::make_unique<SimulcastEncoderAdapter>(
4264*d9f75844SAndroid Build Coastguard Worker             &internal_encoder_factory, SdpVideoFormat("VP8"));
4265*d9f75844SAndroid Build Coastguard Worker       });
4266*d9f75844SAndroid Build Coastguard Worker 
4267*d9f75844SAndroid Build Coastguard Worker   TestTemporalLayers(&encoder_factory, "VP8",
4268*d9f75844SAndroid Build Coastguard Worker                      /*num_temporal_layers=*/{}, {ScalabilityMode::kL1T2});
4269*d9f75844SAndroid Build Coastguard Worker }
4270*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,TestScalabilityModeVp8Simulcast)4271*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, TestScalabilityModeVp8Simulcast) {
4272*d9f75844SAndroid Build Coastguard Worker   InternalEncoderFactory internal_encoder_factory;
4273*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
4274*d9f75844SAndroid Build Coastguard Worker       [&internal_encoder_factory]() {
4275*d9f75844SAndroid Build Coastguard Worker         return std::make_unique<SimulcastEncoderAdapter>(
4276*d9f75844SAndroid Build Coastguard Worker             &internal_encoder_factory, SdpVideoFormat("VP8"));
4277*d9f75844SAndroid Build Coastguard Worker       });
4278*d9f75844SAndroid Build Coastguard Worker 
4279*d9f75844SAndroid Build Coastguard Worker   TestTemporalLayers(&encoder_factory, "VP8",
4280*d9f75844SAndroid Build Coastguard Worker                      /*num_temporal_layers=*/{},
4281*d9f75844SAndroid Build Coastguard Worker                      {ScalabilityMode::kL1T2, ScalabilityMode::kL1T2});
4282*d9f75844SAndroid Build Coastguard Worker }
4283*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,TestScalabilityModeVp8SimulcastWithDifferentMode)4284*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, TestScalabilityModeVp8SimulcastWithDifferentMode) {
4285*d9f75844SAndroid Build Coastguard Worker   InternalEncoderFactory internal_encoder_factory;
4286*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
4287*d9f75844SAndroid Build Coastguard Worker       [&internal_encoder_factory]() {
4288*d9f75844SAndroid Build Coastguard Worker         return std::make_unique<SimulcastEncoderAdapter>(
4289*d9f75844SAndroid Build Coastguard Worker             &internal_encoder_factory, SdpVideoFormat("VP8"));
4290*d9f75844SAndroid Build Coastguard Worker       });
4291*d9f75844SAndroid Build Coastguard Worker 
4292*d9f75844SAndroid Build Coastguard Worker   TestTemporalLayers(&encoder_factory, "VP8",
4293*d9f75844SAndroid Build Coastguard Worker                      /*num_temporal_layers=*/{},
4294*d9f75844SAndroid Build Coastguard Worker                      {ScalabilityMode::kL1T3, ScalabilityMode::kL1T1});
4295*d9f75844SAndroid Build Coastguard Worker }
4296*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,TestScalabilityModeVp8SimulcastWithoutSimAdapter)4297*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, TestScalabilityModeVp8SimulcastWithoutSimAdapter) {
4298*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
4299*d9f75844SAndroid Build Coastguard Worker       []() { return VP8Encoder::Create(); });
4300*d9f75844SAndroid Build Coastguard Worker 
4301*d9f75844SAndroid Build Coastguard Worker   TestTemporalLayers(&encoder_factory, "VP8",
4302*d9f75844SAndroid Build Coastguard Worker                      /*num_temporal_layers=*/{},
4303*d9f75844SAndroid Build Coastguard Worker                      {ScalabilityMode::kL1T2, ScalabilityMode::kL1T2});
4304*d9f75844SAndroid Build Coastguard Worker }
4305*d9f75844SAndroid Build Coastguard Worker 
TEST_F(VideoSendStreamTest,TestTemporalLayersVp9)4306*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoSendStreamTest, TestTemporalLayersVp9) {
4307*d9f75844SAndroid Build Coastguard Worker   test::FunctionVideoEncoderFactory encoder_factory(
4308*d9f75844SAndroid Build Coastguard Worker       []() { return VP9Encoder::Create(); });
4309*d9f75844SAndroid Build Coastguard Worker 
4310*d9f75844SAndroid Build Coastguard Worker   TestTemporalLayers(&encoder_factory, "VP9",
4311*d9f75844SAndroid Build Coastguard Worker                      /*num_temporal_layers=*/{2},
4312*d9f75844SAndroid Build Coastguard Worker                      /*scalability_mode=*/{});
4313*d9f75844SAndroid Build Coastguard Worker }
4314*d9f75844SAndroid Build Coastguard Worker 
4315*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
4316