blob: af28a2db56c2cbc35187f73aa83ce3b3fef1175f [file] [log] [blame]
Henrik Boström933d8b02017-10-10 17:05:161/*
2 * Copyright 2017 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
Harald Alvestrandc24a2182022-02-23 13:44:5911#include <stddef.h>
Jonas Olssona4d87372019-07-05 17:08:3312
Harald Alvestrandc24a2182022-02-23 13:44:5913#include <cstdint>
Henrik Boström933d8b02017-10-10 17:05:1614#include <memory>
Florent Castelli8037fc62024-08-29 13:00:4015#include <optional>
Yves Gerey3e707812018-11-28 15:47:4916#include <string>
17#include <utility>
Henrik Boström933d8b02017-10-10 17:05:1618#include <vector>
19
Karl Wiberg1b0eae32017-10-17 12:48:5420#include "api/audio_codecs/builtin_audio_decoder_factory.h"
21#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Mirko Bonadei2ff3f492018-11-22 08:00:1322#include "api/create_peerconnection_factory.h"
Henrik Boström933d8b02017-10-10 17:05:1623#include "api/jsep.h"
Evan Shrubsole3e8e4782025-01-08 11:30:3124#include "api/make_ref_counted.h"
Steve Anton10542f22019-01-11 17:11:0025#include "api/media_stream_interface.h"
26#include "api/media_types.h"
27#include "api/peer_connection_interface.h"
28#include "api/rtc_error.h"
29#include "api/rtp_parameters.h"
30#include "api/rtp_receiver_interface.h"
31#include "api/rtp_sender_interface.h"
Harald Alvestrandc24a2182022-02-23 13:44:5932#include "api/rtp_transceiver_direction.h"
Steve Anton10542f22019-01-11 17:11:0033#include "api/rtp_transceiver_interface.h"
Mirko Bonadeid9708072019-01-25 19:26:4834#include "api/scoped_refptr.h"
Steve Anton10542f22019-01-11 17:11:0035#include "api/set_remote_description_observer_interface.h"
Evan Shrubsole3e8e4782025-01-08 11:30:3136#include "api/test/rtc_error_matchers.h"
37#include "api/video_codecs/sdp_video_format.h"
Åsa Persson0587aae2023-03-31 14:49:1438#include "api/video_codecs/video_decoder_factory_template.h"
39#include "api/video_codecs/video_decoder_factory_template_dav1d_adapter.h"
40#include "api/video_codecs/video_decoder_factory_template_libvpx_vp8_adapter.h"
41#include "api/video_codecs/video_decoder_factory_template_libvpx_vp9_adapter.h"
42#include "api/video_codecs/video_decoder_factory_template_open_h264_adapter.h"
43#include "api/video_codecs/video_encoder_factory_template.h"
44#include "api/video_codecs/video_encoder_factory_template_libaom_av1_adapter.h"
45#include "api/video_codecs/video_encoder_factory_template_libvpx_vp8_adapter.h"
46#include "api/video_codecs/video_encoder_factory_template_libvpx_vp9_adapter.h"
47#include "api/video_codecs/video_encoder_factory_template_open_h264_adapter.h"
Evan Shrubsole3e8e4782025-01-08 11:30:3148#include "media/base/codec.h"
Steve Anton10542f22019-01-11 17:11:0049#include "media/base/stream_params.h"
Steve Anton10542f22019-01-11 17:11:0050#include "pc/media_session.h"
51#include "pc/peer_connection_wrapper.h"
52#include "pc/sdp_utils.h"
53#include "pc/session_description.h"
54#include "pc/test/fake_audio_capture_module.h"
Philipp Hanckef16e1392023-10-05 12:12:3155#include "pc/test/integration_test_helpers.h"
Steve Anton10542f22019-01-11 17:11:0056#include "pc/test/mock_peer_connection_observers.h"
Henrik Boström933d8b02017-10-10 17:05:1657#include "rtc_base/checks.h"
Henrik Boström933d8b02017-10-10 17:05:1658#include "rtc_base/thread.h"
Mirko Bonadei17f48782018-09-28 06:51:1059#include "system_wrappers/include/metrics.h"
Steve Anton9158ef62017-11-27 21:01:5260#include "test/gmock.h"
Yves Gerey3e707812018-11-28 15:47:4961#include "test/gtest.h"
Evan Shrubsole3e8e4782025-01-08 11:30:3162#include "test/wait_until.h"
Henrik Boström933d8b02017-10-10 17:05:1663
64// This file contains tests for RTP Media API-related behavior of
Artem Titovcfea2182021-08-09 23:22:3165// `webrtc::PeerConnection`, see https://w3c.github.io/webrtc-pc/#rtp-media-api.
Henrik Boström933d8b02017-10-10 17:05:1666
Steve Anton9158ef62017-11-27 21:01:5267namespace webrtc {
68
69using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
70using ::testing::ElementsAre;
71using ::testing::UnorderedElementsAre;
Steve Anton3172c032018-05-03 22:30:1872using ::testing::Values;
Henrik Boström933d8b02017-10-10 17:05:1673
Henrik Boström31638672017-11-23 16:48:3274template <typename MethodFunctor>
Harald Alvestranda6544372023-11-13 09:33:5675class OnSuccessObserver : public SetRemoteDescriptionObserverInterface {
Henrik Boström31638672017-11-23 16:48:3276 public:
77 explicit OnSuccessObserver(MethodFunctor on_success)
78 : on_success_(std::move(on_success)) {}
79
Harald Alvestranda6544372023-11-13 09:33:5680 // SetRemoteDescriptionObserverInterface implementation.
81 void OnSetRemoteDescriptionComplete(RTCError error) override {
Henrik Boström31638672017-11-23 16:48:3282 RTC_CHECK(error.ok());
83 on_success_();
84 }
85
86 private:
87 MethodFunctor on_success_;
88};
89
Mirko Bonadei6a489f22019-04-09 13:11:1290class PeerConnectionRtpBaseTest : public ::testing::Test {
Henrik Boström933d8b02017-10-10 17:05:1691 public:
Steve Anton3172c032018-05-03 22:30:1892 explicit PeerConnectionRtpBaseTest(SdpSemantics sdp_semantics)
93 : sdp_semantics_(sdp_semantics),
Åsa Persson0587aae2023-03-31 14:49:1494 pc_factory_(CreatePeerConnectionFactory(
95 rtc::Thread::Current(),
96 rtc::Thread::Current(),
97 rtc::Thread::Current(),
98 FakeAudioCaptureModule::Create(),
99 CreateBuiltinAudioEncoderFactory(),
100 CreateBuiltinAudioDecoderFactory(),
101 std::make_unique<
102 VideoEncoderFactoryTemplate<LibvpxVp8EncoderTemplateAdapter,
103 LibvpxVp9EncoderTemplateAdapter,
104 OpenH264EncoderTemplateAdapter,
105 LibaomAv1EncoderTemplateAdapter>>(),
106 std::make_unique<
107 VideoDecoderFactoryTemplate<LibvpxVp8DecoderTemplateAdapter,
108 LibvpxVp9DecoderTemplateAdapter,
109 OpenH264DecoderTemplateAdapter,
110 Dav1dDecoderTemplateAdapter>>(),
111 nullptr /* audio_mixer */,
112 nullptr /* audio_processing */)) {
Harald Alvestranda6544372023-11-13 09:33:56113 metrics::Reset();
Qingsi Wang7fc821d2018-07-12 19:54:53114 }
Henrik Boström933d8b02017-10-10 17:05:16115
Steve Anton9158ef62017-11-27 21:01:52116 std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection() {
117 return CreatePeerConnection(RTCConfiguration());
118 }
119
Steve Antone831b8c2018-02-01 20:22:16120 std::unique_ptr<PeerConnectionWrapper> CreatePeerConnectionWithPlanB() {
121 RTCConfiguration config;
Florent Castelli15a38de2022-04-05 22:38:21122 config.sdp_semantics = SdpSemantics::kPlanB_DEPRECATED;
Steve Anton3172c032018-05-03 22:30:18123 return CreatePeerConnectionInternal(config);
Steve Antone831b8c2018-02-01 20:22:16124 }
125
Steve Anton9158ef62017-11-27 21:01:52126 std::unique_ptr<PeerConnectionWrapper> CreatePeerConnectionWithUnifiedPlan() {
127 RTCConfiguration config;
128 config.sdp_semantics = SdpSemantics::kUnifiedPlan;
Steve Anton3172c032018-05-03 22:30:18129 return CreatePeerConnectionInternal(config);
Steve Anton9158ef62017-11-27 21:01:52130 }
131
132 std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection(
133 const RTCConfiguration& config) {
Steve Anton3172c032018-05-03 22:30:18134 RTCConfiguration modified_config = config;
135 modified_config.sdp_semantics = sdp_semantics_;
136 return CreatePeerConnectionInternal(modified_config);
137 }
138
139 protected:
140 const SdpSemantics sdp_semantics_;
141 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
142
143 private:
144 // Private so that tests don't accidentally bypass the SdpSemantics
145 // adjustment.
146 std::unique_ptr<PeerConnectionWrapper> CreatePeerConnectionInternal(
147 const RTCConfiguration& config) {
Mirko Bonadei317a1f02019-09-17 15:06:18148 auto observer = std::make_unique<MockPeerConnectionObserver>();
Florent Castelli72424402022-04-06 01:45:10149 auto result = pc_factory_->CreatePeerConnectionOrError(
150 config, PeerConnectionDependencies(observer.get()));
151 EXPECT_TRUE(result.ok());
Niels Möllerafb246b2022-04-20 12:26:50152 observer->SetPeerConnectionInterface(result.value().get());
Florent Castelli72424402022-04-06 01:45:10153 return std::make_unique<PeerConnectionWrapper>(
154 pc_factory_, result.MoveValue(), std::move(observer));
Henrik Boström933d8b02017-10-10 17:05:16155 }
Niels Möller83830f32022-05-20 07:12:57156
157 rtc::AutoThread main_thread_;
Steve Anton3172c032018-05-03 22:30:18158};
Henrik Boström933d8b02017-10-10 17:05:16159
Steve Anton3172c032018-05-03 22:30:18160class PeerConnectionRtpTest
161 : public PeerConnectionRtpBaseTest,
162 public ::testing::WithParamInterface<SdpSemantics> {
Henrik Boström933d8b02017-10-10 17:05:16163 protected:
Steve Anton3172c032018-05-03 22:30:18164 PeerConnectionRtpTest() : PeerConnectionRtpBaseTest(GetParam()) {}
165};
166
167class PeerConnectionRtpTestPlanB : public PeerConnectionRtpBaseTest {
168 protected:
169 PeerConnectionRtpTestPlanB()
Florent Castelli15a38de2022-04-05 22:38:21170 : PeerConnectionRtpBaseTest(SdpSemantics::kPlanB_DEPRECATED) {}
Steve Anton3172c032018-05-03 22:30:18171};
172
173class PeerConnectionRtpTestUnifiedPlan : public PeerConnectionRtpBaseTest {
174 protected:
175 PeerConnectionRtpTestUnifiedPlan()
176 : PeerConnectionRtpBaseTest(SdpSemantics::kUnifiedPlan) {}
Harald Alvestrand09bd9ba2020-10-09 08:13:30177
178 // Helper to emulate an SFU that rejects an offered media section
179 // in answer.
180 bool ExchangeOfferAnswerWhereRemoteStopsTransceiver(
181 PeerConnectionWrapper* caller,
182 PeerConnectionWrapper* callee,
183 size_t mid_to_stop) {
184 auto offer = caller->CreateOffer();
185 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
186 callee->SetRemoteDescription(std::move(offer));
187 EXPECT_LT(mid_to_stop, callee->pc()->GetTransceivers().size());
188 // Must use StopInternal in order to do instant reject.
189 callee->pc()->GetTransceivers()[mid_to_stop]->StopInternal();
190 auto answer = callee->CreateAnswer();
191 EXPECT_TRUE(answer);
192 bool set_local_answer =
193 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
194 EXPECT_TRUE(set_local_answer);
195 bool set_remote_answer = caller->SetRemoteDescription(std::move(answer));
196 EXPECT_TRUE(set_remote_answer);
197 return set_remote_answer;
198 }
Henrik Boström933d8b02017-10-10 17:05:16199};
200
Harald Alvestranda6544372023-11-13 09:33:56201// These tests cover `PeerConnectionObserver` callbacks firing upon
Henrik Boström31638672017-11-23 16:48:32202// setting the remote description.
Henrik Boström31638672017-11-23 16:48:32203
Steve Anton3172c032018-05-03 22:30:18204TEST_P(PeerConnectionRtpTest, AddTrackWithoutStreamFiresOnAddTrack) {
Henrik Boström933d8b02017-10-10 17:05:16205 auto caller = CreatePeerConnection();
206 auto callee = CreatePeerConnection();
207
Steve Anton3172c032018-05-03 22:30:18208 ASSERT_TRUE(caller->AddAudioTrack("audio_track"));
Seth Hampson5897a6e2018-04-03 18:16:33209 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boström933d8b02017-10-10 17:05:16210
Henrik Boström31638672017-11-23 16:48:32211 ASSERT_EQ(callee->observer()->add_track_events_.size(), 1u);
Steve Anton3172c032018-05-03 22:30:18212 const auto& add_track_event = callee->observer()->add_track_events_[0];
Henrik Boström9e6fd2b2017-11-21 12:41:51213 EXPECT_EQ(add_track_event.streams, add_track_event.receiver->streams());
Steve Anton3172c032018-05-03 22:30:18214
Florent Castelli15a38de2022-04-05 22:38:21215 if (sdp_semantics_ == SdpSemantics::kPlanB_DEPRECATED) {
Steve Anton3172c032018-05-03 22:30:18216 // Since we are not supporting the no stream case with Plan B, there should
217 // be a generated stream, even though we didn't set one with AddTrack.
218 ASSERT_EQ(1u, add_track_event.streams.size());
219 EXPECT_TRUE(add_track_event.streams[0]->FindAudioTrack("audio_track"));
220 } else {
221 EXPECT_EQ(0u, add_track_event.streams.size());
222 }
Henrik Boström933d8b02017-10-10 17:05:16223}
224
Steve Anton3172c032018-05-03 22:30:18225TEST_P(PeerConnectionRtpTest, AddTrackWithStreamFiresOnAddTrack) {
Henrik Boström933d8b02017-10-10 17:05:16226 auto caller = CreatePeerConnection();
227 auto callee = CreatePeerConnection();
228
Steve Anton3172c032018-05-03 22:30:18229 ASSERT_TRUE(caller->AddAudioTrack("audio_track", {"audio_stream"}));
Seth Hampson5897a6e2018-04-03 18:16:33230 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boström933d8b02017-10-10 17:05:16231
Henrik Boström31638672017-11-23 16:48:32232 ASSERT_EQ(callee->observer()->add_track_events_.size(), 1u);
Henrik Boström9e6fd2b2017-11-21 12:41:51233 auto& add_track_event = callee->observer()->add_track_events_[0];
Henrik Boström31638672017-11-23 16:48:32234 ASSERT_EQ(add_track_event.streams.size(), 1u);
Seth Hampson13b8bad2018-03-13 23:05:28235 EXPECT_EQ("audio_stream", add_track_event.streams[0]->id());
Henrik Boström9e6fd2b2017-11-21 12:41:51236 EXPECT_TRUE(add_track_event.streams[0]->FindAudioTrack("audio_track"));
237 EXPECT_EQ(add_track_event.streams, add_track_event.receiver->streams());
Henrik Boström933d8b02017-10-10 17:05:16238}
239
Steve Anton3172c032018-05-03 22:30:18240TEST_P(PeerConnectionRtpTest, RemoveTrackWithoutStreamFiresOnRemoveTrack) {
Henrik Boström933d8b02017-10-10 17:05:16241 auto caller = CreatePeerConnection();
242 auto callee = CreatePeerConnection();
243
Steve Anton3172c032018-05-03 22:30:18244 auto sender = caller->AddAudioTrack("audio_track", {});
Seth Hampson5897a6e2018-04-03 18:16:33245 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boström31638672017-11-23 16:48:32246 ASSERT_EQ(callee->observer()->add_track_events_.size(), 1u);
Steve Anton3172c032018-05-03 22:30:18247 ASSERT_TRUE(
248 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
249
Harald Alvestrand93dd7632022-01-19 12:28:45250 EXPECT_TRUE(caller->pc()->RemoveTrackOrError(sender).ok());
Seth Hampson5897a6e2018-04-03 18:16:33251 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boström933d8b02017-10-10 17:05:16252
Henrik Boström31638672017-11-23 16:48:32253 ASSERT_EQ(callee->observer()->add_track_events_.size(), 1u);
Henrik Boström933d8b02017-10-10 17:05:16254 EXPECT_EQ(callee->observer()->GetAddTrackReceivers(),
255 callee->observer()->remove_track_events_);
256}
257
Steve Anton3172c032018-05-03 22:30:18258TEST_P(PeerConnectionRtpTest, RemoveTrackWithStreamFiresOnRemoveTrack) {
Henrik Boström933d8b02017-10-10 17:05:16259 auto caller = CreatePeerConnection();
260 auto callee = CreatePeerConnection();
261
Steve Anton3172c032018-05-03 22:30:18262 auto sender = caller->AddAudioTrack("audio_track", {"audio_stream"});
Seth Hampson5897a6e2018-04-03 18:16:33263 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boström31638672017-11-23 16:48:32264 ASSERT_EQ(callee->observer()->add_track_events_.size(), 1u);
Steve Anton3172c032018-05-03 22:30:18265 ASSERT_TRUE(
266 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
267
Harald Alvestrand93dd7632022-01-19 12:28:45268 EXPECT_TRUE(caller->pc()->RemoveTrackOrError(sender).ok());
Seth Hampson5897a6e2018-04-03 18:16:33269 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boström933d8b02017-10-10 17:05:16270
Henrik Boström31638672017-11-23 16:48:32271 ASSERT_EQ(callee->observer()->add_track_events_.size(), 1u);
Henrik Boström933d8b02017-10-10 17:05:16272 EXPECT_EQ(callee->observer()->GetAddTrackReceivers(),
273 callee->observer()->remove_track_events_);
Steve Anton3172c032018-05-03 22:30:18274 EXPECT_EQ(0u, callee->observer()->remote_streams()->count());
Henrik Boström933d8b02017-10-10 17:05:16275}
276
Steve Anton3172c032018-05-03 22:30:18277TEST_P(PeerConnectionRtpTest, RemoveTrackWithSharedStreamFiresOnRemoveTrack) {
Henrik Boström933d8b02017-10-10 17:05:16278 auto caller = CreatePeerConnection();
279 auto callee = CreatePeerConnection();
280
Seth Hampson845e8782018-03-02 19:34:10281 const char kSharedStreamId[] = "shared_audio_stream";
Steve Anton3172c032018-05-03 22:30:18282 auto sender1 = caller->AddAudioTrack("audio_track1", {kSharedStreamId});
283 auto sender2 = caller->AddAudioTrack("audio_track2", {kSharedStreamId});
Seth Hampson5897a6e2018-04-03 18:16:33284 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boström31638672017-11-23 16:48:32285 ASSERT_EQ(callee->observer()->add_track_events_.size(), 2u);
Steve Anton3172c032018-05-03 22:30:18286 ASSERT_TRUE(
287 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
Henrik Boström933d8b02017-10-10 17:05:16288
289 // Remove "audio_track1".
Harald Alvestrand93dd7632022-01-19 12:28:45290 EXPECT_TRUE(caller->pc()->RemoveTrackOrError(sender1).ok());
Seth Hampson5897a6e2018-04-03 18:16:33291 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boström31638672017-11-23 16:48:32292 ASSERT_EQ(callee->observer()->add_track_events_.size(), 2u);
Henrik Boström933d8b02017-10-10 17:05:16293 EXPECT_EQ(
Steve Anton9158ef62017-11-27 21:01:52294 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>{
Henrik Boström933d8b02017-10-10 17:05:16295 callee->observer()->add_track_events_[0].receiver},
296 callee->observer()->remove_track_events_);
Steve Anton3172c032018-05-03 22:30:18297 ASSERT_EQ(1u, callee->observer()->remote_streams()->count());
298 ASSERT_TRUE(
299 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
Henrik Boström933d8b02017-10-10 17:05:16300
301 // Remove "audio_track2".
Harald Alvestrand93dd7632022-01-19 12:28:45302 EXPECT_TRUE(caller->pc()->RemoveTrackOrError(sender2).ok());
Seth Hampson5897a6e2018-04-03 18:16:33303 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boström31638672017-11-23 16:48:32304 ASSERT_EQ(callee->observer()->add_track_events_.size(), 2u);
Henrik Boström933d8b02017-10-10 17:05:16305 EXPECT_EQ(callee->observer()->GetAddTrackReceivers(),
306 callee->observer()->remove_track_events_);
Steve Anton3172c032018-05-03 22:30:18307 EXPECT_EQ(0u, callee->observer()->remote_streams()->count());
Henrik Boström933d8b02017-10-10 17:05:16308}
309
Seth Hampson5b4f0752018-04-02 23:31:36310// Tests the edge case that if a stream ID changes for a given track that both
311// OnRemoveTrack and OnAddTrack is fired.
Steve Anton3172c032018-05-03 22:30:18312TEST_F(PeerConnectionRtpTestPlanB,
Seth Hampson5b4f0752018-04-02 23:31:36313 RemoteStreamIdChangesFiresOnRemoveAndOnAddTrack) {
314 auto caller = CreatePeerConnection();
315 auto callee = CreatePeerConnection();
316
317 const char kStreamId1[] = "stream1";
318 const char kStreamId2[] = "stream2";
Steve Anton3172c032018-05-03 22:30:18319 caller->AddAudioTrack("audio_track1", {kStreamId1});
Seth Hampson5897a6e2018-04-03 18:16:33320 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Seth Hampson5b4f0752018-04-02 23:31:36321 EXPECT_EQ(callee->observer()->add_track_events_.size(), 1u);
322
323 // Change the stream ID of the sender in the session description.
324 auto offer = caller->CreateOfferAndSetAsLocal();
Steve Anton3172c032018-05-03 22:30:18325 auto* audio_desc =
326 cricket::GetFirstAudioContentDescription(offer->description());
Seth Hampson5b4f0752018-04-02 23:31:36327 ASSERT_EQ(audio_desc->mutable_streams().size(), 1u);
328 audio_desc->mutable_streams()[0].set_stream_ids({kStreamId2});
Steve Anton3172c032018-05-03 22:30:18329 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
Seth Hampson5b4f0752018-04-02 23:31:36330
331 ASSERT_EQ(callee->observer()->add_track_events_.size(), 2u);
332 EXPECT_EQ(callee->observer()->add_track_events_[1].streams[0]->id(),
333 kStreamId2);
334 ASSERT_EQ(callee->observer()->remove_track_events_.size(), 1u);
335 EXPECT_EQ(callee->observer()->remove_track_events_[0]->streams()[0]->id(),
336 kStreamId1);
337}
338
Steve Anton8b815cd2018-02-17 00:14:42339// Tests that setting a remote description with sending transceivers will fire
340// the OnTrack callback for each transceiver and setting a remote description
Seth Hampson5b4f0752018-04-02 23:31:36341// with receive only transceivers will not call OnTrack. One transceiver is
342// created without any stream_ids, while the other is created with multiple
343// stream_ids.
Steve Anton3172c032018-05-03 22:30:18344TEST_F(PeerConnectionRtpTestUnifiedPlan, AddTransceiverCallsOnTrack) {
Seth Hampson5b4f0752018-04-02 23:31:36345 const std::string kStreamId1 = "video_stream1";
346 const std::string kStreamId2 = "video_stream2";
Steve Anton3172c032018-05-03 22:30:18347 auto caller = CreatePeerConnection();
348 auto callee = CreatePeerConnection();
Steve Anton8b815cd2018-02-17 00:14:42349
350 auto audio_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
Seth Hampson5b4f0752018-04-02 23:31:36351 RtpTransceiverInit video_transceiver_init;
352 video_transceiver_init.stream_ids = {kStreamId1, kStreamId2};
353 auto video_transceiver =
354 caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, video_transceiver_init);
Steve Anton8b815cd2018-02-17 00:14:42355
356 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
357
358 ASSERT_EQ(0u, caller->observer()->on_track_transceivers_.size());
359 ASSERT_EQ(2u, callee->observer()->on_track_transceivers_.size());
360 EXPECT_EQ(audio_transceiver->mid(),
361 callee->pc()->GetTransceivers()[0]->mid());
362 EXPECT_EQ(video_transceiver->mid(),
363 callee->pc()->GetTransceivers()[1]->mid());
Seth Hampson5b4f0752018-04-02 23:31:36364 std::vector<rtc::scoped_refptr<MediaStreamInterface>> audio_streams =
365 callee->pc()->GetTransceivers()[0]->receiver()->streams();
366 std::vector<rtc::scoped_refptr<MediaStreamInterface>> video_streams =
367 callee->pc()->GetTransceivers()[1]->receiver()->streams();
368 ASSERT_EQ(0u, audio_streams.size());
369 ASSERT_EQ(2u, video_streams.size());
370 EXPECT_EQ(kStreamId1, video_streams[0]->id());
371 EXPECT_EQ(kStreamId2, video_streams[1]->id());
Steve Anton8b815cd2018-02-17 00:14:42372}
373
374// Test that doing additional offer/answer exchanges with no changes to tracks
375// will cause no additional OnTrack calls after the tracks have been negotiated.
Steve Anton3172c032018-05-03 22:30:18376TEST_F(PeerConnectionRtpTestUnifiedPlan, ReofferDoesNotCallOnTrack) {
377 auto caller = CreatePeerConnection();
378 auto callee = CreatePeerConnection();
Steve Anton8b815cd2018-02-17 00:14:42379
380 caller->AddAudioTrack("audio");
381 callee->AddAudioTrack("audio");
382
383 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
384 EXPECT_EQ(1u, caller->observer()->on_track_transceivers_.size());
385 EXPECT_EQ(1u, callee->observer()->on_track_transceivers_.size());
386
387 // If caller reoffers with no changes expect no additional OnTrack calls.
388 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
389 EXPECT_EQ(1u, caller->observer()->on_track_transceivers_.size());
390 EXPECT_EQ(1u, callee->observer()->on_track_transceivers_.size());
391
392 // Also if callee reoffers with no changes expect no additional OnTrack calls.
393 ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
394 EXPECT_EQ(1u, caller->observer()->on_track_transceivers_.size());
395 EXPECT_EQ(1u, callee->observer()->on_track_transceivers_.size());
396}
397
398// Test that OnTrack is called when the transceiver direction changes to send
399// the track.
Steve Anton3172c032018-05-03 22:30:18400TEST_F(PeerConnectionRtpTestUnifiedPlan, SetDirectionCallsOnTrack) {
401 auto caller = CreatePeerConnection();
402 auto callee = CreatePeerConnection();
Steve Anton8b815cd2018-02-17 00:14:42403
404 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
Harald Alvestrand6060df52020-08-11 07:54:02405 EXPECT_TRUE(
406 transceiver->SetDirectionWithError(RtpTransceiverDirection::kInactive)
407 .ok());
Steve Anton8b815cd2018-02-17 00:14:42408 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
409 EXPECT_EQ(0u, caller->observer()->on_track_transceivers_.size());
410 EXPECT_EQ(0u, callee->observer()->on_track_transceivers_.size());
411
Harald Alvestrand6060df52020-08-11 07:54:02412 EXPECT_TRUE(
413 transceiver->SetDirectionWithError(RtpTransceiverDirection::kSendOnly)
414 .ok());
Steve Anton8b815cd2018-02-17 00:14:42415 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
416 EXPECT_EQ(0u, caller->observer()->on_track_transceivers_.size());
417 EXPECT_EQ(1u, callee->observer()->on_track_transceivers_.size());
418
419 // If the direction changes but it is still receiving on the remote side, then
420 // OnTrack should not be fired again.
Harald Alvestrand6060df52020-08-11 07:54:02421 EXPECT_TRUE(
422 transceiver->SetDirectionWithError(RtpTransceiverDirection::kSendRecv)
423 .ok());
Steve Anton8b815cd2018-02-17 00:14:42424 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
425 EXPECT_EQ(0u, caller->observer()->on_track_transceivers_.size());
426 EXPECT_EQ(1u, callee->observer()->on_track_transceivers_.size());
427}
428
429// Test that OnTrack is called twice when a sendrecv call is started, the callee
430// changes the direction to inactive, then changes it back to sendrecv.
Steve Anton3172c032018-05-03 22:30:18431TEST_F(PeerConnectionRtpTestUnifiedPlan, SetDirectionHoldCallsOnTrackTwice) {
432 auto caller = CreatePeerConnection();
433 auto callee = CreatePeerConnection();
Steve Anton8b815cd2018-02-17 00:14:42434
435 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
436
437 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
438 EXPECT_EQ(0u, caller->observer()->on_track_transceivers_.size());
439 EXPECT_EQ(1u, callee->observer()->on_track_transceivers_.size());
440
441 // Put the call on hold by no longer receiving the track.
Harald Alvestrand6060df52020-08-11 07:54:02442 EXPECT_TRUE(callee->pc()
443 ->GetTransceivers()[0]
444 ->SetDirectionWithError(RtpTransceiverDirection::kInactive)
445 .ok());
Steve Anton8b815cd2018-02-17 00:14:42446
447 ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
448 EXPECT_EQ(0u, caller->observer()->on_track_transceivers_.size());
449 EXPECT_EQ(1u, callee->observer()->on_track_transceivers_.size());
450
451 // Resume the call by changing the direction to recvonly. This should call
452 // OnTrack again on the callee side.
Harald Alvestrand6060df52020-08-11 07:54:02453 EXPECT_TRUE(callee->pc()
454 ->GetTransceivers()[0]
455 ->SetDirectionWithError(RtpTransceiverDirection::kRecvOnly)
456 .ok());
Steve Anton8b815cd2018-02-17 00:14:42457
458 ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
459 EXPECT_EQ(0u, caller->observer()->on_track_transceivers_.size());
460 EXPECT_EQ(2u, callee->observer()->on_track_transceivers_.size());
461}
462
Steve Anton3172c032018-05-03 22:30:18463// Test that setting a remote offer twice with no answer in the middle results
Steve Anton0f5400a2018-07-17 21:25:36464// in OnAddTrack being fired only once.
Steve Anton3172c032018-05-03 22:30:18465TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Anton0f5400a2018-07-17 21:25:36466 ApplyTwoRemoteOffersWithNoAnswerResultsInOneAddTrackEvent) {
Henrik Boström31638672017-11-23 16:48:32467 auto caller = CreatePeerConnection();
468 auto callee = CreatePeerConnection();
469
Steve Anton3172c032018-05-03 22:30:18470 caller->AddAudioTrack("audio_track", {});
471
Amit Hilbuchae3df542019-01-07 20:13:08472 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Steve Anton3172c032018-05-03 22:30:18473 ASSERT_EQ(1u, callee->observer()->add_track_events_.size());
474
Amit Hilbuchae3df542019-01-07 20:13:08475 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Steve Anton0f5400a2018-07-17 21:25:36476 EXPECT_EQ(1u, callee->observer()->add_track_events_.size());
Steve Anton3172c032018-05-03 22:30:18477}
478
479// Test that setting a remote offer twice with no answer in the middle and the
480// track being removed between the two offers results in OnAddTrack being called
Steve Anton0f5400a2018-07-17 21:25:36481// once the first time and OnRemoveTrack being called once the second time.
Steve Anton3172c032018-05-03 22:30:18482TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Anton0f5400a2018-07-17 21:25:36483 ApplyRemoteOfferAddThenRemoteOfferRemoveResultsInOneRemoveTrackEvent) {
Steve Anton3172c032018-05-03 22:30:18484 auto caller = CreatePeerConnection();
485 auto callee = CreatePeerConnection();
486
487 auto sender = caller->AddAudioTrack("audio_track", {});
488
Amit Hilbuchae3df542019-01-07 20:13:08489 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Steve Anton3172c032018-05-03 22:30:18490 ASSERT_EQ(1u, callee->observer()->add_track_events_.size());
Steve Anton0f5400a2018-07-17 21:25:36491 EXPECT_EQ(0u, callee->observer()->remove_track_events_.size());
Steve Anton3172c032018-05-03 22:30:18492
Harald Alvestrand93dd7632022-01-19 12:28:45493 caller->pc()->RemoveTrackOrError(sender);
Steve Anton3172c032018-05-03 22:30:18494
Amit Hilbuchae3df542019-01-07 20:13:08495 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Steve Anton3172c032018-05-03 22:30:18496 EXPECT_EQ(1u, callee->observer()->add_track_events_.size());
Steve Anton0f5400a2018-07-17 21:25:36497 EXPECT_EQ(1u, callee->observer()->remove_track_events_.size());
498}
499
500// Test that changing the direction from receiving to not receiving between
501// setting the remote offer and creating / setting the local answer results in
502// a remove track event when SetLocalDescription is called.
503TEST_F(PeerConnectionRtpTestUnifiedPlan,
504 ChangeDirectionInAnswerResultsInRemoveTrackEvent) {
505 auto caller = CreatePeerConnection();
506 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
507 auto callee = CreatePeerConnection();
508 callee->AddAudioTrack("audio_track", {});
509
510 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
511 EXPECT_EQ(1u, callee->observer()->add_track_events_.size());
Steve Anton3172c032018-05-03 22:30:18512 EXPECT_EQ(0u, callee->observer()->remove_track_events_.size());
Steve Anton0f5400a2018-07-17 21:25:36513
514 auto callee_transceiver = callee->pc()->GetTransceivers()[0];
Harald Alvestrand6060df52020-08-11 07:54:02515 EXPECT_TRUE(callee_transceiver
516 ->SetDirectionWithError(RtpTransceiverDirection::kSendOnly)
517 .ok());
Steve Anton0f5400a2018-07-17 21:25:36518
519 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
520 EXPECT_EQ(1u, callee->observer()->add_track_events_.size());
521 EXPECT_EQ(1u, callee->observer()->remove_track_events_.size());
Steve Anton3172c032018-05-03 22:30:18522}
523
Henrik Boströmafa07dd2018-12-20 10:06:02524TEST_F(PeerConnectionRtpTestUnifiedPlan, ChangeMsidWhileReceiving) {
525 auto caller = CreatePeerConnection();
526 caller->AddAudioTrack("audio_track", {"stream1"});
527 auto callee = CreatePeerConnection();
Amit Hilbuchae3df542019-01-07 20:13:08528 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boströmafa07dd2018-12-20 10:06:02529
530 ASSERT_EQ(1u, callee->observer()->on_track_transceivers_.size());
531 auto transceiver = callee->observer()->on_track_transceivers_[0];
532 ASSERT_EQ(1u, transceiver->receiver()->streams().size());
533 EXPECT_EQ("stream1", transceiver->receiver()->streams()[0]->id());
534
Amit Hilbuchae3df542019-01-07 20:13:08535 ASSERT_TRUE(callee->CreateAnswerAndSetAsLocal());
Henrik Boströmafa07dd2018-12-20 10:06:02536
537 // Change the stream ID in the offer.
Guido Urdaneta1ff16c82019-05-20 17:31:53538 caller->pc()->GetSenders()[0]->SetStreams({"stream2"});
539 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boströmafa07dd2018-12-20 10:06:02540 ASSERT_EQ(1u, transceiver->receiver()->streams().size());
541 EXPECT_EQ("stream2", transceiver->receiver()->streams()[0]->id());
542}
543
Steve Anton3172c032018-05-03 22:30:18544// These tests examine the state of the peer connection as a result of
545// performing SetRemoteDescription().
546
547TEST_P(PeerConnectionRtpTest, AddTrackWithoutStreamAddsReceiver) {
548 auto caller = CreatePeerConnection();
549 auto callee = CreatePeerConnection();
550
551 ASSERT_TRUE(caller->AddAudioTrack("audio_track", {}));
Seth Hampson5897a6e2018-04-03 18:16:33552 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boström31638672017-11-23 16:48:32553
554 EXPECT_EQ(callee->pc()->GetReceivers().size(), 1u);
555 auto receiver_added = callee->pc()->GetReceivers()[0];
556 EXPECT_EQ("audio_track", receiver_added->track()->id());
Steve Anton3172c032018-05-03 22:30:18557
Florent Castelli15a38de2022-04-05 22:38:21558 if (sdp_semantics_ == SdpSemantics::kPlanB_DEPRECATED) {
Steve Anton3172c032018-05-03 22:30:18559 // Since we are not supporting the no stream case with Plan B, there should
560 // be a generated stream, even though we didn't set one with AddTrack.
561 ASSERT_EQ(1u, receiver_added->streams().size());
562 EXPECT_TRUE(receiver_added->streams()[0]->FindAudioTrack("audio_track"));
563 } else {
564 EXPECT_EQ(0u, receiver_added->streams().size());
565 }
Henrik Boström31638672017-11-23 16:48:32566}
567
Steve Anton3172c032018-05-03 22:30:18568TEST_P(PeerConnectionRtpTest, AddTrackWithStreamAddsReceiver) {
Henrik Boström31638672017-11-23 16:48:32569 auto caller = CreatePeerConnection();
570 auto callee = CreatePeerConnection();
571
Steve Anton3172c032018-05-03 22:30:18572 ASSERT_TRUE(caller->AddAudioTrack("audio_track", {"audio_stream"}));
Seth Hampson5897a6e2018-04-03 18:16:33573 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Henrik Boström31638672017-11-23 16:48:32574
575 EXPECT_EQ(callee->pc()->GetReceivers().size(), 1u);
576 auto receiver_added = callee->pc()->GetReceivers()[0];
577 EXPECT_EQ("audio_track", receiver_added->track()->id());
578 EXPECT_EQ(receiver_added->streams().size(), 1u);
Seth Hampson13b8bad2018-03-13 23:05:28579 EXPECT_EQ("audio_stream", receiver_added->streams()[0]->id());
Henrik Boström31638672017-11-23 16:48:32580 EXPECT_TRUE(receiver_added->streams()[0]->FindAudioTrack("audio_track"));
581}
582
Steve Anton3172c032018-05-03 22:30:18583TEST_P(PeerConnectionRtpTest, RemoveTrackWithoutStreamRemovesReceiver) {
Henrik Boström31638672017-11-23 16:48:32584 auto caller = CreatePeerConnection();
585 auto callee = CreatePeerConnection();
586
Steve Anton3172c032018-05-03 22:30:18587 auto sender = caller->AddAudioTrack("audio_track", {});
Henrik Boström31638672017-11-23 16:48:32588 ASSERT_TRUE(sender);
Steve Anton3172c032018-05-03 22:30:18589 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
590
Henrik Boström31638672017-11-23 16:48:32591 ASSERT_EQ(callee->pc()->GetReceivers().size(), 1u);
592 auto receiver = callee->pc()->GetReceivers()[0];
Harald Alvestrand93dd7632022-01-19 12:28:45593 ASSERT_TRUE(caller->pc()->RemoveTrackOrError(sender).ok());
Steve Anton3172c032018-05-03 22:30:18594 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Henrik Boström31638672017-11-23 16:48:32595
Steve Anton3172c032018-05-03 22:30:18596 if (sdp_semantics_ == SdpSemantics::kUnifiedPlan) {
597 // With Unified Plan the receiver stays but the transceiver transitions to
598 // inactive.
599 ASSERT_EQ(1u, callee->pc()->GetReceivers().size());
600 EXPECT_EQ(RtpTransceiverDirection::kInactive,
601 callee->pc()->GetTransceivers()[0]->current_direction());
602 } else {
603 // With Plan B the receiver is removed.
604 ASSERT_EQ(0u, callee->pc()->GetReceivers().size());
605 }
Henrik Boström31638672017-11-23 16:48:32606}
607
Steve Anton3172c032018-05-03 22:30:18608TEST_P(PeerConnectionRtpTest, RemoveTrackWithStreamRemovesReceiver) {
Henrik Boström31638672017-11-23 16:48:32609 auto caller = CreatePeerConnection();
610 auto callee = CreatePeerConnection();
611
Steve Anton3172c032018-05-03 22:30:18612 auto sender = caller->AddAudioTrack("audio_track", {"audio_stream"});
Henrik Boström31638672017-11-23 16:48:32613 ASSERT_TRUE(sender);
Steve Anton3172c032018-05-03 22:30:18614 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Henrik Boström31638672017-11-23 16:48:32615 ASSERT_EQ(callee->pc()->GetReceivers().size(), 1u);
616 auto receiver = callee->pc()->GetReceivers()[0];
Harald Alvestrand93dd7632022-01-19 12:28:45617 ASSERT_TRUE(caller->pc()->RemoveTrackOrError(sender).ok());
Steve Anton3172c032018-05-03 22:30:18618 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Henrik Boström31638672017-11-23 16:48:32619
Steve Anton3172c032018-05-03 22:30:18620 if (sdp_semantics_ == SdpSemantics::kUnifiedPlan) {
621 // With Unified Plan the receiver stays but the transceiver transitions to
622 // inactive.
623 EXPECT_EQ(1u, callee->pc()->GetReceivers().size());
624 EXPECT_EQ(RtpTransceiverDirection::kInactive,
625 callee->pc()->GetTransceivers()[0]->current_direction());
626 } else {
627 // With Plan B the receiver is removed.
628 EXPECT_EQ(0u, callee->pc()->GetReceivers().size());
629 }
Henrik Boström31638672017-11-23 16:48:32630}
631
Steve Anton3172c032018-05-03 22:30:18632TEST_P(PeerConnectionRtpTest, RemoveTrackWithSharedStreamRemovesReceiver) {
Henrik Boström31638672017-11-23 16:48:32633 auto caller = CreatePeerConnection();
634 auto callee = CreatePeerConnection();
635
Seth Hampson845e8782018-03-02 19:34:10636 const char kSharedStreamId[] = "shared_audio_stream";
Steve Anton3172c032018-05-03 22:30:18637 auto sender1 = caller->AddAudioTrack("audio_track1", {kSharedStreamId});
638 auto sender2 = caller->AddAudioTrack("audio_track2", {kSharedStreamId});
639 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
640 ASSERT_EQ(2u, callee->pc()->GetReceivers().size());
Henrik Boström31638672017-11-23 16:48:32641
642 // Remove "audio_track1".
Harald Alvestrand93dd7632022-01-19 12:28:45643 EXPECT_TRUE(caller->pc()->RemoveTrackOrError(sender1).ok());
Steve Anton3172c032018-05-03 22:30:18644 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
645
646 if (sdp_semantics_ == SdpSemantics::kUnifiedPlan) {
647 // With Unified Plan the receiver stays but the transceiver transitions to
648 // inactive.
649 ASSERT_EQ(2u, callee->pc()->GetReceivers().size());
650 auto transceiver = callee->pc()->GetTransceivers()[0];
651 EXPECT_EQ("audio_track1", transceiver->receiver()->track()->id());
652 EXPECT_EQ(RtpTransceiverDirection::kInactive,
653 transceiver->current_direction());
654 } else {
655 // With Plan B the receiver is removed.
656 ASSERT_EQ(1u, callee->pc()->GetReceivers().size());
657 EXPECT_EQ("audio_track2", callee->pc()->GetReceivers()[0]->track()->id());
658 }
Henrik Boström31638672017-11-23 16:48:32659
660 // Remove "audio_track2".
Harald Alvestrand93dd7632022-01-19 12:28:45661 EXPECT_TRUE(caller->pc()->RemoveTrackOrError(sender2).ok());
Steve Anton3172c032018-05-03 22:30:18662 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
663
664 if (sdp_semantics_ == SdpSemantics::kUnifiedPlan) {
665 // With Unified Plan the receiver stays but the transceiver transitions to
666 // inactive.
667 ASSERT_EQ(2u, callee->pc()->GetReceivers().size());
668 auto transceiver = callee->pc()->GetTransceivers()[1];
669 EXPECT_EQ("audio_track2", transceiver->receiver()->track()->id());
670 EXPECT_EQ(RtpTransceiverDirection::kInactive,
671 transceiver->current_direction());
672 } else {
673 // With Plan B the receiver is removed.
674 ASSERT_EQ(0u, callee->pc()->GetReceivers().size());
675 }
Henrik Boström31638672017-11-23 16:48:32676}
677
Florent Castelliabe301f2018-06-12 16:33:49678TEST_P(PeerConnectionRtpTest, AudioGetParametersHasHeaderExtensions) {
679 auto caller = CreatePeerConnection();
680 auto callee = CreatePeerConnection();
681 auto sender = caller->AddAudioTrack("audio_track");
682 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
683
684 ASSERT_GT(caller->pc()->GetSenders().size(), 0u);
685 EXPECT_GT(sender->GetParameters().header_extensions.size(), 0u);
686
687 ASSERT_GT(callee->pc()->GetReceivers().size(), 0u);
688 auto receiver = callee->pc()->GetReceivers()[0];
689 EXPECT_GT(receiver->GetParameters().header_extensions.size(), 0u);
690}
691
692TEST_P(PeerConnectionRtpTest, VideoGetParametersHasHeaderExtensions) {
693 auto caller = CreatePeerConnection();
694 auto callee = CreatePeerConnection();
695 auto sender = caller->AddVideoTrack("video_track");
696 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
697
698 ASSERT_GT(caller->pc()->GetSenders().size(), 0u);
699 EXPECT_GT(sender->GetParameters().header_extensions.size(), 0u);
700
701 ASSERT_GT(callee->pc()->GetReceivers().size(), 0u);
702 auto receiver = callee->pc()->GetReceivers()[0];
703 EXPECT_GT(receiver->GetParameters().header_extensions.size(), 0u);
704}
705
Henrik Boström31638672017-11-23 16:48:32706// Invokes SetRemoteDescription() twice in a row without synchronizing the two
707// calls and examine the state of the peer connection inside the callbacks to
708// ensure that the second call does not occur prematurely, contaminating the
709// state of the peer connection of the first callback.
Steve Anton3172c032018-05-03 22:30:18710TEST_F(PeerConnectionRtpTestPlanB,
Henrik Boström31638672017-11-23 16:48:32711 StatesCorrelateWithSetRemoteDescriptionCall) {
712 auto caller = CreatePeerConnection();
713 auto callee = CreatePeerConnection();
714
Henrik Boström31638672017-11-23 16:48:32715 // Create SDP for adding a track and for removing it. This will be used in the
716 // first and second SetRemoteDescription() calls.
Steve Anton3172c032018-05-03 22:30:18717 auto sender = caller->AddAudioTrack("audio_track", {});
Henrik Boström31638672017-11-23 16:48:32718 auto srd1_sdp = caller->CreateOfferAndSetAsLocal();
Harald Alvestrand93dd7632022-01-19 12:28:45719 EXPECT_TRUE(caller->pc()->RemoveTrackOrError(sender).ok());
Henrik Boström31638672017-11-23 16:48:32720 auto srd2_sdp = caller->CreateOfferAndSetAsLocal();
721
722 // In the first SetRemoteDescription() callback, check that we have a
723 // receiver for the track.
724 auto pc = callee->pc();
725 bool srd1_callback_called = false;
726 auto srd1_callback = [&srd1_callback_called, &pc]() {
727 EXPECT_EQ(pc->GetReceivers().size(), 1u);
728 srd1_callback_called = true;
729 };
730
731 // In the second SetRemoteDescription() callback, check that the receiver has
732 // been removed.
733 // TODO(hbos): When we implement Unified Plan, receivers will not be removed.
734 // Instead, the transceiver owning the receiver will become inactive.
735 // https://crbug.com/webrtc/7600
736 bool srd2_callback_called = false;
737 auto srd2_callback = [&srd2_callback_called, &pc]() {
738 EXPECT_TRUE(pc->GetReceivers().empty());
739 srd2_callback_called = true;
740 };
741
742 // Invoke SetRemoteDescription() twice in a row without synchronizing the two
743 // calls. The callbacks verify that the two calls are synchronized, as in, the
744 // effects of the second SetRemoteDescription() call must not have happened by
745 // the time the first callback is invoked. If it has then the receiver that is
746 // added as a result of the first SetRemoteDescription() call will already
747 // have been removed as a result of the second SetRemoteDescription() call
748 // when the first callback is invoked.
749 callee->pc()->SetRemoteDescription(
750 std::move(srd1_sdp),
Niels Möllere7cc8832022-01-04 14:20:03751 rtc::make_ref_counted<OnSuccessObserver<decltype(srd1_callback)>>(
752 srd1_callback));
Henrik Boström31638672017-11-23 16:48:32753 callee->pc()->SetRemoteDescription(
754 std::move(srd2_sdp),
Niels Möllere7cc8832022-01-04 14:20:03755 rtc::make_ref_counted<OnSuccessObserver<decltype(srd2_callback)>>(
756 srd2_callback));
Evan Shrubsole3e8e4782025-01-08 11:30:31757 EXPECT_THAT(
758 WaitUntil([&] { return srd1_callback_called; }, ::testing::IsTrue()),
759 IsRtcOk());
760 EXPECT_THAT(
761 WaitUntil([&] { return srd2_callback_called; }, ::testing::IsTrue()),
762 IsRtcOk());
Henrik Boström31638672017-11-23 16:48:32763}
764
Seth Hampson5897a6e2018-04-03 18:16:33765// Tests that a remote track is created with the signaled MSIDs when they are
766// communicated with a=msid and no SSRCs are signaled at all (i.e., no a=ssrc
767// lines).
Steve Anton3172c032018-05-03 22:30:18768TEST_F(PeerConnectionRtpTestUnifiedPlan, UnsignaledSsrcCreatesReceiverStreams) {
769 auto caller = CreatePeerConnection();
770 auto callee = CreatePeerConnection();
Seth Hampson5897a6e2018-04-03 18:16:33771 const char kStreamId1[] = "stream1";
772 const char kStreamId2[] = "stream2";
773 caller->AddTrack(caller->CreateAudioTrack("audio_track1"),
774 {kStreamId1, kStreamId2});
775
776 auto offer = caller->CreateOfferAndSetAsLocal();
777 // Munge the offer to take out everything but the stream_ids.
778 auto contents = offer->description()->contents();
779 ASSERT_TRUE(!contents.empty());
780 ASSERT_TRUE(!contents[0].media_description()->streams().empty());
781 std::vector<std::string> stream_ids =
782 contents[0].media_description()->streams()[0].stream_ids();
783 contents[0].media_description()->mutable_streams().clear();
784 cricket::StreamParams new_stream;
785 new_stream.set_stream_ids(stream_ids);
786 contents[0].media_description()->AddStream(new_stream);
787
788 // Set the remote description and verify that the streams were added to the
789 // receiver correctly.
790 ASSERT_TRUE(
791 callee->SetRemoteDescription(CloneSessionDescription(offer.get())));
792 auto receivers = callee->pc()->GetReceivers();
793 ASSERT_EQ(receivers.size(), 1u);
794 ASSERT_EQ(receivers[0]->streams().size(), 2u);
795 EXPECT_EQ(receivers[0]->streams()[0]->id(), kStreamId1);
796 EXPECT_EQ(receivers[0]->streams()[1]->id(), kStreamId2);
797}
Henrik Boströmc335b0e2021-04-08 05:25:38798TEST_F(PeerConnectionRtpTestUnifiedPlan, TracksDoNotEndWhenSsrcChanges) {
799 constexpr uint32_t kFirstMungedSsrc = 1337u;
800
801 auto caller = CreatePeerConnection();
802 auto callee = CreatePeerConnection();
803
804 // Caller offers to receive audio and video.
805 RtpTransceiverInit init;
806 init.direction = RtpTransceiverDirection::kRecvOnly;
807 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, init);
808 caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
809
810 // Callee wants to send audio and video tracks.
811 callee->AddTrack(callee->CreateAudioTrack("audio_track"), {});
812 callee->AddTrack(callee->CreateVideoTrack("video_track"), {});
813
814 // Do inittial offer/answer exchange.
815 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
816 ASSERT_TRUE(
817 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
818 ASSERT_EQ(caller->observer()->add_track_events_.size(), 2u);
819 ASSERT_EQ(caller->pc()->GetReceivers().size(), 2u);
820
821 // Do a follow-up offer/answer exchange where the SSRCs are modified.
822 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
823 auto answer = callee->CreateAnswer();
824 auto& contents = answer->description()->contents();
825 ASSERT_TRUE(!contents.empty());
826 for (size_t i = 0; i < contents.size(); ++i) {
827 auto& mutable_streams = contents[i].media_description()->mutable_streams();
828 ASSERT_EQ(mutable_streams.size(), 1u);
Philipp Hanckef16e1392023-10-05 12:12:31829 ReplaceFirstSsrc(mutable_streams[0],
830 kFirstMungedSsrc + static_cast<uint32_t>(i));
Henrik Boströmc335b0e2021-04-08 05:25:38831 }
832 ASSERT_TRUE(
833 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
834 ASSERT_TRUE(
835 caller->SetRemoteDescription(CloneSessionDescription(answer.get())));
836
837 // No furher track events should fire because we never changed direction, only
838 // SSRCs.
839 ASSERT_EQ(caller->observer()->add_track_events_.size(), 2u);
840 // We should have the same number of receivers as before.
841 auto receivers = caller->pc()->GetReceivers();
842 ASSERT_EQ(receivers.size(), 2u);
843 // The tracks are still alive.
844 EXPECT_EQ(receivers[0]->track()->state(),
845 MediaStreamTrackInterface::TrackState::kLive);
846 EXPECT_EQ(receivers[1]->track()->state(),
847 MediaStreamTrackInterface::TrackState::kLive);
848}
Seth Hampson5897a6e2018-04-03 18:16:33849
Seth Hampson5b4f0752018-04-02 23:31:36850// Tests that with Unified Plan if the the stream id changes for a track when
851// when setting a new remote description, that the media stream is updated
852// appropriately for the receiver.
Steve Anton0f5400a2018-07-17 21:25:36853// TODO(https://github.com/w3c/webrtc-pc/issues/1937): Resolve spec issue or fix
854// test.
855TEST_F(PeerConnectionRtpTestUnifiedPlan,
856 DISABLED_RemoteStreamIdChangesUpdatesReceiver) {
Steve Anton3172c032018-05-03 22:30:18857 auto caller = CreatePeerConnection();
858 auto callee = CreatePeerConnection();
Seth Hampson5b4f0752018-04-02 23:31:36859
860 const char kStreamId1[] = "stream1";
861 const char kStreamId2[] = "stream2";
Steve Anton0f5400a2018-07-17 21:25:36862 caller->AddAudioTrack("audio_track1", {kStreamId1});
Seth Hampson5897a6e2018-04-03 18:16:33863 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
Seth Hampson5b4f0752018-04-02 23:31:36864 EXPECT_EQ(callee->observer()->add_track_events_.size(), 1u);
865
866 // Change the stream id of the sender in the session description.
867 auto offer = caller->CreateOfferAndSetAsLocal();
868 auto contents = offer->description()->contents();
869 ASSERT_EQ(contents.size(), 1u);
870 ASSERT_EQ(contents[0].media_description()->mutable_streams().size(), 1u);
871 contents[0].media_description()->mutable_streams()[0].set_stream_ids(
872 {kStreamId2});
873
Steve Anton0f5400a2018-07-17 21:25:36874 // Set the remote description and verify that the stream was updated
875 // properly.
876 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
Seth Hampson5b4f0752018-04-02 23:31:36877 auto receivers = callee->pc()->GetReceivers();
878 ASSERT_EQ(receivers.size(), 1u);
879 ASSERT_EQ(receivers[0]->streams().size(), 1u);
880 EXPECT_EQ(receivers[0]->streams()[0]->id(), kStreamId2);
881}
882
883// This tests a regression caught by a downstream client, that occured when
884// applying a remote description with a SessionDescription object that
885// contained StreamParams that didn't have ids. Although there were multiple
886// remote audio senders, FindSenderInfo didn't find them as unique, because
887// it looked up by StreamParam.id, which none had. This meant only one
888// AudioRtpReceiver was created, as opposed to one for each remote sender.
Steve Anton3172c032018-05-03 22:30:18889TEST_F(PeerConnectionRtpTestPlanB,
Seth Hampson5b4f0752018-04-02 23:31:36890 MultipleRemoteSendersWithoutStreamParamIdAddsMultipleReceivers) {
891 auto caller = CreatePeerConnection();
892 auto callee = CreatePeerConnection();
893
894 const char kStreamId1[] = "stream1";
895 const char kStreamId2[] = "stream2";
896 caller->AddAudioTrack("audio_track1", {kStreamId1});
897 caller->AddAudioTrack("audio_track2", {kStreamId2});
898
899 auto offer = caller->CreateOfferAndSetAsLocal();
900 auto mutable_streams =
901 cricket::GetFirstAudioContentDescription(offer->description())
902 ->mutable_streams();
903 ASSERT_EQ(mutable_streams.size(), 2u);
904 // Clear the IDs in the StreamParams.
905 mutable_streams[0].id.clear();
906 mutable_streams[1].id.clear();
907 ASSERT_TRUE(
908 callee->SetRemoteDescription(CloneSessionDescription(offer.get())));
909
910 auto receivers = callee->pc()->GetReceivers();
911 ASSERT_EQ(receivers.size(), 2u);
912 ASSERT_EQ(receivers[0]->streams().size(), 1u);
913 EXPECT_EQ(kStreamId1, receivers[0]->streams()[0]->id());
914 ASSERT_EQ(receivers[1]->streams().size(), 1u);
915 EXPECT_EQ(kStreamId2, receivers[1]->streams()[0]->id());
916}
917
Henrik Boström31638672017-11-23 16:48:32918// Tests for the legacy SetRemoteDescription() function signature.
Henrik Boström31638672017-11-23 16:48:32919
920// Sanity test making sure the callback is invoked.
Steve Anton3172c032018-05-03 22:30:18921TEST_P(PeerConnectionRtpTest, LegacyObserverOnSuccess) {
Henrik Boström31638672017-11-23 16:48:32922 auto caller = CreatePeerConnection();
923 auto callee = CreatePeerConnection();
924
925 std::string error;
926 ASSERT_TRUE(
927 callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(), &error));
928}
929
930// Verifies legacy behavior: The observer is not called if if the peer
931// connection is destroyed because the asynchronous callback is executed in the
932// peer connection's message handler.
Steve Anton3172c032018-05-03 22:30:18933TEST_P(PeerConnectionRtpTest,
934 LegacyObserverNotCalledIfPeerConnectionDereferenced) {
Henrik Boström31638672017-11-23 16:48:32935 auto caller = CreatePeerConnection();
936 auto callee = CreatePeerConnection();
937
Harald Alvestranda6544372023-11-13 09:33:56938 rtc::scoped_refptr<MockSetSessionDescriptionObserver> observer =
939 rtc::make_ref_counted<MockSetSessionDescriptionObserver>();
Henrik Boström31638672017-11-23 16:48:32940
941 auto offer = caller->CreateOfferAndSetAsLocal();
Niels Möllerafb246b2022-04-20 12:26:50942 callee->pc()->SetRemoteDescription(observer.get(), offer.release());
Henrik Boström31638672017-11-23 16:48:32943 callee = nullptr;
944 rtc::Thread::Current()->ProcessMessages(0);
945 EXPECT_FALSE(observer->called());
946}
947
Steve Antonf9381f02017-12-14 18:23:57948// RtpTransceiver Tests.
Steve Anton9158ef62017-11-27 21:01:52949
950// Test that by default there are no transceivers with Unified Plan.
Steve Anton3172c032018-05-03 22:30:18951TEST_F(PeerConnectionRtpTestUnifiedPlan, PeerConnectionHasNoTransceivers) {
952 auto caller = CreatePeerConnection();
Steve Anton9158ef62017-11-27 21:01:52953 EXPECT_THAT(caller->pc()->GetTransceivers(), ElementsAre());
954}
955
956// Test that a transceiver created with the audio kind has the correct initial
957// properties.
Steve Anton3172c032018-05-03 22:30:18958TEST_F(PeerConnectionRtpTestUnifiedPlan,
959 AddTransceiverHasCorrectInitProperties) {
960 auto caller = CreatePeerConnection();
Steve Anton9158ef62017-11-27 21:01:52961
962 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
Florent Castelli8037fc62024-08-29 13:00:40963 EXPECT_EQ(std::nullopt, transceiver->mid());
Steve Anton9158ef62017-11-27 21:01:52964 EXPECT_FALSE(transceiver->stopped());
965 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, transceiver->direction());
Florent Castelli8037fc62024-08-29 13:00:40966 EXPECT_EQ(std::nullopt, transceiver->current_direction());
Steve Anton9158ef62017-11-27 21:01:52967}
968
969// Test that adding a transceiver with the audio kind creates an audio sender
970// and audio receiver with the receiver having a live audio track.
Steve Anton3172c032018-05-03 22:30:18971TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Anton9158ef62017-11-27 21:01:52972 AddAudioTransceiverCreatesAudioSenderAndReceiver) {
Steve Anton3172c032018-05-03 22:30:18973 auto caller = CreatePeerConnection();
Steve Anton9158ef62017-11-27 21:01:52974
975 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
Steve Anton69470252018-02-09 19:43:08976 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, transceiver->media_type());
Steve Anton9158ef62017-11-27 21:01:52977
978 ASSERT_TRUE(transceiver->sender());
979 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, transceiver->sender()->media_type());
980
981 ASSERT_TRUE(transceiver->receiver());
982 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, transceiver->receiver()->media_type());
983
984 auto track = transceiver->receiver()->track();
985 ASSERT_TRUE(track);
986 EXPECT_EQ(MediaStreamTrackInterface::kAudioKind, track->kind());
987 EXPECT_EQ(MediaStreamTrackInterface::TrackState::kLive, track->state());
988}
989
990// Test that adding a transceiver with the video kind creates an video sender
991// and video receiver with the receiver having a live video track.
Steve Anton3172c032018-05-03 22:30:18992TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Anton9158ef62017-11-27 21:01:52993 AddAudioTransceiverCreatesVideoSenderAndReceiver) {
Steve Anton3172c032018-05-03 22:30:18994 auto caller = CreatePeerConnection();
Steve Anton9158ef62017-11-27 21:01:52995
996 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
Steve Anton69470252018-02-09 19:43:08997 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, transceiver->media_type());
Steve Anton9158ef62017-11-27 21:01:52998
999 ASSERT_TRUE(transceiver->sender());
1000 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, transceiver->sender()->media_type());
1001
1002 ASSERT_TRUE(transceiver->receiver());
1003 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, transceiver->receiver()->media_type());
1004
1005 auto track = transceiver->receiver()->track();
1006 ASSERT_TRUE(track);
1007 EXPECT_EQ(MediaStreamTrackInterface::kVideoKind, track->kind());
1008 EXPECT_EQ(MediaStreamTrackInterface::TrackState::kLive, track->state());
1009}
1010
1011// Test that after a call to AddTransceiver, the transceiver shows in
1012// GetTransceivers(), the transceiver's sender shows in GetSenders(), and the
1013// transceiver's receiver shows in GetReceivers().
Steve Anton3172c032018-05-03 22:30:181014TEST_F(PeerConnectionRtpTestUnifiedPlan, AddTransceiverShowsInLists) {
1015 auto caller = CreatePeerConnection();
Steve Anton9158ef62017-11-27 21:01:521016
1017 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1018 EXPECT_EQ(
1019 std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>{transceiver},
1020 caller->pc()->GetTransceivers());
1021 EXPECT_EQ(
1022 std::vector<rtc::scoped_refptr<RtpSenderInterface>>{
1023 transceiver->sender()},
1024 caller->pc()->GetSenders());
1025 EXPECT_EQ(
1026 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>{
1027 transceiver->receiver()},
1028 caller->pc()->GetReceivers());
1029}
1030
1031// Test that the direction passed in through the AddTransceiver init parameter
1032// is set in the returned transceiver.
Steve Anton3172c032018-05-03 22:30:181033TEST_F(PeerConnectionRtpTestUnifiedPlan,
1034 AddTransceiverWithDirectionIsReflected) {
1035 auto caller = CreatePeerConnection();
Steve Anton9158ef62017-11-27 21:01:521036
1037 RtpTransceiverInit init;
1038 init.direction = RtpTransceiverDirection::kSendOnly;
1039 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, init);
1040 EXPECT_EQ(RtpTransceiverDirection::kSendOnly, transceiver->direction());
1041}
1042
Steve Anton9158ef62017-11-27 21:01:521043// Test that calling AddTransceiver with a track creates a transceiver which has
1044// its sender's track set to the passed-in track.
Steve Anton3172c032018-05-03 22:30:181045TEST_F(PeerConnectionRtpTestUnifiedPlan,
1046 AddTransceiverWithTrackCreatesSenderWithTrack) {
1047 auto caller = CreatePeerConnection();
Steve Anton9158ef62017-11-27 21:01:521048
1049 auto audio_track = caller->CreateAudioTrack("audio track");
1050 auto transceiver = caller->AddTransceiver(audio_track);
1051
1052 auto sender = transceiver->sender();
1053 ASSERT_TRUE(sender->track());
1054 EXPECT_EQ(audio_track, sender->track());
1055
1056 auto receiver = transceiver->receiver();
1057 ASSERT_TRUE(receiver->track());
1058 EXPECT_EQ(MediaStreamTrackInterface::kAudioKind, receiver->track()->kind());
1059 EXPECT_EQ(MediaStreamTrackInterface::TrackState::kLive,
1060 receiver->track()->state());
1061}
1062
1063// Test that calling AddTransceiver twice with the same track creates distinct
1064// transceivers, senders with the same track.
Steve Anton3172c032018-05-03 22:30:181065TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Anton9158ef62017-11-27 21:01:521066 AddTransceiverTwiceWithSameTrackCreatesMultipleTransceivers) {
Steve Anton3172c032018-05-03 22:30:181067 auto caller = CreatePeerConnection();
Steve Anton9158ef62017-11-27 21:01:521068
1069 auto audio_track = caller->CreateAudioTrack("audio track");
1070
1071 auto transceiver1 = caller->AddTransceiver(audio_track);
1072 auto transceiver2 = caller->AddTransceiver(audio_track);
1073
1074 EXPECT_NE(transceiver1, transceiver2);
1075
1076 auto sender1 = transceiver1->sender();
1077 auto sender2 = transceiver2->sender();
1078 EXPECT_NE(sender1, sender2);
1079 EXPECT_EQ(audio_track, sender1->track());
1080 EXPECT_EQ(audio_track, sender2->track());
1081
1082 EXPECT_THAT(caller->pc()->GetTransceivers(),
1083 UnorderedElementsAre(transceiver1, transceiver2));
1084 EXPECT_THAT(caller->pc()->GetSenders(),
1085 UnorderedElementsAre(sender1, sender2));
1086}
1087
Steve Anton3fe1b152017-12-12 18:20:081088// RtpTransceiver error handling tests.
1089
Steve Anton3172c032018-05-03 22:30:181090TEST_F(PeerConnectionRtpTestUnifiedPlan,
1091 AddTransceiverWithInvalidKindReturnsError) {
1092 auto caller = CreatePeerConnection();
Steve Anton3fe1b152017-12-12 18:20:081093
1094 auto result = caller->pc()->AddTransceiver(cricket::MEDIA_TYPE_DATA);
1095 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
1096}
1097
Steve Anton3172c032018-05-03 22:30:181098TEST_F(PeerConnectionRtpTestUnifiedPlan,
1099 CanClosePeerConnectionWithoutCrashing) {
1100 auto caller = CreatePeerConnection();
Steve Anton3fe1b152017-12-12 18:20:081101
1102 caller->pc()->Close();
1103}
1104
Steve Antonf9381f02017-12-14 18:23:571105// Unified Plan AddTrack tests.
1106
Steve Antonf9381f02017-12-14 18:23:571107// Test that adding an audio track creates a new audio RtpSender with the given
1108// track.
Steve Anton3172c032018-05-03 22:30:181109TEST_F(PeerConnectionRtpTestUnifiedPlan, AddAudioTrackCreatesAudioSender) {
1110 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571111
1112 auto audio_track = caller->CreateAudioTrack("a");
Steve Anton2d6c76a2018-01-06 01:10:521113 auto sender = caller->AddTrack(audio_track);
Steve Antonf9381f02017-12-14 18:23:571114 ASSERT_TRUE(sender);
1115
1116 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, sender->media_type());
1117 EXPECT_EQ(audio_track, sender->track());
1118}
1119
1120// Test that adding a video track creates a new video RtpSender with the given
1121// track.
Steve Anton3172c032018-05-03 22:30:181122TEST_F(PeerConnectionRtpTestUnifiedPlan, AddVideoTrackCreatesVideoSender) {
1123 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571124
1125 auto video_track = caller->CreateVideoTrack("a");
Steve Anton2d6c76a2018-01-06 01:10:521126 auto sender = caller->AddTrack(video_track);
Steve Antonf9381f02017-12-14 18:23:571127 ASSERT_TRUE(sender);
1128
1129 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, sender->media_type());
1130 EXPECT_EQ(video_track, sender->track());
1131}
1132
1133// Test that adding a track to a new PeerConnection creates an RtpTransceiver
1134// with the sender that AddTrack returns and in the sendrecv direction.
Steve Anton3172c032018-05-03 22:30:181135TEST_F(PeerConnectionRtpTestUnifiedPlan, AddFirstTrackCreatesTransceiver) {
1136 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571137
1138 auto sender = caller->AddAudioTrack("a");
1139 ASSERT_TRUE(sender);
1140
1141 auto transceivers = caller->pc()->GetTransceivers();
1142 ASSERT_EQ(1u, transceivers.size());
1143 EXPECT_EQ(sender, transceivers[0]->sender());
1144 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, transceivers[0]->direction());
1145}
1146
1147// Test that if a transceiver of the same type but no track had been added to
1148// the PeerConnection and later a call to AddTrack is made, the resulting sender
1149// is the transceiver's sender and the sender's track is the newly-added track.
Steve Anton3172c032018-05-03 22:30:181150TEST_F(PeerConnectionRtpTestUnifiedPlan, AddTrackReusesTransceiver) {
1151 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571152
1153 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1154 auto audio_track = caller->CreateAudioTrack("a");
Steve Anton2d6c76a2018-01-06 01:10:521155 auto sender = caller->AddTrack(audio_track);
Steve Antonf9381f02017-12-14 18:23:571156 ASSERT_TRUE(sender);
1157
1158 auto transceivers = caller->pc()->GetTransceivers();
1159 ASSERT_EQ(1u, transceivers.size());
1160 EXPECT_EQ(transceiver, transceivers[0]);
1161 EXPECT_EQ(sender, transceiver->sender());
1162 EXPECT_EQ(audio_track, sender->track());
1163}
1164
Jonas Oreland4b2a1062022-10-19 07:24:421165TEST_F(PeerConnectionRtpTestUnifiedPlan,
1166 AddTrackWithSendEncodingDoesNotReuseTransceiver) {
1167 auto caller = CreatePeerConnection();
1168
1169 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1170 auto audio_track = caller->CreateAudioTrack("a");
1171 RtpEncodingParameters encoding;
1172 auto sender = caller->AddTrack(audio_track, {}, {encoding});
1173 ASSERT_TRUE(sender);
1174
1175 auto transceivers = caller->pc()->GetTransceivers();
1176 ASSERT_EQ(2u, transceivers.size());
1177 EXPECT_EQ(transceiver, transceivers[0]);
1178 EXPECT_NE(sender, transceiver->sender());
1179 EXPECT_EQ(audio_track, sender->track());
1180}
1181
Steve Antonf9381f02017-12-14 18:23:571182// Test that adding two tracks to a new PeerConnection creates two
1183// RtpTransceivers in the same order.
Steve Anton3172c032018-05-03 22:30:181184TEST_F(PeerConnectionRtpTestUnifiedPlan, TwoAddTrackCreatesTwoTransceivers) {
1185 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571186
1187 auto sender1 = caller->AddAudioTrack("a");
1188 auto sender2 = caller->AddVideoTrack("v");
1189 ASSERT_TRUE(sender2);
1190
1191 auto transceivers = caller->pc()->GetTransceivers();
1192 ASSERT_EQ(2u, transceivers.size());
1193 EXPECT_EQ(sender1, transceivers[0]->sender());
1194 EXPECT_EQ(sender2, transceivers[1]->sender());
1195}
1196
1197// Test that if there are multiple transceivers with no sending track then a
1198// later call to AddTrack will use the one of the same type as the newly-added
1199// track.
Steve Anton3172c032018-05-03 22:30:181200TEST_F(PeerConnectionRtpTestUnifiedPlan, AddTrackReusesTransceiverOfType) {
1201 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571202
1203 auto audio_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1204 auto video_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
1205 auto sender = caller->AddVideoTrack("v");
1206
1207 ASSERT_EQ(2u, caller->pc()->GetTransceivers().size());
1208 EXPECT_NE(sender, audio_transceiver->sender());
1209 EXPECT_EQ(sender, video_transceiver->sender());
1210}
1211
1212// Test that if the only transceivers that do not have a sending track have a
1213// different type from the added track, then AddTrack will create a new
1214// transceiver for the track.
Steve Anton3172c032018-05-03 22:30:181215TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Antonf9381f02017-12-14 18:23:571216 AddTrackDoesNotReuseTransceiverOfWrongType) {
Steve Anton3172c032018-05-03 22:30:181217 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571218
1219 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1220 auto sender = caller->AddVideoTrack("v");
1221
1222 auto transceivers = caller->pc()->GetTransceivers();
1223 ASSERT_EQ(2u, transceivers.size());
1224 EXPECT_NE(sender, transceivers[0]->sender());
1225 EXPECT_EQ(sender, transceivers[1]->sender());
1226}
1227
1228// Test that the first available transceiver is reused by AddTrack when multiple
1229// are available.
Steve Anton3172c032018-05-03 22:30:181230TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Antonf9381f02017-12-14 18:23:571231 AddTrackReusesFirstMatchingTransceiver) {
Steve Anton3172c032018-05-03 22:30:181232 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571233
1234 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1235 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1236 auto sender = caller->AddAudioTrack("a");
1237
1238 auto transceivers = caller->pc()->GetTransceivers();
1239 ASSERT_EQ(2u, transceivers.size());
1240 EXPECT_EQ(sender, transceivers[0]->sender());
1241 EXPECT_NE(sender, transceivers[1]->sender());
1242}
1243
1244// Test that a call to AddTrack that reuses a transceiver will change the
1245// direction from inactive to sendonly.
Steve Anton3172c032018-05-03 22:30:181246TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Antonf9381f02017-12-14 18:23:571247 AddTrackChangesDirectionFromInactiveToSendOnly) {
Steve Anton3172c032018-05-03 22:30:181248 auto caller = CreatePeerConnection();
Guido Urdaneta70c2db12019-04-16 10:24:141249 auto callee = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571250
1251 RtpTransceiverInit init;
1252 init.direction = RtpTransceiverDirection::kInactive;
1253 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, init);
Henrik Boströme574a312020-08-25 08:20:111254 EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1255 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571256
Guido Urdaneta70c2db12019-04-16 10:24:141257 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Henrik Boströme574a312020-08-25 08:20:111258 caller->observer()->clear_legacy_renegotiation_needed();
1259 caller->observer()->clear_latest_negotiation_needed_event();
Steve Antonf9381f02017-12-14 18:23:571260 ASSERT_TRUE(caller->AddAudioTrack("a"));
Henrik Boströme574a312020-08-25 08:20:111261 EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1262 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571263
1264 EXPECT_EQ(RtpTransceiverDirection::kSendOnly, transceiver->direction());
1265}
1266
1267// Test that a call to AddTrack that reuses a transceiver will change the
1268// direction from recvonly to sendrecv.
Steve Anton3172c032018-05-03 22:30:181269TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Antonf9381f02017-12-14 18:23:571270 AddTrackChangesDirectionFromRecvOnlyToSendRecv) {
Steve Anton3172c032018-05-03 22:30:181271 auto caller = CreatePeerConnection();
Guido Urdaneta70c2db12019-04-16 10:24:141272 auto callee = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571273
1274 RtpTransceiverInit init;
1275 init.direction = RtpTransceiverDirection::kRecvOnly;
1276 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, init);
Henrik Boströme574a312020-08-25 08:20:111277 EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1278 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571279
Guido Urdaneta70c2db12019-04-16 10:24:141280 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Henrik Boströme574a312020-08-25 08:20:111281 caller->observer()->clear_legacy_renegotiation_needed();
1282 caller->observer()->clear_latest_negotiation_needed_event();
Steve Antonf9381f02017-12-14 18:23:571283 ASSERT_TRUE(caller->AddAudioTrack("a"));
Henrik Boströme574a312020-08-25 08:20:111284 EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1285 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571286
1287 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, transceiver->direction());
1288}
1289
Steve Anton3172c032018-05-03 22:30:181290TEST_F(PeerConnectionRtpTestUnifiedPlan, AddTrackCreatesSenderWithTrackId) {
Steve Anton02ee47c2018-01-11 00:26:061291 const std::string kTrackId = "audio_track";
1292
Steve Anton3172c032018-05-03 22:30:181293 auto caller = CreatePeerConnection();
Steve Anton02ee47c2018-01-11 00:26:061294
1295 auto audio_track = caller->CreateAudioTrack(kTrackId);
1296 auto sender = caller->AddTrack(audio_track);
1297
1298 EXPECT_EQ(kTrackId, sender->id());
1299}
1300
Steve Antonf9381f02017-12-14 18:23:571301// Unified Plan AddTrack error handling.
1302
Steve Anton3172c032018-05-03 22:30:181303TEST_F(PeerConnectionRtpTestUnifiedPlan, AddTrackErrorIfClosed) {
1304 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571305
1306 auto audio_track = caller->CreateAudioTrack("a");
1307 caller->pc()->Close();
1308
Henrik Boströme574a312020-08-25 08:20:111309 caller->observer()->clear_legacy_renegotiation_needed();
1310 caller->observer()->clear_latest_negotiation_needed_event();
Yves Gerey665174f2018-06-19 13:03:051311 auto result = caller->pc()->AddTrack(audio_track, std::vector<std::string>());
Steve Anton2d6c76a2018-01-06 01:10:521312 EXPECT_EQ(RTCErrorType::INVALID_STATE, result.error().type());
Henrik Boströme574a312020-08-25 08:20:111313 EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1314 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571315}
1316
Steve Anton3172c032018-05-03 22:30:181317TEST_F(PeerConnectionRtpTestUnifiedPlan, AddTrackErrorIfTrackAlreadyHasSender) {
1318 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571319
1320 auto audio_track = caller->CreateAudioTrack("a");
Steve Anton2d6c76a2018-01-06 01:10:521321 ASSERT_TRUE(caller->AddTrack(audio_track));
Steve Antonf9381f02017-12-14 18:23:571322
Henrik Boströme574a312020-08-25 08:20:111323 caller->observer()->clear_legacy_renegotiation_needed();
1324 caller->observer()->clear_latest_negotiation_needed_event();
Yves Gerey665174f2018-06-19 13:03:051325 auto result = caller->pc()->AddTrack(audio_track, std::vector<std::string>());
Steve Anton2d6c76a2018-01-06 01:10:521326 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
Henrik Boströme574a312020-08-25 08:20:111327 EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1328 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571329}
1330
1331// Unified Plan RemoveTrack tests.
1332
1333// Test that calling RemoveTrack on a sender with a previously-added track
1334// clears the sender's track.
Steve Anton3172c032018-05-03 22:30:181335TEST_F(PeerConnectionRtpTestUnifiedPlan, RemoveTrackClearsSenderTrack) {
1336 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571337
1338 auto sender = caller->AddAudioTrack("a");
Harald Alvestrand93dd7632022-01-19 12:28:451339 ASSERT_TRUE(caller->pc()->RemoveTrackOrError(sender).ok());
Steve Antonf9381f02017-12-14 18:23:571340
1341 EXPECT_FALSE(sender->track());
1342}
1343
1344// Test that calling RemoveTrack on a sender where the transceiver is configured
1345// in the sendrecv direction changes the transceiver's direction to recvonly.
Steve Anton3172c032018-05-03 22:30:181346TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Antonf9381f02017-12-14 18:23:571347 RemoveTrackChangesDirectionFromSendRecvToRecvOnly) {
Steve Anton3172c032018-05-03 22:30:181348 auto caller = CreatePeerConnection();
Guido Urdaneta70c2db12019-04-16 10:24:141349 auto callee = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571350
1351 RtpTransceiverInit init;
1352 init.direction = RtpTransceiverDirection::kSendRecv;
1353 auto transceiver =
1354 caller->AddTransceiver(caller->CreateAudioTrack("a"), init);
Henrik Boströme574a312020-08-25 08:20:111355 EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1356 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571357
Guido Urdaneta70c2db12019-04-16 10:24:141358 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Henrik Boströme574a312020-08-25 08:20:111359 caller->observer()->clear_legacy_renegotiation_needed();
1360 caller->observer()->clear_latest_negotiation_needed_event();
Guido Urdaneta70c2db12019-04-16 10:24:141361
Harald Alvestrand93dd7632022-01-19 12:28:451362 ASSERT_TRUE(caller->pc()->RemoveTrackOrError(transceiver->sender()).ok());
Henrik Boströme574a312020-08-25 08:20:111363 EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1364 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571365
1366 EXPECT_EQ(RtpTransceiverDirection::kRecvOnly, transceiver->direction());
Steve Antonf9381f02017-12-14 18:23:571367}
1368
1369// Test that calling RemoveTrack on a sender where the transceiver is configured
1370// in the sendonly direction changes the transceiver's direction to inactive.
Steve Anton3172c032018-05-03 22:30:181371TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Antonf9381f02017-12-14 18:23:571372 RemoveTrackChangesDirectionFromSendOnlyToInactive) {
Steve Anton3172c032018-05-03 22:30:181373 auto caller = CreatePeerConnection();
Guido Urdaneta70c2db12019-04-16 10:24:141374 auto callee = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571375
1376 RtpTransceiverInit init;
1377 init.direction = RtpTransceiverDirection::kSendOnly;
1378 auto transceiver =
1379 caller->AddTransceiver(caller->CreateAudioTrack("a"), init);
Henrik Boströme574a312020-08-25 08:20:111380 EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1381 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571382
Guido Urdaneta70c2db12019-04-16 10:24:141383 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Henrik Boströme574a312020-08-25 08:20:111384 caller->observer()->clear_legacy_renegotiation_needed();
1385 caller->observer()->clear_latest_negotiation_needed_event();
Guido Urdaneta70c2db12019-04-16 10:24:141386
Harald Alvestrand93dd7632022-01-19 12:28:451387 ASSERT_TRUE(caller->pc()->RemoveTrackOrError(transceiver->sender()).ok());
Henrik Boströme574a312020-08-25 08:20:111388 EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1389 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571390
1391 EXPECT_EQ(RtpTransceiverDirection::kInactive, transceiver->direction());
1392}
1393
1394// Test that calling RemoveTrack with a sender that has a null track results in
1395// no change in state.
Steve Anton3172c032018-05-03 22:30:181396TEST_F(PeerConnectionRtpTestUnifiedPlan, RemoveTrackWithNullSenderTrackIsNoOp) {
1397 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571398
1399 auto sender = caller->AddAudioTrack("a");
1400 auto transceiver = caller->pc()->GetTransceivers()[0];
1401 ASSERT_TRUE(sender->SetTrack(nullptr));
1402
Henrik Boströme574a312020-08-25 08:20:111403 caller->observer()->clear_legacy_renegotiation_needed();
1404 caller->observer()->clear_latest_negotiation_needed_event();
Harald Alvestrand93dd7632022-01-19 12:28:451405 ASSERT_TRUE(caller->pc()->RemoveTrackOrError(sender).ok());
Henrik Boströme574a312020-08-25 08:20:111406 EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1407 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571408
1409 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, transceiver->direction());
1410}
1411
1412// Unified Plan RemoveTrack error handling.
1413
Steve Anton3172c032018-05-03 22:30:181414TEST_F(PeerConnectionRtpTestUnifiedPlan, RemoveTrackErrorIfClosed) {
1415 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571416
1417 auto sender = caller->AddAudioTrack("a");
1418 caller->pc()->Close();
1419
Henrik Boströme574a312020-08-25 08:20:111420 caller->observer()->clear_legacy_renegotiation_needed();
1421 caller->observer()->clear_latest_negotiation_needed_event();
Harald Alvestrand93dd7632022-01-19 12:28:451422 EXPECT_FALSE(caller->pc()->RemoveTrackOrError(sender).ok());
Henrik Boströme574a312020-08-25 08:20:111423 EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1424 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571425}
1426
Steve Anton3172c032018-05-03 22:30:181427TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Antonf9381f02017-12-14 18:23:571428 RemoveTrackNoErrorIfTrackAlreadyRemoved) {
Steve Anton3172c032018-05-03 22:30:181429 auto caller = CreatePeerConnection();
Steve Antonf9381f02017-12-14 18:23:571430
1431 auto sender = caller->AddAudioTrack("a");
Harald Alvestrand93dd7632022-01-19 12:28:451432 ASSERT_TRUE(caller->pc()->RemoveTrackOrError(sender).ok());
Steve Antonf9381f02017-12-14 18:23:571433
Henrik Boströme574a312020-08-25 08:20:111434 caller->observer()->clear_legacy_renegotiation_needed();
1435 caller->observer()->clear_latest_negotiation_needed_event();
Harald Alvestrand93dd7632022-01-19 12:28:451436 EXPECT_TRUE(caller->pc()->RemoveTrackOrError(sender).ok());
Henrik Boströme574a312020-08-25 08:20:111437 EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1438 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
Steve Antonf9381f02017-12-14 18:23:571439}
1440
Steve Anton60b6c1d2018-06-13 18:32:271441// Test that setting offers that add/remove/add a track repeatedly without
1442// setting the appropriate answer in between works.
1443// These are regression tests for bugs.webrtc.org/9401
1444TEST_F(PeerConnectionRtpTestUnifiedPlan, AddRemoveAddTrackOffersWorksAudio) {
1445 auto caller = CreatePeerConnection();
1446
1447 auto sender1 = caller->AddAudioTrack("audio1");
1448 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
1449
Harald Alvestrand93dd7632022-01-19 12:28:451450 caller->pc()->RemoveTrackOrError(sender1);
Steve Anton60b6c1d2018-06-13 18:32:271451 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
1452
1453 // This will re-use the transceiver created by the first AddTrack.
1454 auto sender2 = caller->AddAudioTrack("audio2");
1455 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
1456
1457 EXPECT_EQ(1u, caller->pc()->GetTransceivers().size());
1458 EXPECT_EQ(sender1, sender2);
1459}
1460TEST_F(PeerConnectionRtpTestUnifiedPlan, AddRemoveAddTrackOffersWorksVideo) {
1461 auto caller = CreatePeerConnection();
1462
1463 auto sender1 = caller->AddVideoTrack("video1");
1464 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
1465
Harald Alvestrand93dd7632022-01-19 12:28:451466 caller->pc()->RemoveTrackOrError(sender1);
Steve Anton60b6c1d2018-06-13 18:32:271467 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
1468
1469 // This will re-use the transceiver created by the first AddTrack.
1470 auto sender2 = caller->AddVideoTrack("video2");
1471 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
1472
1473 EXPECT_EQ(1u, caller->pc()->GetTransceivers().size());
1474 EXPECT_EQ(sender1, sender2);
1475}
1476
Steve Anton07563732018-06-26 18:13:501477// Test that CreateOffer succeeds if two tracks with the same label are added.
1478TEST_F(PeerConnectionRtpTestUnifiedPlan, CreateOfferSameTrackLabel) {
1479 auto caller = CreatePeerConnection();
1480
1481 auto audio_sender = caller->AddAudioTrack("track", {});
1482 auto video_sender = caller->AddVideoTrack("track", {});
1483
1484 EXPECT_TRUE(caller->CreateOffer());
1485
1486 EXPECT_EQ(audio_sender->track()->id(), video_sender->track()->id());
1487 EXPECT_NE(audio_sender->id(), video_sender->id());
1488}
1489
1490// Test that CreateAnswer succeeds if two tracks with the same label are added.
1491TEST_F(PeerConnectionRtpTestUnifiedPlan, CreateAnswerSameTrackLabel) {
1492 auto caller = CreatePeerConnection();
1493 auto callee = CreatePeerConnection();
1494
1495 RtpTransceiverInit recvonly;
1496 recvonly.direction = RtpTransceiverDirection::kRecvOnly;
1497 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, recvonly);
1498 caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, recvonly);
1499
1500 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
1501
1502 auto audio_sender = callee->AddAudioTrack("track", {});
1503 auto video_sender = callee->AddVideoTrack("track", {});
1504
1505 EXPECT_TRUE(callee->CreateAnswer());
1506
1507 EXPECT_EQ(audio_sender->track()->id(), video_sender->track()->id());
1508 EXPECT_NE(audio_sender->id(), video_sender->id());
1509}
1510
1511// Test that calling AddTrack, RemoveTrack and AddTrack again creates a second
1512// m= section with a random sender id (different from the first, now rejected,
1513// m= section).
1514TEST_F(PeerConnectionRtpTestUnifiedPlan,
1515 AddRemoveAddTrackGeneratesNewSenderId) {
1516 auto caller = CreatePeerConnection();
1517 auto callee = CreatePeerConnection();
1518
1519 auto track = caller->CreateVideoTrack("video");
1520 auto sender1 = caller->AddTrack(track);
1521 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1522
Harald Alvestrand93dd7632022-01-19 12:28:451523 caller->pc()->RemoveTrackOrError(sender1);
Steve Anton07563732018-06-26 18:13:501524 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1525
1526 auto sender2 = caller->AddTrack(track);
1527
1528 EXPECT_NE(sender1, sender2);
1529 EXPECT_NE(sender1->id(), sender2->id());
1530 std::string sender2_id = sender2->id();
1531
1532 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1533
1534 // The sender's ID should not change after negotiation.
1535 EXPECT_EQ(sender2_id, sender2->id());
1536}
1537
Steve Anton52d86772018-02-20 23:48:121538// Test that OnRenegotiationNeeded is fired if SetDirection is called on an
1539// active RtpTransceiver with a new direction.
Steve Anton3172c032018-05-03 22:30:181540TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Anton52d86772018-02-20 23:48:121541 RenegotiationNeededAfterTransceiverSetDirection) {
Steve Anton3172c032018-05-03 22:30:181542 auto caller = CreatePeerConnection();
Guido Urdaneta70c2db12019-04-16 10:24:141543 auto callee = CreatePeerConnection();
Henrik Boströme574a312020-08-25 08:20:111544 EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1545 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
Steve Anton52d86772018-02-20 23:48:121546
1547 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
Henrik Boströme574a312020-08-25 08:20:111548 EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1549 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
Steve Anton52d86772018-02-20 23:48:121550
Guido Urdaneta70c2db12019-04-16 10:24:141551 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Henrik Boströme574a312020-08-25 08:20:111552 caller->observer()->clear_legacy_renegotiation_needed();
1553 caller->observer()->clear_latest_negotiation_needed_event();
Guido Urdaneta70c2db12019-04-16 10:24:141554
Harald Alvestrand6060df52020-08-11 07:54:021555 transceiver->SetDirectionWithError(RtpTransceiverDirection::kInactive);
Henrik Boströme574a312020-08-25 08:20:111556 EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1557 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
Steve Anton52d86772018-02-20 23:48:121558}
1559
1560// Test that OnRenegotiationNeeded is not fired if SetDirection is called on an
1561// active RtpTransceiver with current direction.
Steve Anton3172c032018-05-03 22:30:181562TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Anton52d86772018-02-20 23:48:121563 NoRenegotiationNeededAfterTransceiverSetSameDirection) {
Steve Anton3172c032018-05-03 22:30:181564 auto caller = CreatePeerConnection();
Steve Anton52d86772018-02-20 23:48:121565
1566 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1567
Henrik Boströme574a312020-08-25 08:20:111568 caller->observer()->clear_legacy_renegotiation_needed();
1569 caller->observer()->clear_latest_negotiation_needed_event();
Harald Alvestrand6060df52020-08-11 07:54:021570 transceiver->SetDirectionWithError(transceiver->direction());
Henrik Boströme574a312020-08-25 08:20:111571 EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1572 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
Steve Anton52d86772018-02-20 23:48:121573}
1574
1575// Test that OnRenegotiationNeeded is not fired if SetDirection is called on a
1576// stopped RtpTransceiver.
Steve Anton3172c032018-05-03 22:30:181577TEST_F(PeerConnectionRtpTestUnifiedPlan,
Steve Anton52d86772018-02-20 23:48:121578 NoRenegotiationNeededAfterSetDirectionOnStoppedTransceiver) {
Steve Anton3172c032018-05-03 22:30:181579 auto caller = CreatePeerConnection();
Steve Anton52d86772018-02-20 23:48:121580
1581 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
Harald Alvestrand6060df52020-08-11 07:54:021582 transceiver->StopInternal();
Steve Anton52d86772018-02-20 23:48:121583
Henrik Boströme574a312020-08-25 08:20:111584 caller->observer()->clear_legacy_renegotiation_needed();
1585 caller->observer()->clear_latest_negotiation_needed_event();
Harald Alvestrand6060df52020-08-11 07:54:021586 transceiver->SetDirectionWithError(RtpTransceiverDirection::kInactive);
Henrik Boströme574a312020-08-25 08:20:111587 EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1588 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
Steve Anton52d86772018-02-20 23:48:121589}
1590
Harald Alvestrand6060df52020-08-11 07:54:021591// Test that currentDirection returnes "stopped" if the transceiver was stopped.
1592TEST_F(PeerConnectionRtpTestUnifiedPlan,
1593 CheckStoppedCurrentDirectionOnStoppedTransceiver) {
1594 auto caller = CreatePeerConnection();
1595
1596 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1597 transceiver->StopInternal();
1598
1599 EXPECT_TRUE(transceiver->stopping());
1600 EXPECT_TRUE(transceiver->stopped());
1601 EXPECT_EQ(RtpTransceiverDirection::kStopped,
1602 transceiver->current_direction());
1603}
1604
1605// Test that InvalidState is thrown on a stopping transceiver.
1606TEST_F(PeerConnectionRtpTestUnifiedPlan,
1607 CheckForInvalidStateOnStoppingTransceiver) {
1608 auto caller = CreatePeerConnection();
1609
1610 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1611 transceiver->StopStandard();
1612
1613 EXPECT_TRUE(transceiver->stopping());
1614 EXPECT_FALSE(transceiver->stopped());
1615 EXPECT_EQ(
1616 RTCErrorType::INVALID_STATE,
1617 transceiver->SetDirectionWithError(RtpTransceiverDirection::kInactive)
1618 .type());
1619}
1620
1621// Test that InvalidState is thrown on a stopped transceiver.
1622TEST_F(PeerConnectionRtpTestUnifiedPlan,
1623 CheckForInvalidStateOnStoppedTransceiver) {
1624 auto caller = CreatePeerConnection();
1625
1626 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1627 transceiver->StopInternal();
1628
1629 EXPECT_TRUE(transceiver->stopping());
1630 EXPECT_TRUE(transceiver->stopped());
1631 EXPECT_EQ(
1632 RTCErrorType::INVALID_STATE,
1633 transceiver->SetDirectionWithError(RtpTransceiverDirection::kInactive)
1634 .type());
1635}
1636
1637// Test that TypeError is thrown if the direction is set to "stopped".
1638TEST_F(PeerConnectionRtpTestUnifiedPlan,
1639 CheckForTypeErrorForStoppedOnTransceiver) {
1640 auto caller = CreatePeerConnection();
1641
1642 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1643 EXPECT_EQ(
1644 RTCErrorType::INVALID_PARAMETER,
1645 transceiver->SetDirectionWithError(RtpTransceiverDirection::kStopped)
1646 .type());
1647}
1648
Harald Alvestrand198cd732020-09-16 12:41:231649// Test that you can do createOffer/setLocalDescription with a stopped
1650// media section.
1651TEST_F(PeerConnectionRtpTestUnifiedPlan,
1652 SetLocalDescriptionWithStoppedMediaSection) {
1653 auto caller = CreatePeerConnection();
1654 auto callee = CreatePeerConnection();
1655 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1656 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1657 callee->pc()->GetTransceivers()[0]->StopStandard();
1658 ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
1659 EXPECT_EQ(RtpTransceiverDirection::kStopped,
1660 transceiver->current_direction());
1661 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1662}
1663
Harald Alvestrand936f1af2020-09-22 07:41:501664TEST_F(PeerConnectionRtpTestUnifiedPlan,
1665 StopAndNegotiateCausesTransceiverToDisappear) {
1666 auto caller = CreatePeerConnection();
1667 auto callee = CreatePeerConnection();
1668 auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
1669 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1670 callee->pc()->GetTransceivers()[0]->StopStandard();
1671 ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
1672 EXPECT_EQ(RtpTransceiverDirection::kStopped,
1673 transceiver->current_direction());
1674 EXPECT_EQ(0U, caller->pc()->GetTransceivers().size());
1675 EXPECT_EQ(0U, callee->pc()->GetTransceivers().size());
1676 EXPECT_EQ(0U, caller->pc()->GetSenders().size());
1677 EXPECT_EQ(0U, callee->pc()->GetSenders().size());
1678 EXPECT_EQ(0U, caller->pc()->GetReceivers().size());
1679 EXPECT_EQ(0U, callee->pc()->GetReceivers().size());
1680}
1681
Harald Alvestrand09bd9ba2020-10-09 08:13:301682TEST_F(PeerConnectionRtpTestUnifiedPlan,
1683 SetLocalDescriptionWorksAfterRepeatedAddRemove) {
1684 auto caller = CreatePeerConnection();
1685 auto callee = CreatePeerConnection();
1686 auto video_track = caller->CreateVideoTrack("v");
1687 auto track = caller->CreateAudioTrack("a");
1688 caller->AddTransceiver(video_track);
1689 auto transceiver = caller->AddTransceiver(track);
1690 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Harald Alvestrand93dd7632022-01-19 12:28:451691 caller->pc()->RemoveTrackOrError(transceiver->sender());
Harald Alvestrand09bd9ba2020-10-09 08:13:301692 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1693 caller->AddTrack(track);
1694 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Harald Alvestrand93dd7632022-01-19 12:28:451695 caller->pc()->RemoveTrackOrError(transceiver->sender());
Harald Alvestrand09bd9ba2020-10-09 08:13:301696 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1697}
1698
1699// This is a repro of Chromium bug https://crbug.com/1134686
1700TEST_F(PeerConnectionRtpTestUnifiedPlan,
1701 SetLocalDescriptionWorksAfterRepeatedAddRemoveWithRemoteReject) {
1702 auto caller = CreatePeerConnection();
1703 auto callee = CreatePeerConnection();
1704 auto video_track = caller->CreateVideoTrack("v");
1705 auto track = caller->CreateAudioTrack("a");
1706 caller->AddTransceiver(video_track);
1707 auto transceiver = caller->AddTransceiver(track);
1708 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Harald Alvestrand93dd7632022-01-19 12:28:451709 caller->pc()->RemoveTrackOrError(transceiver->sender());
Harald Alvestrand09bd9ba2020-10-09 08:13:301710 ExchangeOfferAnswerWhereRemoteStopsTransceiver(caller.get(), callee.get(), 1);
1711 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1712 caller->AddTrack(track);
1713 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Harald Alvestrand93dd7632022-01-19 12:28:451714 caller->pc()->RemoveTrackOrError(transceiver->sender());
Harald Alvestrand09bd9ba2020-10-09 08:13:301715 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1716}
1717
Florent Castelli892acf02018-10-01 20:47:201718// Test that AddTransceiver fails if trying to use unimplemented RTP encoding
1719// parameters with the send_encodings parameters.
1720TEST_F(PeerConnectionRtpTestUnifiedPlan,
1721 CheckForUnsupportedEncodingParameters) {
1722 auto caller = CreatePeerConnection();
1723
1724 RtpTransceiverInit init;
1725 init.send_encodings.emplace_back();
1726
1727 auto default_send_encodings = init.send_encodings;
1728
Henrik Grunelle1301a82018-12-13 12:13:221729 // Unimplemented RtpParameters: ssrc, codec_payload_type, fec, rtx, dtx,
Amit Hilbuchaa584152019-02-07 01:09:521730 // ptime, scale_framerate_down_by, dependency_rids.
Florent Castelli892acf02018-10-01 20:47:201731 init.send_encodings[0].ssrc = 1;
1732 EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
1733 caller->pc()
1734 ->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, init)
1735 .error()
1736 .type());
1737 init.send_encodings = default_send_encodings;
Florent Castelli892acf02018-10-01 20:47:201738}
1739
Florent Castellic1a0bcb2019-01-29 13:26:481740// Test that AddTransceiver fails if trying to use invalid RTP encoding
1741// parameters with the send_encodings parameters.
1742TEST_F(PeerConnectionRtpTestUnifiedPlan, CheckForInvalidEncodingParameters) {
1743 auto caller = CreatePeerConnection();
1744
1745 RtpTransceiverInit init;
1746 init.send_encodings.emplace_back();
1747
1748 auto default_send_encodings = init.send_encodings;
1749
1750 init.send_encodings[0].scale_resolution_down_by = 0.5;
1751 EXPECT_EQ(RTCErrorType::INVALID_RANGE,
1752 caller->pc()
1753 ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
1754 .error()
1755 .type());
1756 init.send_encodings = default_send_encodings;
1757
1758 init.send_encodings[0].bitrate_priority = 0;
1759 EXPECT_EQ(RTCErrorType::INVALID_RANGE,
1760 caller->pc()
1761 ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
1762 .error()
1763 .type());
1764 init.send_encodings = default_send_encodings;
1765
1766 init.send_encodings[0].min_bitrate_bps = 200000;
1767 init.send_encodings[0].max_bitrate_bps = 100000;
1768 EXPECT_EQ(RTCErrorType::INVALID_RANGE,
1769 caller->pc()
1770 ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
1771 .error()
1772 .type());
1773 init.send_encodings = default_send_encodings;
1774
1775 init.send_encodings[0].num_temporal_layers = 0;
1776 EXPECT_EQ(RTCErrorType::INVALID_RANGE,
1777 caller->pc()
1778 ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
1779 .error()
1780 .type());
1781 init.send_encodings = default_send_encodings;
1782
1783 init.send_encodings[0].num_temporal_layers = 5;
1784 EXPECT_EQ(RTCErrorType::INVALID_RANGE,
1785 caller->pc()
1786 ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
1787 .error()
1788 .type());
1789 init.send_encodings = default_send_encodings;
Åsa Persson929c02a2024-10-18 13:50:271790
1791 init.send_encodings[0].scalability_mode = std::nullopt;
1792 init.send_encodings[0].codec =
1793 cricket::CreateVideoCodec(SdpVideoFormat("VP8", {})).ToCodecParameters();
1794 EXPECT_EQ(RTCErrorType::NONE,
1795 caller->pc()
1796 ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
1797 .error()
1798 .type());
1799 init.send_encodings = default_send_encodings;
1800
1801 init.send_encodings[0].scalability_mode = "L1T2";
1802 init.send_encodings[0].codec =
1803 cricket::CreateVideoCodec(SdpVideoFormat("VP8", {})).ToCodecParameters();
1804 EXPECT_EQ(RTCErrorType::NONE,
1805 caller->pc()
1806 ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
1807 .error()
1808 .type());
1809 init.send_encodings = default_send_encodings;
1810
1811 init.send_encodings[0].scalability_mode = "L2T2";
1812 init.send_encodings[0].codec =
1813 cricket::CreateVideoCodec(SdpVideoFormat("VP8", {})).ToCodecParameters();
1814 EXPECT_EQ(RTCErrorType::UNSUPPORTED_OPERATION,
1815 caller->pc()
1816 ->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init)
1817 .error()
1818 .type());
1819 init.send_encodings = default_send_encodings;
Florent Castellic1a0bcb2019-01-29 13:26:481820}
1821
Florent Castelli892acf02018-10-01 20:47:201822// Test that AddTransceiver transfers the send_encodings to the sender and they
1823// are retained after SetLocalDescription().
1824TEST_F(PeerConnectionRtpTestUnifiedPlan, SendEncodingsPassedToSender) {
1825 auto caller = CreatePeerConnection();
1826
1827 RtpTransceiverInit init;
1828 init.send_encodings.emplace_back();
1829 init.send_encodings[0].active = false;
1830 init.send_encodings[0].max_bitrate_bps = 180000;
1831
1832 auto result = caller->pc()->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, init);
1833 ASSERT_TRUE(result.ok());
1834
1835 auto init_send_encodings = result.value()->sender()->init_send_encodings();
1836 EXPECT_FALSE(init_send_encodings[0].active);
1837 EXPECT_EQ(init_send_encodings[0].max_bitrate_bps, 180000);
1838
1839 auto parameters = result.value()->sender()->GetParameters();
1840 EXPECT_FALSE(parameters.encodings[0].active);
1841 EXPECT_EQ(parameters.encodings[0].max_bitrate_bps, 180000);
1842
1843 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
1844
1845 parameters = result.value()->sender()->GetParameters();
1846 EXPECT_FALSE(parameters.encodings[0].active);
1847 EXPECT_EQ(parameters.encodings[0].max_bitrate_bps, 180000);
1848}
1849
Steve Antone831b8c2018-02-01 20:22:161850// Test MSID signaling between Unified Plan and Plan B endpoints. There are two
1851// options for this kind of signaling: media section based (a=msid) and ssrc
1852// based (a=ssrc MSID). While JSEP only specifies media section MSID signaling,
1853// we want to ensure compatibility with older Plan B endpoints that might expect
1854// ssrc based MSID signaling. Thus we test here that Unified Plan offers both
1855// types but answers with the same type as the offer.
1856
Steve Anton3172c032018-05-03 22:30:181857class PeerConnectionMsidSignalingTest
1858 : public PeerConnectionRtpTestUnifiedPlan {};
Steve Antone831b8c2018-02-01 20:22:161859
1860TEST_F(PeerConnectionMsidSignalingTest, UnifiedPlanTalkingToOurself) {
1861 auto caller = CreatePeerConnectionWithUnifiedPlan();
1862 caller->AddAudioTrack("caller_audio");
1863 auto callee = CreatePeerConnectionWithUnifiedPlan();
1864 callee->AddAudioTrack("callee_audio");
1865
1866 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1867
1868 // Offer should have had both a=msid and a=ssrc MSID lines.
1869 auto* offer = callee->pc()->remote_description();
Philipp Hancke6f0f1582023-12-12 12:15:031870 EXPECT_EQ(
1871 (cricket::kMsidSignalingSemantic | cricket::kMsidSignalingMediaSection |
1872 cricket::kMsidSignalingSsrcAttribute),
1873 offer->description()->msid_signaling());
Steve Antone831b8c2018-02-01 20:22:161874
1875 // Answer should have had only a=msid lines.
1876 auto* answer = caller->pc()->remote_description();
Philipp Hancke6f0f1582023-12-12 12:15:031877 EXPECT_EQ(
1878 cricket::kMsidSignalingSemantic | cricket::kMsidSignalingMediaSection,
1879 answer->description()->msid_signaling());
Steve Antone831b8c2018-02-01 20:22:161880}
1881
1882TEST_F(PeerConnectionMsidSignalingTest, PlanBOfferToUnifiedPlanAnswer) {
1883 auto caller = CreatePeerConnectionWithPlanB();
1884 caller->AddAudioTrack("caller_audio");
1885 auto callee = CreatePeerConnectionWithUnifiedPlan();
1886 callee->AddAudioTrack("callee_audio");
1887
1888 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1889
1890 // Offer should have only a=ssrc MSID lines.
1891 auto* offer = callee->pc()->remote_description();
Philipp Hancke6f0f1582023-12-12 12:15:031892 EXPECT_EQ(
1893 cricket::kMsidSignalingSemantic | cricket::kMsidSignalingSsrcAttribute,
1894 offer->description()->msid_signaling());
Steve Antone831b8c2018-02-01 20:22:161895
1896 // Answer should have only a=ssrc MSID lines to match the offer.
1897 auto* answer = caller->pc()->remote_description();
Philipp Hancke6f0f1582023-12-12 12:15:031898 EXPECT_EQ(
1899 cricket::kMsidSignalingSemantic | cricket::kMsidSignalingSsrcAttribute,
1900 answer->description()->msid_signaling());
Steve Antone831b8c2018-02-01 20:22:161901}
1902
Seth Hampson5b4f0752018-04-02 23:31:361903// This tests that a Plan B endpoint appropriately sets the remote description
1904// from a Unified Plan offer. When the Unified Plan offer contains a=msid lines
1905// that signal no stream ids or multiple stream ids we expect that the Plan B
1906// endpoint always has exactly one media stream per track.
1907TEST_F(PeerConnectionMsidSignalingTest, UnifiedPlanToPlanBAnswer) {
1908 const std::string kStreamId1 = "audio_stream_1";
1909 const std::string kStreamId2 = "audio_stream_2";
1910
1911 auto caller = CreatePeerConnectionWithUnifiedPlan();
1912 caller->AddAudioTrack("caller_audio", {kStreamId1, kStreamId2});
1913 caller->AddVideoTrack("caller_video", {});
1914 auto callee = CreatePeerConnectionWithPlanB();
1915 callee->AddAudioTrack("callee_audio");
1916 caller->AddVideoTrack("callee_video");
1917
1918 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1919
1920 // Offer should have had both a=msid and a=ssrc MSID lines.
1921 auto* offer = callee->pc()->remote_description();
Philipp Hancke6f0f1582023-12-12 12:15:031922 EXPECT_EQ(
1923 (cricket::kMsidSignalingSemantic | cricket::kMsidSignalingMediaSection |
1924 cricket::kMsidSignalingSsrcAttribute),
1925 offer->description()->msid_signaling());
Seth Hampson5b4f0752018-04-02 23:31:361926
1927 // Callee should always have 1 stream for all of it's receivers.
1928 const auto& track_events = callee->observer()->add_track_events_;
1929 ASSERT_EQ(2u, track_events.size());
1930 ASSERT_EQ(1u, track_events[0].streams.size());
1931 EXPECT_EQ(kStreamId1, track_events[0].streams[0]->id());
1932 ASSERT_EQ(1u, track_events[1].streams.size());
1933 // This autogenerated a stream id for the empty one signalled.
1934 EXPECT_FALSE(track_events[1].streams[0]->id().empty());
1935}
1936
Steve Antone831b8c2018-02-01 20:22:161937TEST_F(PeerConnectionMsidSignalingTest, PureUnifiedPlanToUs) {
1938 auto caller = CreatePeerConnectionWithUnifiedPlan();
1939 caller->AddAudioTrack("caller_audio");
1940 auto callee = CreatePeerConnectionWithUnifiedPlan();
1941 callee->AddAudioTrack("callee_audio");
1942
1943 auto offer = caller->CreateOffer();
1944 // Simulate a pure Unified Plan offerer by setting the MSID signaling to media
1945 // section only.
Philipp Hancke6f0f1582023-12-12 12:15:031946 offer->description()->set_msid_signaling(cricket::kMsidSignalingSemantic |
1947 cricket::kMsidSignalingMediaSection);
Steve Antone831b8c2018-02-01 20:22:161948
1949 ASSERT_TRUE(
1950 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1951 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1952
1953 // Answer should have only a=msid to match the offer.
1954 auto answer = callee->CreateAnswer();
Philipp Hancke6f0f1582023-12-12 12:15:031955 EXPECT_EQ(
1956 cricket::kMsidSignalingSemantic | cricket::kMsidSignalingMediaSection,
1957 answer->description()->msid_signaling());
Steve Antone831b8c2018-02-01 20:22:161958}
1959
Henrik Boström91d039b2018-01-11 16:43:301960// Sender setups in a call.
1961
Steve Anton3172c032018-05-03 22:30:181962TEST_P(PeerConnectionRtpTest, CreateTwoSendersWithSameTrack) {
Henrik Boström91d039b2018-01-11 16:43:301963 auto caller = CreatePeerConnection();
1964 auto callee = CreatePeerConnection();
1965
1966 auto track = caller->CreateAudioTrack("audio_track");
1967 auto sender1 = caller->AddTrack(track);
1968 ASSERT_TRUE(sender1);
1969 // We need to temporarily reset the track for the subsequent AddTrack() to
1970 // succeed.
1971 EXPECT_TRUE(sender1->SetTrack(nullptr));
1972 auto sender2 = caller->AddTrack(track);
1973 EXPECT_TRUE(sender2);
Niels Möllerafb246b2022-04-20 12:26:501974 EXPECT_TRUE(sender1->SetTrack(track.get()));
Henrik Boström91d039b2018-01-11 16:43:301975
Florent Castelli15a38de2022-04-05 22:38:211976 if (sdp_semantics_ == SdpSemantics::kPlanB_DEPRECATED) {
Steve Anton3172c032018-05-03 22:30:181977 // TODO(hbos): When https://crbug.com/webrtc/8734 is resolved, this should
Artem Titovcfea2182021-08-09 23:22:311978 // return true, and doing `callee->SetRemoteDescription()` should work.
Steve Anton3172c032018-05-03 22:30:181979 EXPECT_FALSE(caller->CreateOfferAndSetAsLocal());
1980 } else {
1981 EXPECT_TRUE(caller->CreateOfferAndSetAsLocal());
1982 }
Henrik Boström91d039b2018-01-11 16:43:301983}
1984
Guido Urdaneta70c2db12019-04-16 10:24:141985// This test exercises the code path that fires a NegotiationNeeded
1986// notification when the stream IDs of the local description differ from
Guido Urdaneta1ff16c82019-05-20 17:31:531987// the ones in the transceiver.
Guido Urdaneta70c2db12019-04-16 10:24:141988TEST_F(PeerConnectionRtpTestUnifiedPlan,
1989 ChangeAssociatedStreamsTriggersRenegotiation) {
1990 auto caller = CreatePeerConnection();
1991 auto callee = CreatePeerConnection();
1992
1993 RtpTransceiverInit init;
1994 init.direction = RtpTransceiverDirection::kSendRecv;
1995 auto transceiver =
1996 caller->AddTransceiver(caller->CreateAudioTrack("a"), init);
Henrik Boströme574a312020-08-25 08:20:111997 EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1998 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
Guido Urdaneta70c2db12019-04-16 10:24:141999
2000 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Henrik Boströme574a312020-08-25 08:20:112001 caller->observer()->clear_legacy_renegotiation_needed();
2002 caller->observer()->clear_latest_negotiation_needed_event();
Guido Urdaneta70c2db12019-04-16 10:24:142003
Guido Urdaneta1ff16c82019-05-20 17:31:532004 transceiver->sender()->SetStreams({"stream3", "stream4", "stream5"});
Henrik Boströme574a312020-08-25 08:20:112005 EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
2006 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
Guido Urdaneta1ff16c82019-05-20 17:31:532007
2008 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
2009 auto callee_streams = callee->pc()->GetReceivers()[0]->streams();
2010 ASSERT_EQ(3u, callee_streams.size());
2011 EXPECT_EQ("stream3", callee_streams[0]->id());
2012 EXPECT_EQ("stream4", callee_streams[1]->id());
2013 EXPECT_EQ("stream5", callee_streams[2]->id());
Guido Urdaneta70c2db12019-04-16 10:24:142014}
2015
Mirko Bonadeic84f6612019-01-31 11:20:572016INSTANTIATE_TEST_SUITE_P(PeerConnectionRtpTest,
2017 PeerConnectionRtpTest,
Florent Castelli15a38de2022-04-05 22:38:212018 Values(SdpSemantics::kPlanB_DEPRECATED,
Mirko Bonadeic84f6612019-01-31 11:20:572019 SdpSemantics::kUnifiedPlan));
Steve Anton3172c032018-05-03 22:30:182020
Steve Anton9158ef62017-11-27 21:01:522021} // namespace webrtc