xref: /aosp_15_r20/external/webrtc/pc/peer_connection_adaptation_integrationtest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2020 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 
11*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <memory>
14*d9f75844SAndroid Build Coastguard Worker #include <string>
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
17*d9f75844SAndroid Build Coastguard Worker #include "api/adaptation/resource.h"
18*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/builtin_audio_decoder_factory.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/builtin_audio_encoder_factory.h"
20*d9f75844SAndroid Build Coastguard Worker #include "api/media_stream_interface.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/peer_connection_interface.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/rtc_error.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_parameters.h"
24*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_sender_interface.h"
25*d9f75844SAndroid Build Coastguard Worker #include "api/scoped_refptr.h"
26*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_source_interface.h"
27*d9f75844SAndroid Build Coastguard Worker #include "call/adaptation/test/fake_resource.h"
28*d9f75844SAndroid Build Coastguard Worker #include "pc/test/fake_periodic_video_source.h"
29*d9f75844SAndroid Build Coastguard Worker #include "pc/test/fake_periodic_video_track_source.h"
30*d9f75844SAndroid Build Coastguard Worker #include "pc/test/peer_connection_test_wrapper.h"
31*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
32*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
33*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread.h"
34*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
35*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/virtual_socket_server.h"
36*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
37*d9f75844SAndroid Build Coastguard Worker 
38*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
39*d9f75844SAndroid Build Coastguard Worker 
40*d9f75844SAndroid Build Coastguard Worker const int64_t kDefaultTimeoutMs = 5000;
41*d9f75844SAndroid Build Coastguard Worker 
42*d9f75844SAndroid Build Coastguard Worker struct TrackWithPeriodicSource {
43*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<VideoTrackInterface> track;
44*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<FakePeriodicVideoTrackSource> periodic_track_source;
45*d9f75844SAndroid Build Coastguard Worker };
46*d9f75844SAndroid Build Coastguard Worker 
47*d9f75844SAndroid Build Coastguard Worker // Performs an O/A exchange and waits until the signaling state is stable again.
Negotiate(rtc::scoped_refptr<PeerConnectionTestWrapper> caller,rtc::scoped_refptr<PeerConnectionTestWrapper> callee)48*d9f75844SAndroid Build Coastguard Worker void Negotiate(rtc::scoped_refptr<PeerConnectionTestWrapper> caller,
49*d9f75844SAndroid Build Coastguard Worker                rtc::scoped_refptr<PeerConnectionTestWrapper> callee) {
50*d9f75844SAndroid Build Coastguard Worker   // Wire up callbacks and listeners such that a full O/A is performed in
51*d9f75844SAndroid Build Coastguard Worker   // response to CreateOffer().
52*d9f75844SAndroid Build Coastguard Worker   PeerConnectionTestWrapper::Connect(caller.get(), callee.get());
53*d9f75844SAndroid Build Coastguard Worker   caller->CreateOffer(PeerConnectionInterface::RTCOfferAnswerOptions());
54*d9f75844SAndroid Build Coastguard Worker   caller->WaitForNegotiation();
55*d9f75844SAndroid Build Coastguard Worker }
56*d9f75844SAndroid Build Coastguard Worker 
CreateTrackWithPeriodicSource(rtc::scoped_refptr<PeerConnectionFactoryInterface> factory)57*d9f75844SAndroid Build Coastguard Worker TrackWithPeriodicSource CreateTrackWithPeriodicSource(
58*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<PeerConnectionFactoryInterface> factory) {
59*d9f75844SAndroid Build Coastguard Worker   FakePeriodicVideoSource::Config periodic_track_source_config;
60*d9f75844SAndroid Build Coastguard Worker   periodic_track_source_config.frame_interval_ms = 100;
61*d9f75844SAndroid Build Coastguard Worker   periodic_track_source_config.timestamp_offset_ms = rtc::TimeMillis();
62*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<FakePeriodicVideoTrackSource> periodic_track_source =
63*d9f75844SAndroid Build Coastguard Worker       rtc::make_ref_counted<FakePeriodicVideoTrackSource>(
64*d9f75844SAndroid Build Coastguard Worker           periodic_track_source_config, /* remote */ false);
65*d9f75844SAndroid Build Coastguard Worker   TrackWithPeriodicSource track_with_source;
66*d9f75844SAndroid Build Coastguard Worker   track_with_source.track =
67*d9f75844SAndroid Build Coastguard Worker       factory->CreateVideoTrack("PeriodicTrack", periodic_track_source.get());
68*d9f75844SAndroid Build Coastguard Worker   track_with_source.periodic_track_source = periodic_track_source;
69*d9f75844SAndroid Build Coastguard Worker   return track_with_source;
70*d9f75844SAndroid Build Coastguard Worker }
71*d9f75844SAndroid Build Coastguard Worker 
72*d9f75844SAndroid Build Coastguard Worker // Triggers overuse and obtains VideoSinkWants. Adaptation processing happens in
73*d9f75844SAndroid Build Coastguard Worker // parallel and this function makes no guarantee that the returnd VideoSinkWants
74*d9f75844SAndroid Build Coastguard Worker // have yet to reflect the overuse signal. Used together with EXPECT_TRUE_WAIT
75*d9f75844SAndroid Build Coastguard Worker // to "spam overuse until a change is observed".
TriggerOveruseAndGetSinkWants(rtc::scoped_refptr<FakeResource> fake_resource,const FakePeriodicVideoSource & source)76*d9f75844SAndroid Build Coastguard Worker rtc::VideoSinkWants TriggerOveruseAndGetSinkWants(
77*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<FakeResource> fake_resource,
78*d9f75844SAndroid Build Coastguard Worker     const FakePeriodicVideoSource& source) {
79*d9f75844SAndroid Build Coastguard Worker   fake_resource->SetUsageState(ResourceUsageState::kOveruse);
80*d9f75844SAndroid Build Coastguard Worker   return source.wants();
81*d9f75844SAndroid Build Coastguard Worker }
82*d9f75844SAndroid Build Coastguard Worker 
83*d9f75844SAndroid Build Coastguard Worker class PeerConnectionAdaptationIntegrationTest : public ::testing::Test {
84*d9f75844SAndroid Build Coastguard Worker  public:
PeerConnectionAdaptationIntegrationTest()85*d9f75844SAndroid Build Coastguard Worker   PeerConnectionAdaptationIntegrationTest()
86*d9f75844SAndroid Build Coastguard Worker       : virtual_socket_server_(),
87*d9f75844SAndroid Build Coastguard Worker         network_thread_(new rtc::Thread(&virtual_socket_server_)),
88*d9f75844SAndroid Build Coastguard Worker         worker_thread_(rtc::Thread::Create()) {
89*d9f75844SAndroid Build Coastguard Worker     RTC_CHECK(network_thread_->Start());
90*d9f75844SAndroid Build Coastguard Worker     RTC_CHECK(worker_thread_->Start());
91*d9f75844SAndroid Build Coastguard Worker   }
92*d9f75844SAndroid Build Coastguard Worker 
CreatePcWrapper(const char * name)93*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<PeerConnectionTestWrapper> CreatePcWrapper(
94*d9f75844SAndroid Build Coastguard Worker       const char* name) {
95*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<PeerConnectionTestWrapper> pc_wrapper =
96*d9f75844SAndroid Build Coastguard Worker         rtc::make_ref_counted<PeerConnectionTestWrapper>(
97*d9f75844SAndroid Build Coastguard Worker             name, &virtual_socket_server_, network_thread_.get(),
98*d9f75844SAndroid Build Coastguard Worker             worker_thread_.get());
99*d9f75844SAndroid Build Coastguard Worker     PeerConnectionInterface::RTCConfiguration config;
100*d9f75844SAndroid Build Coastguard Worker     config.sdp_semantics = SdpSemantics::kUnifiedPlan;
101*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(pc_wrapper->CreatePc(config, CreateBuiltinAudioEncoderFactory(),
102*d9f75844SAndroid Build Coastguard Worker                                      CreateBuiltinAudioDecoderFactory()));
103*d9f75844SAndroid Build Coastguard Worker     return pc_wrapper;
104*d9f75844SAndroid Build Coastguard Worker   }
105*d9f75844SAndroid Build Coastguard Worker 
106*d9f75844SAndroid Build Coastguard Worker  protected:
107*d9f75844SAndroid Build Coastguard Worker   rtc::VirtualSocketServer virtual_socket_server_;
108*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<rtc::Thread> network_thread_;
109*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<rtc::Thread> worker_thread_;
110*d9f75844SAndroid Build Coastguard Worker };
111*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionAdaptationIntegrationTest,ResouceInjectedAfterNegotiationCausesReductionInResolution)112*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionAdaptationIntegrationTest,
113*d9f75844SAndroid Build Coastguard Worker        ResouceInjectedAfterNegotiationCausesReductionInResolution) {
114*d9f75844SAndroid Build Coastguard Worker   auto caller_wrapper = CreatePcWrapper("caller");
115*d9f75844SAndroid Build Coastguard Worker   auto caller = caller_wrapper->pc();
116*d9f75844SAndroid Build Coastguard Worker   auto callee_wrapper = CreatePcWrapper("callee");
117*d9f75844SAndroid Build Coastguard Worker 
118*d9f75844SAndroid Build Coastguard Worker   // Adding a track and negotiating ensures that a VideoSendStream exists.
119*d9f75844SAndroid Build Coastguard Worker   TrackWithPeriodicSource track_with_source =
120*d9f75844SAndroid Build Coastguard Worker       CreateTrackWithPeriodicSource(caller_wrapper->pc_factory());
121*d9f75844SAndroid Build Coastguard Worker   auto sender = caller->AddTrack(track_with_source.track, {}).value();
122*d9f75844SAndroid Build Coastguard Worker   Negotiate(caller_wrapper, callee_wrapper);
123*d9f75844SAndroid Build Coastguard Worker   // Prefer degrading resolution.
124*d9f75844SAndroid Build Coastguard Worker   auto parameters = sender->GetParameters();
125*d9f75844SAndroid Build Coastguard Worker   parameters.degradation_preference = DegradationPreference::MAINTAIN_FRAMERATE;
126*d9f75844SAndroid Build Coastguard Worker   sender->SetParameters(parameters);
127*d9f75844SAndroid Build Coastguard Worker 
128*d9f75844SAndroid Build Coastguard Worker   const auto& source =
129*d9f75844SAndroid Build Coastguard Worker       track_with_source.periodic_track_source->fake_periodic_source();
130*d9f75844SAndroid Build Coastguard Worker   int pixel_count_before_overuse = source.wants().max_pixel_count;
131*d9f75844SAndroid Build Coastguard Worker 
132*d9f75844SAndroid Build Coastguard Worker   // Inject a fake resource and spam kOveruse until resolution becomes limited.
133*d9f75844SAndroid Build Coastguard Worker   auto fake_resource = FakeResource::Create("FakeResource");
134*d9f75844SAndroid Build Coastguard Worker   caller->AddAdaptationResource(fake_resource);
135*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(
136*d9f75844SAndroid Build Coastguard Worker       TriggerOveruseAndGetSinkWants(fake_resource, source).max_pixel_count <
137*d9f75844SAndroid Build Coastguard Worker           pixel_count_before_overuse,
138*d9f75844SAndroid Build Coastguard Worker       kDefaultTimeoutMs);
139*d9f75844SAndroid Build Coastguard Worker }
140*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionAdaptationIntegrationTest,ResouceInjectedBeforeNegotiationCausesReductionInResolution)141*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionAdaptationIntegrationTest,
142*d9f75844SAndroid Build Coastguard Worker        ResouceInjectedBeforeNegotiationCausesReductionInResolution) {
143*d9f75844SAndroid Build Coastguard Worker   auto caller_wrapper = CreatePcWrapper("caller");
144*d9f75844SAndroid Build Coastguard Worker   auto caller = caller_wrapper->pc();
145*d9f75844SAndroid Build Coastguard Worker   auto callee_wrapper = CreatePcWrapper("callee");
146*d9f75844SAndroid Build Coastguard Worker 
147*d9f75844SAndroid Build Coastguard Worker   // Inject a fake resource before adding any tracks or negotiating.
148*d9f75844SAndroid Build Coastguard Worker   auto fake_resource = FakeResource::Create("FakeResource");
149*d9f75844SAndroid Build Coastguard Worker   caller->AddAdaptationResource(fake_resource);
150*d9f75844SAndroid Build Coastguard Worker 
151*d9f75844SAndroid Build Coastguard Worker   // Adding a track and negotiating ensures that a VideoSendStream exists.
152*d9f75844SAndroid Build Coastguard Worker   TrackWithPeriodicSource track_with_source =
153*d9f75844SAndroid Build Coastguard Worker       CreateTrackWithPeriodicSource(caller_wrapper->pc_factory());
154*d9f75844SAndroid Build Coastguard Worker   auto sender = caller->AddTrack(track_with_source.track, {}).value();
155*d9f75844SAndroid Build Coastguard Worker   Negotiate(caller_wrapper, callee_wrapper);
156*d9f75844SAndroid Build Coastguard Worker   // Prefer degrading resolution.
157*d9f75844SAndroid Build Coastguard Worker   auto parameters = sender->GetParameters();
158*d9f75844SAndroid Build Coastguard Worker   parameters.degradation_preference = DegradationPreference::MAINTAIN_FRAMERATE;
159*d9f75844SAndroid Build Coastguard Worker   sender->SetParameters(parameters);
160*d9f75844SAndroid Build Coastguard Worker 
161*d9f75844SAndroid Build Coastguard Worker   const auto& source =
162*d9f75844SAndroid Build Coastguard Worker       track_with_source.periodic_track_source->fake_periodic_source();
163*d9f75844SAndroid Build Coastguard Worker   int pixel_count_before_overuse = source.wants().max_pixel_count;
164*d9f75844SAndroid Build Coastguard Worker 
165*d9f75844SAndroid Build Coastguard Worker   // Spam kOveruse until resolution becomes limited.
166*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(
167*d9f75844SAndroid Build Coastguard Worker       TriggerOveruseAndGetSinkWants(fake_resource, source).max_pixel_count <
168*d9f75844SAndroid Build Coastguard Worker           pixel_count_before_overuse,
169*d9f75844SAndroid Build Coastguard Worker       kDefaultTimeoutMs);
170*d9f75844SAndroid Build Coastguard Worker }
171*d9f75844SAndroid Build Coastguard Worker 
172*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
173