blob: dfb12971b4e10531dba25ac0884b004e988434b7 [file] [log] [blame]
Henrik Boström4c1e7cc2020-06-11 10:26:531/*
2 * Copyright 2020 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <memory>
12
13#include "api/audio_codecs/builtin_audio_decoder_factory.h"
14#include "api/audio_codecs/builtin_audio_encoder_factory.h"
15#include "api/rtp_parameters.h"
16#include "api/scoped_refptr.h"
17#include "call/adaptation/test/fake_resource.h"
18#include "pc/test/fake_periodic_video_source.h"
19#include "pc/test/fake_periodic_video_track_source.h"
20#include "pc/test/peer_connection_test_wrapper.h"
21#include "rtc_base/checks.h"
22#include "rtc_base/gunit.h"
23#include "rtc_base/ref_counted_object.h"
24#include "rtc_base/thread.h"
25#include "rtc_base/virtual_socket_server.h"
26#include "test/gtest.h"
27
28namespace webrtc {
29
30const int64_t kDefaultTimeoutMs = 5000;
31
32struct TrackWithPeriodicSource {
33 rtc::scoped_refptr<VideoTrackInterface> track;
34 rtc::scoped_refptr<FakePeriodicVideoTrackSource> periodic_track_source;
35};
36
37// Performs an O/A exchange and waits until the signaling state is stable again.
38void Negotiate(rtc::scoped_refptr<PeerConnectionTestWrapper> caller,
39 rtc::scoped_refptr<PeerConnectionTestWrapper> callee) {
40 // Wire up callbacks and listeners such that a full O/A is performed in
41 // response to CreateOffer().
42 PeerConnectionTestWrapper::Connect(caller.get(), callee.get());
43 caller->CreateOffer(PeerConnectionInterface::RTCOfferAnswerOptions());
44 caller->WaitForNegotiation();
45}
46
47TrackWithPeriodicSource CreateTrackWithPeriodicSource(
48 rtc::scoped_refptr<PeerConnectionFactoryInterface> factory) {
49 FakePeriodicVideoSource::Config periodic_track_source_config;
50 periodic_track_source_config.frame_interval_ms = 100;
51 periodic_track_source_config.timestamp_offset_ms = rtc::TimeMillis();
52 rtc::scoped_refptr<FakePeriodicVideoTrackSource> periodic_track_source =
Tommi87f70902021-04-27 12:43:0853 rtc::make_ref_counted<FakePeriodicVideoTrackSource>(
Henrik Boström4c1e7cc2020-06-11 10:26:5354 periodic_track_source_config, /* remote */ false);
55 TrackWithPeriodicSource track_with_source;
56 track_with_source.track =
57 factory->CreateVideoTrack("PeriodicTrack", periodic_track_source);
58 track_with_source.periodic_track_source = periodic_track_source;
59 return track_with_source;
60}
61
62// Triggers overuse and obtains VideoSinkWants. Adaptation processing happens in
63// parallel and this function makes no guarantee that the returnd VideoSinkWants
64// have yet to reflect the overuse signal. Used together with EXPECT_TRUE_WAIT
65// to "spam overuse until a change is observed".
66rtc::VideoSinkWants TriggerOveruseAndGetSinkWants(
67 rtc::scoped_refptr<FakeResource> fake_resource,
68 const FakePeriodicVideoSource& source) {
69 fake_resource->SetUsageState(ResourceUsageState::kOveruse);
70 return source.wants();
71}
72
73class PeerConnectionAdaptationIntegrationTest : public ::testing::Test {
74 public:
75 PeerConnectionAdaptationIntegrationTest()
76 : virtual_socket_server_(),
77 network_thread_(new rtc::Thread(&virtual_socket_server_)),
78 worker_thread_(rtc::Thread::Create()) {
79 RTC_CHECK(network_thread_->Start());
80 RTC_CHECK(worker_thread_->Start());
81 }
82
83 rtc::scoped_refptr<PeerConnectionTestWrapper> CreatePcWrapper(
84 const char* name) {
85 rtc::scoped_refptr<PeerConnectionTestWrapper> pc_wrapper =
Tommi87f70902021-04-27 12:43:0886 rtc::make_ref_counted<PeerConnectionTestWrapper>(
Henrik Boström4c1e7cc2020-06-11 10:26:5387 name, network_thread_.get(), worker_thread_.get());
88 PeerConnectionInterface::RTCConfiguration config;
89 config.sdp_semantics = SdpSemantics::kUnifiedPlan;
90 EXPECT_TRUE(pc_wrapper->CreatePc(config, CreateBuiltinAudioEncoderFactory(),
91 CreateBuiltinAudioDecoderFactory()));
92 return pc_wrapper;
93 }
94
95 protected:
96 rtc::VirtualSocketServer virtual_socket_server_;
97 std::unique_ptr<rtc::Thread> network_thread_;
98 std::unique_ptr<rtc::Thread> worker_thread_;
99};
100
101TEST_F(PeerConnectionAdaptationIntegrationTest,
102 ResouceInjectedAfterNegotiationCausesReductionInResolution) {
103 auto caller_wrapper = CreatePcWrapper("caller");
104 auto caller = caller_wrapper->pc();
105 auto callee_wrapper = CreatePcWrapper("callee");
106
107 // Adding a track and negotiating ensures that a VideoSendStream exists.
108 TrackWithPeriodicSource track_with_source =
109 CreateTrackWithPeriodicSource(caller_wrapper->pc_factory());
110 auto sender = caller->AddTrack(track_with_source.track, {}).value();
111 Negotiate(caller_wrapper, callee_wrapper);
112 // Prefer degrading resolution.
113 auto parameters = sender->GetParameters();
114 parameters.degradation_preference = DegradationPreference::MAINTAIN_FRAMERATE;
115 sender->SetParameters(parameters);
116
117 const auto& source =
118 track_with_source.periodic_track_source->fake_periodic_source();
119 int pixel_count_before_overuse = source.wants().max_pixel_count;
120
121 // Inject a fake resource and spam kOveruse until resolution becomes limited.
122 auto fake_resource = FakeResource::Create("FakeResource");
123 caller->AddAdaptationResource(fake_resource);
124 EXPECT_TRUE_WAIT(
125 TriggerOveruseAndGetSinkWants(fake_resource, source).max_pixel_count <
126 pixel_count_before_overuse,
127 kDefaultTimeoutMs);
128}
129
130TEST_F(PeerConnectionAdaptationIntegrationTest,
131 ResouceInjectedBeforeNegotiationCausesReductionInResolution) {
132 auto caller_wrapper = CreatePcWrapper("caller");
133 auto caller = caller_wrapper->pc();
134 auto callee_wrapper = CreatePcWrapper("callee");
135
136 // Inject a fake resource before adding any tracks or negotiating.
137 auto fake_resource = FakeResource::Create("FakeResource");
138 caller->AddAdaptationResource(fake_resource);
139
140 // Adding a track and negotiating ensures that a VideoSendStream exists.
141 TrackWithPeriodicSource track_with_source =
142 CreateTrackWithPeriodicSource(caller_wrapper->pc_factory());
143 auto sender = caller->AddTrack(track_with_source.track, {}).value();
144 Negotiate(caller_wrapper, callee_wrapper);
145 // Prefer degrading resolution.
146 auto parameters = sender->GetParameters();
147 parameters.degradation_preference = DegradationPreference::MAINTAIN_FRAMERATE;
148 sender->SetParameters(parameters);
149
150 const auto& source =
151 track_with_source.periodic_track_source->fake_periodic_source();
152 int pixel_count_before_overuse = source.wants().max_pixel_count;
153
154 // Spam kOveruse until resolution becomes limited.
155 EXPECT_TRUE_WAIT(
156 TriggerOveruseAndGetSinkWants(fake_resource, source).max_pixel_count <
157 pixel_count_before_overuse,
158 kDefaultTimeoutMs);
159}
160
161} // namespace webrtc