xref: /aosp_15_r20/external/webrtc/pc/peer_connection_header_extension_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
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 #include <string>
13 #include <tuple>
14 #include <utility>
15 #include <vector>
16 
17 #include "absl/strings/string_view.h"
18 #include "absl/types/optional.h"
19 #include "api/call/call_factory_interface.h"
20 #include "api/jsep.h"
21 #include "api/media_types.h"
22 #include "api/peer_connection_interface.h"
23 #include "api/rtc_error.h"
24 #include "api/rtc_event_log/rtc_event_log_factory.h"
25 #include "api/rtc_event_log/rtc_event_log_factory_interface.h"
26 #include "api/rtp_parameters.h"
27 #include "api/rtp_transceiver_direction.h"
28 #include "api/rtp_transceiver_interface.h"
29 #include "api/scoped_refptr.h"
30 #include "api/task_queue/default_task_queue_factory.h"
31 #include "api/task_queue/task_queue_factory.h"
32 #include "media/base/fake_media_engine.h"
33 #include "media/base/media_engine.h"
34 #include "p2p/base/fake_port_allocator.h"
35 #include "p2p/base/port_allocator.h"
36 #include "pc/peer_connection_wrapper.h"
37 #include "pc/session_description.h"
38 #include "pc/test/mock_peer_connection_observers.h"
39 #include "rtc_base/internal/default_socket_server.h"
40 #include "rtc_base/rtc_certificate_generator.h"
41 #include "rtc_base/strings/string_builder.h"
42 #include "rtc_base/thread.h"
43 #include "test/gmock.h"
44 #include "test/gtest.h"
45 
46 namespace webrtc {
47 
48 using ::testing::Combine;
49 using ::testing::ElementsAre;
50 using ::testing::Field;
51 using ::testing::Return;
52 using ::testing::Values;
53 
54 class PeerConnectionHeaderExtensionTest
55     : public ::testing::TestWithParam<
56           std::tuple<cricket::MediaType, SdpSemantics>> {
57  protected:
PeerConnectionHeaderExtensionTest()58   PeerConnectionHeaderExtensionTest()
59       : socket_server_(rtc::CreateDefaultSocketServer()),
60         main_thread_(socket_server_.get()),
61         extensions_(
62             {RtpHeaderExtensionCapability("uri1",
63                                           1,
64                                           RtpTransceiverDirection::kStopped),
65              RtpHeaderExtensionCapability("uri2",
66                                           2,
67                                           RtpTransceiverDirection::kSendOnly),
68              RtpHeaderExtensionCapability("uri3",
69                                           3,
70                                           RtpTransceiverDirection::kRecvOnly),
71              RtpHeaderExtensionCapability(
72                  "uri4",
73                  4,
74                  RtpTransceiverDirection::kSendRecv)}) {}
75 
CreatePeerConnection(cricket::MediaType media_type,absl::optional<SdpSemantics> semantics)76   std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection(
77       cricket::MediaType media_type,
78       absl::optional<SdpSemantics> semantics) {
79     auto voice = std::make_unique<cricket::FakeVoiceEngine>();
80     auto video = std::make_unique<cricket::FakeVideoEngine>();
81     if (media_type == cricket::MediaType::MEDIA_TYPE_AUDIO)
82       voice->SetRtpHeaderExtensions(extensions_);
83     else
84       video->SetRtpHeaderExtensions(extensions_);
85     auto media_engine = std::make_unique<cricket::CompositeMediaEngine>(
86         std::move(voice), std::move(video));
87     PeerConnectionFactoryDependencies factory_dependencies;
88     factory_dependencies.network_thread = rtc::Thread::Current();
89     factory_dependencies.worker_thread = rtc::Thread::Current();
90     factory_dependencies.signaling_thread = rtc::Thread::Current();
91     factory_dependencies.task_queue_factory = CreateDefaultTaskQueueFactory();
92     factory_dependencies.media_engine = std::move(media_engine);
93     factory_dependencies.call_factory = CreateCallFactory();
94     factory_dependencies.event_log_factory =
95         std::make_unique<RtcEventLogFactory>(
96             factory_dependencies.task_queue_factory.get());
97 
98     auto pc_factory =
99         CreateModularPeerConnectionFactory(std::move(factory_dependencies));
100 
101     auto fake_port_allocator = std::make_unique<cricket::FakePortAllocator>(
102         rtc::Thread::Current(),
103         std::make_unique<rtc::BasicPacketSocketFactory>(socket_server_.get()));
104     auto observer = std::make_unique<MockPeerConnectionObserver>();
105     PeerConnectionInterface::RTCConfiguration config;
106     if (semantics)
107       config.sdp_semantics = *semantics;
108     PeerConnectionDependencies pc_dependencies(observer.get());
109     pc_dependencies.allocator = std::move(fake_port_allocator);
110     auto result = pc_factory->CreatePeerConnectionOrError(
111         config, std::move(pc_dependencies));
112     EXPECT_TRUE(result.ok());
113     observer->SetPeerConnectionInterface(result.value().get());
114     return std::make_unique<PeerConnectionWrapper>(
115         pc_factory, result.MoveValue(), std::move(observer));
116   }
117 
118   std::unique_ptr<rtc::SocketServer> socket_server_;
119   rtc::AutoSocketServerThread main_thread_;
120   std::vector<RtpHeaderExtensionCapability> extensions_;
121 };
122 
TEST_P(PeerConnectionHeaderExtensionTest,TransceiverOffersHeaderExtensions)123 TEST_P(PeerConnectionHeaderExtensionTest, TransceiverOffersHeaderExtensions) {
124   cricket::MediaType media_type;
125   SdpSemantics semantics;
126   std::tie(media_type, semantics) = GetParam();
127   if (semantics != SdpSemantics::kUnifiedPlan)
128     return;
129   std::unique_ptr<PeerConnectionWrapper> wrapper =
130       CreatePeerConnection(media_type, semantics);
131   auto transceiver = wrapper->AddTransceiver(media_type);
132   EXPECT_EQ(transceiver->HeaderExtensionsToOffer(), extensions_);
133 }
134 
TEST_P(PeerConnectionHeaderExtensionTest,SenderReceiverCapabilitiesReturnNotStoppedExtensions)135 TEST_P(PeerConnectionHeaderExtensionTest,
136        SenderReceiverCapabilitiesReturnNotStoppedExtensions) {
137   cricket::MediaType media_type;
138   SdpSemantics semantics;
139   std::tie(media_type, semantics) = GetParam();
140   std::unique_ptr<PeerConnectionWrapper> wrapper =
141       CreatePeerConnection(media_type, semantics);
142   EXPECT_THAT(wrapper->pc_factory()
143                   ->GetRtpSenderCapabilities(media_type)
144                   .header_extensions,
145               ElementsAre(Field(&RtpHeaderExtensionCapability::uri, "uri2"),
146                           Field(&RtpHeaderExtensionCapability::uri, "uri3"),
147                           Field(&RtpHeaderExtensionCapability::uri, "uri4")));
148   EXPECT_EQ(wrapper->pc_factory()
149                 ->GetRtpReceiverCapabilities(media_type)
150                 .header_extensions,
151             wrapper->pc_factory()
152                 ->GetRtpSenderCapabilities(media_type)
153                 .header_extensions);
154 }
155 
TEST_P(PeerConnectionHeaderExtensionTest,OffersUnstoppedDefaultExtensions)156 TEST_P(PeerConnectionHeaderExtensionTest, OffersUnstoppedDefaultExtensions) {
157   cricket::MediaType media_type;
158   SdpSemantics semantics;
159   std::tie(media_type, semantics) = GetParam();
160   if (semantics != SdpSemantics::kUnifiedPlan)
161     return;
162   std::unique_ptr<PeerConnectionWrapper> wrapper =
163       CreatePeerConnection(media_type, semantics);
164   auto transceiver = wrapper->AddTransceiver(media_type);
165   auto session_description = wrapper->CreateOffer();
166   EXPECT_THAT(session_description->description()
167                   ->contents()[0]
168                   .media_description()
169                   ->rtp_header_extensions(),
170               ElementsAre(Field(&RtpExtension::uri, "uri2"),
171                           Field(&RtpExtension::uri, "uri3"),
172                           Field(&RtpExtension::uri, "uri4")));
173 }
174 
TEST_P(PeerConnectionHeaderExtensionTest,OffersUnstoppedModifiedExtensions)175 TEST_P(PeerConnectionHeaderExtensionTest, OffersUnstoppedModifiedExtensions) {
176   cricket::MediaType media_type;
177   SdpSemantics semantics;
178   std::tie(media_type, semantics) = GetParam();
179   if (semantics != SdpSemantics::kUnifiedPlan)
180     return;
181   std::unique_ptr<PeerConnectionWrapper> wrapper =
182       CreatePeerConnection(media_type, semantics);
183   auto transceiver = wrapper->AddTransceiver(media_type);
184   auto modified_extensions = transceiver->HeaderExtensionsToOffer();
185   modified_extensions[0].direction = RtpTransceiverDirection::kSendRecv;
186   modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
187   EXPECT_TRUE(
188       transceiver->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
189   auto session_description = wrapper->CreateOffer();
190   EXPECT_THAT(session_description->description()
191                   ->contents()[0]
192                   .media_description()
193                   ->rtp_header_extensions(),
194               ElementsAre(Field(&RtpExtension::uri, "uri1"),
195                           Field(&RtpExtension::uri, "uri2"),
196                           Field(&RtpExtension::uri, "uri3")));
197 }
198 
TEST_P(PeerConnectionHeaderExtensionTest,NegotiatedExtensionsAreAccessible)199 TEST_P(PeerConnectionHeaderExtensionTest, NegotiatedExtensionsAreAccessible) {
200   cricket::MediaType media_type;
201   SdpSemantics semantics;
202   std::tie(media_type, semantics) = GetParam();
203   if (semantics != SdpSemantics::kUnifiedPlan)
204     return;
205   std::unique_ptr<PeerConnectionWrapper> pc1 =
206       CreatePeerConnection(media_type, semantics);
207   auto transceiver1 = pc1->AddTransceiver(media_type);
208   auto modified_extensions = transceiver1->HeaderExtensionsToOffer();
209   modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
210   transceiver1->SetOfferedRtpHeaderExtensions(modified_extensions);
211   auto offer = pc1->CreateOfferAndSetAsLocal(
212       PeerConnectionInterface::RTCOfferAnswerOptions());
213 
214   std::unique_ptr<PeerConnectionWrapper> pc2 =
215       CreatePeerConnection(media_type, semantics);
216   auto transceiver2 = pc2->AddTransceiver(media_type);
217   pc2->SetRemoteDescription(std::move(offer));
218   auto answer = pc2->CreateAnswerAndSetAsLocal(
219       PeerConnectionInterface::RTCOfferAnswerOptions());
220   pc1->SetRemoteDescription(std::move(answer));
221 
222   // PC1 has exts 2-4 unstopped and PC2 has exts 1-3 unstopped -> ext 2, 3
223   // survives.
224   EXPECT_THAT(transceiver1->HeaderExtensionsNegotiated(),
225               ElementsAre(Field(&RtpHeaderExtensionCapability::uri, "uri2"),
226                           Field(&RtpHeaderExtensionCapability::uri, "uri3")));
227 }
228 
229 INSTANTIATE_TEST_SUITE_P(
230     ,
231     PeerConnectionHeaderExtensionTest,
232     Combine(Values(SdpSemantics::kPlanB_DEPRECATED, SdpSemantics::kUnifiedPlan),
233             Values(cricket::MediaType::MEDIA_TYPE_AUDIO,
234                    cricket::MediaType::MEDIA_TYPE_VIDEO)),
235     [](const testing::TestParamInfo<
__anonb8353a710102(const testing::TestParamInfo< PeerConnectionHeaderExtensionTest::ParamType>& info) 236         PeerConnectionHeaderExtensionTest::ParamType>& info) {
237       cricket::MediaType media_type;
238       SdpSemantics semantics;
239       std::tie(media_type, semantics) = info.param;
240       return (rtc::StringBuilder("With")
241               << (semantics == SdpSemantics::kPlanB_DEPRECATED ? "PlanB"
242                                                                : "UnifiedPlan")
243               << "And"
244               << (media_type == cricket::MediaType::MEDIA_TYPE_AUDIO ? "Voice"
245                                                                      : "Video")
246               << "Engine")
247           .str();
248     });
249 
250 }  // namespace webrtc
251