blob: ba78dd85fce33f87bc80e164437cd58b94b810ec [file] [log] [blame]
Markus Handell0357b3e2020-03-16 13:40:51 +01001/*
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>
Harald Alvestrandc24a2182022-02-23 13:44:59 +000012#include <string>
Markus Handell0357b3e2020-03-16 13:40:51 +010013#include <tuple>
Harald Alvestrandc24a2182022-02-23 13:44:59 +000014#include <utility>
15#include <vector>
Markus Handell0357b3e2020-03-16 13:40:51 +010016
Harald Alvestrandc24a2182022-02-23 13:44:59 +000017#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"
Markus Handell0357b3e2020-03-16 13:40:51 +010024#include "api/rtc_event_log/rtc_event_log_factory.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000025#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"
Markus Handell0357b3e2020-03-16 13:40:51 +010030#include "api/task_queue/default_task_queue_factory.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000031#include "api/task_queue/task_queue_factory.h"
Markus Handell0357b3e2020-03-16 13:40:51 +010032#include "media/base/fake_media_engine.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000033#include "media/base/media_engine.h"
Markus Handell0357b3e2020-03-16 13:40:51 +010034#include "p2p/base/fake_port_allocator.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000035#include "p2p/base/port_allocator.h"
Markus Handell0357b3e2020-03-16 13:40:51 +010036#include "pc/peer_connection_wrapper.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000037#include "pc/session_description.h"
38#include "pc/test/mock_peer_connection_observers.h"
39#include "rtc_base/rtc_certificate_generator.h"
Markus Handell0357b3e2020-03-16 13:40:51 +010040#include "rtc_base/strings/string_builder.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000041#include "rtc_base/thread.h"
Markus Handell0357b3e2020-03-16 13:40:51 +010042#include "test/gmock.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000043#include "test/gtest.h"
Markus Handell0357b3e2020-03-16 13:40:51 +010044
45namespace webrtc {
46
47using ::testing::Combine;
48using ::testing::ElementsAre;
49using ::testing::Field;
50using ::testing::Return;
51using ::testing::Values;
52
53class PeerConnectionHeaderExtensionTest
54 : public ::testing::TestWithParam<
55 std::tuple<cricket::MediaType, SdpSemantics>> {
56 protected:
Markus Handell755c65d2020-06-24 01:06:10 +020057 PeerConnectionHeaderExtensionTest()
58 : extensions_(
59 {RtpHeaderExtensionCapability("uri1",
60 1,
61 RtpTransceiverDirection::kStopped),
62 RtpHeaderExtensionCapability("uri2",
63 2,
64 RtpTransceiverDirection::kSendOnly),
65 RtpHeaderExtensionCapability("uri3",
66 3,
67 RtpTransceiverDirection::kRecvOnly),
68 RtpHeaderExtensionCapability(
69 "uri4",
70 4,
71 RtpTransceiverDirection::kSendRecv)}) {}
72
Markus Handell0357b3e2020-03-16 13:40:51 +010073 std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection(
74 cricket::MediaType media_type,
Markus Handell755c65d2020-06-24 01:06:10 +020075 absl::optional<SdpSemantics> semantics) {
Markus Handell0357b3e2020-03-16 13:40:51 +010076 auto voice = std::make_unique<cricket::FakeVoiceEngine>();
77 auto video = std::make_unique<cricket::FakeVideoEngine>();
78 if (media_type == cricket::MediaType::MEDIA_TYPE_AUDIO)
Markus Handell755c65d2020-06-24 01:06:10 +020079 voice->SetRtpHeaderExtensions(extensions_);
Markus Handell0357b3e2020-03-16 13:40:51 +010080 else
Markus Handell755c65d2020-06-24 01:06:10 +020081 video->SetRtpHeaderExtensions(extensions_);
Markus Handell0357b3e2020-03-16 13:40:51 +010082 auto media_engine = std::make_unique<cricket::CompositeMediaEngine>(
83 std::move(voice), std::move(video));
84 PeerConnectionFactoryDependencies factory_dependencies;
85 factory_dependencies.network_thread = rtc::Thread::Current();
86 factory_dependencies.worker_thread = rtc::Thread::Current();
87 factory_dependencies.signaling_thread = rtc::Thread::Current();
88 factory_dependencies.task_queue_factory = CreateDefaultTaskQueueFactory();
89 factory_dependencies.media_engine = std::move(media_engine);
90 factory_dependencies.call_factory = CreateCallFactory();
91 factory_dependencies.event_log_factory =
92 std::make_unique<RtcEventLogFactory>(
93 factory_dependencies.task_queue_factory.get());
94
95 auto pc_factory =
96 CreateModularPeerConnectionFactory(std::move(factory_dependencies));
97
98 auto fake_port_allocator = std::make_unique<cricket::FakePortAllocator>(
99 rtc::Thread::Current(), nullptr);
100 auto observer = std::make_unique<MockPeerConnectionObserver>();
101 PeerConnectionInterface::RTCConfiguration config;
102 if (semantics)
103 config.sdp_semantics = *semantics;
Florent Castelli72424402022-04-06 03:45:10 +0200104 PeerConnectionDependencies pc_dependencies(observer.get());
105 pc_dependencies.allocator = std::move(fake_port_allocator);
106 auto result = pc_factory->CreatePeerConnectionOrError(
107 config, std::move(pc_dependencies));
108 EXPECT_TRUE(result.ok());
Niels Möllerafb246b2022-04-20 14:26:50 +0200109 observer->SetPeerConnectionInterface(result.value().get());
Florent Castelli72424402022-04-06 03:45:10 +0200110 return std::make_unique<PeerConnectionWrapper>(
111 pc_factory, result.MoveValue(), std::move(observer));
Markus Handell0357b3e2020-03-16 13:40:51 +0100112 }
Markus Handell755c65d2020-06-24 01:06:10 +0200113
114 std::vector<RtpHeaderExtensionCapability> extensions_;
Markus Handell0357b3e2020-03-16 13:40:51 +0100115};
116
117TEST_P(PeerConnectionHeaderExtensionTest, TransceiverOffersHeaderExtensions) {
118 cricket::MediaType media_type;
119 SdpSemantics semantics;
120 std::tie(media_type, semantics) = GetParam();
121 if (semantics != SdpSemantics::kUnifiedPlan)
122 return;
Markus Handell0357b3e2020-03-16 13:40:51 +0100123 std::unique_ptr<PeerConnectionWrapper> wrapper =
Markus Handell755c65d2020-06-24 01:06:10 +0200124 CreatePeerConnection(media_type, semantics);
Markus Handell0357b3e2020-03-16 13:40:51 +0100125 auto transceiver = wrapper->AddTransceiver(media_type);
Markus Handell755c65d2020-06-24 01:06:10 +0200126 EXPECT_EQ(transceiver->HeaderExtensionsToOffer(), extensions_);
Markus Handell0357b3e2020-03-16 13:40:51 +0100127}
128
129TEST_P(PeerConnectionHeaderExtensionTest,
130 SenderReceiverCapabilitiesReturnNotStoppedExtensions) {
131 cricket::MediaType media_type;
132 SdpSemantics semantics;
133 std::tie(media_type, semantics) = GetParam();
Markus Handell755c65d2020-06-24 01:06:10 +0200134 std::unique_ptr<PeerConnectionWrapper> wrapper =
135 CreatePeerConnection(media_type, semantics);
Markus Handell0357b3e2020-03-16 13:40:51 +0100136 EXPECT_THAT(wrapper->pc_factory()
137 ->GetRtpSenderCapabilities(media_type)
138 .header_extensions,
Markus Handell755c65d2020-06-24 01:06:10 +0200139 ElementsAre(Field(&RtpHeaderExtensionCapability::uri, "uri2"),
140 Field(&RtpHeaderExtensionCapability::uri, "uri3"),
141 Field(&RtpHeaderExtensionCapability::uri, "uri4")));
Markus Handell0357b3e2020-03-16 13:40:51 +0100142 EXPECT_EQ(wrapper->pc_factory()
143 ->GetRtpReceiverCapabilities(media_type)
144 .header_extensions,
145 wrapper->pc_factory()
146 ->GetRtpSenderCapabilities(media_type)
147 .header_extensions);
148}
149
Markus Handell755c65d2020-06-24 01:06:10 +0200150TEST_P(PeerConnectionHeaderExtensionTest, OffersUnstoppedDefaultExtensions) {
151 cricket::MediaType media_type;
152 SdpSemantics semantics;
153 std::tie(media_type, semantics) = GetParam();
154 if (semantics != SdpSemantics::kUnifiedPlan)
155 return;
156 std::unique_ptr<PeerConnectionWrapper> wrapper =
157 CreatePeerConnection(media_type, semantics);
158 auto transceiver = wrapper->AddTransceiver(media_type);
159 auto session_description = wrapper->CreateOffer();
160 EXPECT_THAT(session_description->description()
161 ->contents()[0]
162 .media_description()
163 ->rtp_header_extensions(),
164 ElementsAre(Field(&RtpExtension::uri, "uri2"),
165 Field(&RtpExtension::uri, "uri3"),
166 Field(&RtpExtension::uri, "uri4")));
167}
168
169TEST_P(PeerConnectionHeaderExtensionTest, OffersUnstoppedModifiedExtensions) {
170 cricket::MediaType media_type;
171 SdpSemantics semantics;
172 std::tie(media_type, semantics) = GetParam();
173 if (semantics != SdpSemantics::kUnifiedPlan)
174 return;
175 std::unique_ptr<PeerConnectionWrapper> wrapper =
176 CreatePeerConnection(media_type, semantics);
177 auto transceiver = wrapper->AddTransceiver(media_type);
178 auto modified_extensions = transceiver->HeaderExtensionsToOffer();
179 modified_extensions[0].direction = RtpTransceiverDirection::kSendRecv;
180 modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
181 EXPECT_TRUE(
182 transceiver->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
183 auto session_description = wrapper->CreateOffer();
184 EXPECT_THAT(session_description->description()
185 ->contents()[0]
186 .media_description()
187 ->rtp_header_extensions(),
188 ElementsAre(Field(&RtpExtension::uri, "uri1"),
189 Field(&RtpExtension::uri, "uri2"),
190 Field(&RtpExtension::uri, "uri3")));
191}
192
Markus Handell5932fe12020-12-17 22:19:40 +0100193TEST_P(PeerConnectionHeaderExtensionTest, NegotiatedExtensionsAreAccessible) {
194 cricket::MediaType media_type;
195 SdpSemantics semantics;
196 std::tie(media_type, semantics) = GetParam();
197 if (semantics != SdpSemantics::kUnifiedPlan)
198 return;
199 std::unique_ptr<PeerConnectionWrapper> pc1 =
200 CreatePeerConnection(media_type, semantics);
201 auto transceiver1 = pc1->AddTransceiver(media_type);
202 auto modified_extensions = transceiver1->HeaderExtensionsToOffer();
203 modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
204 transceiver1->SetOfferedRtpHeaderExtensions(modified_extensions);
205 auto offer = pc1->CreateOfferAndSetAsLocal(
206 PeerConnectionInterface::RTCOfferAnswerOptions());
207
208 std::unique_ptr<PeerConnectionWrapper> pc2 =
209 CreatePeerConnection(media_type, semantics);
210 auto transceiver2 = pc2->AddTransceiver(media_type);
211 pc2->SetRemoteDescription(std::move(offer));
212 auto answer = pc2->CreateAnswerAndSetAsLocal(
213 PeerConnectionInterface::RTCOfferAnswerOptions());
214 pc1->SetRemoteDescription(std::move(answer));
215
216 // PC1 has exts 2-4 unstopped and PC2 has exts 1-3 unstopped -> ext 2, 3
217 // survives.
218 EXPECT_THAT(transceiver1->HeaderExtensionsNegotiated(),
219 ElementsAre(Field(&RtpHeaderExtensionCapability::uri, "uri2"),
220 Field(&RtpHeaderExtensionCapability::uri, "uri3")));
221}
222
Markus Handell0357b3e2020-03-16 13:40:51 +0100223INSTANTIATE_TEST_SUITE_P(
224 ,
225 PeerConnectionHeaderExtensionTest,
Florent Castelli15a38de2022-04-06 00:38:21 +0200226 Combine(Values(SdpSemantics::kPlanB_DEPRECATED, SdpSemantics::kUnifiedPlan),
Björn Terelius99261af2021-05-12 17:06:49 +0000227 Values(cricket::MediaType::MEDIA_TYPE_AUDIO,
228 cricket::MediaType::MEDIA_TYPE_VIDEO)),
Markus Handell0357b3e2020-03-16 13:40:51 +0100229 [](const testing::TestParamInfo<
230 PeerConnectionHeaderExtensionTest::ParamType>& info) {
231 cricket::MediaType media_type;
232 SdpSemantics semantics;
233 std::tie(media_type, semantics) = info.param;
234 return (rtc::StringBuilder("With")
Florent Castelli15a38de2022-04-06 00:38:21 +0200235 << (semantics == SdpSemantics::kPlanB_DEPRECATED ? "PlanB"
236 : "UnifiedPlan")
Markus Handell0357b3e2020-03-16 13:40:51 +0100237 << "And"
238 << (media_type == cricket::MediaType::MEDIA_TYPE_AUDIO ? "Voice"
239 : "Video")
240 << "Engine")
241 .str();
242 });
243
244} // namespace webrtc