blob: dbcb9b4ca14a1a840e69328bc122a283c36a8372 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander65c7f672016-02-12 00:05:01 -08002 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander65c7f672016-02-12 00:05:01 -08004 * 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.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
kwiberg31022942016-03-11 14:18:21 -080011#include <memory>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012#include <string>
13#include <vector>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "media/base/codec.h"
16#include "media/base/testutils.h"
17#include "p2p/base/p2pconstants.h"
18#include "p2p/base/transportdescription.h"
19#include "p2p/base/transportinfo.h"
20#include "pc/mediasession.h"
Steve Anton1d03a752017-11-27 14:30:09 -080021#include "pc/rtpmediautils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "pc/srtpfilter.h"
23#include "rtc_base/checks.h"
24#include "rtc_base/fakesslidentity.h"
25#include "rtc_base/gunit.h"
26#include "rtc_base/messagedigest.h"
27#include "rtc_base/ssladapter.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020028#include "rtc_base/strings/string_builder.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000029
Yves Gerey665174f2018-06-19 15:03:05 +020030#define ASSERT_CRYPTO(cd, s, cs) \
31 ASSERT_EQ(s, cd->cryptos().size()); \
32 ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
henrike@webrtc.org28e20752013-07-10 00:45:36 +000033
34typedef std::vector<cricket::Candidate> Candidates;
35
36using cricket::MediaContentDescription;
37using cricket::MediaSessionDescriptionFactory;
zhihuang1c378ed2017-08-17 14:10:50 -070038using cricket::MediaDescriptionOptions;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000039using cricket::MediaSessionOptions;
40using cricket::MediaType;
Steve Anton5adfafd2017-12-20 16:34:00 -080041using cricket::MediaProtocolType;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042using cricket::SessionDescription;
43using cricket::SsrcGroup;
44using cricket::StreamParams;
45using cricket::StreamParamsVec;
46using cricket::TransportDescription;
47using cricket::TransportDescriptionFactory;
48using cricket::TransportInfo;
49using cricket::ContentInfo;
50using cricket::CryptoParamsVec;
51using cricket::AudioContentDescription;
52using cricket::VideoContentDescription;
53using cricket::DataContentDescription;
deadbeef44f08192015-12-15 16:20:09 -080054using cricket::GetFirstAudioContent;
55using cricket::GetFirstVideoContent;
56using cricket::GetFirstDataContent;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000057using cricket::GetFirstAudioContentDescription;
58using cricket::GetFirstVideoContentDescription;
59using cricket::GetFirstDataContentDescription;
60using cricket::kAutoBandwidth;
61using cricket::AudioCodec;
62using cricket::VideoCodec;
63using cricket::DataCodec;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064using cricket::MEDIA_TYPE_AUDIO;
65using cricket::MEDIA_TYPE_VIDEO;
66using cricket::MEDIA_TYPE_DATA;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067using cricket::SEC_DISABLED;
68using cricket::SEC_ENABLED;
69using cricket::SEC_REQUIRED;
Guo-wei Shieh456696a2015-09-30 21:48:54 -070070using rtc::CS_AES_CM_128_HMAC_SHA1_32;
71using rtc::CS_AES_CM_128_HMAC_SHA1_80;
jbauchcb560652016-08-04 05:20:32 -070072using rtc::CS_AEAD_AES_128_GCM;
73using rtc::CS_AEAD_AES_256_GCM;
isheriff6f8d6862016-05-26 11:24:55 -070074using webrtc::RtpExtension;
Steve Anton4e70a722017-11-28 14:57:10 -080075using webrtc::RtpTransceiverDirection;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000076
77static const AudioCodec kAudioCodecs1[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070078 AudioCodec(103, "ISAC", 16000, -1, 1),
79 AudioCodec(102, "iLBC", 8000, 13300, 1),
80 AudioCodec(0, "PCMU", 8000, 64000, 1),
81 AudioCodec(8, "PCMA", 8000, 64000, 1),
82 AudioCodec(117, "red", 8000, 0, 1),
83 AudioCodec(107, "CN", 48000, 0, 1)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084
85static const AudioCodec kAudioCodecs2[] = {
Henrik Lundinf8ed5612018-05-07 12:05:57 +020086 AudioCodec(126, "foo", 16000, 22000, 1),
deadbeef67cf2c12016-04-13 10:07:16 -070087 AudioCodec(0, "PCMU", 8000, 64000, 1),
88 AudioCodec(127, "iLBC", 8000, 13300, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089};
90
91static const AudioCodec kAudioCodecsAnswer[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070092 AudioCodec(102, "iLBC", 8000, 13300, 1),
93 AudioCodec(0, "PCMU", 8000, 64000, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094};
95
perkj26752742016-10-24 01:21:16 -070096static const VideoCodec kVideoCodecs1[] = {VideoCodec(96, "H264-SVC"),
97 VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000098
zhihuang1c378ed2017-08-17 14:10:50 -070099static const VideoCodec kVideoCodecs1Reverse[] = {VideoCodec(97, "H264"),
100 VideoCodec(96, "H264-SVC")};
101
perkj26752742016-10-24 01:21:16 -0700102static const VideoCodec kVideoCodecs2[] = {VideoCodec(126, "H264"),
103 VideoCodec(127, "H263")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000104
perkj26752742016-10-24 01:21:16 -0700105static const VideoCodec kVideoCodecsAnswer[] = {VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000106
deadbeef67cf2c12016-04-13 10:07:16 -0700107static const DataCodec kDataCodecs1[] = {DataCodec(98, "binary-data"),
108 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000109
deadbeef67cf2c12016-04-13 10:07:16 -0700110static const DataCodec kDataCodecs2[] = {DataCodec(126, "binary-data"),
111 DataCodec(127, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000112
deadbeef67cf2c12016-04-13 10:07:16 -0700113static const DataCodec kDataCodecsAnswer[] = {DataCodec(98, "binary-data"),
114 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000115
isheriff6f8d6862016-05-26 11:24:55 -0700116static const RtpExtension kAudioRtpExtension1[] = {
117 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
118 RtpExtension("http://google.com/testing/audio_something", 10),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119};
120
jbauch5869f502017-06-29 12:31:36 -0700121static const RtpExtension kAudioRtpExtensionEncrypted1[] = {
122 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
123 RtpExtension("http://google.com/testing/audio_something", 10),
124 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 12, true),
125};
126
isheriff6f8d6862016-05-26 11:24:55 -0700127static const RtpExtension kAudioRtpExtension2[] = {
128 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
129 RtpExtension("http://google.com/testing/audio_something_else", 8),
130 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000131};
132
isheriff6f8d6862016-05-26 11:24:55 -0700133static const RtpExtension kAudioRtpExtension3[] = {
134 RtpExtension("http://google.com/testing/audio_something", 2),
135 RtpExtension("http://google.com/testing/both_audio_and_video", 3),
deadbeefa5b273a2015-08-20 17:30:13 -0700136};
137
jbauch5869f502017-06-29 12:31:36 -0700138static const RtpExtension kAudioRtpExtension3ForEncryption[] = {
139 RtpExtension("http://google.com/testing/audio_something", 2),
140 // Use RTP extension that supports encryption.
141 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 3),
142};
143
144static const RtpExtension kAudioRtpExtension3ForEncryptionOffer[] = {
145 RtpExtension("http://google.com/testing/audio_something", 2),
146 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 3),
147 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14, true),
148};
149
isheriff6f8d6862016-05-26 11:24:55 -0700150static const RtpExtension kAudioRtpExtensionAnswer[] = {
151 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152};
153
jbauch5869f502017-06-29 12:31:36 -0700154static const RtpExtension kAudioRtpExtensionEncryptedAnswer[] = {
155 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 12, true),
156};
157
isheriff6f8d6862016-05-26 11:24:55 -0700158static const RtpExtension kVideoRtpExtension1[] = {
159 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
160 RtpExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000161};
162
jbauch5869f502017-06-29 12:31:36 -0700163static const RtpExtension kVideoRtpExtensionEncrypted1[] = {
164 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
165 RtpExtension("http://google.com/testing/video_something", 13),
166 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 11, true),
167};
168
isheriff6f8d6862016-05-26 11:24:55 -0700169static const RtpExtension kVideoRtpExtension2[] = {
170 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
171 RtpExtension("http://google.com/testing/video_something_else", 14),
172 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000173};
174
isheriff6f8d6862016-05-26 11:24:55 -0700175static const RtpExtension kVideoRtpExtension3[] = {
176 RtpExtension("http://google.com/testing/video_something", 4),
177 RtpExtension("http://google.com/testing/both_audio_and_video", 5),
deadbeefa5b273a2015-08-20 17:30:13 -0700178};
179
jbauch5869f502017-06-29 12:31:36 -0700180static const RtpExtension kVideoRtpExtension3ForEncryption[] = {
181 RtpExtension("http://google.com/testing/video_something", 4),
182 // Use RTP extension that supports encryption.
183 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 5),
184};
185
isheriff6f8d6862016-05-26 11:24:55 -0700186static const RtpExtension kVideoRtpExtensionAnswer[] = {
187 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000188};
189
jbauch5869f502017-06-29 12:31:36 -0700190static const RtpExtension kVideoRtpExtensionEncryptedAnswer[] = {
191 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 11, true),
192};
193
Peter Boström0c4e06b2015-10-07 12:23:21 +0200194static const uint32_t kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
195static const uint32_t kSimSsrc[] = {10, 20, 30};
196static const uint32_t kFec1Ssrc[] = {10, 11};
197static const uint32_t kFec2Ssrc[] = {20, 21};
198static const uint32_t kFec3Ssrc[] = {30, 31};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000199
200static const char kMediaStream1[] = "stream_1";
201static const char kMediaStream2[] = "stream_2";
202static const char kVideoTrack1[] = "video_1";
203static const char kVideoTrack2[] = "video_2";
204static const char kAudioTrack1[] = "audio_1";
205static const char kAudioTrack2[] = "audio_2";
206static const char kAudioTrack3[] = "audio_3";
207static const char kDataTrack1[] = "data_1";
208static const char kDataTrack2[] = "data_2";
209static const char kDataTrack3[] = "data_3";
210
zhihuangcf5b37c2016-05-05 11:44:35 -0700211static const char* kMediaProtocols[] = {"RTP/AVP", "RTP/SAVP", "RTP/AVPF",
212 "RTP/SAVPF"};
213static const char* kMediaProtocolsDtls[] = {
214 "TCP/TLS/RTP/SAVPF", "TCP/TLS/RTP/SAVP", "UDP/TLS/RTP/SAVPF",
215 "UDP/TLS/RTP/SAVP"};
216
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700217// SRTP cipher name negotiated by the tests. This must be updated if the
218// default changes.
219static const char* kDefaultSrtpCryptoSuite = CS_AES_CM_128_HMAC_SHA1_80;
220static const char* kDefaultSrtpCryptoSuiteGcm = CS_AEAD_AES_256_GCM;
221
zhihuang1c378ed2017-08-17 14:10:50 -0700222// These constants are used to make the code using "AddMediaSection" more
223// readable.
224static constexpr bool kStopped = true;
225static constexpr bool kActive = false;
226
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000227static bool IsMediaContentOfType(const ContentInfo* content,
228 MediaType media_type) {
Steve Antonb1c1de12017-12-21 15:14:30 -0800229 RTC_DCHECK(content);
230 return content->media_description()->type() == media_type;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000231}
232
Steve Anton4e70a722017-11-28 14:57:10 -0800233static RtpTransceiverDirection GetMediaDirection(const ContentInfo* content) {
Steve Antonb1c1de12017-12-21 15:14:30 -0800234 RTC_DCHECK(content);
235 return content->media_description()->direction();
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000236}
237
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000238static void AddRtxCodec(const VideoCodec& rtx_codec,
239 std::vector<VideoCodec>* codecs) {
magjedb05fa242016-11-11 04:00:16 -0800240 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000241 codecs->push_back(rtx_codec);
242}
243
244template <class T>
245static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
246 std::vector<std::string> codec_names;
247 for (const auto& codec : codecs) {
248 codec_names.push_back(codec.name);
249 }
250 return codec_names;
251}
252
zhihuang1c378ed2017-08-17 14:10:50 -0700253// This is used for test only. MIDs are not the identification of the
254// MediaDescriptionOptions since some end points may not support MID and the SDP
255// may not contain 'mid'.
256std::vector<MediaDescriptionOptions>::iterator FindFirstMediaDescriptionByMid(
257 const std::string& mid,
258 MediaSessionOptions* opts) {
259 return std::find_if(
260 opts->media_description_options.begin(),
261 opts->media_description_options.end(),
Steve Anton36b29d12017-10-30 09:57:42 -0700262 [&mid](const MediaDescriptionOptions& t) { return t.mid == mid; });
263}
264
265std::vector<MediaDescriptionOptions>::const_iterator
266FindFirstMediaDescriptionByMid(const std::string& mid,
267 const MediaSessionOptions& opts) {
268 return std::find_if(
269 opts.media_description_options.begin(),
270 opts.media_description_options.end(),
271 [&mid](const MediaDescriptionOptions& t) { return t.mid == mid; });
zhihuang1c378ed2017-08-17 14:10:50 -0700272}
273
274// Add a media section to the |session_options|.
275static void AddMediaSection(MediaType type,
276 const std::string& mid,
Steve Anton4e70a722017-11-28 14:57:10 -0800277 RtpTransceiverDirection direction,
zhihuang1c378ed2017-08-17 14:10:50 -0700278 bool stopped,
279 MediaSessionOptions* opts) {
Steve Anton4e70a722017-11-28 14:57:10 -0800280 opts->media_description_options.push_back(
281 MediaDescriptionOptions(type, mid, direction, stopped));
zhihuang1c378ed2017-08-17 14:10:50 -0700282}
283
Steve Anton4e70a722017-11-28 14:57:10 -0800284static void AddAudioVideoSections(RtpTransceiverDirection direction,
zhihuang1c378ed2017-08-17 14:10:50 -0700285 MediaSessionOptions* opts) {
286 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", direction, kActive, opts);
287 AddMediaSection(MEDIA_TYPE_VIDEO, "video", direction, kActive, opts);
288}
289
290static void AddDataSection(cricket::DataChannelType dct,
Steve Anton4e70a722017-11-28 14:57:10 -0800291 RtpTransceiverDirection direction,
zhihuang1c378ed2017-08-17 14:10:50 -0700292 MediaSessionOptions* opts) {
293 opts->data_channel_type = dct;
294 AddMediaSection(MEDIA_TYPE_DATA, "data", direction, kActive, opts);
295}
296
Steve Anton8ffb9c32017-08-31 15:45:38 -0700297static void AttachSenderToMediaSection(
298 const std::string& mid,
299 MediaType type,
300 const std::string& track_id,
301 const std::vector<std::string>& stream_ids,
302 int num_sim_layer,
303 MediaSessionOptions* session_options) {
zhihuang1c378ed2017-08-17 14:10:50 -0700304 auto it = FindFirstMediaDescriptionByMid(mid, session_options);
305 switch (type) {
306 case MEDIA_TYPE_AUDIO:
Steve Anton8ffb9c32017-08-31 15:45:38 -0700307 it->AddAudioSender(track_id, stream_ids);
zhihuang1c378ed2017-08-17 14:10:50 -0700308 break;
309 case MEDIA_TYPE_VIDEO:
Steve Anton8ffb9c32017-08-31 15:45:38 -0700310 it->AddVideoSender(track_id, stream_ids, num_sim_layer);
zhihuang1c378ed2017-08-17 14:10:50 -0700311 break;
312 case MEDIA_TYPE_DATA:
Steve Anton8ffb9c32017-08-31 15:45:38 -0700313 RTC_CHECK(stream_ids.size() == 1U);
314 it->AddRtpDataChannel(track_id, stream_ids[0]);
zhihuang1c378ed2017-08-17 14:10:50 -0700315 break;
316 default:
317 RTC_NOTREACHED();
318 }
319}
320
321static void DetachSenderFromMediaSection(const std::string& mid,
322 const std::string& track_id,
323 MediaSessionOptions* session_options) {
324 auto it = FindFirstMediaDescriptionByMid(mid, session_options);
325 auto sender_it = it->sender_options.begin();
326 for (; sender_it != it->sender_options.end(); ++sender_it) {
327 if (sender_it->track_id == track_id) {
328 it->sender_options.erase(sender_it);
329 return;
330 }
331 }
332 RTC_NOTREACHED();
333}
334
335// Helper function used to create a default MediaSessionOptions for Plan B SDP.
336// (https://tools.ietf.org/html/draft-uberti-rtcweb-plan-00).
337static MediaSessionOptions CreatePlanBMediaSessionOptions() {
338 MediaSessionOptions session_options;
Steve Anton4e70a722017-11-28 14:57:10 -0800339 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
340 kActive, &session_options);
zhihuang1c378ed2017-08-17 14:10:50 -0700341 return session_options;
342}
343
344// TODO(zhihuang): Most of these tests were written while MediaSessionOptions
345// was designed for Plan B SDP, where only one audio "m=" section and one video
346// "m=" section could be generated, and ordering couldn't be controlled. Many of
347// these tests may be obsolete as a result, and should be refactored or removed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000348class MediaSessionDescriptionFactoryTest : public testing::Test {
349 public:
zhihuang1c378ed2017-08-17 14:10:50 -0700350 MediaSessionDescriptionFactoryTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -0700351 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
352 MAKE_VECTOR(kAudioCodecs1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000353 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
354 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -0700355 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
356 MAKE_VECTOR(kAudioCodecs2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000357 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
358 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200359 tdf1_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700360 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200361 tdf2_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700362 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000363 }
364
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000365 // Create a video StreamParamsVec object with:
366 // - one video stream with 3 simulcast streams and FEC,
367 StreamParamsVec CreateComplexVideoStreamParamsVec() {
368 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
369 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
370 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
371 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
372
373 std::vector<SsrcGroup> ssrc_groups;
374 ssrc_groups.push_back(sim_group);
375 ssrc_groups.push_back(fec_group1);
376 ssrc_groups.push_back(fec_group2);
377 ssrc_groups.push_back(fec_group3);
378
379 StreamParams simulcast_params;
380 simulcast_params.id = kVideoTrack1;
381 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
382 simulcast_params.ssrc_groups = ssrc_groups;
383 simulcast_params.cname = "Video_SIM_FEC";
Seth Hampson845e8782018-03-02 11:34:10 -0800384 simulcast_params.set_stream_ids({kMediaStream1});
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000385
386 StreamParamsVec video_streams;
387 video_streams.push_back(simulcast_params);
388
389 return video_streams;
390 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000391
392 bool CompareCryptoParams(const CryptoParamsVec& c1,
393 const CryptoParamsVec& c2) {
394 if (c1.size() != c2.size())
395 return false;
396 for (size_t i = 0; i < c1.size(); ++i)
397 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
398 c1[i].key_params != c2[i].key_params ||
399 c1[i].session_params != c2[i].session_params)
400 return false;
401 return true;
402 }
403
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700404 // Returns true if the transport info contains "renomination" as an
405 // ICE option.
406 bool GetIceRenomination(const TransportInfo* transport_info) {
407 const std::vector<std::string>& ice_options =
408 transport_info->description.transport_options;
deadbeef30952b42017-04-21 02:41:29 -0700409 auto iter =
410 std::find(ice_options.begin(), ice_options.end(), "renomination");
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700411 return iter != ice_options.end();
412 }
413
zhihuang1c378ed2017-08-17 14:10:50 -0700414 void TestTransportInfo(bool offer,
Steve Anton36b29d12017-10-30 09:57:42 -0700415 const MediaSessionOptions& options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000416 bool has_current_desc) {
417 const std::string current_audio_ufrag = "current_audio_ufrag";
418 const std::string current_audio_pwd = "current_audio_pwd";
419 const std::string current_video_ufrag = "current_video_ufrag";
420 const std::string current_video_pwd = "current_video_pwd";
421 const std::string current_data_ufrag = "current_data_ufrag";
422 const std::string current_data_pwd = "current_data_pwd";
kwiberg31022942016-03-11 14:18:21 -0800423 std::unique_ptr<SessionDescription> current_desc;
424 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000425 if (has_current_desc) {
426 current_desc.reset(new SessionDescription());
Yves Gerey665174f2018-06-19 15:03:05 +0200427 EXPECT_TRUE(current_desc->AddTransportInfo(TransportInfo(
428 "audio",
429 TransportDescription(current_audio_ufrag, current_audio_pwd))));
430 EXPECT_TRUE(current_desc->AddTransportInfo(TransportInfo(
431 "video",
432 TransportDescription(current_video_ufrag, current_video_pwd))));
433 EXPECT_TRUE(current_desc->AddTransportInfo(TransportInfo(
434 "data", TransportDescription(current_data_ufrag, current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000435 }
436 if (offer) {
437 desc.reset(f1_.CreateOffer(options, current_desc.get()));
438 } else {
kwiberg31022942016-03-11 14:18:21 -0800439 std::unique_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000440 offer.reset(f1_.CreateOffer(options, NULL));
441 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
442 }
443 ASSERT_TRUE(desc.get() != NULL);
444 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000445 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000446 EXPECT_TRUE(ti_audio != NULL);
447 if (has_current_desc) {
448 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
449 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
450 } else {
451 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
452 ti_audio->description.ice_ufrag.size());
453 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
454 ti_audio->description.ice_pwd.size());
455 }
zhihuang1c378ed2017-08-17 14:10:50 -0700456 auto media_desc_options_it =
Steve Anton36b29d12017-10-30 09:57:42 -0700457 FindFirstMediaDescriptionByMid("audio", options);
zhihuang1c378ed2017-08-17 14:10:50 -0700458 EXPECT_EQ(
459 media_desc_options_it->transport_options.enable_ice_renomination,
460 GetIceRenomination(ti_audio));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000461
462 } else {
463 EXPECT_TRUE(ti_audio == NULL);
464 }
465 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000466 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000467 EXPECT_TRUE(ti_video != NULL);
468 if (options.bundle_enabled) {
469 EXPECT_EQ(ti_audio->description.ice_ufrag,
470 ti_video->description.ice_ufrag);
Yves Gerey665174f2018-06-19 15:03:05 +0200471 EXPECT_EQ(ti_audio->description.ice_pwd, ti_video->description.ice_pwd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000472 } else {
473 if (has_current_desc) {
474 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
475 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
476 } else {
477 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
478 ti_video->description.ice_ufrag.size());
479 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
480 ti_video->description.ice_pwd.size());
481 }
482 }
zhihuang1c378ed2017-08-17 14:10:50 -0700483 auto media_desc_options_it =
Steve Anton36b29d12017-10-30 09:57:42 -0700484 FindFirstMediaDescriptionByMid("video", options);
zhihuang1c378ed2017-08-17 14:10:50 -0700485 EXPECT_EQ(
486 media_desc_options_it->transport_options.enable_ice_renomination,
487 GetIceRenomination(ti_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488 } else {
489 EXPECT_TRUE(ti_video == NULL);
490 }
491 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
492 if (options.has_data()) {
493 EXPECT_TRUE(ti_data != NULL);
494 if (options.bundle_enabled) {
495 EXPECT_EQ(ti_audio->description.ice_ufrag,
496 ti_data->description.ice_ufrag);
Yves Gerey665174f2018-06-19 15:03:05 +0200497 EXPECT_EQ(ti_audio->description.ice_pwd, ti_data->description.ice_pwd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000498 } else {
499 if (has_current_desc) {
500 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
501 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
502 } else {
503 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
504 ti_data->description.ice_ufrag.size());
505 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
506 ti_data->description.ice_pwd.size());
507 }
508 }
zhihuang1c378ed2017-08-17 14:10:50 -0700509 auto media_desc_options_it =
Steve Anton36b29d12017-10-30 09:57:42 -0700510 FindFirstMediaDescriptionByMid("data", options);
zhihuang1c378ed2017-08-17 14:10:50 -0700511 EXPECT_EQ(
512 media_desc_options_it->transport_options.enable_ice_renomination,
513 GetIceRenomination(ti_data));
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700514
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000515 } else {
516 EXPECT_TRUE(ti_video == NULL);
517 }
518 }
519
520 void TestCryptoWithBundle(bool offer) {
521 f1_.set_secure(SEC_ENABLED);
522 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -0800523 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
524 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
525 &options);
kwiberg31022942016-03-11 14:18:21 -0800526 std::unique_ptr<SessionDescription> ref_desc;
527 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528 if (offer) {
529 options.bundle_enabled = false;
530 ref_desc.reset(f1_.CreateOffer(options, NULL));
531 options.bundle_enabled = true;
532 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
533 } else {
534 options.bundle_enabled = true;
535 ref_desc.reset(f1_.CreateOffer(options, NULL));
536 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
537 }
Steve Antonb1c1de12017-12-21 15:14:30 -0800538 ASSERT_TRUE(desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000539 const cricket::MediaContentDescription* audio_media_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -0800540 desc->GetContentDescriptionByName("audio");
541 ASSERT_TRUE(audio_media_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000542 const cricket::MediaContentDescription* video_media_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -0800543 desc->GetContentDescriptionByName("video");
544 ASSERT_TRUE(video_media_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000545 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
546 video_media_desc->cryptos()));
547 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700548 EXPECT_EQ(std::string(kDefaultSrtpCryptoSuite),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000549 audio_media_desc->cryptos()[0].cipher_suite);
550
551 // Verify the selected crypto is one from the reference audio
552 // media content.
553 const cricket::MediaContentDescription* ref_audio_media_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -0800554 ref_desc->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000555 bool found = false;
556 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
557 if (ref_audio_media_desc->cryptos()[i].Matches(
Yves Gerey665174f2018-06-19 15:03:05 +0200558 audio_media_desc->cryptos()[0])) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000559 found = true;
560 break;
561 }
562 }
563 EXPECT_TRUE(found);
564 }
565
566 // This test that the audio and video media direction is set to
567 // |expected_direction_in_answer| in an answer if the offer direction is set
zhihuang1c378ed2017-08-17 14:10:50 -0700568 // to |direction_in_offer| and the answer is willing to both send and receive.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000569 void TestMediaDirectionInAnswer(
Steve Anton4e70a722017-11-28 14:57:10 -0800570 RtpTransceiverDirection direction_in_offer,
571 RtpTransceiverDirection expected_direction_in_answer) {
zhihuang1c378ed2017-08-17 14:10:50 -0700572 MediaSessionOptions offer_opts;
573 AddAudioVideoSections(direction_in_offer, &offer_opts);
574
575 std::unique_ptr<SessionDescription> offer(
576 f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000577 ASSERT_TRUE(offer.get() != NULL);
terelius8c011e52016-04-26 05:28:11 -0700578 ContentInfo* ac_offer = offer->GetContentByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000579 ASSERT_TRUE(ac_offer != NULL);
terelius8c011e52016-04-26 05:28:11 -0700580 ContentInfo* vc_offer = offer->GetContentByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000581 ASSERT_TRUE(vc_offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000582
zhihuang1c378ed2017-08-17 14:10:50 -0700583 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800584 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &answer_opts);
kwiberg31022942016-03-11 14:18:21 -0800585 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -0700586 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000587 const AudioContentDescription* acd_answer =
588 GetFirstAudioContentDescription(answer.get());
589 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
590 const VideoContentDescription* vcd_answer =
591 GetFirstVideoContentDescription(answer.get());
592 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
593 }
594
595 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
Steve Antonb1c1de12017-12-21 15:14:30 -0800596 RTC_DCHECK(content);
597 RTC_CHECK(content->media_description());
598 const cricket::AudioContentDescription* audio_desc =
599 content->media_description()->as_audio();
600 RTC_CHECK(audio_desc);
601 for (const cricket::AudioCodec& codec : audio_desc->codecs()) {
602 if (codec.name == "CN") {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000603 return false;
Steve Antonb1c1de12017-12-21 15:14:30 -0800604 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000605 }
606 return true;
607 }
608
jbauchcb560652016-08-04 05:20:32 -0700609 void TestVideoGcmCipher(bool gcm_offer, bool gcm_answer) {
610 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800611 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &offer_opts);
jbauchcb560652016-08-04 05:20:32 -0700612 offer_opts.crypto_options.enable_gcm_crypto_suites = gcm_offer;
zhihuang1c378ed2017-08-17 14:10:50 -0700613
jbauchcb560652016-08-04 05:20:32 -0700614 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800615 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &answer_opts);
jbauchcb560652016-08-04 05:20:32 -0700616 answer_opts.crypto_options.enable_gcm_crypto_suites = gcm_answer;
zhihuang1c378ed2017-08-17 14:10:50 -0700617
jbauchcb560652016-08-04 05:20:32 -0700618 f1_.set_secure(SEC_ENABLED);
619 f2_.set_secure(SEC_ENABLED);
620 std::unique_ptr<SessionDescription> offer(
621 f1_.CreateOffer(offer_opts, NULL));
622 ASSERT_TRUE(offer.get() != NULL);
623 std::unique_ptr<SessionDescription> answer(
624 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
625 const ContentInfo* ac = answer->GetContentByName("audio");
626 const ContentInfo* vc = answer->GetContentByName("video");
627 ASSERT_TRUE(ac != NULL);
628 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800629 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
630 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800631 const AudioContentDescription* acd = ac->media_description()->as_audio();
632 const VideoContentDescription* vcd = vc->media_description()->as_video();
jbauchcb560652016-08-04 05:20:32 -0700633 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
634 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
635 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -0700636 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -0700637 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
638 if (gcm_offer && gcm_answer) {
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700639 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
jbauchcb560652016-08-04 05:20:32 -0700640 } else {
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700641 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
jbauchcb560652016-08-04 05:20:32 -0700642 }
643 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
644 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
Yves Gerey665174f2018-06-19 15:03:05 +0200645 EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
646 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
jbauchcb560652016-08-04 05:20:32 -0700647 if (gcm_offer && gcm_answer) {
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700648 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuiteGcm);
jbauchcb560652016-08-04 05:20:32 -0700649 } else {
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700650 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
jbauchcb560652016-08-04 05:20:32 -0700651 }
652 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
653 }
654
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000655 protected:
656 MediaSessionDescriptionFactory f1_;
657 MediaSessionDescriptionFactory f2_;
658 TransportDescriptionFactory tdf1_;
659 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000660};
661
662// Create a typical audio offer, and ensure it matches what we expect.
663TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
664 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800665 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -0700666 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000667 ASSERT_TRUE(offer.get() != NULL);
668 const ContentInfo* ac = offer->GetContentByName("audio");
669 const ContentInfo* vc = offer->GetContentByName("video");
670 ASSERT_TRUE(ac != NULL);
671 ASSERT_TRUE(vc == NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800672 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800673 const AudioContentDescription* acd = ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000674 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700675 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700676 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000677 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
678 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700679 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000680 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
681}
682
683// Create a typical video offer, and ensure it matches what we expect.
684TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
685 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800686 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000687 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800688 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000689 ASSERT_TRUE(offer.get() != NULL);
690 const ContentInfo* ac = offer->GetContentByName("audio");
691 const ContentInfo* vc = offer->GetContentByName("video");
692 ASSERT_TRUE(ac != NULL);
693 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800694 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
695 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800696 const AudioContentDescription* acd = ac->media_description()->as_audio();
697 const VideoContentDescription* vcd = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000698 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700699 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700700 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000701 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
702 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700703 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000704 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
705 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
706 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700707 EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000708 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
709 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700710 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000711 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
712}
713
714// Test creating an offer with bundle where the Codecs have the same dynamic
715// RTP playlod type. The test verifies that the offer don't contain the
716// duplicate RTP payload types.
717TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
718 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
ossudedfd282016-06-14 07:12:39 -0700719 const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000720 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
721 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
722 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
723
724 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800725 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
726 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000727 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800728 std::unique_ptr<SessionDescription> offer(f2_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000729 const VideoContentDescription* vcd =
730 GetFirstVideoContentDescription(offer.get());
731 const AudioContentDescription* acd =
732 GetFirstAudioContentDescription(offer.get());
733 const DataContentDescription* dcd =
734 GetFirstDataContentDescription(offer.get());
735 ASSERT_TRUE(NULL != vcd);
736 ASSERT_TRUE(NULL != acd);
737 ASSERT_TRUE(NULL != dcd);
738 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
739 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
740 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
741 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
742 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
743 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
744}
745
zhihuang1c378ed2017-08-17 14:10:50 -0700746// Test creating an updated offer with bundle, audio, video and data
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000747// after an audio only session has been negotiated.
748TEST_F(MediaSessionDescriptionFactoryTest,
749 TestCreateUpdatedVideoOfferWithBundle) {
750 f1_.set_secure(SEC_ENABLED);
751 f2_.set_secure(SEC_ENABLED);
752 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800753 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
754 kActive, &opts);
755 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kInactive,
756 kStopped, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000757 opts.data_channel_type = cricket::DCT_NONE;
758 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800759 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
760 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000761 f2_.CreateAnswer(offer.get(), opts, NULL));
762
763 MediaSessionOptions updated_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800764 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &updated_opts);
765 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
766 &updated_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000767 updated_opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800768 std::unique_ptr<SessionDescription> updated_offer(
769 f1_.CreateOffer(updated_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000770
771 const AudioContentDescription* acd =
772 GetFirstAudioContentDescription(updated_offer.get());
773 const VideoContentDescription* vcd =
774 GetFirstVideoContentDescription(updated_offer.get());
775 const DataContentDescription* dcd =
776 GetFirstDataContentDescription(updated_offer.get());
777 EXPECT_TRUE(NULL != vcd);
778 EXPECT_TRUE(NULL != acd);
779 EXPECT_TRUE(NULL != dcd);
780
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700781 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000782 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700783 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000784 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700785 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000786 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
787}
deadbeef44f08192015-12-15 16:20:09 -0800788
wu@webrtc.org78187522013-10-07 23:32:02 +0000789// Create a RTP data offer, and ensure it matches what we expect.
790TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000791 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800792 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
793 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000794 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800795 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000796 ASSERT_TRUE(offer.get() != NULL);
797 const ContentInfo* ac = offer->GetContentByName("audio");
798 const ContentInfo* dc = offer->GetContentByName("data");
799 ASSERT_TRUE(ac != NULL);
800 ASSERT_TRUE(dc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800801 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
802 EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800803 const AudioContentDescription* acd = ac->media_description()->as_audio();
804 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000805 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700806 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700807 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attched.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000808 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
809 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700810 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000811 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
812 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
813 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700814 EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000815 EXPECT_EQ(cricket::kDataMaxBandwidth,
Yves Gerey665174f2018-06-19 15:03:05 +0200816 dcd->bandwidth()); // default bandwidth (auto)
817 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700818 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000819 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
820}
821
wu@webrtc.org78187522013-10-07 23:32:02 +0000822// Create an SCTP data offer with bundle without error.
823TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
824 MediaSessionOptions opts;
wu@webrtc.org78187522013-10-07 23:32:02 +0000825 opts.bundle_enabled = true;
Steve Anton4e70a722017-11-28 14:57:10 -0800826 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
wu@webrtc.org78187522013-10-07 23:32:02 +0000827 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800828 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000829 EXPECT_TRUE(offer.get() != NULL);
830 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
831}
832
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000833// Test creating an sctp data channel from an already generated offer.
834TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
835 MediaSessionOptions opts;
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000836 opts.bundle_enabled = true;
Steve Anton4e70a722017-11-28 14:57:10 -0800837 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000838 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800839 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000840 ASSERT_TRUE(offer1.get() != NULL);
841 const ContentInfo* data = offer1->GetContentByName("data");
842 ASSERT_TRUE(data != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -0800843 ASSERT_EQ(cricket::kMediaProtocolSctp, data->media_description()->protocol());
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000844
845 // Now set data_channel_type to 'none' (default) and make sure that the
846 // datachannel type that gets generated from the previous offer, is of the
847 // same type.
848 opts.data_channel_type = cricket::DCT_NONE;
kwiberg31022942016-03-11 14:18:21 -0800849 std::unique_ptr<SessionDescription> offer2(
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000850 f1_.CreateOffer(opts, offer1.get()));
851 data = offer2->GetContentByName("data");
852 ASSERT_TRUE(data != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -0800853 EXPECT_EQ(cricket::kMediaProtocolSctp, data->media_description()->protocol());
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000854}
855
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000856// Create an audio, video offer without legacy StreamParams.
857TEST_F(MediaSessionDescriptionFactoryTest,
858 TestCreateOfferWithoutLegacyStreams) {
859 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800860 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
kwiberg31022942016-03-11 14:18:21 -0800861 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000862 ASSERT_TRUE(offer.get() != NULL);
863 const ContentInfo* ac = offer->GetContentByName("audio");
864 const ContentInfo* vc = offer->GetContentByName("video");
865 ASSERT_TRUE(ac != NULL);
866 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -0800867 const AudioContentDescription* acd = ac->media_description()->as_audio();
868 const VideoContentDescription* vcd = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000869
Yves Gerey665174f2018-06-19 15:03:05 +0200870 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
871 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000872}
873
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000874// Creates an audio+video sendonly offer.
875TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -0700876 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800877 AddAudioVideoSections(RtpTransceiverDirection::kSendOnly, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -0700878 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -0700879 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -0700880 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -0700881 {kMediaStream1}, 1, &opts);
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000882
zhihuang1c378ed2017-08-17 14:10:50 -0700883 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000884 ASSERT_TRUE(offer.get() != NULL);
885 EXPECT_EQ(2u, offer->contents().size());
886 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
887 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
888
Steve Anton4e70a722017-11-28 14:57:10 -0800889 EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
890 GetMediaDirection(&offer->contents()[0]));
891 EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
892 GetMediaDirection(&offer->contents()[1]));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000893}
894
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000895// Verifies that the order of the media contents in the current
896// SessionDescription is preserved in the new SessionDescription.
897TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
898 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800899 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000900
kwiberg31022942016-03-11 14:18:21 -0800901 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000902 ASSERT_TRUE(offer1.get() != NULL);
903 EXPECT_EQ(1u, offer1->contents().size());
904 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
905
Steve Anton4e70a722017-11-28 14:57:10 -0800906 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
907 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -0800908 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000909 f1_.CreateOffer(opts, offer1.get()));
910 ASSERT_TRUE(offer2.get() != NULL);
911 EXPECT_EQ(2u, offer2->contents().size());
912 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
913 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
914
Steve Anton4e70a722017-11-28 14:57:10 -0800915 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
916 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -0800917 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000918 f1_.CreateOffer(opts, offer2.get()));
919 ASSERT_TRUE(offer3.get() != NULL);
920 EXPECT_EQ(3u, offer3->contents().size());
921 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
922 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
923 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000924}
925
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000926// Create a typical audio answer, and ensure it matches what we expect.
927TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
928 f1_.set_secure(SEC_ENABLED);
929 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800930 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -0700931 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000932 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800933 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -0700934 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000935 const ContentInfo* ac = answer->GetContentByName("audio");
936 const ContentInfo* vc = answer->GetContentByName("video");
937 ASSERT_TRUE(ac != NULL);
938 ASSERT_TRUE(vc == NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800939 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800940 const AudioContentDescription* acd = ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000941 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
942 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700943 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000944 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
945 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700946 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000947 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
948}
949
jbauchcb560652016-08-04 05:20:32 -0700950// Create a typical audio answer with GCM ciphers enabled, and ensure it
951// matches what we expect.
952TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
953 f1_.set_secure(SEC_ENABLED);
954 f2_.set_secure(SEC_ENABLED);
zhihuang1c378ed2017-08-17 14:10:50 -0700955 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
956 opts.crypto_options.enable_gcm_crypto_suites = true;
957 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
jbauchcb560652016-08-04 05:20:32 -0700958 ASSERT_TRUE(offer.get() != NULL);
959 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -0700960 f2_.CreateAnswer(offer.get(), opts, NULL));
jbauchcb560652016-08-04 05:20:32 -0700961 const ContentInfo* ac = answer->GetContentByName("audio");
962 const ContentInfo* vc = answer->GetContentByName("video");
963 ASSERT_TRUE(ac != NULL);
964 ASSERT_TRUE(vc == NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800965 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800966 const AudioContentDescription* acd = ac->media_description()->as_audio();
jbauchcb560652016-08-04 05:20:32 -0700967 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
968 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700969 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -0700970 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
971 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700972 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
jbauchcb560652016-08-04 05:20:32 -0700973 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
974}
975
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000976// Create a typical video answer, and ensure it matches what we expect.
977TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
978 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800979 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000980 f1_.set_secure(SEC_ENABLED);
981 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800982 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000983 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800984 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000985 f2_.CreateAnswer(offer.get(), opts, NULL));
986 const ContentInfo* ac = answer->GetContentByName("audio");
987 const ContentInfo* vc = answer->GetContentByName("video");
988 ASSERT_TRUE(ac != NULL);
989 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800990 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
991 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800992 const AudioContentDescription* acd = ac->media_description()->as_audio();
993 const VideoContentDescription* vcd = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000994 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
995 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
996 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -0700997 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000998 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700999 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001000 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1001 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
Yves Gerey665174f2018-06-19 15:03:05 +02001002 EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
1003 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001004 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001005 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
1006}
1007
jbauchcb560652016-08-04 05:20:32 -07001008// Create a typical video answer with GCM ciphers enabled, and ensure it
1009// matches what we expect.
1010TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcm) {
1011 TestVideoGcmCipher(true, true);
1012}
1013
1014// Create a typical video answer with GCM ciphers enabled for the offer only,
1015// and ensure it matches what we expect.
1016TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmOffer) {
1017 TestVideoGcmCipher(true, false);
1018}
1019
1020// Create a typical video answer with GCM ciphers enabled for the answer only,
1021// and ensure it matches what we expect.
1022TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmAnswer) {
1023 TestVideoGcmCipher(false, true);
1024}
1025
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001026TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
zhihuang1c378ed2017-08-17 14:10:50 -07001027 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
Steve Anton4e70a722017-11-28 14:57:10 -08001028 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001029 f1_.set_secure(SEC_ENABLED);
1030 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001031 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001032 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001033 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001034 f2_.CreateAnswer(offer.get(), opts, NULL));
1035 const ContentInfo* ac = answer->GetContentByName("audio");
zstein4b2e0822017-02-17 19:48:38 -08001036 const ContentInfo* dc = answer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001037 ASSERT_TRUE(ac != NULL);
zstein4b2e0822017-02-17 19:48:38 -08001038 ASSERT_TRUE(dc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08001039 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
1040 EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08001041 const AudioContentDescription* acd = ac->media_description()->as_audio();
1042 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001043 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1044 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1045 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -07001046 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001047 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001048 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
zstein4b2e0822017-02-17 19:48:38 -08001049 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1050 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -07001051 EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached
zstein4b2e0822017-02-17 19:48:38 -08001052 EXPECT_TRUE(dcd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001053 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
zstein4b2e0822017-02-17 19:48:38 -08001054 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001055}
1056
jbauchcb560652016-08-04 05:20:32 -07001057TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerGcm) {
zhihuang1c378ed2017-08-17 14:10:50 -07001058 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
Steve Anton4e70a722017-11-28 14:57:10 -08001059 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
jbauchcb560652016-08-04 05:20:32 -07001060 opts.crypto_options.enable_gcm_crypto_suites = true;
1061 f1_.set_secure(SEC_ENABLED);
1062 f2_.set_secure(SEC_ENABLED);
1063 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1064 ASSERT_TRUE(offer.get() != NULL);
1065 std::unique_ptr<SessionDescription> answer(
1066 f2_.CreateAnswer(offer.get(), opts, NULL));
1067 const ContentInfo* ac = answer->GetContentByName("audio");
zstein4b2e0822017-02-17 19:48:38 -08001068 const ContentInfo* dc = answer->GetContentByName("data");
jbauchcb560652016-08-04 05:20:32 -07001069 ASSERT_TRUE(ac != NULL);
zstein4b2e0822017-02-17 19:48:38 -08001070 ASSERT_TRUE(dc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08001071 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
1072 EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08001073 const AudioContentDescription* acd = ac->media_description()->as_audio();
1074 const DataContentDescription* dcd = dc->media_description()->as_data();
jbauchcb560652016-08-04 05:20:32 -07001075 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1076 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1077 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -07001078 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -07001079 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001080 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
zstein4b2e0822017-02-17 19:48:38 -08001081 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1082 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -07001083 EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached
zstein4b2e0822017-02-17 19:48:38 -08001084 EXPECT_TRUE(dcd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001085 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuiteGcm);
zstein4b2e0822017-02-17 19:48:38 -08001086 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
1087}
1088
1089// The use_sctpmap flag should be set in a DataContentDescription by default.
1090// The answer's use_sctpmap flag should match the offer's.
1091TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerUsesSctpmap) {
1092 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001093 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
zstein4b2e0822017-02-17 19:48:38 -08001094 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1095 ASSERT_TRUE(offer.get() != NULL);
1096 ContentInfo* dc_offer = offer->GetContentByName("data");
1097 ASSERT_TRUE(dc_offer != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001098 DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
zstein4b2e0822017-02-17 19:48:38 -08001099 EXPECT_TRUE(dcd_offer->use_sctpmap());
1100
1101 std::unique_ptr<SessionDescription> answer(
1102 f2_.CreateAnswer(offer.get(), opts, NULL));
1103 const ContentInfo* dc_answer = answer->GetContentByName("data");
1104 ASSERT_TRUE(dc_answer != NULL);
1105 const DataContentDescription* dcd_answer =
Steve Antonb1c1de12017-12-21 15:14:30 -08001106 dc_answer->media_description()->as_data();
zstein4b2e0822017-02-17 19:48:38 -08001107 EXPECT_TRUE(dcd_answer->use_sctpmap());
1108}
1109
1110// The answer's use_sctpmap flag should match the offer's.
1111TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerWithoutSctpmap) {
1112 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001113 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
zstein4b2e0822017-02-17 19:48:38 -08001114 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1115 ASSERT_TRUE(offer.get() != NULL);
1116 ContentInfo* dc_offer = offer->GetContentByName("data");
1117 ASSERT_TRUE(dc_offer != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001118 DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
zstein4b2e0822017-02-17 19:48:38 -08001119 dcd_offer->set_use_sctpmap(false);
1120
1121 std::unique_ptr<SessionDescription> answer(
1122 f2_.CreateAnswer(offer.get(), opts, NULL));
1123 const ContentInfo* dc_answer = answer->GetContentByName("data");
1124 ASSERT_TRUE(dc_answer != NULL);
1125 const DataContentDescription* dcd_answer =
Steve Antonb1c1de12017-12-21 15:14:30 -08001126 dc_answer->media_description()->as_data();
zstein4b2e0822017-02-17 19:48:38 -08001127 EXPECT_FALSE(dcd_answer->use_sctpmap());
jbauchcb560652016-08-04 05:20:32 -07001128}
1129
deadbeef8b7e9ad2017-05-25 09:38:55 -07001130// Test that a valid answer will be created for "DTLS/SCTP", "UDP/DTLS/SCTP"
1131// and "TCP/DTLS/SCTP" offers.
1132TEST_F(MediaSessionDescriptionFactoryTest,
1133 TestCreateDataAnswerToDifferentOfferedProtos) {
1134 // Need to enable DTLS offer/answer generation (disabled by default in this
1135 // test).
1136 f1_.set_secure(SEC_ENABLED);
1137 f2_.set_secure(SEC_ENABLED);
1138 tdf1_.set_secure(SEC_ENABLED);
1139 tdf2_.set_secure(SEC_ENABLED);
1140
1141 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001142 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
deadbeef8b7e9ad2017-05-25 09:38:55 -07001143 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
1144 ASSERT_TRUE(offer.get() != nullptr);
1145 ContentInfo* dc_offer = offer->GetContentByName("data");
1146 ASSERT_TRUE(dc_offer != nullptr);
Steve Antonb1c1de12017-12-21 15:14:30 -08001147 DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
deadbeef8b7e9ad2017-05-25 09:38:55 -07001148
1149 std::vector<std::string> protos = {"DTLS/SCTP", "UDP/DTLS/SCTP",
1150 "TCP/DTLS/SCTP"};
1151 for (const std::string& proto : protos) {
1152 dcd_offer->set_protocol(proto);
1153 std::unique_ptr<SessionDescription> answer(
1154 f2_.CreateAnswer(offer.get(), opts, nullptr));
1155 const ContentInfo* dc_answer = answer->GetContentByName("data");
1156 ASSERT_TRUE(dc_answer != nullptr);
1157 const DataContentDescription* dcd_answer =
Steve Antonb1c1de12017-12-21 15:14:30 -08001158 dc_answer->media_description()->as_data();
deadbeef8b7e9ad2017-05-25 09:38:55 -07001159 EXPECT_FALSE(dc_answer->rejected);
1160 EXPECT_EQ(proto, dcd_answer->protocol());
1161 }
1162}
1163
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001164// Verifies that the order of the media contents in the offer is preserved in
1165// the answer.
1166TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
1167 MediaSessionOptions opts;
1168
1169 // Creates a data only offer.
Steve Anton4e70a722017-11-28 14:57:10 -08001170 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
kwiberg31022942016-03-11 14:18:21 -08001171 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001172 ASSERT_TRUE(offer1.get() != NULL);
1173
1174 // Appends audio to the offer.
Steve Anton4e70a722017-11-28 14:57:10 -08001175 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1176 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001177 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001178 f1_.CreateOffer(opts, offer1.get()));
1179 ASSERT_TRUE(offer2.get() != NULL);
1180
1181 // Appends video to the offer.
Steve Anton4e70a722017-11-28 14:57:10 -08001182 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1183 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001184 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001185 f1_.CreateOffer(opts, offer2.get()));
1186 ASSERT_TRUE(offer3.get() != NULL);
1187
kwiberg31022942016-03-11 14:18:21 -08001188 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001189 f2_.CreateAnswer(offer3.get(), opts, NULL));
1190 ASSERT_TRUE(answer.get() != NULL);
1191 EXPECT_EQ(3u, answer->contents().size());
1192 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
1193 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
1194 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
1195}
1196
ossu075af922016-06-14 03:29:38 -07001197// TODO(deadbeef): Extend these tests to ensure the correct direction with other
1198// answerer settings.
1199
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001200// This test that the media direction is set to send/receive in an answer if
1201// the offer is send receive.
1202TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001203 TestMediaDirectionInAnswer(RtpTransceiverDirection::kSendRecv,
1204 RtpTransceiverDirection::kSendRecv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001205}
1206
1207// This test that the media direction is set to receive only in an answer if
1208// the offer is send only.
1209TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001210 TestMediaDirectionInAnswer(RtpTransceiverDirection::kSendOnly,
1211 RtpTransceiverDirection::kRecvOnly);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001212}
1213
1214// This test that the media direction is set to send only in an answer if
1215// the offer is recv only.
1216TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001217 TestMediaDirectionInAnswer(RtpTransceiverDirection::kRecvOnly,
1218 RtpTransceiverDirection::kSendOnly);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001219}
1220
1221// This test that the media direction is set to inactive in an answer if
1222// the offer is inactive.
1223TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001224 TestMediaDirectionInAnswer(RtpTransceiverDirection::kInactive,
1225 RtpTransceiverDirection::kInactive);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001226}
1227
1228// Test that a data content with an unknown protocol is rejected in an answer.
1229TEST_F(MediaSessionDescriptionFactoryTest,
1230 CreateDataAnswerToOfferWithUnknownProtocol) {
1231 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001232 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001233 f1_.set_secure(SEC_ENABLED);
1234 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001235 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
terelius8c011e52016-04-26 05:28:11 -07001236 ContentInfo* dc_offer = offer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001237 ASSERT_TRUE(dc_offer != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001238 DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001239 ASSERT_TRUE(dcd_offer != NULL);
1240 std::string protocol = "a weird unknown protocol";
1241 dcd_offer->set_protocol(protocol);
1242
kwiberg31022942016-03-11 14:18:21 -08001243 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001244 f2_.CreateAnswer(offer.get(), opts, NULL));
1245
1246 const ContentInfo* dc_answer = answer->GetContentByName("data");
1247 ASSERT_TRUE(dc_answer != NULL);
1248 EXPECT_TRUE(dc_answer->rejected);
1249 const DataContentDescription* dcd_answer =
Steve Antonb1c1de12017-12-21 15:14:30 -08001250 dc_answer->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001251 ASSERT_TRUE(dcd_answer != NULL);
1252 EXPECT_EQ(protocol, dcd_answer->protocol());
1253}
1254
1255// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
1256TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
zhihuang1c378ed2017-08-17 14:10:50 -07001257 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001258 f1_.set_secure(SEC_DISABLED);
1259 f2_.set_secure(SEC_DISABLED);
1260 tdf1_.set_secure(SEC_DISABLED);
1261 tdf2_.set_secure(SEC_DISABLED);
1262
kwiberg31022942016-03-11 14:18:21 -08001263 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001264 const AudioContentDescription* offer_acd =
1265 GetFirstAudioContentDescription(offer.get());
1266 ASSERT_TRUE(offer_acd != NULL);
1267 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
1268
kwiberg31022942016-03-11 14:18:21 -08001269 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001270 f2_.CreateAnswer(offer.get(), opts, NULL));
1271
1272 const ContentInfo* ac_answer = answer->GetContentByName("audio");
1273 ASSERT_TRUE(ac_answer != NULL);
1274 EXPECT_FALSE(ac_answer->rejected);
1275
1276 const AudioContentDescription* answer_acd =
1277 GetFirstAudioContentDescription(answer.get());
1278 ASSERT_TRUE(answer_acd != NULL);
1279 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
1280}
1281
1282// Create a video offer and answer and ensure the RTP header extensions
1283// matches what we expect.
1284TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
1285 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001286 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001287 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1288 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1289 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1290 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1291
kwiberg31022942016-03-11 14:18:21 -08001292 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001293 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001294 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001295 f2_.CreateAnswer(offer.get(), opts, NULL));
1296
Yves Gerey665174f2018-06-19 15:03:05 +02001297 EXPECT_EQ(
1298 MAKE_VECTOR(kAudioRtpExtension1),
1299 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1300 EXPECT_EQ(
1301 MAKE_VECTOR(kVideoRtpExtension1),
1302 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1303 EXPECT_EQ(
1304 MAKE_VECTOR(kAudioRtpExtensionAnswer),
1305 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1306 EXPECT_EQ(
1307 MAKE_VECTOR(kVideoRtpExtensionAnswer),
1308 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001309}
1310
jbauch5869f502017-06-29 12:31:36 -07001311TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02001312 TestOfferAnswerWithEncryptedRtpExtensionsBoth) {
jbauch5869f502017-06-29 12:31:36 -07001313 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001314 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07001315
1316 f1_.set_enable_encrypted_rtp_header_extensions(true);
1317 f2_.set_enable_encrypted_rtp_header_extensions(true);
1318
Yves Gerey665174f2018-06-19 15:03:05 +02001319 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1320 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1321 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1322 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
jbauch5869f502017-06-29 12:31:36 -07001323
1324 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1325 ASSERT_TRUE(offer.get() != NULL);
1326 std::unique_ptr<SessionDescription> answer(
1327 f2_.CreateAnswer(offer.get(), opts, NULL));
1328
Yves Gerey665174f2018-06-19 15:03:05 +02001329 EXPECT_EQ(
1330 MAKE_VECTOR(kAudioRtpExtensionEncrypted1),
1331 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1332 EXPECT_EQ(
1333 MAKE_VECTOR(kVideoRtpExtensionEncrypted1),
1334 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1335 EXPECT_EQ(
1336 MAKE_VECTOR(kAudioRtpExtensionEncryptedAnswer),
1337 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1338 EXPECT_EQ(
1339 MAKE_VECTOR(kVideoRtpExtensionEncryptedAnswer),
1340 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07001341}
1342
1343TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02001344 TestOfferAnswerWithEncryptedRtpExtensionsOffer) {
jbauch5869f502017-06-29 12:31:36 -07001345 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001346 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07001347
1348 f1_.set_enable_encrypted_rtp_header_extensions(true);
1349
Yves Gerey665174f2018-06-19 15:03:05 +02001350 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1351 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1352 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1353 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
jbauch5869f502017-06-29 12:31:36 -07001354
1355 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1356 ASSERT_TRUE(offer.get() != NULL);
1357 std::unique_ptr<SessionDescription> answer(
1358 f2_.CreateAnswer(offer.get(), opts, NULL));
1359
Yves Gerey665174f2018-06-19 15:03:05 +02001360 EXPECT_EQ(
1361 MAKE_VECTOR(kAudioRtpExtensionEncrypted1),
1362 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1363 EXPECT_EQ(
1364 MAKE_VECTOR(kVideoRtpExtensionEncrypted1),
1365 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1366 EXPECT_EQ(
1367 MAKE_VECTOR(kAudioRtpExtensionAnswer),
1368 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1369 EXPECT_EQ(
1370 MAKE_VECTOR(kVideoRtpExtensionAnswer),
1371 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07001372}
1373
1374TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02001375 TestOfferAnswerWithEncryptedRtpExtensionsAnswer) {
jbauch5869f502017-06-29 12:31:36 -07001376 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001377 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07001378
1379 f2_.set_enable_encrypted_rtp_header_extensions(true);
1380
Yves Gerey665174f2018-06-19 15:03:05 +02001381 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1382 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1383 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1384 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
jbauch5869f502017-06-29 12:31:36 -07001385
1386 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1387 ASSERT_TRUE(offer.get() != NULL);
1388 std::unique_ptr<SessionDescription> answer(
1389 f2_.CreateAnswer(offer.get(), opts, NULL));
1390
Yves Gerey665174f2018-06-19 15:03:05 +02001391 EXPECT_EQ(
1392 MAKE_VECTOR(kAudioRtpExtension1),
1393 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1394 EXPECT_EQ(
1395 MAKE_VECTOR(kVideoRtpExtension1),
1396 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1397 EXPECT_EQ(
1398 MAKE_VECTOR(kAudioRtpExtensionAnswer),
1399 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1400 EXPECT_EQ(
1401 MAKE_VECTOR(kVideoRtpExtensionAnswer),
1402 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07001403}
1404
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001405// Create an audio, video, data answer without legacy StreamParams.
1406TEST_F(MediaSessionDescriptionFactoryTest,
1407 TestCreateAnswerWithoutLegacyStreams) {
1408 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001409 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1410 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
kwiberg31022942016-03-11 14:18:21 -08001411 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001412 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001413 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001414 f2_.CreateAnswer(offer.get(), opts, NULL));
1415 const ContentInfo* ac = answer->GetContentByName("audio");
1416 const ContentInfo* vc = answer->GetContentByName("video");
1417 const ContentInfo* dc = answer->GetContentByName("data");
1418 ASSERT_TRUE(ac != NULL);
1419 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001420 const AudioContentDescription* acd = ac->media_description()->as_audio();
1421 const VideoContentDescription* vcd = vc->media_description()->as_video();
1422 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001423
1424 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1425 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1426 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1427}
1428
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001429// Create a typical video answer, and ensure it matches what we expect.
1430TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1431 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001432 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &offer_opts);
1433 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv,
1434 &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001435
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001436 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001437 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &answer_opts);
1438 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv,
1439 &answer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001440
kwiberg31022942016-03-11 14:18:21 -08001441 std::unique_ptr<SessionDescription> offer;
1442 std::unique_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001443
1444 offer_opts.rtcp_mux_enabled = true;
1445 answer_opts.rtcp_mux_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001446 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1447 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1448 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1449 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1450 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1451 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1452 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1453 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1454 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1455 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1456 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1457 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1458 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1459 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1460
1461 offer_opts.rtcp_mux_enabled = true;
1462 answer_opts.rtcp_mux_enabled = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001463 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1464 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1465 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1466 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1467 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1468 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1469 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1470 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1471 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1472 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1473 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1474 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1475 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1476 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1477
1478 offer_opts.rtcp_mux_enabled = false;
1479 answer_opts.rtcp_mux_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001480 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1481 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1482 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1483 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1484 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1485 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1486 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1487 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1488 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1489 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1490 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1491 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1492 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1493 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1494
1495 offer_opts.rtcp_mux_enabled = false;
1496 answer_opts.rtcp_mux_enabled = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001497 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1498 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1499 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1500 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1501 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1502 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1503 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1504 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1505 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1506 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1507 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1508 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1509 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1510 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1511}
1512
1513// Create an audio-only answer to a video offer.
1514TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1515 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001516 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1517 kActive, &opts);
1518 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1519 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001520 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001521 ASSERT_TRUE(offer.get() != NULL);
zhihuang1c378ed2017-08-17 14:10:50 -07001522
1523 opts.media_description_options[1].stopped = true;
kwiberg31022942016-03-11 14:18:21 -08001524 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001525 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001526 const ContentInfo* ac = answer->GetContentByName("audio");
1527 const ContentInfo* vc = answer->GetContentByName("video");
1528 ASSERT_TRUE(ac != NULL);
1529 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001530 ASSERT_TRUE(vc->media_description() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001531 EXPECT_TRUE(vc->rejected);
1532}
1533
1534// Create an audio-only answer to an offer with data.
1535TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07001536 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001537 opts.data_channel_type = cricket::DCT_RTP;
Steve Anton4e70a722017-11-28 14:57:10 -08001538 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kRecvOnly,
1539 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001540 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001541 ASSERT_TRUE(offer.get() != NULL);
zhihuang1c378ed2017-08-17 14:10:50 -07001542
1543 opts.media_description_options[1].stopped = true;
kwiberg31022942016-03-11 14:18:21 -08001544 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001545 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546 const ContentInfo* ac = answer->GetContentByName("audio");
1547 const ContentInfo* dc = answer->GetContentByName("data");
1548 ASSERT_TRUE(ac != NULL);
1549 ASSERT_TRUE(dc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001550 ASSERT_TRUE(dc->media_description() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001551 EXPECT_TRUE(dc->rejected);
1552}
1553
1554// Create an answer that rejects the contents which are rejected in the offer.
1555TEST_F(MediaSessionDescriptionFactoryTest,
1556 CreateAnswerToOfferWithRejectedMedia) {
1557 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001558 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1559 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
kwiberg31022942016-03-11 14:18:21 -08001560 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001561 ASSERT_TRUE(offer.get() != NULL);
1562 ContentInfo* ac = offer->GetContentByName("audio");
1563 ContentInfo* vc = offer->GetContentByName("video");
1564 ContentInfo* dc = offer->GetContentByName("data");
1565 ASSERT_TRUE(ac != NULL);
1566 ASSERT_TRUE(vc != NULL);
1567 ASSERT_TRUE(dc != NULL);
1568 ac->rejected = true;
1569 vc->rejected = true;
1570 dc->rejected = true;
kwiberg31022942016-03-11 14:18:21 -08001571 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001572 f2_.CreateAnswer(offer.get(), opts, NULL));
1573 ac = answer->GetContentByName("audio");
1574 vc = answer->GetContentByName("video");
1575 dc = answer->GetContentByName("data");
1576 ASSERT_TRUE(ac != NULL);
1577 ASSERT_TRUE(vc != NULL);
1578 ASSERT_TRUE(dc != NULL);
1579 EXPECT_TRUE(ac->rejected);
1580 EXPECT_TRUE(vc->rejected);
1581 EXPECT_TRUE(dc->rejected);
1582}
1583
1584// Create an audio and video offer with:
1585// - one video track
1586// - two audio tracks
1587// - two data tracks
1588// and ensure it matches what we expect. Also updates the initial offer by
1589// adding a new video track and replaces one of the audio tracks.
1590TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1591 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001592 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001593 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001594 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001595 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001596 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001597 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001598 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001599
Steve Anton4e70a722017-11-28 14:57:10 -08001600 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001601 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001602 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001603 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001604 {kMediaStream1}, 1, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001605
1606 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001607 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001608
1609 ASSERT_TRUE(offer.get() != NULL);
1610 const ContentInfo* ac = offer->GetContentByName("audio");
1611 const ContentInfo* vc = offer->GetContentByName("video");
1612 const ContentInfo* dc = offer->GetContentByName("data");
1613 ASSERT_TRUE(ac != NULL);
1614 ASSERT_TRUE(vc != NULL);
1615 ASSERT_TRUE(dc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001616 const AudioContentDescription* acd = ac->media_description()->as_audio();
1617 const VideoContentDescription* vcd = vc->media_description()->as_video();
1618 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001619 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -07001620 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001621
1622 const StreamParamsVec& audio_streams = acd->streams();
1623 ASSERT_EQ(2U, audio_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001624 EXPECT_EQ(audio_streams[0].cname, audio_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001625 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1626 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1627 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1628 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1629 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1630 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1631
1632 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1633 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001634 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001635
1636 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1637 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001638 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001639
1640 const StreamParamsVec& video_streams = vcd->streams();
1641 ASSERT_EQ(1U, video_streams.size());
1642 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1643 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1644 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1645 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1646
1647 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1648 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001649 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001650
1651 const StreamParamsVec& data_streams = dcd->streams();
1652 ASSERT_EQ(2U, data_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001653 EXPECT_EQ(data_streams[0].cname, data_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001654 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1655 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1656 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1657 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1658 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1659 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1660
1661 EXPECT_EQ(cricket::kDataMaxBandwidth,
Yves Gerey665174f2018-06-19 15:03:05 +02001662 dcd->bandwidth()); // default bandwidth (auto)
1663 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001664 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001665
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001666 // Update the offer. Add a new video track that is not synched to the
1667 // other tracks and replace audio track 2 with audio track 3.
zhihuang1c378ed2017-08-17 14:10:50 -07001668 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001669 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001670 DetachSenderFromMediaSection("audio", kAudioTrack2, &opts);
1671 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack3,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001672 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001673 DetachSenderFromMediaSection("data", kDataTrack2, &opts);
1674 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack3,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001675 {kMediaStream1}, 1, &opts);
kwiberg31022942016-03-11 14:18:21 -08001676 std::unique_ptr<SessionDescription> updated_offer(
1677 f1_.CreateOffer(opts, offer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001678
1679 ASSERT_TRUE(updated_offer.get() != NULL);
1680 ac = updated_offer->GetContentByName("audio");
1681 vc = updated_offer->GetContentByName("video");
1682 dc = updated_offer->GetContentByName("data");
1683 ASSERT_TRUE(ac != NULL);
1684 ASSERT_TRUE(vc != NULL);
1685 ASSERT_TRUE(dc != NULL);
1686 const AudioContentDescription* updated_acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001687 ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001688 const VideoContentDescription* updated_vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001689 vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001690 const DataContentDescription* updated_dcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001691 dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001692
1693 EXPECT_EQ(acd->type(), updated_acd->type());
1694 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1695 EXPECT_EQ(vcd->type(), updated_vcd->type());
1696 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1697 EXPECT_EQ(dcd->type(), updated_dcd->type());
1698 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001699 ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001700 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001701 ASSERT_CRYPTO(updated_vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001702 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001703 ASSERT_CRYPTO(updated_dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001704 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1705
1706 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1707 ASSERT_EQ(2U, updated_audio_streams.size());
1708 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1709 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1710 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1711 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1712 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1713
1714 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1715 ASSERT_EQ(2U, updated_video_streams.size());
1716 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1717 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001718 // All the media streams in one PeerConnection share one RTCP CNAME.
1719 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001720
1721 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1722 ASSERT_EQ(2U, updated_data_streams.size());
1723 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1724 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1725 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1726 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1727 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
zhihuang8f65cdf2016-05-06 18:40:30 -07001728 // The stream correctly got the CNAME from the MediaSessionOptions.
1729 // The Expected RTCP CNAME is the default one as we are using the default
1730 // MediaSessionOptions.
1731 EXPECT_EQ(updated_data_streams[0].cname, cricket::kDefaultRtcpCname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001732}
1733
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001734// Create an offer with simulcast video stream.
1735TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1736 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001737 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1738 kActive, &opts);
1739 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
1740 kActive, &opts);
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001741 const int num_sim_layers = 3;
zhihuang1c378ed2017-08-17 14:10:50 -07001742 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001743 {kMediaStream1}, num_sim_layers, &opts);
kwiberg31022942016-03-11 14:18:21 -08001744 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001745
1746 ASSERT_TRUE(offer.get() != NULL);
1747 const ContentInfo* vc = offer->GetContentByName("video");
1748 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001749 const VideoContentDescription* vcd = vc->media_description()->as_video();
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001750
1751 const StreamParamsVec& video_streams = vcd->streams();
1752 ASSERT_EQ(1U, video_streams.size());
1753 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1754 const SsrcGroup* sim_ssrc_group =
1755 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1756 ASSERT_TRUE(sim_ssrc_group != NULL);
1757 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1758}
1759
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001760// Create an audio and video answer to a standard video offer with:
1761// - one video track
1762// - two audio tracks
1763// - two data tracks
1764// and ensure it matches what we expect. Also updates the initial answer by
1765// adding a new video track and removes one of the audio tracks.
1766TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1767 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001768 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1769 kActive, &offer_opts);
1770 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1771 kActive, &offer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001772 offer_opts.data_channel_type = cricket::DCT_RTP;
Steve Anton4e70a722017-11-28 14:57:10 -08001773 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kRecvOnly,
1774 kActive, &offer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001775 f1_.set_secure(SEC_ENABLED);
1776 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001777 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001778
zhihuang1c378ed2017-08-17 14:10:50 -07001779 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001780 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
1781 kActive, &answer_opts);
1782 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
1783 kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001784 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001785 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001786 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001787 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001788 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001789 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001790
Steve Anton4e70a722017-11-28 14:57:10 -08001791 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kSendRecv,
1792 kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001793 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001794 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001795 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001796 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001797 answer_opts.data_channel_type = cricket::DCT_RTP;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001798
kwiberg31022942016-03-11 14:18:21 -08001799 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001800 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001801
1802 ASSERT_TRUE(answer.get() != NULL);
1803 const ContentInfo* ac = answer->GetContentByName("audio");
1804 const ContentInfo* vc = answer->GetContentByName("video");
1805 const ContentInfo* dc = answer->GetContentByName("data");
1806 ASSERT_TRUE(ac != NULL);
1807 ASSERT_TRUE(vc != NULL);
1808 ASSERT_TRUE(dc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001809 const AudioContentDescription* acd = ac->media_description()->as_audio();
1810 const VideoContentDescription* vcd = vc->media_description()->as_video();
1811 const DataContentDescription* dcd = dc->media_description()->as_data();
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001812 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
1813 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
1814 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001815
1816 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1817 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1818
1819 const StreamParamsVec& audio_streams = acd->streams();
1820 ASSERT_EQ(2U, audio_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001821 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001822 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1823 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1824 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1825 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1826 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1827 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1828
1829 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1830 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1831
1832 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1833 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1834
1835 const StreamParamsVec& video_streams = vcd->streams();
1836 ASSERT_EQ(1U, video_streams.size());
1837 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1838 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1839 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1840 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1841
1842 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1843 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1844
1845 const StreamParamsVec& data_streams = dcd->streams();
1846 ASSERT_EQ(2U, data_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001847 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001848 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1849 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1850 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1851 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1852 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1853 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1854
1855 EXPECT_EQ(cricket::kDataMaxBandwidth,
Yves Gerey665174f2018-06-19 15:03:05 +02001856 dcd->bandwidth()); // default bandwidth (auto)
1857 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001858
1859 // Update the answer. Add a new video track that is not synched to the
zhihuang8f65cdf2016-05-06 18:40:30 -07001860 // other tracks and remove 1 audio track.
zhihuang1c378ed2017-08-17 14:10:50 -07001861 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001862 {kMediaStream2}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001863 DetachSenderFromMediaSection("audio", kAudioTrack2, &answer_opts);
1864 DetachSenderFromMediaSection("data", kDataTrack2, &answer_opts);
kwiberg31022942016-03-11 14:18:21 -08001865 std::unique_ptr<SessionDescription> updated_answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001866 f2_.CreateAnswer(offer.get(), answer_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001867
1868 ASSERT_TRUE(updated_answer.get() != NULL);
1869 ac = updated_answer->GetContentByName("audio");
1870 vc = updated_answer->GetContentByName("video");
1871 dc = updated_answer->GetContentByName("data");
1872 ASSERT_TRUE(ac != NULL);
1873 ASSERT_TRUE(vc != NULL);
1874 ASSERT_TRUE(dc != NULL);
1875 const AudioContentDescription* updated_acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001876 ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001877 const VideoContentDescription* updated_vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001878 vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001879 const DataContentDescription* updated_dcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001880 dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001881
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001882 ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001883 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001884 ASSERT_CRYPTO(updated_vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001885 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001886 ASSERT_CRYPTO(updated_dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001887 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1888
1889 EXPECT_EQ(acd->type(), updated_acd->type());
1890 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1891 EXPECT_EQ(vcd->type(), updated_vcd->type());
1892 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1893 EXPECT_EQ(dcd->type(), updated_dcd->type());
1894 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1895
1896 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1897 ASSERT_EQ(1U, updated_audio_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001898 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001899
1900 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1901 ASSERT_EQ(2U, updated_video_streams.size());
1902 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1903 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001904 // All media streams in one PeerConnection share one CNAME.
1905 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001906
1907 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1908 ASSERT_EQ(1U, updated_data_streams.size());
1909 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1910}
1911
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001912// Create an updated offer after creating an answer to the original offer and
1913// verify that the codecs that were part of the original answer are not changed
1914// in the updated offer.
1915TEST_F(MediaSessionDescriptionFactoryTest,
1916 RespondentCreatesOfferAfterCreatingAnswer) {
1917 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001918 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001919
kwiberg31022942016-03-11 14:18:21 -08001920 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1921 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001922 f2_.CreateAnswer(offer.get(), opts, NULL));
1923
1924 const AudioContentDescription* acd =
1925 GetFirstAudioContentDescription(answer.get());
1926 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1927
1928 const VideoContentDescription* vcd =
1929 GetFirstVideoContentDescription(answer.get());
1930 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1931
kwiberg31022942016-03-11 14:18:21 -08001932 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001933 f2_.CreateOffer(opts, answer.get()));
1934
1935 // The expected audio codecs are the common audio codecs from the first
1936 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1937 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001938 // TODO(wu): |updated_offer| should not include the codec
1939 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001940 const AudioCodec kUpdatedAudioCodecOffer[] = {
Yves Gerey665174f2018-06-19 15:03:05 +02001941 kAudioCodecsAnswer[0], kAudioCodecsAnswer[1], kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001942 };
1943
1944 // The expected video codecs are the common video codecs from the first
1945 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1946 // preference order.
1947 const VideoCodec kUpdatedVideoCodecOffer[] = {
Yves Gerey665174f2018-06-19 15:03:05 +02001948 kVideoCodecsAnswer[0], kVideoCodecs2[1],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001949 };
1950
1951 const AudioContentDescription* updated_acd =
1952 GetFirstAudioContentDescription(updated_offer.get());
1953 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1954
1955 const VideoContentDescription* updated_vcd =
1956 GetFirstVideoContentDescription(updated_offer.get());
1957 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1958}
1959
1960// Create an updated offer after creating an answer to the original offer and
1961// verify that the codecs that were part of the original answer are not changed
1962// in the updated offer. In this test Rtx is enabled.
1963TEST_F(MediaSessionDescriptionFactoryTest,
1964 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1965 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001966 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1967 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001968 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001969 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001970 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001971 f1_.set_video_codecs(f1_codecs);
1972
1973 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001974 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001975 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001976 f2_.set_video_codecs(f2_codecs);
1977
kwiberg31022942016-03-11 14:18:21 -08001978 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001979 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001980 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001981 f2_.CreateAnswer(offer.get(), opts, NULL));
1982
1983 const VideoContentDescription* vcd =
1984 GetFirstVideoContentDescription(answer.get());
1985
1986 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001987 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1988 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001989
1990 EXPECT_EQ(expected_codecs, vcd->codecs());
1991
deadbeef67cf2c12016-04-13 10:07:16 -07001992 // Now, make sure we get same result (except for the order) if |f2_| creates
1993 // an updated offer even though the default payload types between |f1_| and
1994 // |f2_| are different.
kwiberg31022942016-03-11 14:18:21 -08001995 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001996 f2_.CreateOffer(opts, answer.get()));
1997 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001998 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001999 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
2000
2001 const VideoContentDescription* updated_vcd =
2002 GetFirstVideoContentDescription(updated_answer.get());
2003
2004 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
2005}
2006
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002007// Regression test for:
2008// https://bugs.chromium.org/p/webrtc/issues/detail?id=8332
2009// Existing codecs should always appear before new codecs in re-offers. But
2010// under a specific set of circumstances, the existing RTX codec was ending up
2011// added to the end of the list.
2012TEST_F(MediaSessionDescriptionFactoryTest,
2013 RespondentCreatesOfferAfterCreatingAnswerWithRemappedRtxPayloadType) {
2014 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002015 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2016 kActive, &opts);
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002017 // We specifically choose different preferred payload types for VP8 to
2018 // trigger the issue.
2019 cricket::VideoCodec vp8_offerer(100, "VP8");
2020 cricket::VideoCodec vp8_offerer_rtx =
2021 VideoCodec::CreateRtxCodec(101, vp8_offerer.id);
2022 cricket::VideoCodec vp8_answerer(110, "VP8");
2023 cricket::VideoCodec vp8_answerer_rtx =
2024 VideoCodec::CreateRtxCodec(111, vp8_answerer.id);
2025 cricket::VideoCodec vp9(120, "VP9");
2026 cricket::VideoCodec vp9_rtx = VideoCodec::CreateRtxCodec(121, vp9.id);
2027
2028 std::vector<VideoCodec> f1_codecs = {vp8_offerer, vp8_offerer_rtx};
2029 // We also specifically cause the answerer to prefer VP9, such that if it
2030 // *doesn't* honor the existing preferred codec (VP8) we'll notice.
2031 std::vector<VideoCodec> f2_codecs = {vp9, vp9_rtx, vp8_answerer,
2032 vp8_answerer_rtx};
2033
2034 f1_.set_video_codecs(f1_codecs);
2035 f2_.set_video_codecs(f2_codecs);
2036 std::vector<AudioCodec> audio_codecs;
2037 f1_.set_audio_codecs(audio_codecs, audio_codecs);
2038 f2_.set_audio_codecs(audio_codecs, audio_codecs);
2039
2040 // Offer will be {VP8, RTX for VP8}. Answer will be the same.
2041 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2042 ASSERT_TRUE(offer.get() != NULL);
2043 std::unique_ptr<SessionDescription> answer(
2044 f2_.CreateAnswer(offer.get(), opts, NULL));
2045
2046 // Updated offer *should* be {VP8, RTX for VP8, VP9, RTX for VP9}.
2047 // But if the bug is triggered, RTX for VP8 ends up last.
2048 std::unique_ptr<SessionDescription> updated_offer(
2049 f2_.CreateOffer(opts, answer.get()));
2050
2051 const VideoContentDescription* vcd =
2052 GetFirstVideoContentDescription(updated_offer.get());
2053 std::vector<cricket::VideoCodec> codecs = vcd->codecs();
2054 ASSERT_EQ(4u, codecs.size());
2055 EXPECT_EQ(vp8_offerer, codecs[0]);
2056 EXPECT_EQ(vp8_offerer_rtx, codecs[1]);
2057 EXPECT_EQ(vp9, codecs[2]);
2058 EXPECT_EQ(vp9_rtx, codecs[3]);
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002059}
2060
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002061// Create an updated offer that adds video after creating an audio only answer
2062// to the original offer. This test verifies that if a video codec and the RTX
2063// codec have the same default payload type as an audio codec that is already in
2064// use, the added codecs payload types are changed.
2065TEST_F(MediaSessionDescriptionFactoryTest,
2066 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
2067 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002068 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002069 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002070 f1_.set_video_codecs(f1_codecs);
2071
2072 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002073 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2074 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002075
kwiberg31022942016-03-11 14:18:21 -08002076 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2077 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002078 f2_.CreateAnswer(offer.get(), opts, NULL));
2079
2080 const AudioContentDescription* acd =
2081 GetFirstAudioContentDescription(answer.get());
2082 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
2083
2084 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
2085 // reference be the same as an audio codec that was negotiated in the
2086 // first offer/answer exchange.
zhihuang1c378ed2017-08-17 14:10:50 -07002087 opts.media_description_options.clear();
Steve Anton4e70a722017-11-28 14:57:10 -08002088 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002089
2090 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2091 int used_pl_type = acd->codecs()[0].id;
2092 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002093 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002094 f2_.set_video_codecs(f2_codecs);
2095
kwiberg31022942016-03-11 14:18:21 -08002096 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002097 f2_.CreateOffer(opts, answer.get()));
2098 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08002099 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002100 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
2101
2102 const AudioContentDescription* updated_acd =
2103 GetFirstAudioContentDescription(answer.get());
2104 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
2105
2106 const VideoContentDescription* updated_vcd =
2107 GetFirstVideoContentDescription(updated_answer.get());
2108
2109 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00002110 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
Yves Gerey665174f2018-06-19 15:03:05 +02002111 int new_h264_pl_type = updated_vcd->codecs()[0].id;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002112 EXPECT_NE(used_pl_type, new_h264_pl_type);
2113 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002114 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002115 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
2116 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
2117}
2118
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002119// Create an updated offer with RTX after creating an answer to an offer
2120// without RTX, and with different default payload types.
2121// Verify that the added RTX codec references the correct payload type.
2122TEST_F(MediaSessionDescriptionFactoryTest,
2123 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
2124 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002125 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002126
2127 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2128 // This creates rtx for H264 with the payload type |f2_| uses.
2129 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
2130 f2_.set_video_codecs(f2_codecs);
2131
kwiberg31022942016-03-11 14:18:21 -08002132 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002133 ASSERT_TRUE(offer.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08002134 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002135 f2_.CreateAnswer(offer.get(), opts, nullptr));
2136
2137 const VideoContentDescription* vcd =
2138 GetFirstVideoContentDescription(answer.get());
2139
2140 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2141 EXPECT_EQ(expected_codecs, vcd->codecs());
2142
2143 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
2144 // updated offer, even though the default payload types are different from
2145 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08002146 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002147 f2_.CreateOffer(opts, answer.get()));
2148 ASSERT_TRUE(updated_offer);
2149
2150 const VideoContentDescription* updated_vcd =
2151 GetFirstVideoContentDescription(updated_offer.get());
2152
2153 // New offer should attempt to add H263, and RTX for H264.
2154 expected_codecs.push_back(kVideoCodecs2[1]);
2155 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
2156 &expected_codecs);
2157 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
2158}
2159
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002160// Test that RTX is ignored when there is no associated payload type parameter.
2161TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
2162 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002163 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2164 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002165 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002166 // This creates RTX without associated payload type parameter.
perkj26752742016-10-24 01:21:16 -07002167 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002168 f1_.set_video_codecs(f1_codecs);
2169
2170 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002171 // This creates RTX for H264 with the payload type |f2_| uses.
2172 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002173 f2_.set_video_codecs(f2_codecs);
2174
kwiberg31022942016-03-11 14:18:21 -08002175 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002176 ASSERT_TRUE(offer.get() != NULL);
2177 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
2178 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
2179 // is possible to test that that RTX is dropped when
2180 // kCodecParamAssociatedPayloadType is missing in the offer.
Steve Antonb1c1de12017-12-21 15:14:30 -08002181 MediaContentDescription* media_desc =
2182 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2183 ASSERT_TRUE(media_desc);
2184 VideoContentDescription* desc = media_desc->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002185 std::vector<VideoCodec> codecs = desc->codecs();
2186 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
2187 iter != codecs.end(); ++iter) {
2188 if (iter->name.find(cricket::kRtxCodecName) == 0) {
2189 iter->params.clear();
2190 }
2191 }
2192 desc->set_codecs(codecs);
2193
kwiberg31022942016-03-11 14:18:21 -08002194 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002195 f2_.CreateAnswer(offer.get(), opts, NULL));
2196
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002197 std::vector<std::string> codec_names =
2198 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
2199 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
2200 cricket::kRtxCodecName));
2201}
2202
2203// Test that RTX will be filtered out in the answer if its associated payload
2204// type doesn't match the local value.
2205TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
2206 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002207 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2208 kActive, &opts);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002209 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2210 // This creates RTX for H264 in sender.
2211 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2212 f1_.set_video_codecs(f1_codecs);
2213
2214 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2215 // This creates RTX for H263 in receiver.
2216 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
2217 f2_.set_video_codecs(f2_codecs);
2218
kwiberg31022942016-03-11 14:18:21 -08002219 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002220 ASSERT_TRUE(offer.get() != NULL);
2221 // Associated payload type doesn't match, therefore, RTX codec is removed in
2222 // the answer.
kwiberg31022942016-03-11 14:18:21 -08002223 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002224 f2_.CreateAnswer(offer.get(), opts, NULL));
2225
2226 std::vector<std::string> codec_names =
2227 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
2228 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
2229 cricket::kRtxCodecName));
2230}
2231
2232// Test that when multiple RTX codecs are offered, only the matched RTX codec
2233// is added in the answer, and the unsupported RTX codec is filtered out.
2234TEST_F(MediaSessionDescriptionFactoryTest,
2235 FilterOutUnsupportedRtxWhenCreatingAnswer) {
2236 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002237 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2238 kActive, &opts);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002239 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2240 // This creates RTX for H264-SVC in sender.
2241 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
2242 f1_.set_video_codecs(f1_codecs);
2243
2244 // This creates RTX for H264 in sender.
2245 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2246 f1_.set_video_codecs(f1_codecs);
2247
2248 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2249 // This creates RTX for H264 in receiver.
2250 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
2251 f2_.set_video_codecs(f2_codecs);
2252
2253 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
2254 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08002255 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002256 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002257 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002258 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002259 const VideoContentDescription* vcd =
2260 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002261 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2262 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2263 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002264
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002265 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002266}
2267
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002268// Test that after one RTX codec has been negotiated, a new offer can attempt
2269// to add another.
2270TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
2271 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002272 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2273 kActive, &opts);
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002274 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2275 // This creates RTX for H264 for the offerer.
2276 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2277 f1_.set_video_codecs(f1_codecs);
2278
kwiberg31022942016-03-11 14:18:21 -08002279 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002280 ASSERT_TRUE(offer);
2281 const VideoContentDescription* vcd =
2282 GetFirstVideoContentDescription(offer.get());
2283
2284 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
2285 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2286 &expected_codecs);
2287 EXPECT_EQ(expected_codecs, vcd->codecs());
2288
2289 // Now, attempt to add RTX for H264-SVC.
2290 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
2291 f1_.set_video_codecs(f1_codecs);
2292
kwiberg31022942016-03-11 14:18:21 -08002293 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002294 f1_.CreateOffer(opts, offer.get()));
2295 ASSERT_TRUE(updated_offer);
2296 vcd = GetFirstVideoContentDescription(updated_offer.get());
2297
2298 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
2299 &expected_codecs);
2300 EXPECT_EQ(expected_codecs, vcd->codecs());
2301}
2302
Noah Richards2e7a0982015-05-18 14:02:54 -07002303// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
2304// generated for each simulcast ssrc and correctly grouped.
2305TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
2306 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002307 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2308 kActive, &opts);
Noah Richards2e7a0982015-05-18 14:02:54 -07002309 // Add simulcast streams.
zhihuang1c378ed2017-08-17 14:10:50 -07002310 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002311 {"stream1label"}, 3, &opts);
Noah Richards2e7a0982015-05-18 14:02:54 -07002312
2313 // Use a single real codec, and then add RTX for it.
2314 std::vector<VideoCodec> f1_codecs;
perkj26752742016-10-24 01:21:16 -07002315 f1_codecs.push_back(VideoCodec(97, "H264"));
Noah Richards2e7a0982015-05-18 14:02:54 -07002316 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
2317 f1_.set_video_codecs(f1_codecs);
2318
2319 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
2320 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08002321 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07002322 ASSERT_TRUE(offer.get() != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002323 MediaContentDescription* media_desc =
2324 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2325 ASSERT_TRUE(media_desc);
2326 VideoContentDescription* desc = media_desc->as_video();
Noah Richards2e7a0982015-05-18 14:02:54 -07002327 const StreamParamsVec& streams = desc->streams();
2328 // Single stream.
2329 ASSERT_EQ(1u, streams.size());
2330 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
2331 EXPECT_EQ(6u, streams[0].ssrcs.size());
2332 // And should have a SIM group for the simulcast.
2333 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2334 // And a FID group for RTX.
2335 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02002336 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002337 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2338 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02002339 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002340 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
2341 EXPECT_EQ(3u, fid_ssrcs.size());
2342}
2343
brandtr03d5fb12016-11-22 03:37:59 -08002344// Test that, when the FlexFEC codec is added, a FlexFEC ssrc is created
2345// together with a FEC-FR grouping.
2346TEST_F(MediaSessionDescriptionFactoryTest, GenerateFlexfecSsrc) {
2347 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002348 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2349 kActive, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002350 // Add single stream.
zhihuang1c378ed2017-08-17 14:10:50 -07002351 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002352 {"stream1label"}, 1, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002353
2354 // Use a single real codec, and then add FlexFEC for it.
2355 std::vector<VideoCodec> f1_codecs;
2356 f1_codecs.push_back(VideoCodec(97, "H264"));
2357 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2358 f1_.set_video_codecs(f1_codecs);
2359
2360 // Ensure that the offer has a single FlexFEC ssrc and that
2361 // there is no FEC-FR ssrc + grouping for each.
2362 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2363 ASSERT_TRUE(offer.get() != nullptr);
Steve Antonb1c1de12017-12-21 15:14:30 -08002364 MediaContentDescription* media_desc =
2365 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2366 ASSERT_TRUE(media_desc);
2367 VideoContentDescription* desc = media_desc->as_video();
brandtr03d5fb12016-11-22 03:37:59 -08002368 const StreamParamsVec& streams = desc->streams();
2369 // Single stream.
2370 ASSERT_EQ(1u, streams.size());
2371 // Stream should have 2 ssrcs: 1 for video, 1 for FlexFEC.
2372 EXPECT_EQ(2u, streams[0].ssrcs.size());
2373 // And should have a FEC-FR group for FlexFEC.
2374 EXPECT_TRUE(streams[0].has_ssrc_group("FEC-FR"));
2375 std::vector<uint32_t> primary_ssrcs;
2376 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2377 ASSERT_EQ(1u, primary_ssrcs.size());
2378 uint32_t flexfec_ssrc;
2379 EXPECT_TRUE(streams[0].GetFecFrSsrc(primary_ssrcs[0], &flexfec_ssrc));
2380 EXPECT_NE(flexfec_ssrc, 0u);
2381}
2382
2383// Test that FlexFEC is disabled for simulcast.
2384// TODO(brandtr): Remove this test when we support simulcast, either through
2385// multiple FlexfecSenders, or through multistream protection.
2386TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateNoFlexfecSsrcs) {
2387 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002388 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2389 kActive, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002390 // Add simulcast streams.
zhihuang1c378ed2017-08-17 14:10:50 -07002391 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002392 {"stream1label"}, 3, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002393
2394 // Use a single real codec, and then add FlexFEC for it.
2395 std::vector<VideoCodec> f1_codecs;
2396 f1_codecs.push_back(VideoCodec(97, "H264"));
2397 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2398 f1_.set_video_codecs(f1_codecs);
2399
2400 // Ensure that the offer has no FlexFEC ssrcs for each regular ssrc, and that
2401 // there is no FEC-FR ssrc + grouping for each.
2402 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2403 ASSERT_TRUE(offer.get() != nullptr);
Steve Antonb1c1de12017-12-21 15:14:30 -08002404 MediaContentDescription* media_desc =
2405 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2406 ASSERT_TRUE(media_desc);
2407 VideoContentDescription* desc = media_desc->as_video();
brandtr03d5fb12016-11-22 03:37:59 -08002408 const StreamParamsVec& streams = desc->streams();
2409 // Single stream.
2410 ASSERT_EQ(1u, streams.size());
2411 // Stream should have 3 ssrcs: 3 for video, 0 for FlexFEC.
2412 EXPECT_EQ(3u, streams[0].ssrcs.size());
2413 // And should have a SIM group for the simulcast.
2414 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2415 // And not a FEC-FR group for FlexFEC.
2416 EXPECT_FALSE(streams[0].has_ssrc_group("FEC-FR"));
2417 std::vector<uint32_t> primary_ssrcs;
2418 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2419 EXPECT_EQ(3u, primary_ssrcs.size());
2420 for (uint32_t primary_ssrc : primary_ssrcs) {
2421 uint32_t flexfec_ssrc;
2422 EXPECT_FALSE(streams[0].GetFecFrSsrc(primary_ssrc, &flexfec_ssrc));
2423 }
2424}
2425
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002426// Create an updated offer after creating an answer to the original offer and
2427// verify that the RTP header extensions that were part of the original answer
2428// are not changed in the updated offer.
2429TEST_F(MediaSessionDescriptionFactoryTest,
2430 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
2431 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002432 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002433
2434 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
2435 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
2436 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
2437 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
2438
kwiberg31022942016-03-11 14:18:21 -08002439 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2440 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002441 f2_.CreateAnswer(offer.get(), opts, NULL));
2442
Yves Gerey665174f2018-06-19 15:03:05 +02002443 EXPECT_EQ(
2444 MAKE_VECTOR(kAudioRtpExtensionAnswer),
2445 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
2446 EXPECT_EQ(
2447 MAKE_VECTOR(kVideoRtpExtensionAnswer),
2448 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002449
kwiberg31022942016-03-11 14:18:21 -08002450 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002451 f2_.CreateOffer(opts, answer.get()));
2452
2453 // The expected RTP header extensions in the new offer are the resulting
2454 // extensions from the first offer/answer exchange plus the extensions only
2455 // |f2_| offer.
2456 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002457 // |f1_| for another extensions, it is changed to 13.
isheriff6f8d6862016-05-26 11:24:55 -07002458 const RtpExtension kUpdatedAudioRtpExtensions[] = {
2459 kAudioRtpExtensionAnswer[0], RtpExtension(kAudioRtpExtension2[1].uri, 13),
2460 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002461 };
2462
2463 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002464 // |f1_| for another extensions, is is changed to 12.
isheriff6f8d6862016-05-26 11:24:55 -07002465 const RtpExtension kUpdatedVideoRtpExtensions[] = {
2466 kVideoRtpExtensionAnswer[0], RtpExtension(kVideoRtpExtension2[1].uri, 12),
2467 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002468 };
2469
2470 const AudioContentDescription* updated_acd =
2471 GetFirstAudioContentDescription(updated_offer.get());
2472 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
2473 updated_acd->rtp_header_extensions());
2474
2475 const VideoContentDescription* updated_vcd =
2476 GetFirstVideoContentDescription(updated_offer.get());
2477 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
2478 updated_vcd->rtp_header_extensions());
2479}
2480
deadbeefa5b273a2015-08-20 17:30:13 -07002481// Verify that if the same RTP extension URI is used for audio and video, the
2482// same ID is used. Also verify that the ID isn't changed when creating an
2483// updated offer (this was previously a bug).
isheriff6f8d6862016-05-26 11:24:55 -07002484TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) {
deadbeefa5b273a2015-08-20 17:30:13 -07002485 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002486 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
deadbeefa5b273a2015-08-20 17:30:13 -07002487
2488 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
2489 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
2490
kwiberg31022942016-03-11 14:18:21 -08002491 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07002492
2493 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
2494 // the video extensions.
isheriff6f8d6862016-05-26 11:24:55 -07002495 const RtpExtension kExpectedVideoRtpExtension[] = {
2496 kVideoRtpExtension3[0], kAudioRtpExtension3[1],
deadbeefa5b273a2015-08-20 17:30:13 -07002497 };
2498
Yves Gerey665174f2018-06-19 15:03:05 +02002499 EXPECT_EQ(
2500 MAKE_VECTOR(kAudioRtpExtension3),
2501 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
2502 EXPECT_EQ(
2503 MAKE_VECTOR(kExpectedVideoRtpExtension),
2504 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
deadbeefa5b273a2015-08-20 17:30:13 -07002505
2506 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08002507 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07002508 f1_.CreateOffer(opts, offer.get()));
2509
2510 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
Yves Gerey665174f2018-06-19 15:03:05 +02002511 GetFirstAudioContentDescription(updated_offer.get())
2512 ->rtp_header_extensions());
deadbeefa5b273a2015-08-20 17:30:13 -07002513 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
Yves Gerey665174f2018-06-19 15:03:05 +02002514 GetFirstVideoContentDescription(updated_offer.get())
2515 ->rtp_header_extensions());
deadbeefa5b273a2015-08-20 17:30:13 -07002516}
2517
jbauch5869f502017-06-29 12:31:36 -07002518// Same as "RtpExtensionIdReused" above for encrypted RTP extensions.
2519TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReusedEncrypted) {
2520 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002521 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07002522
2523 f1_.set_enable_encrypted_rtp_header_extensions(true);
2524 f2_.set_enable_encrypted_rtp_header_extensions(true);
2525
2526 f1_.set_audio_rtp_header_extensions(
2527 MAKE_VECTOR(kAudioRtpExtension3ForEncryption));
2528 f1_.set_video_rtp_header_extensions(
2529 MAKE_VECTOR(kVideoRtpExtension3ForEncryption));
2530
2531 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2532
2533 // The extensions that are shared between audio and video should use the same
2534 // id.
2535 const RtpExtension kExpectedVideoRtpExtension[] = {
2536 kVideoRtpExtension3ForEncryption[0],
2537 kAudioRtpExtension3ForEncryptionOffer[1],
2538 kAudioRtpExtension3ForEncryptionOffer[2],
2539 };
2540
Yves Gerey665174f2018-06-19 15:03:05 +02002541 EXPECT_EQ(
2542 MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
2543 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
2544 EXPECT_EQ(
2545 MAKE_VECTOR(kExpectedVideoRtpExtension),
2546 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07002547
2548 // Nothing should change when creating a new offer
2549 std::unique_ptr<SessionDescription> updated_offer(
2550 f1_.CreateOffer(opts, offer.get()));
2551
2552 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
Yves Gerey665174f2018-06-19 15:03:05 +02002553 GetFirstAudioContentDescription(updated_offer.get())
2554 ->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07002555 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
Yves Gerey665174f2018-06-19 15:03:05 +02002556 GetFirstVideoContentDescription(updated_offer.get())
2557 ->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07002558}
2559
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002560TEST(MediaSessionDescription, CopySessionDescription) {
2561 SessionDescription source;
2562 cricket::ContentGroup group(cricket::CN_AUDIO);
2563 source.AddGroup(group);
2564 AudioContentDescription* acd(new AudioContentDescription());
2565 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
2566 acd->AddLegacyStream(1);
Steve Anton5adfafd2017-12-20 16:34:00 -08002567 source.AddContent(cricket::CN_AUDIO, MediaProtocolType::kRtp, acd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002568 VideoContentDescription* vcd(new VideoContentDescription());
2569 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
2570 vcd->AddLegacyStream(2);
Steve Anton5adfafd2017-12-20 16:34:00 -08002571 source.AddContent(cricket::CN_VIDEO, MediaProtocolType::kRtp, vcd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002572
kwiberg31022942016-03-11 14:18:21 -08002573 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002574 ASSERT_TRUE(copy.get() != NULL);
2575 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
2576 const ContentInfo* ac = copy->GetContentByName("audio");
2577 const ContentInfo* vc = copy->GetContentByName("video");
2578 ASSERT_TRUE(ac != NULL);
2579 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08002580 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08002581 const AudioContentDescription* acd_copy = ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002582 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
2583 EXPECT_EQ(1u, acd->first_ssrc());
2584
Steve Anton5adfafd2017-12-20 16:34:00 -08002585 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08002586 const VideoContentDescription* vcd_copy = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002587 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
2588 EXPECT_EQ(2u, vcd->first_ssrc());
2589}
2590
2591// The below TestTransportInfoXXX tests create different offers/answers, and
2592// ensure the TransportInfo in the SessionDescription matches what we expect.
2593TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
2594 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002595 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2596 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002597 TestTransportInfo(true, options, false);
2598}
2599
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002600TEST_F(MediaSessionDescriptionFactoryTest,
2601 TestTransportInfoOfferIceRenomination) {
2602 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002603 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2604 kActive, &options);
zhihuang1c378ed2017-08-17 14:10:50 -07002605 options.media_description_options[0]
2606 .transport_options.enable_ice_renomination = true;
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002607 TestTransportInfo(true, options, false);
2608}
2609
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002610TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
2611 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002612 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2613 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002614 TestTransportInfo(true, options, true);
2615}
2616
2617TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2618 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002619 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2620 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2621 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002622 TestTransportInfo(true, options, false);
2623}
2624
2625TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02002626 TestTransportInfoOfferMultimediaCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002627 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002628 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2629 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2630 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002631 TestTransportInfo(true, options, true);
2632}
2633
2634TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2635 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002636 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2637 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2638 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002639 options.bundle_enabled = true;
2640 TestTransportInfo(true, options, false);
2641}
2642
2643TEST_F(MediaSessionDescriptionFactoryTest,
2644 TestTransportInfoOfferBundleCurrent) {
2645 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002646 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2647 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2648 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002649 options.bundle_enabled = true;
2650 TestTransportInfo(true, options, true);
2651}
2652
2653TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2654 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002655 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2656 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002657 TestTransportInfo(false, options, false);
2658}
2659
2660TEST_F(MediaSessionDescriptionFactoryTest,
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002661 TestTransportInfoAnswerIceRenomination) {
2662 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002663 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2664 kActive, &options);
zhihuang1c378ed2017-08-17 14:10:50 -07002665 options.media_description_options[0]
2666 .transport_options.enable_ice_renomination = true;
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002667 TestTransportInfo(false, options, false);
2668}
2669
2670TEST_F(MediaSessionDescriptionFactoryTest,
2671 TestTransportInfoAnswerAudioCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002672 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002673 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2674 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002675 TestTransportInfo(false, options, true);
2676}
2677
2678TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2679 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002680 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2681 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2682 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002683 TestTransportInfo(false, options, false);
2684}
2685
2686TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02002687 TestTransportInfoAnswerMultimediaCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002688 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002689 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2690 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2691 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002692 TestTransportInfo(false, options, true);
2693}
2694
2695TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2696 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002697 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2698 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2699 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002700 options.bundle_enabled = true;
2701 TestTransportInfo(false, options, false);
2702}
2703
2704TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02002705 TestTransportInfoAnswerBundleCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002706 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002707 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2708 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2709 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002710 options.bundle_enabled = true;
2711 TestTransportInfo(false, options, true);
2712}
2713
2714// Create an offer with bundle enabled and verify the crypto parameters are
2715// the common set of the available cryptos.
2716TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2717 TestCryptoWithBundle(true);
2718}
2719
2720// Create an answer with bundle enabled and verify the crypto parameters are
2721// the common set of the available cryptos.
2722TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2723 TestCryptoWithBundle(false);
2724}
2725
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002726// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2727// DTLS is not enabled locally.
2728TEST_F(MediaSessionDescriptionFactoryTest,
2729 TestOfferDtlsSavpfWithoutDtlsFailed) {
2730 f1_.set_secure(SEC_ENABLED);
2731 f2_.set_secure(SEC_ENABLED);
2732 tdf1_.set_secure(SEC_DISABLED);
2733 tdf2_.set_secure(SEC_DISABLED);
2734
kwiberg31022942016-03-11 14:18:21 -08002735 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -07002736 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002737 ASSERT_TRUE(offer.get() != NULL);
2738 ContentInfo* offer_content = offer->GetContentByName("audio");
2739 ASSERT_TRUE(offer_content != NULL);
2740 AudioContentDescription* offer_audio_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -08002741 offer_content->media_description()->as_audio();
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002742 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2743
kwiberg31022942016-03-11 14:18:21 -08002744 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07002745 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002746 ASSERT_TRUE(answer != NULL);
2747 ContentInfo* answer_content = answer->GetContentByName("audio");
2748 ASSERT_TRUE(answer_content != NULL);
2749
2750 ASSERT_TRUE(answer_content->rejected);
2751}
2752
2753// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2754// UDP/TLS/RTP/SAVPF.
2755TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2756 f1_.set_secure(SEC_ENABLED);
2757 f2_.set_secure(SEC_ENABLED);
2758 tdf1_.set_secure(SEC_ENABLED);
2759 tdf2_.set_secure(SEC_ENABLED);
2760
kwiberg31022942016-03-11 14:18:21 -08002761 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -07002762 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002763 ASSERT_TRUE(offer.get() != NULL);
2764 ContentInfo* offer_content = offer->GetContentByName("audio");
2765 ASSERT_TRUE(offer_content != NULL);
2766 AudioContentDescription* offer_audio_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -08002767 offer_content->media_description()->as_audio();
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002768 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2769
kwiberg31022942016-03-11 14:18:21 -08002770 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07002771 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002772 ASSERT_TRUE(answer != NULL);
2773
2774 const ContentInfo* answer_content = answer->GetContentByName("audio");
2775 ASSERT_TRUE(answer_content != NULL);
2776 ASSERT_FALSE(answer_content->rejected);
2777
2778 const AudioContentDescription* answer_audio_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -08002779 answer_content->media_description()->as_audio();
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002780 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
Yves Gerey665174f2018-06-19 15:03:05 +02002781 answer_audio_desc->protocol());
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002782}
2783
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002784// Test that we include both SDES and DTLS in the offer, but only include SDES
2785// in the answer if DTLS isn't negotiated.
2786TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2787 f1_.set_secure(SEC_ENABLED);
2788 f2_.set_secure(SEC_ENABLED);
2789 tdf1_.set_secure(SEC_ENABLED);
2790 tdf2_.set_secure(SEC_DISABLED);
2791 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002792 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
kwiberg31022942016-03-11 14:18:21 -08002793 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002794 const cricket::MediaContentDescription* audio_media_desc;
2795 const cricket::MediaContentDescription* video_media_desc;
2796 const cricket::TransportDescription* audio_trans_desc;
2797 const cricket::TransportDescription* video_trans_desc;
2798
2799 // Generate an offer with SDES and DTLS support.
2800 offer.reset(f1_.CreateOffer(options, NULL));
2801 ASSERT_TRUE(offer.get() != NULL);
2802
Steve Antonb1c1de12017-12-21 15:14:30 -08002803 audio_media_desc = offer->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002804 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002805 video_media_desc = offer->GetContentDescriptionByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002806 ASSERT_TRUE(video_media_desc != NULL);
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07002807 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002808 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2809
2810 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2811 ASSERT_TRUE(audio_trans_desc != NULL);
2812 video_trans_desc = offer->GetTransportDescriptionByName("video");
2813 ASSERT_TRUE(video_trans_desc != NULL);
2814 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2815 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2816
2817 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2818 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2819 ASSERT_TRUE(answer.get() != NULL);
2820
Steve Antonb1c1de12017-12-21 15:14:30 -08002821 audio_media_desc = answer->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002822 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002823 video_media_desc = answer->GetContentDescriptionByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002824 ASSERT_TRUE(video_media_desc != NULL);
2825 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2826 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2827
2828 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2829 ASSERT_TRUE(audio_trans_desc != NULL);
2830 video_trans_desc = answer->GetTransportDescriptionByName("video");
2831 ASSERT_TRUE(video_trans_desc != NULL);
2832 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2833 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2834
2835 // Enable DTLS; the answer should now only have DTLS support.
2836 tdf2_.set_secure(SEC_ENABLED);
2837 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2838 ASSERT_TRUE(answer.get() != NULL);
2839
Steve Antonb1c1de12017-12-21 15:14:30 -08002840 audio_media_desc = answer->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002841 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002842 video_media_desc = answer->GetContentDescriptionByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002843 ASSERT_TRUE(video_media_desc != NULL);
2844 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2845 EXPECT_TRUE(video_media_desc->cryptos().empty());
2846 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2847 audio_media_desc->protocol());
2848 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2849 video_media_desc->protocol());
2850
2851 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2852 ASSERT_TRUE(audio_trans_desc != NULL);
2853 video_trans_desc = answer->GetTransportDescriptionByName("video");
2854 ASSERT_TRUE(video_trans_desc != NULL);
2855 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2856 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002857
2858 // Try creating offer again. DTLS enabled now, crypto's should be empty
2859 // in new offer.
2860 offer.reset(f1_.CreateOffer(options, offer.get()));
2861 ASSERT_TRUE(offer.get() != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002862 audio_media_desc = offer->GetContentDescriptionByName("audio");
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002863 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002864 video_media_desc = offer->GetContentDescriptionByName("video");
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002865 ASSERT_TRUE(video_media_desc != NULL);
2866 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2867 EXPECT_TRUE(video_media_desc->cryptos().empty());
2868
2869 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2870 ASSERT_TRUE(audio_trans_desc != NULL);
2871 video_trans_desc = offer->GetTransportDescriptionByName("video");
2872 ASSERT_TRUE(video_trans_desc != NULL);
2873 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2874 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002875}
2876
2877// Test that an answer can't be created if cryptos are required but the offer is
2878// unsecure.
2879TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07002880 MediaSessionOptions options = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002881 f1_.set_secure(SEC_DISABLED);
2882 tdf1_.set_secure(SEC_DISABLED);
2883 f2_.set_secure(SEC_REQUIRED);
2884 tdf1_.set_secure(SEC_ENABLED);
2885
kwiberg31022942016-03-11 14:18:21 -08002886 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002887 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002888 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002889 f2_.CreateAnswer(offer.get(), options, NULL));
2890 EXPECT_TRUE(answer.get() == NULL);
2891}
2892
2893// Test that we accept a DTLS offer without SDES and create an appropriate
2894// answer.
2895TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2896 f1_.set_secure(SEC_DISABLED);
2897 f2_.set_secure(SEC_ENABLED);
2898 tdf1_.set_secure(SEC_ENABLED);
2899 tdf2_.set_secure(SEC_ENABLED);
2900 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002901 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2902 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2903 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002904
kwiberg31022942016-03-11 14:18:21 -08002905 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002906
2907 // Generate an offer with DTLS but without SDES.
2908 offer.reset(f1_.CreateOffer(options, NULL));
2909 ASSERT_TRUE(offer.get() != NULL);
2910
2911 const AudioContentDescription* audio_offer =
2912 GetFirstAudioContentDescription(offer.get());
2913 ASSERT_TRUE(audio_offer->cryptos().empty());
2914 const VideoContentDescription* video_offer =
2915 GetFirstVideoContentDescription(offer.get());
2916 ASSERT_TRUE(video_offer->cryptos().empty());
2917 const DataContentDescription* data_offer =
2918 GetFirstDataContentDescription(offer.get());
2919 ASSERT_TRUE(data_offer->cryptos().empty());
2920
2921 const cricket::TransportDescription* audio_offer_trans_desc =
2922 offer->GetTransportDescriptionByName("audio");
2923 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2924 const cricket::TransportDescription* video_offer_trans_desc =
2925 offer->GetTransportDescriptionByName("video");
2926 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2927 const cricket::TransportDescription* data_offer_trans_desc =
2928 offer->GetTransportDescriptionByName("data");
2929 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2930
2931 // Generate an answer with DTLS.
2932 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2933 ASSERT_TRUE(answer.get() != NULL);
2934
2935 const cricket::TransportDescription* audio_answer_trans_desc =
2936 answer->GetTransportDescriptionByName("audio");
2937 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2938 const cricket::TransportDescription* video_answer_trans_desc =
2939 answer->GetTransportDescriptionByName("video");
2940 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2941 const cricket::TransportDescription* data_answer_trans_desc =
2942 answer->GetTransportDescriptionByName("data");
2943 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2944}
2945
2946// Verifies if vad_enabled option is set to false, CN codecs are not present in
2947// offer or answer.
2948TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2949 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002950 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
kwiberg31022942016-03-11 14:18:21 -08002951 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002952 ASSERT_TRUE(offer.get() != NULL);
2953 const ContentInfo* audio_content = offer->GetContentByName("audio");
2954 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2955
2956 options.vad_enabled = false;
2957 offer.reset(f1_.CreateOffer(options, NULL));
2958 ASSERT_TRUE(offer.get() != NULL);
2959 audio_content = offer->GetContentByName("audio");
2960 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08002961 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002962 f1_.CreateAnswer(offer.get(), options, NULL));
2963 ASSERT_TRUE(answer.get() != NULL);
2964 audio_content = answer->GetContentByName("audio");
2965 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2966}
deadbeef44f08192015-12-15 16:20:09 -08002967
zhihuang1c378ed2017-08-17 14:10:50 -07002968// Test that the generated MIDs match the existing offer.
2969TEST_F(MediaSessionDescriptionFactoryTest, TestMIDsMatchesExistingOffer) {
deadbeef44f08192015-12-15 16:20:09 -08002970 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002971 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_modified",
2972 RtpTransceiverDirection::kRecvOnly, kActive, &opts);
2973 AddMediaSection(MEDIA_TYPE_VIDEO, "video_modified",
2974 RtpTransceiverDirection::kRecvOnly, kActive, &opts);
deadbeef44f08192015-12-15 16:20:09 -08002975 opts.data_channel_type = cricket::DCT_SCTP;
Steve Anton4e70a722017-11-28 14:57:10 -08002976 AddMediaSection(MEDIA_TYPE_DATA, "data_modified",
2977 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07002978 // Create offer.
kwiberg31022942016-03-11 14:18:21 -08002979 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
kwiberg31022942016-03-11 14:18:21 -08002980 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08002981 f1_.CreateOffer(opts, offer.get()));
zhihuang1c378ed2017-08-17 14:10:50 -07002982
deadbeef44f08192015-12-15 16:20:09 -08002983 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
2984 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
2985 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
2986 ASSERT_TRUE(audio_content != nullptr);
2987 ASSERT_TRUE(video_content != nullptr);
2988 ASSERT_TRUE(data_content != nullptr);
2989 EXPECT_EQ("audio_modified", audio_content->name);
2990 EXPECT_EQ("video_modified", video_content->name);
2991 EXPECT_EQ("data_modified", data_content->name);
2992}
zhihuangcf5b37c2016-05-05 11:44:35 -07002993
zhihuang1c378ed2017-08-17 14:10:50 -07002994// The following tests verify that the unified plan SDP is supported.
2995// Test that we can create an offer with multiple media sections of same media
2996// type.
2997TEST_F(MediaSessionDescriptionFactoryTest,
2998 CreateOfferWithMultipleAVMediaSections) {
2999 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003000 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_1",
3001 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003002 AttachSenderToMediaSection("audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003003 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003004
Steve Anton4e70a722017-11-28 14:57:10 -08003005 AddMediaSection(MEDIA_TYPE_VIDEO, "video_1",
3006 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003007 AttachSenderToMediaSection("video_1", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003008 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003009
Steve Anton4e70a722017-11-28 14:57:10 -08003010 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_2",
3011 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003012 AttachSenderToMediaSection("audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003013 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003014
Steve Anton4e70a722017-11-28 14:57:10 -08003015 AddMediaSection(MEDIA_TYPE_VIDEO, "video_2",
3016 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003017 AttachSenderToMediaSection("video_2", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003018 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003019 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3020 ASSERT_TRUE(offer);
3021
3022 ASSERT_EQ(4u, offer->contents().size());
3023 EXPECT_FALSE(offer->contents()[0].rejected);
3024 const AudioContentDescription* acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003025 offer->contents()[0].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003026 ASSERT_EQ(1u, acd->streams().size());
3027 EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003028 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003029
3030 EXPECT_FALSE(offer->contents()[1].rejected);
3031 const VideoContentDescription* vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003032 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003033 ASSERT_EQ(1u, vcd->streams().size());
3034 EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003035 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003036
3037 EXPECT_FALSE(offer->contents()[2].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003038 acd = offer->contents()[2].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003039 ASSERT_EQ(1u, acd->streams().size());
3040 EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003041 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003042
3043 EXPECT_FALSE(offer->contents()[3].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003044 vcd = offer->contents()[3].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003045 ASSERT_EQ(1u, vcd->streams().size());
3046 EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003047 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003048}
3049
3050// Test that we can create an answer with multiple media sections of same media
3051// type.
3052TEST_F(MediaSessionDescriptionFactoryTest,
3053 CreateAnswerWithMultipleAVMediaSections) {
3054 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003055 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_1",
3056 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003057 AttachSenderToMediaSection("audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003058 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003059
Steve Anton4e70a722017-11-28 14:57:10 -08003060 AddMediaSection(MEDIA_TYPE_VIDEO, "video_1",
3061 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003062 AttachSenderToMediaSection("video_1", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003063 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003064
Steve Anton4e70a722017-11-28 14:57:10 -08003065 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_2",
3066 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003067 AttachSenderToMediaSection("audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003068 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003069
Steve Anton4e70a722017-11-28 14:57:10 -08003070 AddMediaSection(MEDIA_TYPE_VIDEO, "video_2",
3071 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003072 AttachSenderToMediaSection("video_2", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003073 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003074
3075 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3076 ASSERT_TRUE(offer);
3077 std::unique_ptr<SessionDescription> answer(
3078 f2_.CreateAnswer(offer.get(), opts, nullptr));
3079
3080 ASSERT_EQ(4u, answer->contents().size());
3081 EXPECT_FALSE(answer->contents()[0].rejected);
3082 const AudioContentDescription* acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003083 answer->contents()[0].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003084 ASSERT_EQ(1u, acd->streams().size());
3085 EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003086 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003087
3088 EXPECT_FALSE(answer->contents()[1].rejected);
3089 const VideoContentDescription* vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003090 answer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003091 ASSERT_EQ(1u, vcd->streams().size());
3092 EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003093 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003094
3095 EXPECT_FALSE(answer->contents()[2].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003096 acd = answer->contents()[2].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003097 ASSERT_EQ(1u, acd->streams().size());
3098 EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003099 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003100
3101 EXPECT_FALSE(answer->contents()[3].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003102 vcd = answer->contents()[3].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003103 ASSERT_EQ(1u, vcd->streams().size());
3104 EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003105 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003106}
3107
3108// Test that the media section will be rejected in offer if the corresponding
3109// MediaDescriptionOptions is stopped by the offerer.
3110TEST_F(MediaSessionDescriptionFactoryTest,
3111 CreateOfferWithMediaSectionStoppedByOfferer) {
3112 // Create an offer with two audio sections and one of them is stopped.
3113 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003114 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3115 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3116 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3117 RtpTransceiverDirection::kInactive, kStopped, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003118 std::unique_ptr<SessionDescription> offer(
3119 f1_.CreateOffer(offer_opts, nullptr));
3120 ASSERT_TRUE(offer);
3121 ASSERT_EQ(2u, offer->contents().size());
3122 EXPECT_FALSE(offer->contents()[0].rejected);
3123 EXPECT_TRUE(offer->contents()[1].rejected);
3124}
3125
3126// Test that the media section will be rejected in answer if the corresponding
3127// MediaDescriptionOptions is stopped by the offerer.
3128TEST_F(MediaSessionDescriptionFactoryTest,
3129 CreateAnswerWithMediaSectionStoppedByOfferer) {
3130 // Create an offer with two audio sections and one of them is stopped.
3131 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003132 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3133 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3134 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3135 RtpTransceiverDirection::kInactive, kStopped, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003136 std::unique_ptr<SessionDescription> offer(
3137 f1_.CreateOffer(offer_opts, nullptr));
3138 ASSERT_TRUE(offer);
3139 ASSERT_EQ(2u, offer->contents().size());
3140 EXPECT_FALSE(offer->contents()[0].rejected);
3141 EXPECT_TRUE(offer->contents()[1].rejected);
3142
3143 // Create an answer based on the offer.
3144 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003145 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3146 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
3147 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3148 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003149 std::unique_ptr<SessionDescription> answer(
3150 f2_.CreateAnswer(offer.get(), answer_opts, nullptr));
3151 ASSERT_EQ(2u, answer->contents().size());
3152 EXPECT_FALSE(answer->contents()[0].rejected);
3153 EXPECT_TRUE(answer->contents()[1].rejected);
3154}
3155
3156// Test that the media section will be rejected in answer if the corresponding
3157// MediaDescriptionOptions is stopped by the answerer.
3158TEST_F(MediaSessionDescriptionFactoryTest,
3159 CreateAnswerWithMediaSectionRejectedByAnswerer) {
3160 // Create an offer with two audio sections.
3161 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003162 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3163 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3164 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3165 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003166 std::unique_ptr<SessionDescription> offer(
3167 f1_.CreateOffer(offer_opts, nullptr));
3168 ASSERT_TRUE(offer);
3169 ASSERT_EQ(2u, offer->contents().size());
3170 ASSERT_FALSE(offer->contents()[0].rejected);
3171 ASSERT_FALSE(offer->contents()[1].rejected);
3172
3173 // The answerer rejects one of the audio sections.
3174 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003175 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3176 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
3177 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3178 RtpTransceiverDirection::kInactive, kStopped, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003179 std::unique_ptr<SessionDescription> answer(
3180 f2_.CreateAnswer(offer.get(), answer_opts, nullptr));
3181 ASSERT_EQ(2u, answer->contents().size());
3182 EXPECT_FALSE(answer->contents()[0].rejected);
3183 EXPECT_TRUE(answer->contents()[1].rejected);
Zhi Huang3518e7b2018-01-30 13:20:35 -08003184
3185 // The TransportInfo of the rejected m= section is expected to be added in the
3186 // answer.
3187 EXPECT_EQ(offer->transport_infos().size(), answer->transport_infos().size());
zhihuang1c378ed2017-08-17 14:10:50 -07003188}
3189
3190// Test the generated media sections has the same order of the
3191// corresponding MediaDescriptionOptions.
3192TEST_F(MediaSessionDescriptionFactoryTest,
3193 CreateOfferRespectsMediaDescriptionOptionsOrder) {
3194 MediaSessionOptions opts;
3195 // This tests put video section first because normally audio comes first by
3196 // default.
Steve Anton4e70a722017-11-28 14:57:10 -08003197 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3198 kActive, &opts);
3199 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
3200 kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003201 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3202
3203 ASSERT_TRUE(offer);
3204 ASSERT_EQ(2u, offer->contents().size());
3205 EXPECT_EQ("video", offer->contents()[0].name);
3206 EXPECT_EQ("audio", offer->contents()[1].name);
3207}
3208
3209// Test that different media sections using the same codec have same payload
3210// type.
3211TEST_F(MediaSessionDescriptionFactoryTest,
3212 PayloadTypesSharedByMediaSectionsOfSameType) {
3213 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003214 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3215 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3216 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3217 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003218 // Create an offer with two video sections using same codecs.
3219 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3220 ASSERT_TRUE(offer);
3221 ASSERT_EQ(2u, offer->contents().size());
3222 const VideoContentDescription* vcd1 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003223 offer->contents()[0].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003224 const VideoContentDescription* vcd2 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003225 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003226 EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
3227 ASSERT_EQ(2u, vcd1->codecs().size());
3228 EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
3229 EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
3230 EXPECT_EQ(vcd1->codecs()[1].name, vcd2->codecs()[1].name);
3231 EXPECT_EQ(vcd1->codecs()[1].id, vcd2->codecs()[1].id);
3232
3233 // Create answer and negotiate the codecs.
3234 std::unique_ptr<SessionDescription> answer(
3235 f2_.CreateAnswer(offer.get(), opts, nullptr));
3236 ASSERT_TRUE(answer);
3237 ASSERT_EQ(2u, answer->contents().size());
Steve Antonb1c1de12017-12-21 15:14:30 -08003238 vcd1 = answer->contents()[0].media_description()->as_video();
3239 vcd2 = answer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003240 EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
3241 ASSERT_EQ(1u, vcd1->codecs().size());
3242 EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
3243 EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
3244}
3245
3246// Test that the codec preference order per media section is respected in
3247// subsequent offer.
3248TEST_F(MediaSessionDescriptionFactoryTest,
3249 CreateOfferRespectsCodecPreferenceOrder) {
3250 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003251 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3252 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3253 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3254 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003255 // Create an offer with two video sections using same codecs.
3256 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3257 ASSERT_TRUE(offer);
3258 ASSERT_EQ(2u, offer->contents().size());
3259 VideoContentDescription* vcd1 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003260 offer->contents()[0].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003261 const VideoContentDescription* vcd2 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003262 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003263 auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
3264 EXPECT_EQ(video_codecs, vcd1->codecs());
3265 EXPECT_EQ(video_codecs, vcd2->codecs());
3266
3267 // Change the codec preference of the first video section and create a
3268 // follow-up offer.
3269 auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
3270 vcd1->set_codecs(video_codecs_reverse);
3271 std::unique_ptr<SessionDescription> updated_offer(
3272 f1_.CreateOffer(opts, offer.get()));
Steve Antonb1c1de12017-12-21 15:14:30 -08003273 vcd1 = updated_offer->contents()[0].media_description()->as_video();
3274 vcd2 = updated_offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003275 // The video codec preference order should be respected.
3276 EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
3277 EXPECT_EQ(video_codecs, vcd2->codecs());
3278}
3279
3280// Test that the codec preference order per media section is respected in
3281// the answer.
3282TEST_F(MediaSessionDescriptionFactoryTest,
3283 CreateAnswerRespectsCodecPreferenceOrder) {
3284 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003285 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3286 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3287 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3288 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003289 // Create an offer with two video sections using same codecs.
3290 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3291 ASSERT_TRUE(offer);
3292 ASSERT_EQ(2u, offer->contents().size());
3293 VideoContentDescription* vcd1 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003294 offer->contents()[0].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003295 const VideoContentDescription* vcd2 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003296 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003297 auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
3298 EXPECT_EQ(video_codecs, vcd1->codecs());
3299 EXPECT_EQ(video_codecs, vcd2->codecs());
3300
3301 // Change the codec preference of the first video section and create an
3302 // answer.
3303 auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
3304 vcd1->set_codecs(video_codecs_reverse);
3305 std::unique_ptr<SessionDescription> answer(
3306 f1_.CreateAnswer(offer.get(), opts, nullptr));
Steve Antonb1c1de12017-12-21 15:14:30 -08003307 vcd1 = answer->contents()[0].media_description()->as_video();
3308 vcd2 = answer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003309 // The video codec preference order should be respected.
3310 EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
3311 EXPECT_EQ(video_codecs, vcd2->codecs());
3312}
3313
Zhi Huang6f367472017-11-22 13:20:02 -08003314// Test that when creating an answer, the codecs use local parameters instead of
3315// the remote ones.
3316TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerWithLocalCodecParams) {
3317 const std::string audio_param_name = "audio_param";
3318 const std::string audio_value1 = "audio_v1";
3319 const std::string audio_value2 = "audio_v2";
3320 const std::string video_param_name = "video_param";
3321 const std::string video_value1 = "video_v1";
3322 const std::string video_value2 = "video_v2";
3323
3324 auto audio_codecs1 = MAKE_VECTOR(kAudioCodecs1);
3325 auto audio_codecs2 = MAKE_VECTOR(kAudioCodecs1);
3326 auto video_codecs1 = MAKE_VECTOR(kVideoCodecs1);
3327 auto video_codecs2 = MAKE_VECTOR(kVideoCodecs1);
3328
3329 // Set the parameters for codecs.
3330 audio_codecs1[0].SetParam(audio_param_name, audio_value1);
3331 video_codecs1[0].SetParam(video_param_name, video_value1);
3332 audio_codecs2[0].SetParam(audio_param_name, audio_value2);
3333 video_codecs2[0].SetParam(video_param_name, video_value2);
3334
3335 f1_.set_audio_codecs(audio_codecs1, audio_codecs1);
3336 f1_.set_video_codecs(video_codecs1);
3337 f2_.set_audio_codecs(audio_codecs2, audio_codecs2);
3338 f2_.set_video_codecs(video_codecs2);
3339
3340 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003341 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
3342 kActive, &opts);
3343 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3344 kActive, &opts);
Zhi Huang6f367472017-11-22 13:20:02 -08003345
3346 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3347 ASSERT_TRUE(offer);
Steve Antonb1c1de12017-12-21 15:14:30 -08003348 auto offer_acd = offer->contents()[0].media_description()->as_audio();
3349 auto offer_vcd = offer->contents()[1].media_description()->as_video();
Zhi Huang6f367472017-11-22 13:20:02 -08003350 std::string value;
3351 EXPECT_TRUE(offer_acd->codecs()[0].GetParam(audio_param_name, &value));
3352 EXPECT_EQ(audio_value1, value);
3353 EXPECT_TRUE(offer_vcd->codecs()[0].GetParam(video_param_name, &value));
3354 EXPECT_EQ(video_value1, value);
3355
3356 std::unique_ptr<SessionDescription> answer(
3357 f2_.CreateAnswer(offer.get(), opts, nullptr));
3358 ASSERT_TRUE(answer);
Steve Antonb1c1de12017-12-21 15:14:30 -08003359 auto answer_acd = answer->contents()[0].media_description()->as_audio();
3360 auto answer_vcd = answer->contents()[1].media_description()->as_video();
Zhi Huang6f367472017-11-22 13:20:02 -08003361 // Use the parameters from the local codecs.
3362 EXPECT_TRUE(answer_acd->codecs()[0].GetParam(audio_param_name, &value));
3363 EXPECT_EQ(audio_value2, value);
3364 EXPECT_TRUE(answer_vcd->codecs()[0].GetParam(video_param_name, &value));
3365 EXPECT_EQ(video_value2, value);
3366}
3367
Steve Anton9c1fb1e2018-02-26 15:09:41 -08003368// Test that matching packetization-mode is part of the criteria for matching
3369// H264 codecs (in addition to profile-level-id). Previously, this was not the
3370// case, so the first H264 codec with the same profile-level-id would match and
3371// the payload type in the answer would be incorrect.
3372// This is a regression test for bugs.webrtc.org/8808
3373TEST_F(MediaSessionDescriptionFactoryTest,
3374 H264MatchCriteriaIncludesPacketizationMode) {
3375 // Create two H264 codecs with the same profile level ID and different
3376 // packetization modes.
3377 VideoCodec h264_pm0(96, "H264");
3378 h264_pm0.params[cricket::kH264FmtpProfileLevelId] = "42c01f";
3379 h264_pm0.params[cricket::kH264FmtpPacketizationMode] = "0";
3380 VideoCodec h264_pm1(97, "H264");
3381 h264_pm1.params[cricket::kH264FmtpProfileLevelId] = "42c01f";
3382 h264_pm1.params[cricket::kH264FmtpPacketizationMode] = "1";
3383
3384 // Offerer will send both codecs, answerer should choose the one with matching
3385 // packetization mode (and not the first one it sees).
3386 f1_.set_video_codecs({h264_pm0, h264_pm1});
3387 f2_.set_video_codecs({h264_pm1});
3388
3389 MediaSessionOptions opts;
3390 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3391 kActive, &opts);
3392
3393 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3394 ASSERT_TRUE(offer);
3395
3396 std::unique_ptr<SessionDescription> answer(
3397 f2_.CreateAnswer(offer.get(), opts, nullptr));
3398 ASSERT_TRUE(answer);
3399
3400 // Answer should have one negotiated codec with packetization-mode=1 using the
3401 // offered payload type.
3402 ASSERT_EQ(1u, answer->contents().size());
3403 auto answer_vcd = answer->contents()[0].media_description()->as_video();
3404 ASSERT_EQ(1u, answer_vcd->codecs().size());
3405 auto answer_codec = answer_vcd->codecs()[0];
3406 EXPECT_EQ(h264_pm1.id, answer_codec.id);
3407}
3408
zhihuangcf5b37c2016-05-05 11:44:35 -07003409class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
3410 public:
3411 MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -07003412 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
3413 MAKE_VECTOR(kAudioCodecs1));
zhihuangcf5b37c2016-05-05 11:44:35 -07003414 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
3415 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -07003416 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
3417 MAKE_VECTOR(kAudioCodecs2));
zhihuangcf5b37c2016-05-05 11:44:35 -07003418 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
3419 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
3420 f1_.set_secure(SEC_ENABLED);
3421 f2_.set_secure(SEC_ENABLED);
3422 tdf1_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07003423 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07003424 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07003425 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07003426 tdf1_.set_secure(SEC_ENABLED);
3427 tdf2_.set_secure(SEC_ENABLED);
3428 }
3429
3430 protected:
3431 MediaSessionDescriptionFactory f1_;
3432 MediaSessionDescriptionFactory f2_;
3433 TransportDescriptionFactory tdf1_;
3434 TransportDescriptionFactory tdf2_;
3435};
3436
3437TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
3438 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003439 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
zhihuangcf5b37c2016-05-05 11:44:35 -07003440 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3441 ASSERT_TRUE(offer.get() != nullptr);
3442 // Set the protocol for all the contents.
3443 for (auto content : offer.get()->contents()) {
Steve Antonb1c1de12017-12-21 15:14:30 -08003444 content.media_description()->set_protocol(GetParam());
zhihuangcf5b37c2016-05-05 11:44:35 -07003445 }
3446 std::unique_ptr<SessionDescription> answer(
3447 f2_.CreateAnswer(offer.get(), opts, nullptr));
3448 const ContentInfo* ac = answer->GetContentByName("audio");
3449 const ContentInfo* vc = answer->GetContentByName("video");
3450 ASSERT_TRUE(ac != nullptr);
3451 ASSERT_TRUE(vc != nullptr);
3452 EXPECT_FALSE(ac->rejected); // the offer is accepted
3453 EXPECT_FALSE(vc->rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003454 const AudioContentDescription* acd = ac->media_description()->as_audio();
3455 const VideoContentDescription* vcd = vc->media_description()->as_video();
zhihuangcf5b37c2016-05-05 11:44:35 -07003456 EXPECT_EQ(GetParam(), acd->protocol());
3457 EXPECT_EQ(GetParam(), vcd->protocol());
3458}
3459
3460INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest,
3461 MediaProtocolTest,
3462 ::testing::ValuesIn(kMediaProtocols));
3463INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest,
3464 MediaProtocolTest,
3465 ::testing::ValuesIn(kMediaProtocolsDtls));
ossu075af922016-06-14 03:29:38 -07003466
3467TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) {
3468 TransportDescriptionFactory tdf;
3469 MediaSessionDescriptionFactory sf(&tdf);
3470 std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
3471 std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
3472
3473 // The merged list of codecs should contain any send codecs that are also
3474 // nominally in the recieve codecs list. Payload types should be picked from
3475 // the send codecs and a number-of-channels of 0 and 1 should be equivalent
3476 // (set to 1). This equals what happens when the send codecs are used in an
3477 // offer and the receive codecs are used in the following answer.
3478 const std::vector<AudioCodec> sendrecv_codecs =
3479 MAKE_VECTOR(kAudioCodecsAnswer);
3480 const std::vector<AudioCodec> no_codecs;
3481
3482 RTC_CHECK_EQ(send_codecs[1].name, "iLBC")
3483 << "Please don't change shared test data!";
3484 RTC_CHECK_EQ(recv_codecs[2].name, "iLBC")
3485 << "Please don't change shared test data!";
3486 // Alter iLBC send codec to have zero channels, to test that that is handled
3487 // properly.
3488 send_codecs[1].channels = 0;
3489
3490 // Alther iLBC receive codec to be lowercase, to test that case conversions
3491 // are handled properly.
3492 recv_codecs[2].name = "ilbc";
3493
3494 // Test proper merge
3495 sf.set_audio_codecs(send_codecs, recv_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003496 EXPECT_EQ(send_codecs, sf.audio_send_codecs());
3497 EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
3498 EXPECT_EQ(sendrecv_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003499
3500 // Test empty send codecs list
3501 sf.set_audio_codecs(no_codecs, recv_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003502 EXPECT_EQ(no_codecs, sf.audio_send_codecs());
3503 EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
3504 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003505
3506 // Test empty recv codecs list
3507 sf.set_audio_codecs(send_codecs, no_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003508 EXPECT_EQ(send_codecs, sf.audio_send_codecs());
3509 EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
3510 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003511
3512 // Test all empty codec lists
3513 sf.set_audio_codecs(no_codecs, no_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003514 EXPECT_EQ(no_codecs, sf.audio_send_codecs());
3515 EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
3516 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003517}
3518
3519namespace {
zhihuang1c378ed2017-08-17 14:10:50 -07003520// Compare the two vectors of codecs ignoring the payload type.
3521template <class Codec>
3522bool CodecsMatch(const std::vector<Codec>& codecs1,
3523 const std::vector<Codec>& codecs2) {
3524 if (codecs1.size() != codecs2.size()) {
3525 return false;
3526 }
3527
3528 for (size_t i = 0; i < codecs1.size(); ++i) {
3529 if (!codecs1[i].Matches(codecs2[i])) {
3530 return false;
3531 }
3532 }
3533 return true;
3534}
3535
Steve Anton4e70a722017-11-28 14:57:10 -08003536void TestAudioCodecsOffer(RtpTransceiverDirection direction) {
ossu075af922016-06-14 03:29:38 -07003537 TransportDescriptionFactory tdf;
3538 MediaSessionDescriptionFactory sf(&tdf);
3539 const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
3540 const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
3541 const std::vector<AudioCodec> sendrecv_codecs =
3542 MAKE_VECTOR(kAudioCodecsAnswer);
3543 sf.set_audio_codecs(send_codecs, recv_codecs);
ossu075af922016-06-14 03:29:38 -07003544
3545 MediaSessionOptions opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003546 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", direction, kActive, &opts);
3547
Steve Anton4e70a722017-11-28 14:57:10 -08003548 if (direction == RtpTransceiverDirection::kSendRecv ||
3549 direction == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003550 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003551 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003552 }
ossu075af922016-06-14 03:29:38 -07003553
3554 std::unique_ptr<SessionDescription> offer(sf.CreateOffer(opts, NULL));
3555 ASSERT_TRUE(offer.get() != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08003556 ContentInfo* ac = offer->GetContentByName("audio");
ossu075af922016-06-14 03:29:38 -07003557
3558 // If the factory didn't add any audio content to the offer, we cannot check
zhihuang1c378ed2017-08-17 14:10:50 -07003559 // that the codecs put in are right. This happens when we neither want to
3560 // send nor receive audio. The checks are still in place if at some point
3561 // we'd instead create an inactive stream.
ossu075af922016-06-14 03:29:38 -07003562 if (ac) {
Steve Antonb1c1de12017-12-21 15:14:30 -08003563 AudioContentDescription* acd = ac->media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003564 // sendrecv and inactive should both present lists as if the channel was
3565 // to be used for sending and receiving. Inactive essentially means it
3566 // might eventually be used anything, but we don't know more at this
3567 // moment.
Steve Anton4e70a722017-11-28 14:57:10 -08003568 if (acd->direction() == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003569 EXPECT_TRUE(CodecsMatch<AudioCodec>(send_codecs, acd->codecs()));
Steve Anton4e70a722017-11-28 14:57:10 -08003570 } else if (acd->direction() == RtpTransceiverDirection::kRecvOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003571 EXPECT_TRUE(CodecsMatch<AudioCodec>(recv_codecs, acd->codecs()));
ossu075af922016-06-14 03:29:38 -07003572 } else {
zhihuang1c378ed2017-08-17 14:10:50 -07003573 EXPECT_TRUE(CodecsMatch<AudioCodec>(sendrecv_codecs, acd->codecs()));
ossu075af922016-06-14 03:29:38 -07003574 }
3575 }
3576}
3577
3578static const AudioCodec kOfferAnswerCodecs[] = {
zhihuang1c378ed2017-08-17 14:10:50 -07003579 AudioCodec(0, "codec0", 16000, -1, 1),
3580 AudioCodec(1, "codec1", 8000, 13300, 1),
3581 AudioCodec(2, "codec2", 8000, 64000, 1),
3582 AudioCodec(3, "codec3", 8000, 64000, 1),
3583 AudioCodec(4, "codec4", 8000, 0, 2),
3584 AudioCodec(5, "codec5", 32000, 0, 1),
3585 AudioCodec(6, "codec6", 48000, 0, 1)};
ossu075af922016-06-14 03:29:38 -07003586
zhihuang1c378ed2017-08-17 14:10:50 -07003587/* The codecs groups below are chosen as per the matrix below. The objective
3588 * is to have different sets of codecs in the inputs, to get unique sets of
3589 * codecs after negotiation, depending on offer and answer communication
3590 * directions. One-way directions in the offer should either result in the
3591 * opposite direction in the answer, or an inactive answer. Regardless, the
3592 * choice of codecs should be as if the answer contained the opposite
3593 * direction. Inactive offers should be treated as sendrecv/sendrecv.
ossu075af922016-06-14 03:29:38 -07003594 *
3595 * | Offer | Answer | Result
3596 * codec|send recv sr | send recv sr | s/r r/s sr/s sr/r sr/sr
3597 * 0 | x - - | - x - | x - - - -
3598 * 1 | x x x | - x - | x - - x -
3599 * 2 | - x - | x - - | - x - - -
3600 * 3 | x x x | x - - | - x x - -
3601 * 4 | - x - | x x x | - x - - -
3602 * 5 | x - - | x x x | x - - - -
3603 * 6 | x x x | x x x | x x x x x
3604 */
3605// Codecs used by offerer in the AudioCodecsAnswerTest
zhihuang1c378ed2017-08-17 14:10:50 -07003606static const int kOfferSendCodecs[] = {0, 1, 3, 5, 6};
3607static const int kOfferRecvCodecs[] = {1, 2, 3, 4, 6};
ossu075af922016-06-14 03:29:38 -07003608// Codecs used in the answerer in the AudioCodecsAnswerTest. The order is
3609// jumbled to catch the answer not following the order in the offer.
zhihuang1c378ed2017-08-17 14:10:50 -07003610static const int kAnswerSendCodecs[] = {6, 5, 2, 3, 4};
3611static const int kAnswerRecvCodecs[] = {6, 5, 4, 1, 0};
ossu075af922016-06-14 03:29:38 -07003612// The resulting sets of codecs in the answer in the AudioCodecsAnswerTest
zhihuang1c378ed2017-08-17 14:10:50 -07003613static const int kResultSend_RecvCodecs[] = {0, 1, 5, 6};
3614static const int kResultRecv_SendCodecs[] = {2, 3, 4, 6};
3615static const int kResultSendrecv_SendCodecs[] = {3, 6};
3616static const int kResultSendrecv_RecvCodecs[] = {1, 6};
3617static const int kResultSendrecv_SendrecvCodecs[] = {6};
ossu075af922016-06-14 03:29:38 -07003618
3619template <typename T, int IDXS>
3620std::vector<T> VectorFromIndices(const T* array, const int (&indices)[IDXS]) {
3621 std::vector<T> out;
3622 out.reserve(IDXS);
3623 for (int idx : indices)
3624 out.push_back(array[idx]);
3625
3626 return out;
3627}
3628
Steve Anton4e70a722017-11-28 14:57:10 -08003629void TestAudioCodecsAnswer(RtpTransceiverDirection offer_direction,
3630 RtpTransceiverDirection answer_direction,
ossu075af922016-06-14 03:29:38 -07003631 bool add_legacy_stream) {
3632 TransportDescriptionFactory offer_tdf;
3633 TransportDescriptionFactory answer_tdf;
3634 MediaSessionDescriptionFactory offer_factory(&offer_tdf);
3635 MediaSessionDescriptionFactory answer_factory(&answer_tdf);
3636 offer_factory.set_audio_codecs(
3637 VectorFromIndices(kOfferAnswerCodecs, kOfferSendCodecs),
3638 VectorFromIndices(kOfferAnswerCodecs, kOfferRecvCodecs));
3639 answer_factory.set_audio_codecs(
3640 VectorFromIndices(kOfferAnswerCodecs, kAnswerSendCodecs),
3641 VectorFromIndices(kOfferAnswerCodecs, kAnswerRecvCodecs));
3642
ossu075af922016-06-14 03:29:38 -07003643 MediaSessionOptions offer_opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003644 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", offer_direction, kActive,
3645 &offer_opts);
3646
Steve Anton4e70a722017-11-28 14:57:10 -08003647 if (webrtc::RtpTransceiverDirectionHasSend(offer_direction)) {
zhihuang1c378ed2017-08-17 14:10:50 -07003648 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003649 {kMediaStream1}, 1, &offer_opts);
ossu075af922016-06-14 03:29:38 -07003650 }
3651
3652 std::unique_ptr<SessionDescription> offer(
3653 offer_factory.CreateOffer(offer_opts, NULL));
3654 ASSERT_TRUE(offer.get() != NULL);
3655
3656 MediaSessionOptions answer_opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003657 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", answer_direction, kActive,
3658 &answer_opts);
3659
Steve Anton4e70a722017-11-28 14:57:10 -08003660 if (webrtc::RtpTransceiverDirectionHasSend(answer_direction)) {
zhihuang1c378ed2017-08-17 14:10:50 -07003661 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003662 {kMediaStream1}, 1, &answer_opts);
ossu075af922016-06-14 03:29:38 -07003663 }
3664 std::unique_ptr<SessionDescription> answer(
3665 answer_factory.CreateAnswer(offer.get(), answer_opts, NULL));
3666 const ContentInfo* ac = answer->GetContentByName("audio");
3667
zhihuang1c378ed2017-08-17 14:10:50 -07003668 // If the factory didn't add any audio content to the answer, we cannot
3669 // check that the codecs put in are right. This happens when we neither want
3670 // to send nor receive audio. The checks are still in place if at some point
3671 // we'd instead create an inactive stream.
ossu075af922016-06-14 03:29:38 -07003672 if (ac) {
Steve Antonb1c1de12017-12-21 15:14:30 -08003673 ASSERT_EQ(MEDIA_TYPE_AUDIO, ac->media_description()->type());
3674 const AudioContentDescription* acd = ac->media_description()->as_audio();
ossu075af922016-06-14 03:29:38 -07003675
ossu075af922016-06-14 03:29:38 -07003676 std::vector<AudioCodec> target_codecs;
3677 // For offers with sendrecv or inactive, we should never reply with more
3678 // codecs than offered, with these codec sets.
3679 switch (offer_direction) {
Steve Anton4e70a722017-11-28 14:57:10 -08003680 case RtpTransceiverDirection::kInactive:
ossu075af922016-06-14 03:29:38 -07003681 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3682 kResultSendrecv_SendrecvCodecs);
3683 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003684 case RtpTransceiverDirection::kSendOnly:
zhihuang1c378ed2017-08-17 14:10:50 -07003685 target_codecs =
3686 VectorFromIndices(kOfferAnswerCodecs, kResultSend_RecvCodecs);
ossu075af922016-06-14 03:29:38 -07003687 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003688 case RtpTransceiverDirection::kRecvOnly:
zhihuang1c378ed2017-08-17 14:10:50 -07003689 target_codecs =
3690 VectorFromIndices(kOfferAnswerCodecs, kResultRecv_SendCodecs);
ossu075af922016-06-14 03:29:38 -07003691 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003692 case RtpTransceiverDirection::kSendRecv:
3693 if (acd->direction() == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003694 target_codecs =
3695 VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_SendCodecs);
Steve Anton4e70a722017-11-28 14:57:10 -08003696 } else if (acd->direction() == RtpTransceiverDirection::kRecvOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003697 target_codecs =
3698 VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_RecvCodecs);
ossu075af922016-06-14 03:29:38 -07003699 } else {
3700 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3701 kResultSendrecv_SendrecvCodecs);
3702 }
3703 break;
3704 }
3705
zhihuang1c378ed2017-08-17 14:10:50 -07003706 auto format_codecs = [](const std::vector<AudioCodec>& codecs) {
Jonas Olsson366a50c2018-09-06 13:41:30 +02003707 rtc::StringBuilder os;
ossu075af922016-06-14 03:29:38 -07003708 bool first = true;
3709 os << "{";
3710 for (const auto& c : codecs) {
3711 os << (first ? " " : ", ") << c.id;
3712 first = false;
3713 }
3714 os << " }";
3715 return os.str();
3716 };
3717
3718 EXPECT_TRUE(acd->codecs() == target_codecs)
3719 << "Expected: " << format_codecs(target_codecs)
Steve Anton4e70a722017-11-28 14:57:10 -08003720 << ", got: " << format_codecs(acd->codecs()) << "; Offered: "
3721 << webrtc::RtpTransceiverDirectionToString(offer_direction)
ossu075af922016-06-14 03:29:38 -07003722 << ", answerer wants: "
Steve Anton4e70a722017-11-28 14:57:10 -08003723 << webrtc::RtpTransceiverDirectionToString(answer_direction)
3724 << "; got: "
3725 << webrtc::RtpTransceiverDirectionToString(acd->direction());
ossu075af922016-06-14 03:29:38 -07003726 } else {
Steve Anton4e70a722017-11-28 14:57:10 -08003727 EXPECT_EQ(offer_direction, RtpTransceiverDirection::kInactive)
zhihuang1c378ed2017-08-17 14:10:50 -07003728 << "Only inactive offers are allowed to not generate any audio "
3729 "content";
ossu075af922016-06-14 03:29:38 -07003730 }
3731}
brandtr03d5fb12016-11-22 03:37:59 -08003732
3733} // namespace
ossu075af922016-06-14 03:29:38 -07003734
3735class AudioCodecsOfferTest
Steve Anton4e70a722017-11-28 14:57:10 -08003736 : public ::testing::TestWithParam<RtpTransceiverDirection> {};
ossu075af922016-06-14 03:29:38 -07003737
3738TEST_P(AudioCodecsOfferTest, TestCodecsInOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07003739 TestAudioCodecsOffer(GetParam());
ossu075af922016-06-14 03:29:38 -07003740}
3741
3742INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
3743 AudioCodecsOfferTest,
Steve Anton4e70a722017-11-28 14:57:10 -08003744 ::testing::Values(RtpTransceiverDirection::kSendOnly,
3745 RtpTransceiverDirection::kRecvOnly,
3746 RtpTransceiverDirection::kSendRecv,
3747 RtpTransceiverDirection::kInactive));
ossu075af922016-06-14 03:29:38 -07003748
3749class AudioCodecsAnswerTest
Steve Anton4e70a722017-11-28 14:57:10 -08003750 : public ::testing::TestWithParam<::testing::tuple<RtpTransceiverDirection,
3751 RtpTransceiverDirection,
zhihuang1c378ed2017-08-17 14:10:50 -07003752 bool>> {};
ossu075af922016-06-14 03:29:38 -07003753
3754TEST_P(AudioCodecsAnswerTest, TestCodecsInAnswer) {
ehmaldonadoabcef5d2017-02-08 04:07:11 -08003755 TestAudioCodecsAnswer(::testing::get<0>(GetParam()),
3756 ::testing::get<1>(GetParam()),
3757 ::testing::get<2>(GetParam()));
ossu075af922016-06-14 03:29:38 -07003758}
3759
zhihuang1c378ed2017-08-17 14:10:50 -07003760INSTANTIATE_TEST_CASE_P(
3761 MediaSessionDescriptionFactoryTest,
3762 AudioCodecsAnswerTest,
Steve Anton4e70a722017-11-28 14:57:10 -08003763 ::testing::Combine(::testing::Values(RtpTransceiverDirection::kSendOnly,
3764 RtpTransceiverDirection::kRecvOnly,
3765 RtpTransceiverDirection::kSendRecv,
3766 RtpTransceiverDirection::kInactive),
3767 ::testing::Values(RtpTransceiverDirection::kSendOnly,
3768 RtpTransceiverDirection::kRecvOnly,
3769 RtpTransceiverDirection::kSendRecv,
3770 RtpTransceiverDirection::kInactive),
zhihuang1c378ed2017-08-17 14:10:50 -07003771 ::testing::Bool()));