blob: 3af86eaa8a2f14779ef90139f3d1e1e487a02063 [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) {
Steve Anton3a66edf2018-09-10 12:57:37 -0700324 std::vector<cricket::SenderOptions>& sender_options_list =
325 FindFirstMediaDescriptionByMid(mid, session_options)->sender_options;
326 auto sender_it =
327 std::find_if(sender_options_list.begin(), sender_options_list.end(),
328 [track_id](const cricket::SenderOptions& sender_options) {
329 return sender_options.track_id == track_id;
330 });
331 RTC_DCHECK(sender_it != sender_options_list.end());
332 sender_options_list.erase(sender_it);
zhihuang1c378ed2017-08-17 14:10:50 -0700333}
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);
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700612 offer_opts.crypto_options.srtp.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);
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700616 answer_opts.crypto_options.srtp.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();
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700956 opts.crypto_options.srtp.enable_gcm_crypto_suites = true;
zhihuang1c378ed2017-08-17 14:10:50 -0700957 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);
Benjamin Wrighta54daf12018-10-11 15:33:17 -07001060 opts.crypto_options.srtp.enable_gcm_crypto_suites = true;
jbauchcb560652016-08-04 05:20:32 -07001061 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
Johannes Kron0854eb62018-10-10 22:33:20 +02001584TEST_F(MediaSessionDescriptionFactoryTest,
1585 CreateAnswerSupportsMixedOneAndTwoByteHeaderExtensions) {
1586 MediaSessionOptions opts;
1587 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1588 // Offer without request of mixed one- and two-byte header extensions.
Johannes Kron9581bc42018-10-23 10:17:39 +02001589 offer->set_extmap_allow_mixed(false);
Johannes Kron0854eb62018-10-10 22:33:20 +02001590 ASSERT_TRUE(offer.get() != NULL);
1591 std::unique_ptr<SessionDescription> answer_no_support(
1592 f2_.CreateAnswer(offer.get(), opts, NULL));
Johannes Kron9581bc42018-10-23 10:17:39 +02001593 EXPECT_FALSE(answer_no_support->extmap_allow_mixed());
Johannes Kron0854eb62018-10-10 22:33:20 +02001594
1595 // Offer with request of mixed one- and two-byte header extensions.
Johannes Kron9581bc42018-10-23 10:17:39 +02001596 offer->set_extmap_allow_mixed(true);
Johannes Kron0854eb62018-10-10 22:33:20 +02001597 ASSERT_TRUE(offer.get() != NULL);
1598 std::unique_ptr<SessionDescription> answer_support(
1599 f2_.CreateAnswer(offer.get(), opts, NULL));
Johannes Kron9581bc42018-10-23 10:17:39 +02001600 EXPECT_TRUE(answer_support->extmap_allow_mixed());
Johannes Kron0854eb62018-10-10 22:33:20 +02001601}
1602
1603TEST_F(MediaSessionDescriptionFactoryTest,
1604 CreateAnswerSupportsMixedOneAndTwoByteHeaderExtensionsOnMediaLevel) {
1605 MediaSessionOptions opts;
1606 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
1607 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1608 MediaContentDescription* video_offer =
1609 offer->GetContentDescriptionByName("video");
1610 ASSERT_TRUE(video_offer);
1611 MediaContentDescription* audio_offer =
1612 offer->GetContentDescriptionByName("audio");
1613 ASSERT_TRUE(audio_offer);
1614
1615 // Explicit disable of mixed one-two byte header support in offer.
Johannes Kron9581bc42018-10-23 10:17:39 +02001616 video_offer->set_extmap_allow_mixed_enum(MediaContentDescription::kNo);
1617 audio_offer->set_extmap_allow_mixed_enum(MediaContentDescription::kNo);
Johannes Kron0854eb62018-10-10 22:33:20 +02001618
1619 ASSERT_TRUE(offer.get() != NULL);
1620 std::unique_ptr<SessionDescription> answer_no_support(
1621 f2_.CreateAnswer(offer.get(), opts, NULL));
1622 MediaContentDescription* video_answer =
1623 answer_no_support->GetContentDescriptionByName("video");
1624 MediaContentDescription* audio_answer =
1625 answer_no_support->GetContentDescriptionByName("audio");
1626 EXPECT_EQ(MediaContentDescription::kNo,
Johannes Kron9581bc42018-10-23 10:17:39 +02001627 video_answer->extmap_allow_mixed_enum());
Johannes Kron0854eb62018-10-10 22:33:20 +02001628 EXPECT_EQ(MediaContentDescription::kNo,
Johannes Kron9581bc42018-10-23 10:17:39 +02001629 audio_answer->extmap_allow_mixed_enum());
Johannes Kron0854eb62018-10-10 22:33:20 +02001630
1631 // Enable mixed one-two byte header support in offer.
Johannes Kron9581bc42018-10-23 10:17:39 +02001632 video_offer->set_extmap_allow_mixed_enum(MediaContentDescription::kMedia);
1633 audio_offer->set_extmap_allow_mixed_enum(MediaContentDescription::kMedia);
Johannes Kron0854eb62018-10-10 22:33:20 +02001634 ASSERT_TRUE(offer.get() != NULL);
1635 std::unique_ptr<SessionDescription> answer_support(
1636 f2_.CreateAnswer(offer.get(), opts, NULL));
1637 video_answer = answer_support->GetContentDescriptionByName("video");
1638 audio_answer = answer_support->GetContentDescriptionByName("audio");
1639 EXPECT_EQ(MediaContentDescription::kMedia,
Johannes Kron9581bc42018-10-23 10:17:39 +02001640 video_answer->extmap_allow_mixed_enum());
Johannes Kron0854eb62018-10-10 22:33:20 +02001641 EXPECT_EQ(MediaContentDescription::kMedia,
Johannes Kron9581bc42018-10-23 10:17:39 +02001642 audio_answer->extmap_allow_mixed_enum());
Johannes Kron0854eb62018-10-10 22:33:20 +02001643}
1644
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001645// Create an audio and video offer with:
1646// - one video track
1647// - two audio tracks
1648// - two data tracks
1649// and ensure it matches what we expect. Also updates the initial offer by
1650// adding a new video track and replaces one of the audio tracks.
1651TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1652 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001653 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001654 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001655 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001656 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001657 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001658 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001659 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001660
Steve Anton4e70a722017-11-28 14:57:10 -08001661 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001662 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001663 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001664 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001665 {kMediaStream1}, 1, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001666
1667 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001668 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001669
1670 ASSERT_TRUE(offer.get() != NULL);
1671 const ContentInfo* ac = offer->GetContentByName("audio");
1672 const ContentInfo* vc = offer->GetContentByName("video");
1673 const ContentInfo* dc = offer->GetContentByName("data");
1674 ASSERT_TRUE(ac != NULL);
1675 ASSERT_TRUE(vc != NULL);
1676 ASSERT_TRUE(dc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001677 const AudioContentDescription* acd = ac->media_description()->as_audio();
1678 const VideoContentDescription* vcd = vc->media_description()->as_video();
1679 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001680 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -07001681 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001682
1683 const StreamParamsVec& audio_streams = acd->streams();
1684 ASSERT_EQ(2U, audio_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001685 EXPECT_EQ(audio_streams[0].cname, audio_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001686 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1687 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1688 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1689 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1690 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1691 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1692
1693 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1694 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001695 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001696
1697 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1698 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001699 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001700
1701 const StreamParamsVec& video_streams = vcd->streams();
1702 ASSERT_EQ(1U, video_streams.size());
1703 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1704 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1705 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1706 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1707
1708 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1709 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001710 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001711
1712 const StreamParamsVec& data_streams = dcd->streams();
1713 ASSERT_EQ(2U, data_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001714 EXPECT_EQ(data_streams[0].cname, data_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001715 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1716 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1717 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1718 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1719 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1720 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1721
1722 EXPECT_EQ(cricket::kDataMaxBandwidth,
Yves Gerey665174f2018-06-19 15:03:05 +02001723 dcd->bandwidth()); // default bandwidth (auto)
1724 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001725 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001726
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001727 // Update the offer. Add a new video track that is not synched to the
1728 // other tracks and replace audio track 2 with audio track 3.
zhihuang1c378ed2017-08-17 14:10:50 -07001729 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001730 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001731 DetachSenderFromMediaSection("audio", kAudioTrack2, &opts);
1732 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack3,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001733 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001734 DetachSenderFromMediaSection("data", kDataTrack2, &opts);
1735 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack3,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001736 {kMediaStream1}, 1, &opts);
kwiberg31022942016-03-11 14:18:21 -08001737 std::unique_ptr<SessionDescription> updated_offer(
1738 f1_.CreateOffer(opts, offer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001739
1740 ASSERT_TRUE(updated_offer.get() != NULL);
1741 ac = updated_offer->GetContentByName("audio");
1742 vc = updated_offer->GetContentByName("video");
1743 dc = updated_offer->GetContentByName("data");
1744 ASSERT_TRUE(ac != NULL);
1745 ASSERT_TRUE(vc != NULL);
1746 ASSERT_TRUE(dc != NULL);
1747 const AudioContentDescription* updated_acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001748 ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001749 const VideoContentDescription* updated_vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001750 vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001751 const DataContentDescription* updated_dcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001752 dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001753
1754 EXPECT_EQ(acd->type(), updated_acd->type());
1755 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1756 EXPECT_EQ(vcd->type(), updated_vcd->type());
1757 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1758 EXPECT_EQ(dcd->type(), updated_dcd->type());
1759 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001760 ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001761 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001762 ASSERT_CRYPTO(updated_vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001763 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001764 ASSERT_CRYPTO(updated_dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001765 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1766
1767 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1768 ASSERT_EQ(2U, updated_audio_streams.size());
1769 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1770 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1771 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1772 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1773 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1774
1775 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1776 ASSERT_EQ(2U, updated_video_streams.size());
1777 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1778 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001779 // All the media streams in one PeerConnection share one RTCP CNAME.
1780 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001781
1782 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1783 ASSERT_EQ(2U, updated_data_streams.size());
1784 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1785 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1786 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1787 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1788 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
zhihuang8f65cdf2016-05-06 18:40:30 -07001789 // The stream correctly got the CNAME from the MediaSessionOptions.
1790 // The Expected RTCP CNAME is the default one as we are using the default
1791 // MediaSessionOptions.
1792 EXPECT_EQ(updated_data_streams[0].cname, cricket::kDefaultRtcpCname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001793}
1794
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001795// Create an offer with simulcast video stream.
1796TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1797 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001798 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1799 kActive, &opts);
1800 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
1801 kActive, &opts);
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001802 const int num_sim_layers = 3;
zhihuang1c378ed2017-08-17 14:10:50 -07001803 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001804 {kMediaStream1}, num_sim_layers, &opts);
kwiberg31022942016-03-11 14:18:21 -08001805 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001806
1807 ASSERT_TRUE(offer.get() != NULL);
1808 const ContentInfo* vc = offer->GetContentByName("video");
1809 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001810 const VideoContentDescription* vcd = vc->media_description()->as_video();
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001811
1812 const StreamParamsVec& video_streams = vcd->streams();
1813 ASSERT_EQ(1U, video_streams.size());
1814 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1815 const SsrcGroup* sim_ssrc_group =
1816 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1817 ASSERT_TRUE(sim_ssrc_group != NULL);
1818 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1819}
1820
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001821// Create an audio and video answer to a standard video offer with:
1822// - one video track
1823// - two audio tracks
1824// - two data tracks
1825// and ensure it matches what we expect. Also updates the initial answer by
1826// adding a new video track and removes one of the audio tracks.
1827TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1828 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001829 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1830 kActive, &offer_opts);
1831 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1832 kActive, &offer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001833 offer_opts.data_channel_type = cricket::DCT_RTP;
Steve Anton4e70a722017-11-28 14:57:10 -08001834 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kRecvOnly,
1835 kActive, &offer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001836 f1_.set_secure(SEC_ENABLED);
1837 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001838 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001839
zhihuang1c378ed2017-08-17 14:10:50 -07001840 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001841 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
1842 kActive, &answer_opts);
1843 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
1844 kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001845 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001846 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001847 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001848 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001849 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001850 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001851
Steve Anton4e70a722017-11-28 14:57:10 -08001852 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kSendRecv,
1853 kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001854 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001855 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001856 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001857 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001858 answer_opts.data_channel_type = cricket::DCT_RTP;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001859
kwiberg31022942016-03-11 14:18:21 -08001860 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001861 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001862
1863 ASSERT_TRUE(answer.get() != NULL);
1864 const ContentInfo* ac = answer->GetContentByName("audio");
1865 const ContentInfo* vc = answer->GetContentByName("video");
1866 const ContentInfo* dc = answer->GetContentByName("data");
1867 ASSERT_TRUE(ac != NULL);
1868 ASSERT_TRUE(vc != NULL);
1869 ASSERT_TRUE(dc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001870 const AudioContentDescription* acd = ac->media_description()->as_audio();
1871 const VideoContentDescription* vcd = vc->media_description()->as_video();
1872 const DataContentDescription* dcd = dc->media_description()->as_data();
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001873 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
1874 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
1875 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001876
1877 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1878 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1879
1880 const StreamParamsVec& audio_streams = acd->streams();
1881 ASSERT_EQ(2U, audio_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001882 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001883 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1884 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1885 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1886 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1887 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1888 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1889
1890 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1891 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1892
1893 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1894 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1895
1896 const StreamParamsVec& video_streams = vcd->streams();
1897 ASSERT_EQ(1U, video_streams.size());
1898 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1899 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1900 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1901 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1902
1903 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1904 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1905
1906 const StreamParamsVec& data_streams = dcd->streams();
1907 ASSERT_EQ(2U, data_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001908 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001909 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1910 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1911 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1912 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1913 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1914 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1915
1916 EXPECT_EQ(cricket::kDataMaxBandwidth,
Yves Gerey665174f2018-06-19 15:03:05 +02001917 dcd->bandwidth()); // default bandwidth (auto)
1918 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001919
1920 // Update the answer. Add a new video track that is not synched to the
zhihuang8f65cdf2016-05-06 18:40:30 -07001921 // other tracks and remove 1 audio track.
zhihuang1c378ed2017-08-17 14:10:50 -07001922 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001923 {kMediaStream2}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001924 DetachSenderFromMediaSection("audio", kAudioTrack2, &answer_opts);
1925 DetachSenderFromMediaSection("data", kDataTrack2, &answer_opts);
kwiberg31022942016-03-11 14:18:21 -08001926 std::unique_ptr<SessionDescription> updated_answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001927 f2_.CreateAnswer(offer.get(), answer_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001928
1929 ASSERT_TRUE(updated_answer.get() != NULL);
1930 ac = updated_answer->GetContentByName("audio");
1931 vc = updated_answer->GetContentByName("video");
1932 dc = updated_answer->GetContentByName("data");
1933 ASSERT_TRUE(ac != NULL);
1934 ASSERT_TRUE(vc != NULL);
1935 ASSERT_TRUE(dc != NULL);
1936 const AudioContentDescription* updated_acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001937 ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001938 const VideoContentDescription* updated_vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001939 vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001940 const DataContentDescription* updated_dcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001941 dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001942
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001943 ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001944 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001945 ASSERT_CRYPTO(updated_vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001946 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001947 ASSERT_CRYPTO(updated_dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001948 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1949
1950 EXPECT_EQ(acd->type(), updated_acd->type());
1951 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1952 EXPECT_EQ(vcd->type(), updated_vcd->type());
1953 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1954 EXPECT_EQ(dcd->type(), updated_dcd->type());
1955 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1956
1957 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1958 ASSERT_EQ(1U, updated_audio_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001959 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001960
1961 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1962 ASSERT_EQ(2U, updated_video_streams.size());
1963 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1964 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001965 // All media streams in one PeerConnection share one CNAME.
1966 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001967
1968 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1969 ASSERT_EQ(1U, updated_data_streams.size());
1970 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1971}
1972
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001973// Create an updated offer after creating an answer to the original offer and
1974// verify that the codecs that were part of the original answer are not changed
1975// in the updated offer.
1976TEST_F(MediaSessionDescriptionFactoryTest,
1977 RespondentCreatesOfferAfterCreatingAnswer) {
1978 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001979 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001980
kwiberg31022942016-03-11 14:18:21 -08001981 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1982 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001983 f2_.CreateAnswer(offer.get(), opts, NULL));
1984
1985 const AudioContentDescription* acd =
1986 GetFirstAudioContentDescription(answer.get());
1987 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1988
1989 const VideoContentDescription* vcd =
1990 GetFirstVideoContentDescription(answer.get());
1991 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1992
kwiberg31022942016-03-11 14:18:21 -08001993 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001994 f2_.CreateOffer(opts, answer.get()));
1995
1996 // The expected audio codecs are the common audio codecs from the first
1997 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1998 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001999 // TODO(wu): |updated_offer| should not include the codec
2000 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002001 const AudioCodec kUpdatedAudioCodecOffer[] = {
Yves Gerey665174f2018-06-19 15:03:05 +02002002 kAudioCodecsAnswer[0], kAudioCodecsAnswer[1], kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002003 };
2004
2005 // The expected video codecs are the common video codecs from the first
2006 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
2007 // preference order.
2008 const VideoCodec kUpdatedVideoCodecOffer[] = {
Yves Gerey665174f2018-06-19 15:03:05 +02002009 kVideoCodecsAnswer[0], kVideoCodecs2[1],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002010 };
2011
2012 const AudioContentDescription* updated_acd =
2013 GetFirstAudioContentDescription(updated_offer.get());
2014 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
2015
2016 const VideoContentDescription* updated_vcd =
2017 GetFirstVideoContentDescription(updated_offer.get());
2018 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
2019}
2020
2021// Create an updated offer after creating an answer to the original offer and
2022// verify that the codecs that were part of the original answer are not changed
2023// in the updated offer. In this test Rtx is enabled.
2024TEST_F(MediaSessionDescriptionFactoryTest,
2025 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
2026 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002027 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2028 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002029 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002030 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002031 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002032 f1_.set_video_codecs(f1_codecs);
2033
2034 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002035 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002036 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002037 f2_.set_video_codecs(f2_codecs);
2038
kwiberg31022942016-03-11 14:18:21 -08002039 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002040 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002041 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002042 f2_.CreateAnswer(offer.get(), opts, NULL));
2043
2044 const VideoContentDescription* vcd =
2045 GetFirstVideoContentDescription(answer.get());
2046
2047 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002048 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2049 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002050
2051 EXPECT_EQ(expected_codecs, vcd->codecs());
2052
deadbeef67cf2c12016-04-13 10:07:16 -07002053 // Now, make sure we get same result (except for the order) if |f2_| creates
2054 // an updated offer even though the default payload types between |f1_| and
2055 // |f2_| are different.
kwiberg31022942016-03-11 14:18:21 -08002056 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002057 f2_.CreateOffer(opts, answer.get()));
2058 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08002059 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002060 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
2061
2062 const VideoContentDescription* updated_vcd =
2063 GetFirstVideoContentDescription(updated_answer.get());
2064
2065 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
2066}
2067
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002068// Regression test for:
2069// https://bugs.chromium.org/p/webrtc/issues/detail?id=8332
2070// Existing codecs should always appear before new codecs in re-offers. But
2071// under a specific set of circumstances, the existing RTX codec was ending up
2072// added to the end of the list.
2073TEST_F(MediaSessionDescriptionFactoryTest,
2074 RespondentCreatesOfferAfterCreatingAnswerWithRemappedRtxPayloadType) {
2075 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002076 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2077 kActive, &opts);
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002078 // We specifically choose different preferred payload types for VP8 to
2079 // trigger the issue.
2080 cricket::VideoCodec vp8_offerer(100, "VP8");
2081 cricket::VideoCodec vp8_offerer_rtx =
2082 VideoCodec::CreateRtxCodec(101, vp8_offerer.id);
2083 cricket::VideoCodec vp8_answerer(110, "VP8");
2084 cricket::VideoCodec vp8_answerer_rtx =
2085 VideoCodec::CreateRtxCodec(111, vp8_answerer.id);
2086 cricket::VideoCodec vp9(120, "VP9");
2087 cricket::VideoCodec vp9_rtx = VideoCodec::CreateRtxCodec(121, vp9.id);
2088
2089 std::vector<VideoCodec> f1_codecs = {vp8_offerer, vp8_offerer_rtx};
2090 // We also specifically cause the answerer to prefer VP9, such that if it
2091 // *doesn't* honor the existing preferred codec (VP8) we'll notice.
2092 std::vector<VideoCodec> f2_codecs = {vp9, vp9_rtx, vp8_answerer,
2093 vp8_answerer_rtx};
2094
2095 f1_.set_video_codecs(f1_codecs);
2096 f2_.set_video_codecs(f2_codecs);
2097 std::vector<AudioCodec> audio_codecs;
2098 f1_.set_audio_codecs(audio_codecs, audio_codecs);
2099 f2_.set_audio_codecs(audio_codecs, audio_codecs);
2100
2101 // Offer will be {VP8, RTX for VP8}. Answer will be the same.
2102 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2103 ASSERT_TRUE(offer.get() != NULL);
2104 std::unique_ptr<SessionDescription> answer(
2105 f2_.CreateAnswer(offer.get(), opts, NULL));
2106
2107 // Updated offer *should* be {VP8, RTX for VP8, VP9, RTX for VP9}.
2108 // But if the bug is triggered, RTX for VP8 ends up last.
2109 std::unique_ptr<SessionDescription> updated_offer(
2110 f2_.CreateOffer(opts, answer.get()));
2111
2112 const VideoContentDescription* vcd =
2113 GetFirstVideoContentDescription(updated_offer.get());
2114 std::vector<cricket::VideoCodec> codecs = vcd->codecs();
2115 ASSERT_EQ(4u, codecs.size());
2116 EXPECT_EQ(vp8_offerer, codecs[0]);
2117 EXPECT_EQ(vp8_offerer_rtx, codecs[1]);
2118 EXPECT_EQ(vp9, codecs[2]);
2119 EXPECT_EQ(vp9_rtx, codecs[3]);
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002120}
2121
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002122// Create an updated offer that adds video after creating an audio only answer
2123// to the original offer. This test verifies that if a video codec and the RTX
2124// codec have the same default payload type as an audio codec that is already in
2125// use, the added codecs payload types are changed.
2126TEST_F(MediaSessionDescriptionFactoryTest,
2127 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
2128 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002129 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002130 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002131 f1_.set_video_codecs(f1_codecs);
2132
2133 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002134 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2135 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002136
kwiberg31022942016-03-11 14:18:21 -08002137 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2138 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002139 f2_.CreateAnswer(offer.get(), opts, NULL));
2140
2141 const AudioContentDescription* acd =
2142 GetFirstAudioContentDescription(answer.get());
2143 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
2144
2145 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
2146 // reference be the same as an audio codec that was negotiated in the
2147 // first offer/answer exchange.
zhihuang1c378ed2017-08-17 14:10:50 -07002148 opts.media_description_options.clear();
Steve Anton4e70a722017-11-28 14:57:10 -08002149 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002150
2151 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2152 int used_pl_type = acd->codecs()[0].id;
2153 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002154 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002155 f2_.set_video_codecs(f2_codecs);
2156
kwiberg31022942016-03-11 14:18:21 -08002157 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002158 f2_.CreateOffer(opts, answer.get()));
2159 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08002160 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002161 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
2162
2163 const AudioContentDescription* updated_acd =
2164 GetFirstAudioContentDescription(answer.get());
2165 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
2166
2167 const VideoContentDescription* updated_vcd =
2168 GetFirstVideoContentDescription(updated_answer.get());
2169
2170 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00002171 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
Yves Gerey665174f2018-06-19 15:03:05 +02002172 int new_h264_pl_type = updated_vcd->codecs()[0].id;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002173 EXPECT_NE(used_pl_type, new_h264_pl_type);
2174 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002175 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002176 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
2177 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
2178}
2179
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002180// Create an updated offer with RTX after creating an answer to an offer
2181// without RTX, and with different default payload types.
2182// Verify that the added RTX codec references the correct payload type.
2183TEST_F(MediaSessionDescriptionFactoryTest,
2184 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
2185 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002186 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002187
2188 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2189 // This creates rtx for H264 with the payload type |f2_| uses.
2190 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
2191 f2_.set_video_codecs(f2_codecs);
2192
kwiberg31022942016-03-11 14:18:21 -08002193 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002194 ASSERT_TRUE(offer.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08002195 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002196 f2_.CreateAnswer(offer.get(), opts, nullptr));
2197
2198 const VideoContentDescription* vcd =
2199 GetFirstVideoContentDescription(answer.get());
2200
2201 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2202 EXPECT_EQ(expected_codecs, vcd->codecs());
2203
2204 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
2205 // updated offer, even though the default payload types are different from
2206 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08002207 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002208 f2_.CreateOffer(opts, answer.get()));
2209 ASSERT_TRUE(updated_offer);
2210
2211 const VideoContentDescription* updated_vcd =
2212 GetFirstVideoContentDescription(updated_offer.get());
2213
2214 // New offer should attempt to add H263, and RTX for H264.
2215 expected_codecs.push_back(kVideoCodecs2[1]);
2216 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
2217 &expected_codecs);
2218 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
2219}
2220
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002221// Test that RTX is ignored when there is no associated payload type parameter.
2222TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
2223 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002224 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2225 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002226 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002227 // This creates RTX without associated payload type parameter.
perkj26752742016-10-24 01:21:16 -07002228 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002229 f1_.set_video_codecs(f1_codecs);
2230
2231 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002232 // This creates RTX for H264 with the payload type |f2_| uses.
2233 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002234 f2_.set_video_codecs(f2_codecs);
2235
kwiberg31022942016-03-11 14:18:21 -08002236 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002237 ASSERT_TRUE(offer.get() != NULL);
2238 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
2239 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
2240 // is possible to test that that RTX is dropped when
2241 // kCodecParamAssociatedPayloadType is missing in the offer.
Steve Antonb1c1de12017-12-21 15:14:30 -08002242 MediaContentDescription* media_desc =
2243 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2244 ASSERT_TRUE(media_desc);
2245 VideoContentDescription* desc = media_desc->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002246 std::vector<VideoCodec> codecs = desc->codecs();
Steve Anton3a66edf2018-09-10 12:57:37 -07002247 for (VideoCodec& codec : codecs) {
2248 if (codec.name.find(cricket::kRtxCodecName) == 0) {
2249 codec.params.clear();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002250 }
2251 }
2252 desc->set_codecs(codecs);
2253
kwiberg31022942016-03-11 14:18:21 -08002254 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002255 f2_.CreateAnswer(offer.get(), opts, NULL));
2256
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002257 std::vector<std::string> codec_names =
2258 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
2259 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
2260 cricket::kRtxCodecName));
2261}
2262
2263// Test that RTX will be filtered out in the answer if its associated payload
2264// type doesn't match the local value.
2265TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
2266 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002267 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2268 kActive, &opts);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002269 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2270 // This creates RTX for H264 in sender.
2271 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2272 f1_.set_video_codecs(f1_codecs);
2273
2274 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2275 // This creates RTX for H263 in receiver.
2276 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
2277 f2_.set_video_codecs(f2_codecs);
2278
kwiberg31022942016-03-11 14:18:21 -08002279 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002280 ASSERT_TRUE(offer.get() != NULL);
2281 // Associated payload type doesn't match, therefore, RTX codec is removed in
2282 // the answer.
kwiberg31022942016-03-11 14:18:21 -08002283 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002284 f2_.CreateAnswer(offer.get(), opts, NULL));
2285
2286 std::vector<std::string> codec_names =
2287 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
2288 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
2289 cricket::kRtxCodecName));
2290}
2291
2292// Test that when multiple RTX codecs are offered, only the matched RTX codec
2293// is added in the answer, and the unsupported RTX codec is filtered out.
2294TEST_F(MediaSessionDescriptionFactoryTest,
2295 FilterOutUnsupportedRtxWhenCreatingAnswer) {
2296 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002297 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2298 kActive, &opts);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002299 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2300 // This creates RTX for H264-SVC in sender.
2301 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
2302 f1_.set_video_codecs(f1_codecs);
2303
2304 // This creates RTX for H264 in sender.
2305 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2306 f1_.set_video_codecs(f1_codecs);
2307
2308 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2309 // This creates RTX for H264 in receiver.
2310 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
2311 f2_.set_video_codecs(f2_codecs);
2312
2313 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
2314 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08002315 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002316 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002317 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002318 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002319 const VideoContentDescription* vcd =
2320 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002321 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2322 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2323 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002324
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002325 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002326}
2327
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002328// Test that after one RTX codec has been negotiated, a new offer can attempt
2329// to add another.
2330TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
2331 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002332 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2333 kActive, &opts);
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002334 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2335 // This creates RTX for H264 for the offerer.
2336 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2337 f1_.set_video_codecs(f1_codecs);
2338
kwiberg31022942016-03-11 14:18:21 -08002339 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002340 ASSERT_TRUE(offer);
2341 const VideoContentDescription* vcd =
2342 GetFirstVideoContentDescription(offer.get());
2343
2344 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
2345 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2346 &expected_codecs);
2347 EXPECT_EQ(expected_codecs, vcd->codecs());
2348
2349 // Now, attempt to add RTX for H264-SVC.
2350 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
2351 f1_.set_video_codecs(f1_codecs);
2352
kwiberg31022942016-03-11 14:18:21 -08002353 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002354 f1_.CreateOffer(opts, offer.get()));
2355 ASSERT_TRUE(updated_offer);
2356 vcd = GetFirstVideoContentDescription(updated_offer.get());
2357
2358 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
2359 &expected_codecs);
2360 EXPECT_EQ(expected_codecs, vcd->codecs());
2361}
2362
Noah Richards2e7a0982015-05-18 14:02:54 -07002363// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
2364// generated for each simulcast ssrc and correctly grouped.
2365TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
2366 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002367 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2368 kActive, &opts);
Noah Richards2e7a0982015-05-18 14:02:54 -07002369 // Add simulcast streams.
zhihuang1c378ed2017-08-17 14:10:50 -07002370 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002371 {"stream1label"}, 3, &opts);
Noah Richards2e7a0982015-05-18 14:02:54 -07002372
2373 // Use a single real codec, and then add RTX for it.
2374 std::vector<VideoCodec> f1_codecs;
perkj26752742016-10-24 01:21:16 -07002375 f1_codecs.push_back(VideoCodec(97, "H264"));
Noah Richards2e7a0982015-05-18 14:02:54 -07002376 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
2377 f1_.set_video_codecs(f1_codecs);
2378
2379 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
2380 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08002381 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07002382 ASSERT_TRUE(offer.get() != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002383 MediaContentDescription* media_desc =
2384 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2385 ASSERT_TRUE(media_desc);
2386 VideoContentDescription* desc = media_desc->as_video();
Noah Richards2e7a0982015-05-18 14:02:54 -07002387 const StreamParamsVec& streams = desc->streams();
2388 // Single stream.
2389 ASSERT_EQ(1u, streams.size());
2390 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
2391 EXPECT_EQ(6u, streams[0].ssrcs.size());
2392 // And should have a SIM group for the simulcast.
2393 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2394 // And a FID group for RTX.
2395 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02002396 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002397 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2398 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02002399 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002400 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
2401 EXPECT_EQ(3u, fid_ssrcs.size());
2402}
2403
brandtr03d5fb12016-11-22 03:37:59 -08002404// Test that, when the FlexFEC codec is added, a FlexFEC ssrc is created
2405// together with a FEC-FR grouping.
2406TEST_F(MediaSessionDescriptionFactoryTest, GenerateFlexfecSsrc) {
2407 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002408 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2409 kActive, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002410 // Add single stream.
zhihuang1c378ed2017-08-17 14:10:50 -07002411 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002412 {"stream1label"}, 1, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002413
2414 // Use a single real codec, and then add FlexFEC for it.
2415 std::vector<VideoCodec> f1_codecs;
2416 f1_codecs.push_back(VideoCodec(97, "H264"));
2417 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2418 f1_.set_video_codecs(f1_codecs);
2419
2420 // Ensure that the offer has a single FlexFEC ssrc and that
2421 // there is no FEC-FR ssrc + grouping for each.
2422 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2423 ASSERT_TRUE(offer.get() != nullptr);
Steve Antonb1c1de12017-12-21 15:14:30 -08002424 MediaContentDescription* media_desc =
2425 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2426 ASSERT_TRUE(media_desc);
2427 VideoContentDescription* desc = media_desc->as_video();
brandtr03d5fb12016-11-22 03:37:59 -08002428 const StreamParamsVec& streams = desc->streams();
2429 // Single stream.
2430 ASSERT_EQ(1u, streams.size());
2431 // Stream should have 2 ssrcs: 1 for video, 1 for FlexFEC.
2432 EXPECT_EQ(2u, streams[0].ssrcs.size());
2433 // And should have a FEC-FR group for FlexFEC.
2434 EXPECT_TRUE(streams[0].has_ssrc_group("FEC-FR"));
2435 std::vector<uint32_t> primary_ssrcs;
2436 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2437 ASSERT_EQ(1u, primary_ssrcs.size());
2438 uint32_t flexfec_ssrc;
2439 EXPECT_TRUE(streams[0].GetFecFrSsrc(primary_ssrcs[0], &flexfec_ssrc));
2440 EXPECT_NE(flexfec_ssrc, 0u);
2441}
2442
2443// Test that FlexFEC is disabled for simulcast.
2444// TODO(brandtr): Remove this test when we support simulcast, either through
2445// multiple FlexfecSenders, or through multistream protection.
2446TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateNoFlexfecSsrcs) {
2447 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002448 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2449 kActive, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002450 // Add simulcast streams.
zhihuang1c378ed2017-08-17 14:10:50 -07002451 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002452 {"stream1label"}, 3, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002453
2454 // Use a single real codec, and then add FlexFEC for it.
2455 std::vector<VideoCodec> f1_codecs;
2456 f1_codecs.push_back(VideoCodec(97, "H264"));
2457 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2458 f1_.set_video_codecs(f1_codecs);
2459
2460 // Ensure that the offer has no FlexFEC ssrcs for each regular ssrc, and that
2461 // there is no FEC-FR ssrc + grouping for each.
2462 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2463 ASSERT_TRUE(offer.get() != nullptr);
Steve Antonb1c1de12017-12-21 15:14:30 -08002464 MediaContentDescription* media_desc =
2465 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2466 ASSERT_TRUE(media_desc);
2467 VideoContentDescription* desc = media_desc->as_video();
brandtr03d5fb12016-11-22 03:37:59 -08002468 const StreamParamsVec& streams = desc->streams();
2469 // Single stream.
2470 ASSERT_EQ(1u, streams.size());
2471 // Stream should have 3 ssrcs: 3 for video, 0 for FlexFEC.
2472 EXPECT_EQ(3u, streams[0].ssrcs.size());
2473 // And should have a SIM group for the simulcast.
2474 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2475 // And not a FEC-FR group for FlexFEC.
2476 EXPECT_FALSE(streams[0].has_ssrc_group("FEC-FR"));
2477 std::vector<uint32_t> primary_ssrcs;
2478 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2479 EXPECT_EQ(3u, primary_ssrcs.size());
2480 for (uint32_t primary_ssrc : primary_ssrcs) {
2481 uint32_t flexfec_ssrc;
2482 EXPECT_FALSE(streams[0].GetFecFrSsrc(primary_ssrc, &flexfec_ssrc));
2483 }
2484}
2485
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002486// Create an updated offer after creating an answer to the original offer and
2487// verify that the RTP header extensions that were part of the original answer
2488// are not changed in the updated offer.
2489TEST_F(MediaSessionDescriptionFactoryTest,
2490 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
2491 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002492 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002493
2494 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
2495 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
2496 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
2497 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
2498
kwiberg31022942016-03-11 14:18:21 -08002499 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2500 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002501 f2_.CreateAnswer(offer.get(), opts, NULL));
2502
Yves Gerey665174f2018-06-19 15:03:05 +02002503 EXPECT_EQ(
2504 MAKE_VECTOR(kAudioRtpExtensionAnswer),
2505 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
2506 EXPECT_EQ(
2507 MAKE_VECTOR(kVideoRtpExtensionAnswer),
2508 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002509
kwiberg31022942016-03-11 14:18:21 -08002510 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002511 f2_.CreateOffer(opts, answer.get()));
2512
2513 // The expected RTP header extensions in the new offer are the resulting
2514 // extensions from the first offer/answer exchange plus the extensions only
2515 // |f2_| offer.
2516 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002517 // |f1_| for another extensions, it is changed to 13.
isheriff6f8d6862016-05-26 11:24:55 -07002518 const RtpExtension kUpdatedAudioRtpExtensions[] = {
2519 kAudioRtpExtensionAnswer[0], RtpExtension(kAudioRtpExtension2[1].uri, 13),
2520 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002521 };
2522
2523 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002524 // |f1_| for another extensions, is is changed to 12.
isheriff6f8d6862016-05-26 11:24:55 -07002525 const RtpExtension kUpdatedVideoRtpExtensions[] = {
2526 kVideoRtpExtensionAnswer[0], RtpExtension(kVideoRtpExtension2[1].uri, 12),
2527 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002528 };
2529
2530 const AudioContentDescription* updated_acd =
2531 GetFirstAudioContentDescription(updated_offer.get());
2532 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
2533 updated_acd->rtp_header_extensions());
2534
2535 const VideoContentDescription* updated_vcd =
2536 GetFirstVideoContentDescription(updated_offer.get());
2537 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
2538 updated_vcd->rtp_header_extensions());
2539}
2540
deadbeefa5b273a2015-08-20 17:30:13 -07002541// Verify that if the same RTP extension URI is used for audio and video, the
2542// same ID is used. Also verify that the ID isn't changed when creating an
2543// updated offer (this was previously a bug).
isheriff6f8d6862016-05-26 11:24:55 -07002544TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) {
deadbeefa5b273a2015-08-20 17:30:13 -07002545 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002546 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
deadbeefa5b273a2015-08-20 17:30:13 -07002547
2548 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
2549 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
2550
kwiberg31022942016-03-11 14:18:21 -08002551 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07002552
2553 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
2554 // the video extensions.
isheriff6f8d6862016-05-26 11:24:55 -07002555 const RtpExtension kExpectedVideoRtpExtension[] = {
2556 kVideoRtpExtension3[0], kAudioRtpExtension3[1],
deadbeefa5b273a2015-08-20 17:30:13 -07002557 };
2558
Yves Gerey665174f2018-06-19 15:03:05 +02002559 EXPECT_EQ(
2560 MAKE_VECTOR(kAudioRtpExtension3),
2561 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
2562 EXPECT_EQ(
2563 MAKE_VECTOR(kExpectedVideoRtpExtension),
2564 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
deadbeefa5b273a2015-08-20 17:30:13 -07002565
2566 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08002567 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07002568 f1_.CreateOffer(opts, offer.get()));
2569
2570 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
Yves Gerey665174f2018-06-19 15:03:05 +02002571 GetFirstAudioContentDescription(updated_offer.get())
2572 ->rtp_header_extensions());
deadbeefa5b273a2015-08-20 17:30:13 -07002573 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
Yves Gerey665174f2018-06-19 15:03:05 +02002574 GetFirstVideoContentDescription(updated_offer.get())
2575 ->rtp_header_extensions());
deadbeefa5b273a2015-08-20 17:30:13 -07002576}
2577
jbauch5869f502017-06-29 12:31:36 -07002578// Same as "RtpExtensionIdReused" above for encrypted RTP extensions.
2579TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReusedEncrypted) {
2580 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002581 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07002582
2583 f1_.set_enable_encrypted_rtp_header_extensions(true);
2584 f2_.set_enable_encrypted_rtp_header_extensions(true);
2585
2586 f1_.set_audio_rtp_header_extensions(
2587 MAKE_VECTOR(kAudioRtpExtension3ForEncryption));
2588 f1_.set_video_rtp_header_extensions(
2589 MAKE_VECTOR(kVideoRtpExtension3ForEncryption));
2590
2591 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2592
2593 // The extensions that are shared between audio and video should use the same
2594 // id.
2595 const RtpExtension kExpectedVideoRtpExtension[] = {
2596 kVideoRtpExtension3ForEncryption[0],
2597 kAudioRtpExtension3ForEncryptionOffer[1],
2598 kAudioRtpExtension3ForEncryptionOffer[2],
2599 };
2600
Yves Gerey665174f2018-06-19 15:03:05 +02002601 EXPECT_EQ(
2602 MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
2603 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
2604 EXPECT_EQ(
2605 MAKE_VECTOR(kExpectedVideoRtpExtension),
2606 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07002607
2608 // Nothing should change when creating a new offer
2609 std::unique_ptr<SessionDescription> updated_offer(
2610 f1_.CreateOffer(opts, offer.get()));
2611
2612 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
Yves Gerey665174f2018-06-19 15:03:05 +02002613 GetFirstAudioContentDescription(updated_offer.get())
2614 ->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07002615 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
Yves Gerey665174f2018-06-19 15:03:05 +02002616 GetFirstVideoContentDescription(updated_offer.get())
2617 ->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07002618}
2619
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002620TEST(MediaSessionDescription, CopySessionDescription) {
2621 SessionDescription source;
2622 cricket::ContentGroup group(cricket::CN_AUDIO);
2623 source.AddGroup(group);
2624 AudioContentDescription* acd(new AudioContentDescription());
2625 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
2626 acd->AddLegacyStream(1);
Steve Anton5adfafd2017-12-20 16:34:00 -08002627 source.AddContent(cricket::CN_AUDIO, MediaProtocolType::kRtp, acd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002628 VideoContentDescription* vcd(new VideoContentDescription());
2629 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
2630 vcd->AddLegacyStream(2);
Steve Anton5adfafd2017-12-20 16:34:00 -08002631 source.AddContent(cricket::CN_VIDEO, MediaProtocolType::kRtp, vcd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002632
kwiberg31022942016-03-11 14:18:21 -08002633 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002634 ASSERT_TRUE(copy.get() != NULL);
2635 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
2636 const ContentInfo* ac = copy->GetContentByName("audio");
2637 const ContentInfo* vc = copy->GetContentByName("video");
2638 ASSERT_TRUE(ac != NULL);
2639 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08002640 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08002641 const AudioContentDescription* acd_copy = ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002642 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
2643 EXPECT_EQ(1u, acd->first_ssrc());
2644
Steve Anton5adfafd2017-12-20 16:34:00 -08002645 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08002646 const VideoContentDescription* vcd_copy = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002647 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
2648 EXPECT_EQ(2u, vcd->first_ssrc());
2649}
2650
2651// The below TestTransportInfoXXX tests create different offers/answers, and
2652// ensure the TransportInfo in the SessionDescription matches what we expect.
2653TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
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(true, options, false);
2658}
2659
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002660TEST_F(MediaSessionDescriptionFactoryTest,
2661 TestTransportInfoOfferIceRenomination) {
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(true, options, false);
2668}
2669
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002670TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
2671 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002672 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2673 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002674 TestTransportInfo(true, options, true);
2675}
2676
2677TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2678 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002679 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2680 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2681 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002682 TestTransportInfo(true, options, false);
2683}
2684
2685TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02002686 TestTransportInfoOfferMultimediaCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002687 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002688 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2689 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2690 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002691 TestTransportInfo(true, options, true);
2692}
2693
2694TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2695 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002696 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2697 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2698 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002699 options.bundle_enabled = true;
2700 TestTransportInfo(true, options, false);
2701}
2702
2703TEST_F(MediaSessionDescriptionFactoryTest,
2704 TestTransportInfoOfferBundleCurrent) {
2705 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002706 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2707 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2708 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002709 options.bundle_enabled = true;
2710 TestTransportInfo(true, options, true);
2711}
2712
2713TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2714 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002715 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2716 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002717 TestTransportInfo(false, options, false);
2718}
2719
2720TEST_F(MediaSessionDescriptionFactoryTest,
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002721 TestTransportInfoAnswerIceRenomination) {
2722 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002723 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2724 kActive, &options);
zhihuang1c378ed2017-08-17 14:10:50 -07002725 options.media_description_options[0]
2726 .transport_options.enable_ice_renomination = true;
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002727 TestTransportInfo(false, options, false);
2728}
2729
2730TEST_F(MediaSessionDescriptionFactoryTest,
2731 TestTransportInfoAnswerAudioCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002732 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002733 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2734 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002735 TestTransportInfo(false, options, true);
2736}
2737
2738TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2739 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002740 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2741 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2742 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002743 TestTransportInfo(false, options, false);
2744}
2745
2746TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02002747 TestTransportInfoAnswerMultimediaCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002748 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002749 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2750 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2751 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002752 TestTransportInfo(false, options, true);
2753}
2754
2755TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2756 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002757 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2758 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2759 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002760 options.bundle_enabled = true;
2761 TestTransportInfo(false, options, false);
2762}
2763
2764TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02002765 TestTransportInfoAnswerBundleCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002766 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002767 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2768 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2769 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002770 options.bundle_enabled = true;
2771 TestTransportInfo(false, options, true);
2772}
2773
2774// Create an offer with bundle enabled and verify the crypto parameters are
2775// the common set of the available cryptos.
2776TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2777 TestCryptoWithBundle(true);
2778}
2779
2780// Create an answer with bundle enabled and verify the crypto parameters are
2781// the common set of the available cryptos.
2782TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2783 TestCryptoWithBundle(false);
2784}
2785
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002786// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2787// DTLS is not enabled locally.
2788TEST_F(MediaSessionDescriptionFactoryTest,
2789 TestOfferDtlsSavpfWithoutDtlsFailed) {
2790 f1_.set_secure(SEC_ENABLED);
2791 f2_.set_secure(SEC_ENABLED);
2792 tdf1_.set_secure(SEC_DISABLED);
2793 tdf2_.set_secure(SEC_DISABLED);
2794
kwiberg31022942016-03-11 14:18:21 -08002795 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -07002796 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002797 ASSERT_TRUE(offer.get() != NULL);
2798 ContentInfo* offer_content = offer->GetContentByName("audio");
2799 ASSERT_TRUE(offer_content != NULL);
2800 AudioContentDescription* offer_audio_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -08002801 offer_content->media_description()->as_audio();
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002802 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2803
kwiberg31022942016-03-11 14:18:21 -08002804 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07002805 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002806 ASSERT_TRUE(answer != NULL);
2807 ContentInfo* answer_content = answer->GetContentByName("audio");
2808 ASSERT_TRUE(answer_content != NULL);
2809
2810 ASSERT_TRUE(answer_content->rejected);
2811}
2812
2813// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2814// UDP/TLS/RTP/SAVPF.
2815TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2816 f1_.set_secure(SEC_ENABLED);
2817 f2_.set_secure(SEC_ENABLED);
2818 tdf1_.set_secure(SEC_ENABLED);
2819 tdf2_.set_secure(SEC_ENABLED);
2820
kwiberg31022942016-03-11 14:18:21 -08002821 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -07002822 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002823 ASSERT_TRUE(offer.get() != NULL);
2824 ContentInfo* offer_content = offer->GetContentByName("audio");
2825 ASSERT_TRUE(offer_content != NULL);
2826 AudioContentDescription* offer_audio_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -08002827 offer_content->media_description()->as_audio();
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002828 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2829
kwiberg31022942016-03-11 14:18:21 -08002830 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07002831 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002832 ASSERT_TRUE(answer != NULL);
2833
2834 const ContentInfo* answer_content = answer->GetContentByName("audio");
2835 ASSERT_TRUE(answer_content != NULL);
2836 ASSERT_FALSE(answer_content->rejected);
2837
2838 const AudioContentDescription* answer_audio_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -08002839 answer_content->media_description()->as_audio();
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002840 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
Yves Gerey665174f2018-06-19 15:03:05 +02002841 answer_audio_desc->protocol());
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002842}
2843
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002844// Test that we include both SDES and DTLS in the offer, but only include SDES
2845// in the answer if DTLS isn't negotiated.
2846TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2847 f1_.set_secure(SEC_ENABLED);
2848 f2_.set_secure(SEC_ENABLED);
2849 tdf1_.set_secure(SEC_ENABLED);
2850 tdf2_.set_secure(SEC_DISABLED);
2851 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002852 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
kwiberg31022942016-03-11 14:18:21 -08002853 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002854 const cricket::MediaContentDescription* audio_media_desc;
2855 const cricket::MediaContentDescription* video_media_desc;
2856 const cricket::TransportDescription* audio_trans_desc;
2857 const cricket::TransportDescription* video_trans_desc;
2858
2859 // Generate an offer with SDES and DTLS support.
2860 offer.reset(f1_.CreateOffer(options, NULL));
2861 ASSERT_TRUE(offer.get() != NULL);
2862
Steve Antonb1c1de12017-12-21 15:14:30 -08002863 audio_media_desc = offer->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002864 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002865 video_media_desc = offer->GetContentDescriptionByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002866 ASSERT_TRUE(video_media_desc != NULL);
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07002867 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002868 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2869
2870 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2871 ASSERT_TRUE(audio_trans_desc != NULL);
2872 video_trans_desc = offer->GetTransportDescriptionByName("video");
2873 ASSERT_TRUE(video_trans_desc != NULL);
2874 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2875 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2876
2877 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2878 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2879 ASSERT_TRUE(answer.get() != NULL);
2880
Steve Antonb1c1de12017-12-21 15:14:30 -08002881 audio_media_desc = answer->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002882 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002883 video_media_desc = answer->GetContentDescriptionByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002884 ASSERT_TRUE(video_media_desc != NULL);
2885 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2886 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2887
2888 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2889 ASSERT_TRUE(audio_trans_desc != NULL);
2890 video_trans_desc = answer->GetTransportDescriptionByName("video");
2891 ASSERT_TRUE(video_trans_desc != NULL);
2892 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2893 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2894
2895 // Enable DTLS; the answer should now only have DTLS support.
2896 tdf2_.set_secure(SEC_ENABLED);
2897 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2898 ASSERT_TRUE(answer.get() != NULL);
2899
Steve Antonb1c1de12017-12-21 15:14:30 -08002900 audio_media_desc = answer->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002901 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002902 video_media_desc = answer->GetContentDescriptionByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002903 ASSERT_TRUE(video_media_desc != NULL);
2904 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2905 EXPECT_TRUE(video_media_desc->cryptos().empty());
2906 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2907 audio_media_desc->protocol());
2908 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2909 video_media_desc->protocol());
2910
2911 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2912 ASSERT_TRUE(audio_trans_desc != NULL);
2913 video_trans_desc = answer->GetTransportDescriptionByName("video");
2914 ASSERT_TRUE(video_trans_desc != NULL);
2915 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2916 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002917
2918 // Try creating offer again. DTLS enabled now, crypto's should be empty
2919 // in new offer.
2920 offer.reset(f1_.CreateOffer(options, offer.get()));
2921 ASSERT_TRUE(offer.get() != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002922 audio_media_desc = offer->GetContentDescriptionByName("audio");
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002923 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002924 video_media_desc = offer->GetContentDescriptionByName("video");
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002925 ASSERT_TRUE(video_media_desc != NULL);
2926 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2927 EXPECT_TRUE(video_media_desc->cryptos().empty());
2928
2929 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2930 ASSERT_TRUE(audio_trans_desc != NULL);
2931 video_trans_desc = offer->GetTransportDescriptionByName("video");
2932 ASSERT_TRUE(video_trans_desc != NULL);
2933 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2934 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002935}
2936
2937// Test that an answer can't be created if cryptos are required but the offer is
2938// unsecure.
2939TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07002940 MediaSessionOptions options = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002941 f1_.set_secure(SEC_DISABLED);
2942 tdf1_.set_secure(SEC_DISABLED);
2943 f2_.set_secure(SEC_REQUIRED);
2944 tdf1_.set_secure(SEC_ENABLED);
2945
kwiberg31022942016-03-11 14:18:21 -08002946 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002947 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002948 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002949 f2_.CreateAnswer(offer.get(), options, NULL));
2950 EXPECT_TRUE(answer.get() == NULL);
2951}
2952
2953// Test that we accept a DTLS offer without SDES and create an appropriate
2954// answer.
2955TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2956 f1_.set_secure(SEC_DISABLED);
2957 f2_.set_secure(SEC_ENABLED);
2958 tdf1_.set_secure(SEC_ENABLED);
2959 tdf2_.set_secure(SEC_ENABLED);
2960 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002961 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2962 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2963 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002964
kwiberg31022942016-03-11 14:18:21 -08002965 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002966
2967 // Generate an offer with DTLS but without SDES.
2968 offer.reset(f1_.CreateOffer(options, NULL));
2969 ASSERT_TRUE(offer.get() != NULL);
2970
2971 const AudioContentDescription* audio_offer =
2972 GetFirstAudioContentDescription(offer.get());
2973 ASSERT_TRUE(audio_offer->cryptos().empty());
2974 const VideoContentDescription* video_offer =
2975 GetFirstVideoContentDescription(offer.get());
2976 ASSERT_TRUE(video_offer->cryptos().empty());
2977 const DataContentDescription* data_offer =
2978 GetFirstDataContentDescription(offer.get());
2979 ASSERT_TRUE(data_offer->cryptos().empty());
2980
2981 const cricket::TransportDescription* audio_offer_trans_desc =
2982 offer->GetTransportDescriptionByName("audio");
2983 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2984 const cricket::TransportDescription* video_offer_trans_desc =
2985 offer->GetTransportDescriptionByName("video");
2986 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2987 const cricket::TransportDescription* data_offer_trans_desc =
2988 offer->GetTransportDescriptionByName("data");
2989 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2990
2991 // Generate an answer with DTLS.
2992 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2993 ASSERT_TRUE(answer.get() != NULL);
2994
2995 const cricket::TransportDescription* audio_answer_trans_desc =
2996 answer->GetTransportDescriptionByName("audio");
2997 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2998 const cricket::TransportDescription* video_answer_trans_desc =
2999 answer->GetTransportDescriptionByName("video");
3000 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
3001 const cricket::TransportDescription* data_answer_trans_desc =
3002 answer->GetTransportDescriptionByName("data");
3003 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
3004}
3005
3006// Verifies if vad_enabled option is set to false, CN codecs are not present in
3007// offer or answer.
3008TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
3009 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08003010 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
kwiberg31022942016-03-11 14:18:21 -08003011 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003012 ASSERT_TRUE(offer.get() != NULL);
3013 const ContentInfo* audio_content = offer->GetContentByName("audio");
3014 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
3015
3016 options.vad_enabled = false;
3017 offer.reset(f1_.CreateOffer(options, NULL));
3018 ASSERT_TRUE(offer.get() != NULL);
3019 audio_content = offer->GetContentByName("audio");
3020 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08003021 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003022 f1_.CreateAnswer(offer.get(), options, NULL));
3023 ASSERT_TRUE(answer.get() != NULL);
3024 audio_content = answer->GetContentByName("audio");
3025 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
3026}
deadbeef44f08192015-12-15 16:20:09 -08003027
zhihuang1c378ed2017-08-17 14:10:50 -07003028// Test that the generated MIDs match the existing offer.
3029TEST_F(MediaSessionDescriptionFactoryTest, TestMIDsMatchesExistingOffer) {
deadbeef44f08192015-12-15 16:20:09 -08003030 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003031 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_modified",
3032 RtpTransceiverDirection::kRecvOnly, kActive, &opts);
3033 AddMediaSection(MEDIA_TYPE_VIDEO, "video_modified",
3034 RtpTransceiverDirection::kRecvOnly, kActive, &opts);
deadbeef44f08192015-12-15 16:20:09 -08003035 opts.data_channel_type = cricket::DCT_SCTP;
Steve Anton4e70a722017-11-28 14:57:10 -08003036 AddMediaSection(MEDIA_TYPE_DATA, "data_modified",
3037 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003038 // Create offer.
kwiberg31022942016-03-11 14:18:21 -08003039 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
kwiberg31022942016-03-11 14:18:21 -08003040 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08003041 f1_.CreateOffer(opts, offer.get()));
zhihuang1c378ed2017-08-17 14:10:50 -07003042
deadbeef44f08192015-12-15 16:20:09 -08003043 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
3044 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
3045 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
3046 ASSERT_TRUE(audio_content != nullptr);
3047 ASSERT_TRUE(video_content != nullptr);
3048 ASSERT_TRUE(data_content != nullptr);
3049 EXPECT_EQ("audio_modified", audio_content->name);
3050 EXPECT_EQ("video_modified", video_content->name);
3051 EXPECT_EQ("data_modified", data_content->name);
3052}
zhihuangcf5b37c2016-05-05 11:44:35 -07003053
zhihuang1c378ed2017-08-17 14:10:50 -07003054// The following tests verify that the unified plan SDP is supported.
3055// Test that we can create an offer with multiple media sections of same media
3056// type.
3057TEST_F(MediaSessionDescriptionFactoryTest,
3058 CreateOfferWithMultipleAVMediaSections) {
3059 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003060 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_1",
3061 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003062 AttachSenderToMediaSection("audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1,
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_VIDEO, "video_1",
3066 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003067 AttachSenderToMediaSection("video_1", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003068 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003069
Steve Anton4e70a722017-11-28 14:57:10 -08003070 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_2",
3071 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003072 AttachSenderToMediaSection("audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003073 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003074
Steve Anton4e70a722017-11-28 14:57:10 -08003075 AddMediaSection(MEDIA_TYPE_VIDEO, "video_2",
3076 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003077 AttachSenderToMediaSection("video_2", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003078 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003079 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3080 ASSERT_TRUE(offer);
3081
3082 ASSERT_EQ(4u, offer->contents().size());
3083 EXPECT_FALSE(offer->contents()[0].rejected);
3084 const AudioContentDescription* acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003085 offer->contents()[0].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003086 ASSERT_EQ(1u, acd->streams().size());
3087 EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003088 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003089
3090 EXPECT_FALSE(offer->contents()[1].rejected);
3091 const VideoContentDescription* vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003092 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003093 ASSERT_EQ(1u, vcd->streams().size());
3094 EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003095 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003096
3097 EXPECT_FALSE(offer->contents()[2].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003098 acd = offer->contents()[2].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003099 ASSERT_EQ(1u, acd->streams().size());
3100 EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003101 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003102
3103 EXPECT_FALSE(offer->contents()[3].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003104 vcd = offer->contents()[3].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003105 ASSERT_EQ(1u, vcd->streams().size());
3106 EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003107 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003108}
3109
3110// Test that we can create an answer with multiple media sections of same media
3111// type.
3112TEST_F(MediaSessionDescriptionFactoryTest,
3113 CreateAnswerWithMultipleAVMediaSections) {
3114 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003115 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_1",
3116 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003117 AttachSenderToMediaSection("audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003118 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003119
Steve Anton4e70a722017-11-28 14:57:10 -08003120 AddMediaSection(MEDIA_TYPE_VIDEO, "video_1",
3121 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003122 AttachSenderToMediaSection("video_1", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003123 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003124
Steve Anton4e70a722017-11-28 14:57:10 -08003125 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_2",
3126 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003127 AttachSenderToMediaSection("audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003128 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003129
Steve Anton4e70a722017-11-28 14:57:10 -08003130 AddMediaSection(MEDIA_TYPE_VIDEO, "video_2",
3131 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003132 AttachSenderToMediaSection("video_2", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003133 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003134
3135 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3136 ASSERT_TRUE(offer);
3137 std::unique_ptr<SessionDescription> answer(
3138 f2_.CreateAnswer(offer.get(), opts, nullptr));
3139
3140 ASSERT_EQ(4u, answer->contents().size());
3141 EXPECT_FALSE(answer->contents()[0].rejected);
3142 const AudioContentDescription* acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003143 answer->contents()[0].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003144 ASSERT_EQ(1u, acd->streams().size());
3145 EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003146 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003147
3148 EXPECT_FALSE(answer->contents()[1].rejected);
3149 const VideoContentDescription* vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003150 answer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003151 ASSERT_EQ(1u, vcd->streams().size());
3152 EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003153 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003154
3155 EXPECT_FALSE(answer->contents()[2].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003156 acd = answer->contents()[2].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003157 ASSERT_EQ(1u, acd->streams().size());
3158 EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003159 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003160
3161 EXPECT_FALSE(answer->contents()[3].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003162 vcd = answer->contents()[3].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003163 ASSERT_EQ(1u, vcd->streams().size());
3164 EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003165 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003166}
3167
3168// Test that the media section will be rejected in offer if the corresponding
3169// MediaDescriptionOptions is stopped by the offerer.
3170TEST_F(MediaSessionDescriptionFactoryTest,
3171 CreateOfferWithMediaSectionStoppedByOfferer) {
3172 // Create an offer with two audio sections and one of them is stopped.
3173 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003174 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3175 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3176 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3177 RtpTransceiverDirection::kInactive, kStopped, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003178 std::unique_ptr<SessionDescription> offer(
3179 f1_.CreateOffer(offer_opts, nullptr));
3180 ASSERT_TRUE(offer);
3181 ASSERT_EQ(2u, offer->contents().size());
3182 EXPECT_FALSE(offer->contents()[0].rejected);
3183 EXPECT_TRUE(offer->contents()[1].rejected);
3184}
3185
3186// Test that the media section will be rejected in answer if the corresponding
3187// MediaDescriptionOptions is stopped by the offerer.
3188TEST_F(MediaSessionDescriptionFactoryTest,
3189 CreateAnswerWithMediaSectionStoppedByOfferer) {
3190 // Create an offer with two audio sections and one of them is stopped.
3191 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003192 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3193 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3194 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3195 RtpTransceiverDirection::kInactive, kStopped, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003196 std::unique_ptr<SessionDescription> offer(
3197 f1_.CreateOffer(offer_opts, nullptr));
3198 ASSERT_TRUE(offer);
3199 ASSERT_EQ(2u, offer->contents().size());
3200 EXPECT_FALSE(offer->contents()[0].rejected);
3201 EXPECT_TRUE(offer->contents()[1].rejected);
3202
3203 // Create an answer based on the offer.
3204 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003205 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3206 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
3207 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3208 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003209 std::unique_ptr<SessionDescription> answer(
3210 f2_.CreateAnswer(offer.get(), answer_opts, nullptr));
3211 ASSERT_EQ(2u, answer->contents().size());
3212 EXPECT_FALSE(answer->contents()[0].rejected);
3213 EXPECT_TRUE(answer->contents()[1].rejected);
3214}
3215
3216// Test that the media section will be rejected in answer if the corresponding
3217// MediaDescriptionOptions is stopped by the answerer.
3218TEST_F(MediaSessionDescriptionFactoryTest,
3219 CreateAnswerWithMediaSectionRejectedByAnswerer) {
3220 // Create an offer with two audio sections.
3221 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003222 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3223 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3224 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3225 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003226 std::unique_ptr<SessionDescription> offer(
3227 f1_.CreateOffer(offer_opts, nullptr));
3228 ASSERT_TRUE(offer);
3229 ASSERT_EQ(2u, offer->contents().size());
3230 ASSERT_FALSE(offer->contents()[0].rejected);
3231 ASSERT_FALSE(offer->contents()[1].rejected);
3232
3233 // The answerer rejects one of the audio sections.
3234 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003235 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3236 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
3237 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3238 RtpTransceiverDirection::kInactive, kStopped, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003239 std::unique_ptr<SessionDescription> answer(
3240 f2_.CreateAnswer(offer.get(), answer_opts, nullptr));
3241 ASSERT_EQ(2u, answer->contents().size());
3242 EXPECT_FALSE(answer->contents()[0].rejected);
3243 EXPECT_TRUE(answer->contents()[1].rejected);
Zhi Huang3518e7b2018-01-30 13:20:35 -08003244
3245 // The TransportInfo of the rejected m= section is expected to be added in the
3246 // answer.
3247 EXPECT_EQ(offer->transport_infos().size(), answer->transport_infos().size());
zhihuang1c378ed2017-08-17 14:10:50 -07003248}
3249
3250// Test the generated media sections has the same order of the
3251// corresponding MediaDescriptionOptions.
3252TEST_F(MediaSessionDescriptionFactoryTest,
3253 CreateOfferRespectsMediaDescriptionOptionsOrder) {
3254 MediaSessionOptions opts;
3255 // This tests put video section first because normally audio comes first by
3256 // default.
Steve Anton4e70a722017-11-28 14:57:10 -08003257 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3258 kActive, &opts);
3259 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
3260 kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003261 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3262
3263 ASSERT_TRUE(offer);
3264 ASSERT_EQ(2u, offer->contents().size());
3265 EXPECT_EQ("video", offer->contents()[0].name);
3266 EXPECT_EQ("audio", offer->contents()[1].name);
3267}
3268
3269// Test that different media sections using the same codec have same payload
3270// type.
3271TEST_F(MediaSessionDescriptionFactoryTest,
3272 PayloadTypesSharedByMediaSectionsOfSameType) {
3273 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003274 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3275 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3276 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3277 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003278 // Create an offer with two video sections using same codecs.
3279 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3280 ASSERT_TRUE(offer);
3281 ASSERT_EQ(2u, offer->contents().size());
3282 const VideoContentDescription* vcd1 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003283 offer->contents()[0].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003284 const VideoContentDescription* vcd2 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003285 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003286 EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
3287 ASSERT_EQ(2u, vcd1->codecs().size());
3288 EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
3289 EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
3290 EXPECT_EQ(vcd1->codecs()[1].name, vcd2->codecs()[1].name);
3291 EXPECT_EQ(vcd1->codecs()[1].id, vcd2->codecs()[1].id);
3292
3293 // Create answer and negotiate the codecs.
3294 std::unique_ptr<SessionDescription> answer(
3295 f2_.CreateAnswer(offer.get(), opts, nullptr));
3296 ASSERT_TRUE(answer);
3297 ASSERT_EQ(2u, answer->contents().size());
Steve Antonb1c1de12017-12-21 15:14:30 -08003298 vcd1 = answer->contents()[0].media_description()->as_video();
3299 vcd2 = answer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003300 EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
3301 ASSERT_EQ(1u, vcd1->codecs().size());
3302 EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
3303 EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
3304}
3305
3306// Test that the codec preference order per media section is respected in
3307// subsequent offer.
3308TEST_F(MediaSessionDescriptionFactoryTest,
3309 CreateOfferRespectsCodecPreferenceOrder) {
3310 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003311 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3312 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3313 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3314 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003315 // Create an offer with two video sections using same codecs.
3316 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3317 ASSERT_TRUE(offer);
3318 ASSERT_EQ(2u, offer->contents().size());
3319 VideoContentDescription* vcd1 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003320 offer->contents()[0].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003321 const VideoContentDescription* vcd2 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003322 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003323 auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
3324 EXPECT_EQ(video_codecs, vcd1->codecs());
3325 EXPECT_EQ(video_codecs, vcd2->codecs());
3326
3327 // Change the codec preference of the first video section and create a
3328 // follow-up offer.
3329 auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
3330 vcd1->set_codecs(video_codecs_reverse);
3331 std::unique_ptr<SessionDescription> updated_offer(
3332 f1_.CreateOffer(opts, offer.get()));
Steve Antonb1c1de12017-12-21 15:14:30 -08003333 vcd1 = updated_offer->contents()[0].media_description()->as_video();
3334 vcd2 = updated_offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003335 // The video codec preference order should be respected.
3336 EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
3337 EXPECT_EQ(video_codecs, vcd2->codecs());
3338}
3339
3340// Test that the codec preference order per media section is respected in
3341// the answer.
3342TEST_F(MediaSessionDescriptionFactoryTest,
3343 CreateAnswerRespectsCodecPreferenceOrder) {
3344 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003345 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3346 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3347 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3348 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003349 // Create an offer with two video sections using same codecs.
3350 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3351 ASSERT_TRUE(offer);
3352 ASSERT_EQ(2u, offer->contents().size());
3353 VideoContentDescription* vcd1 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003354 offer->contents()[0].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003355 const VideoContentDescription* vcd2 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003356 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003357 auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
3358 EXPECT_EQ(video_codecs, vcd1->codecs());
3359 EXPECT_EQ(video_codecs, vcd2->codecs());
3360
3361 // Change the codec preference of the first video section and create an
3362 // answer.
3363 auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
3364 vcd1->set_codecs(video_codecs_reverse);
3365 std::unique_ptr<SessionDescription> answer(
3366 f1_.CreateAnswer(offer.get(), opts, nullptr));
Steve Antonb1c1de12017-12-21 15:14:30 -08003367 vcd1 = answer->contents()[0].media_description()->as_video();
3368 vcd2 = answer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003369 // The video codec preference order should be respected.
3370 EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
3371 EXPECT_EQ(video_codecs, vcd2->codecs());
3372}
3373
Zhi Huang6f367472017-11-22 13:20:02 -08003374// Test that when creating an answer, the codecs use local parameters instead of
3375// the remote ones.
3376TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerWithLocalCodecParams) {
3377 const std::string audio_param_name = "audio_param";
3378 const std::string audio_value1 = "audio_v1";
3379 const std::string audio_value2 = "audio_v2";
3380 const std::string video_param_name = "video_param";
3381 const std::string video_value1 = "video_v1";
3382 const std::string video_value2 = "video_v2";
3383
3384 auto audio_codecs1 = MAKE_VECTOR(kAudioCodecs1);
3385 auto audio_codecs2 = MAKE_VECTOR(kAudioCodecs1);
3386 auto video_codecs1 = MAKE_VECTOR(kVideoCodecs1);
3387 auto video_codecs2 = MAKE_VECTOR(kVideoCodecs1);
3388
3389 // Set the parameters for codecs.
3390 audio_codecs1[0].SetParam(audio_param_name, audio_value1);
3391 video_codecs1[0].SetParam(video_param_name, video_value1);
3392 audio_codecs2[0].SetParam(audio_param_name, audio_value2);
3393 video_codecs2[0].SetParam(video_param_name, video_value2);
3394
3395 f1_.set_audio_codecs(audio_codecs1, audio_codecs1);
3396 f1_.set_video_codecs(video_codecs1);
3397 f2_.set_audio_codecs(audio_codecs2, audio_codecs2);
3398 f2_.set_video_codecs(video_codecs2);
3399
3400 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003401 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
3402 kActive, &opts);
3403 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3404 kActive, &opts);
Zhi Huang6f367472017-11-22 13:20:02 -08003405
3406 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3407 ASSERT_TRUE(offer);
Steve Antonb1c1de12017-12-21 15:14:30 -08003408 auto offer_acd = offer->contents()[0].media_description()->as_audio();
3409 auto offer_vcd = offer->contents()[1].media_description()->as_video();
Zhi Huang6f367472017-11-22 13:20:02 -08003410 std::string value;
3411 EXPECT_TRUE(offer_acd->codecs()[0].GetParam(audio_param_name, &value));
3412 EXPECT_EQ(audio_value1, value);
3413 EXPECT_TRUE(offer_vcd->codecs()[0].GetParam(video_param_name, &value));
3414 EXPECT_EQ(video_value1, value);
3415
3416 std::unique_ptr<SessionDescription> answer(
3417 f2_.CreateAnswer(offer.get(), opts, nullptr));
3418 ASSERT_TRUE(answer);
Steve Antonb1c1de12017-12-21 15:14:30 -08003419 auto answer_acd = answer->contents()[0].media_description()->as_audio();
3420 auto answer_vcd = answer->contents()[1].media_description()->as_video();
Zhi Huang6f367472017-11-22 13:20:02 -08003421 // Use the parameters from the local codecs.
3422 EXPECT_TRUE(answer_acd->codecs()[0].GetParam(audio_param_name, &value));
3423 EXPECT_EQ(audio_value2, value);
3424 EXPECT_TRUE(answer_vcd->codecs()[0].GetParam(video_param_name, &value));
3425 EXPECT_EQ(video_value2, value);
3426}
3427
Steve Anton9c1fb1e2018-02-26 15:09:41 -08003428// Test that matching packetization-mode is part of the criteria for matching
3429// H264 codecs (in addition to profile-level-id). Previously, this was not the
3430// case, so the first H264 codec with the same profile-level-id would match and
3431// the payload type in the answer would be incorrect.
3432// This is a regression test for bugs.webrtc.org/8808
3433TEST_F(MediaSessionDescriptionFactoryTest,
3434 H264MatchCriteriaIncludesPacketizationMode) {
3435 // Create two H264 codecs with the same profile level ID and different
3436 // packetization modes.
3437 VideoCodec h264_pm0(96, "H264");
3438 h264_pm0.params[cricket::kH264FmtpProfileLevelId] = "42c01f";
3439 h264_pm0.params[cricket::kH264FmtpPacketizationMode] = "0";
3440 VideoCodec h264_pm1(97, "H264");
3441 h264_pm1.params[cricket::kH264FmtpProfileLevelId] = "42c01f";
3442 h264_pm1.params[cricket::kH264FmtpPacketizationMode] = "1";
3443
3444 // Offerer will send both codecs, answerer should choose the one with matching
3445 // packetization mode (and not the first one it sees).
3446 f1_.set_video_codecs({h264_pm0, h264_pm1});
3447 f2_.set_video_codecs({h264_pm1});
3448
3449 MediaSessionOptions opts;
3450 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3451 kActive, &opts);
3452
3453 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3454 ASSERT_TRUE(offer);
3455
3456 std::unique_ptr<SessionDescription> answer(
3457 f2_.CreateAnswer(offer.get(), opts, nullptr));
3458 ASSERT_TRUE(answer);
3459
3460 // Answer should have one negotiated codec with packetization-mode=1 using the
3461 // offered payload type.
3462 ASSERT_EQ(1u, answer->contents().size());
3463 auto answer_vcd = answer->contents()[0].media_description()->as_video();
3464 ASSERT_EQ(1u, answer_vcd->codecs().size());
3465 auto answer_codec = answer_vcd->codecs()[0];
3466 EXPECT_EQ(h264_pm1.id, answer_codec.id);
3467}
3468
zhihuangcf5b37c2016-05-05 11:44:35 -07003469class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
3470 public:
3471 MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -07003472 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
3473 MAKE_VECTOR(kAudioCodecs1));
zhihuangcf5b37c2016-05-05 11:44:35 -07003474 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
3475 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -07003476 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
3477 MAKE_VECTOR(kAudioCodecs2));
zhihuangcf5b37c2016-05-05 11:44:35 -07003478 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
3479 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
3480 f1_.set_secure(SEC_ENABLED);
3481 f2_.set_secure(SEC_ENABLED);
3482 tdf1_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07003483 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07003484 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07003485 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07003486 tdf1_.set_secure(SEC_ENABLED);
3487 tdf2_.set_secure(SEC_ENABLED);
3488 }
3489
3490 protected:
3491 MediaSessionDescriptionFactory f1_;
3492 MediaSessionDescriptionFactory f2_;
3493 TransportDescriptionFactory tdf1_;
3494 TransportDescriptionFactory tdf2_;
3495};
3496
3497TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
3498 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003499 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
zhihuangcf5b37c2016-05-05 11:44:35 -07003500 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3501 ASSERT_TRUE(offer.get() != nullptr);
3502 // Set the protocol for all the contents.
3503 for (auto content : offer.get()->contents()) {
Steve Antonb1c1de12017-12-21 15:14:30 -08003504 content.media_description()->set_protocol(GetParam());
zhihuangcf5b37c2016-05-05 11:44:35 -07003505 }
3506 std::unique_ptr<SessionDescription> answer(
3507 f2_.CreateAnswer(offer.get(), opts, nullptr));
3508 const ContentInfo* ac = answer->GetContentByName("audio");
3509 const ContentInfo* vc = answer->GetContentByName("video");
3510 ASSERT_TRUE(ac != nullptr);
3511 ASSERT_TRUE(vc != nullptr);
3512 EXPECT_FALSE(ac->rejected); // the offer is accepted
3513 EXPECT_FALSE(vc->rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003514 const AudioContentDescription* acd = ac->media_description()->as_audio();
3515 const VideoContentDescription* vcd = vc->media_description()->as_video();
zhihuangcf5b37c2016-05-05 11:44:35 -07003516 EXPECT_EQ(GetParam(), acd->protocol());
3517 EXPECT_EQ(GetParam(), vcd->protocol());
3518}
3519
3520INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest,
3521 MediaProtocolTest,
3522 ::testing::ValuesIn(kMediaProtocols));
3523INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest,
3524 MediaProtocolTest,
3525 ::testing::ValuesIn(kMediaProtocolsDtls));
ossu075af922016-06-14 03:29:38 -07003526
3527TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) {
3528 TransportDescriptionFactory tdf;
3529 MediaSessionDescriptionFactory sf(&tdf);
3530 std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
3531 std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
3532
3533 // The merged list of codecs should contain any send codecs that are also
3534 // nominally in the recieve codecs list. Payload types should be picked from
3535 // the send codecs and a number-of-channels of 0 and 1 should be equivalent
3536 // (set to 1). This equals what happens when the send codecs are used in an
3537 // offer and the receive codecs are used in the following answer.
3538 const std::vector<AudioCodec> sendrecv_codecs =
3539 MAKE_VECTOR(kAudioCodecsAnswer);
3540 const std::vector<AudioCodec> no_codecs;
3541
3542 RTC_CHECK_EQ(send_codecs[1].name, "iLBC")
3543 << "Please don't change shared test data!";
3544 RTC_CHECK_EQ(recv_codecs[2].name, "iLBC")
3545 << "Please don't change shared test data!";
3546 // Alter iLBC send codec to have zero channels, to test that that is handled
3547 // properly.
3548 send_codecs[1].channels = 0;
3549
3550 // Alther iLBC receive codec to be lowercase, to test that case conversions
3551 // are handled properly.
3552 recv_codecs[2].name = "ilbc";
3553
3554 // Test proper merge
3555 sf.set_audio_codecs(send_codecs, recv_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003556 EXPECT_EQ(send_codecs, sf.audio_send_codecs());
3557 EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
3558 EXPECT_EQ(sendrecv_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003559
3560 // Test empty send codecs list
3561 sf.set_audio_codecs(no_codecs, recv_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003562 EXPECT_EQ(no_codecs, sf.audio_send_codecs());
3563 EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
3564 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003565
3566 // Test empty recv codecs list
3567 sf.set_audio_codecs(send_codecs, no_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003568 EXPECT_EQ(send_codecs, sf.audio_send_codecs());
3569 EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
3570 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003571
3572 // Test all empty codec lists
3573 sf.set_audio_codecs(no_codecs, no_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003574 EXPECT_EQ(no_codecs, sf.audio_send_codecs());
3575 EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
3576 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003577}
3578
3579namespace {
zhihuang1c378ed2017-08-17 14:10:50 -07003580// Compare the two vectors of codecs ignoring the payload type.
3581template <class Codec>
3582bool CodecsMatch(const std::vector<Codec>& codecs1,
3583 const std::vector<Codec>& codecs2) {
3584 if (codecs1.size() != codecs2.size()) {
3585 return false;
3586 }
3587
3588 for (size_t i = 0; i < codecs1.size(); ++i) {
3589 if (!codecs1[i].Matches(codecs2[i])) {
3590 return false;
3591 }
3592 }
3593 return true;
3594}
3595
Steve Anton4e70a722017-11-28 14:57:10 -08003596void TestAudioCodecsOffer(RtpTransceiverDirection direction) {
ossu075af922016-06-14 03:29:38 -07003597 TransportDescriptionFactory tdf;
3598 MediaSessionDescriptionFactory sf(&tdf);
3599 const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
3600 const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
3601 const std::vector<AudioCodec> sendrecv_codecs =
3602 MAKE_VECTOR(kAudioCodecsAnswer);
3603 sf.set_audio_codecs(send_codecs, recv_codecs);
ossu075af922016-06-14 03:29:38 -07003604
3605 MediaSessionOptions opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003606 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", direction, kActive, &opts);
3607
Steve Anton4e70a722017-11-28 14:57:10 -08003608 if (direction == RtpTransceiverDirection::kSendRecv ||
3609 direction == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003610 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003611 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003612 }
ossu075af922016-06-14 03:29:38 -07003613
3614 std::unique_ptr<SessionDescription> offer(sf.CreateOffer(opts, NULL));
3615 ASSERT_TRUE(offer.get() != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08003616 ContentInfo* ac = offer->GetContentByName("audio");
ossu075af922016-06-14 03:29:38 -07003617
3618 // If the factory didn't add any audio content to the offer, we cannot check
zhihuang1c378ed2017-08-17 14:10:50 -07003619 // that the codecs put in are right. This happens when we neither want to
3620 // send nor receive audio. The checks are still in place if at some point
3621 // we'd instead create an inactive stream.
ossu075af922016-06-14 03:29:38 -07003622 if (ac) {
Steve Antonb1c1de12017-12-21 15:14:30 -08003623 AudioContentDescription* acd = ac->media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003624 // sendrecv and inactive should both present lists as if the channel was
3625 // to be used for sending and receiving. Inactive essentially means it
3626 // might eventually be used anything, but we don't know more at this
3627 // moment.
Steve Anton4e70a722017-11-28 14:57:10 -08003628 if (acd->direction() == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003629 EXPECT_TRUE(CodecsMatch<AudioCodec>(send_codecs, acd->codecs()));
Steve Anton4e70a722017-11-28 14:57:10 -08003630 } else if (acd->direction() == RtpTransceiverDirection::kRecvOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003631 EXPECT_TRUE(CodecsMatch<AudioCodec>(recv_codecs, acd->codecs()));
ossu075af922016-06-14 03:29:38 -07003632 } else {
zhihuang1c378ed2017-08-17 14:10:50 -07003633 EXPECT_TRUE(CodecsMatch<AudioCodec>(sendrecv_codecs, acd->codecs()));
ossu075af922016-06-14 03:29:38 -07003634 }
3635 }
3636}
3637
3638static const AudioCodec kOfferAnswerCodecs[] = {
zhihuang1c378ed2017-08-17 14:10:50 -07003639 AudioCodec(0, "codec0", 16000, -1, 1),
3640 AudioCodec(1, "codec1", 8000, 13300, 1),
3641 AudioCodec(2, "codec2", 8000, 64000, 1),
3642 AudioCodec(3, "codec3", 8000, 64000, 1),
3643 AudioCodec(4, "codec4", 8000, 0, 2),
3644 AudioCodec(5, "codec5", 32000, 0, 1),
3645 AudioCodec(6, "codec6", 48000, 0, 1)};
ossu075af922016-06-14 03:29:38 -07003646
zhihuang1c378ed2017-08-17 14:10:50 -07003647/* The codecs groups below are chosen as per the matrix below. The objective
3648 * is to have different sets of codecs in the inputs, to get unique sets of
3649 * codecs after negotiation, depending on offer and answer communication
3650 * directions. One-way directions in the offer should either result in the
3651 * opposite direction in the answer, or an inactive answer. Regardless, the
3652 * choice of codecs should be as if the answer contained the opposite
3653 * direction. Inactive offers should be treated as sendrecv/sendrecv.
ossu075af922016-06-14 03:29:38 -07003654 *
3655 * | Offer | Answer | Result
3656 * codec|send recv sr | send recv sr | s/r r/s sr/s sr/r sr/sr
3657 * 0 | x - - | - x - | x - - - -
3658 * 1 | x x x | - x - | x - - x -
3659 * 2 | - x - | x - - | - x - - -
3660 * 3 | x x x | x - - | - x x - -
3661 * 4 | - x - | x x x | - x - - -
3662 * 5 | x - - | x x x | x - - - -
3663 * 6 | x x x | x x x | x x x x x
3664 */
3665// Codecs used by offerer in the AudioCodecsAnswerTest
zhihuang1c378ed2017-08-17 14:10:50 -07003666static const int kOfferSendCodecs[] = {0, 1, 3, 5, 6};
3667static const int kOfferRecvCodecs[] = {1, 2, 3, 4, 6};
ossu075af922016-06-14 03:29:38 -07003668// Codecs used in the answerer in the AudioCodecsAnswerTest. The order is
3669// jumbled to catch the answer not following the order in the offer.
zhihuang1c378ed2017-08-17 14:10:50 -07003670static const int kAnswerSendCodecs[] = {6, 5, 2, 3, 4};
3671static const int kAnswerRecvCodecs[] = {6, 5, 4, 1, 0};
ossu075af922016-06-14 03:29:38 -07003672// The resulting sets of codecs in the answer in the AudioCodecsAnswerTest
zhihuang1c378ed2017-08-17 14:10:50 -07003673static const int kResultSend_RecvCodecs[] = {0, 1, 5, 6};
3674static const int kResultRecv_SendCodecs[] = {2, 3, 4, 6};
3675static const int kResultSendrecv_SendCodecs[] = {3, 6};
3676static const int kResultSendrecv_RecvCodecs[] = {1, 6};
3677static const int kResultSendrecv_SendrecvCodecs[] = {6};
ossu075af922016-06-14 03:29:38 -07003678
3679template <typename T, int IDXS>
3680std::vector<T> VectorFromIndices(const T* array, const int (&indices)[IDXS]) {
3681 std::vector<T> out;
3682 out.reserve(IDXS);
3683 for (int idx : indices)
3684 out.push_back(array[idx]);
3685
3686 return out;
3687}
3688
Steve Anton4e70a722017-11-28 14:57:10 -08003689void TestAudioCodecsAnswer(RtpTransceiverDirection offer_direction,
3690 RtpTransceiverDirection answer_direction,
ossu075af922016-06-14 03:29:38 -07003691 bool add_legacy_stream) {
3692 TransportDescriptionFactory offer_tdf;
3693 TransportDescriptionFactory answer_tdf;
3694 MediaSessionDescriptionFactory offer_factory(&offer_tdf);
3695 MediaSessionDescriptionFactory answer_factory(&answer_tdf);
3696 offer_factory.set_audio_codecs(
3697 VectorFromIndices(kOfferAnswerCodecs, kOfferSendCodecs),
3698 VectorFromIndices(kOfferAnswerCodecs, kOfferRecvCodecs));
3699 answer_factory.set_audio_codecs(
3700 VectorFromIndices(kOfferAnswerCodecs, kAnswerSendCodecs),
3701 VectorFromIndices(kOfferAnswerCodecs, kAnswerRecvCodecs));
3702
ossu075af922016-06-14 03:29:38 -07003703 MediaSessionOptions offer_opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003704 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", offer_direction, kActive,
3705 &offer_opts);
3706
Steve Anton4e70a722017-11-28 14:57:10 -08003707 if (webrtc::RtpTransceiverDirectionHasSend(offer_direction)) {
zhihuang1c378ed2017-08-17 14:10:50 -07003708 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003709 {kMediaStream1}, 1, &offer_opts);
ossu075af922016-06-14 03:29:38 -07003710 }
3711
3712 std::unique_ptr<SessionDescription> offer(
3713 offer_factory.CreateOffer(offer_opts, NULL));
3714 ASSERT_TRUE(offer.get() != NULL);
3715
3716 MediaSessionOptions answer_opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003717 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", answer_direction, kActive,
3718 &answer_opts);
3719
Steve Anton4e70a722017-11-28 14:57:10 -08003720 if (webrtc::RtpTransceiverDirectionHasSend(answer_direction)) {
zhihuang1c378ed2017-08-17 14:10:50 -07003721 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003722 {kMediaStream1}, 1, &answer_opts);
ossu075af922016-06-14 03:29:38 -07003723 }
3724 std::unique_ptr<SessionDescription> answer(
3725 answer_factory.CreateAnswer(offer.get(), answer_opts, NULL));
3726 const ContentInfo* ac = answer->GetContentByName("audio");
3727
zhihuang1c378ed2017-08-17 14:10:50 -07003728 // If the factory didn't add any audio content to the answer, we cannot
3729 // check that the codecs put in are right. This happens when we neither want
3730 // to send nor receive audio. The checks are still in place if at some point
3731 // we'd instead create an inactive stream.
ossu075af922016-06-14 03:29:38 -07003732 if (ac) {
Steve Antonb1c1de12017-12-21 15:14:30 -08003733 ASSERT_EQ(MEDIA_TYPE_AUDIO, ac->media_description()->type());
3734 const AudioContentDescription* acd = ac->media_description()->as_audio();
ossu075af922016-06-14 03:29:38 -07003735
ossu075af922016-06-14 03:29:38 -07003736 std::vector<AudioCodec> target_codecs;
3737 // For offers with sendrecv or inactive, we should never reply with more
3738 // codecs than offered, with these codec sets.
3739 switch (offer_direction) {
Steve Anton4e70a722017-11-28 14:57:10 -08003740 case RtpTransceiverDirection::kInactive:
ossu075af922016-06-14 03:29:38 -07003741 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3742 kResultSendrecv_SendrecvCodecs);
3743 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003744 case RtpTransceiverDirection::kSendOnly:
zhihuang1c378ed2017-08-17 14:10:50 -07003745 target_codecs =
3746 VectorFromIndices(kOfferAnswerCodecs, kResultSend_RecvCodecs);
ossu075af922016-06-14 03:29:38 -07003747 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003748 case RtpTransceiverDirection::kRecvOnly:
zhihuang1c378ed2017-08-17 14:10:50 -07003749 target_codecs =
3750 VectorFromIndices(kOfferAnswerCodecs, kResultRecv_SendCodecs);
ossu075af922016-06-14 03:29:38 -07003751 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003752 case RtpTransceiverDirection::kSendRecv:
3753 if (acd->direction() == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003754 target_codecs =
3755 VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_SendCodecs);
Steve Anton4e70a722017-11-28 14:57:10 -08003756 } else if (acd->direction() == RtpTransceiverDirection::kRecvOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003757 target_codecs =
3758 VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_RecvCodecs);
ossu075af922016-06-14 03:29:38 -07003759 } else {
3760 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3761 kResultSendrecv_SendrecvCodecs);
3762 }
3763 break;
3764 }
3765
zhihuang1c378ed2017-08-17 14:10:50 -07003766 auto format_codecs = [](const std::vector<AudioCodec>& codecs) {
Jonas Olsson366a50c2018-09-06 13:41:30 +02003767 rtc::StringBuilder os;
ossu075af922016-06-14 03:29:38 -07003768 bool first = true;
3769 os << "{";
3770 for (const auto& c : codecs) {
3771 os << (first ? " " : ", ") << c.id;
3772 first = false;
3773 }
3774 os << " }";
Jonas Olsson84df1c72018-09-14 16:59:32 +02003775 return os.Release();
ossu075af922016-06-14 03:29:38 -07003776 };
3777
3778 EXPECT_TRUE(acd->codecs() == target_codecs)
3779 << "Expected: " << format_codecs(target_codecs)
Steve Anton4e70a722017-11-28 14:57:10 -08003780 << ", got: " << format_codecs(acd->codecs()) << "; Offered: "
3781 << webrtc::RtpTransceiverDirectionToString(offer_direction)
ossu075af922016-06-14 03:29:38 -07003782 << ", answerer wants: "
Steve Anton4e70a722017-11-28 14:57:10 -08003783 << webrtc::RtpTransceiverDirectionToString(answer_direction)
3784 << "; got: "
3785 << webrtc::RtpTransceiverDirectionToString(acd->direction());
ossu075af922016-06-14 03:29:38 -07003786 } else {
Steve Anton4e70a722017-11-28 14:57:10 -08003787 EXPECT_EQ(offer_direction, RtpTransceiverDirection::kInactive)
zhihuang1c378ed2017-08-17 14:10:50 -07003788 << "Only inactive offers are allowed to not generate any audio "
3789 "content";
ossu075af922016-06-14 03:29:38 -07003790 }
3791}
brandtr03d5fb12016-11-22 03:37:59 -08003792
3793} // namespace
ossu075af922016-06-14 03:29:38 -07003794
3795class AudioCodecsOfferTest
Steve Anton4e70a722017-11-28 14:57:10 -08003796 : public ::testing::TestWithParam<RtpTransceiverDirection> {};
ossu075af922016-06-14 03:29:38 -07003797
3798TEST_P(AudioCodecsOfferTest, TestCodecsInOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07003799 TestAudioCodecsOffer(GetParam());
ossu075af922016-06-14 03:29:38 -07003800}
3801
3802INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
3803 AudioCodecsOfferTest,
Steve Anton4e70a722017-11-28 14:57:10 -08003804 ::testing::Values(RtpTransceiverDirection::kSendOnly,
3805 RtpTransceiverDirection::kRecvOnly,
3806 RtpTransceiverDirection::kSendRecv,
3807 RtpTransceiverDirection::kInactive));
ossu075af922016-06-14 03:29:38 -07003808
3809class AudioCodecsAnswerTest
Steve Anton4e70a722017-11-28 14:57:10 -08003810 : public ::testing::TestWithParam<::testing::tuple<RtpTransceiverDirection,
3811 RtpTransceiverDirection,
zhihuang1c378ed2017-08-17 14:10:50 -07003812 bool>> {};
ossu075af922016-06-14 03:29:38 -07003813
3814TEST_P(AudioCodecsAnswerTest, TestCodecsInAnswer) {
ehmaldonadoabcef5d2017-02-08 04:07:11 -08003815 TestAudioCodecsAnswer(::testing::get<0>(GetParam()),
3816 ::testing::get<1>(GetParam()),
3817 ::testing::get<2>(GetParam()));
ossu075af922016-06-14 03:29:38 -07003818}
3819
zhihuang1c378ed2017-08-17 14:10:50 -07003820INSTANTIATE_TEST_CASE_P(
3821 MediaSessionDescriptionFactoryTest,
3822 AudioCodecsAnswerTest,
Steve Anton4e70a722017-11-28 14:57:10 -08003823 ::testing::Combine(::testing::Values(RtpTransceiverDirection::kSendOnly,
3824 RtpTransceiverDirection::kRecvOnly,
3825 RtpTransceiverDirection::kSendRecv,
3826 RtpTransceiverDirection::kInactive),
3827 ::testing::Values(RtpTransceiverDirection::kSendOnly,
3828 RtpTransceiverDirection::kRecvOnly,
3829 RtpTransceiverDirection::kSendRecv,
3830 RtpTransceiverDirection::kInactive),
zhihuang1c378ed2017-08-17 14:10:50 -07003831 ::testing::Bool()));