blob: 2098ec081943e8e4c26ee704497c9bd36f410bf5 [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"
Steve Antone38a5a12018-11-21 16:05:15 -080029#include "test/gmock.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000030
Yves Gerey665174f2018-06-19 15:03:05 +020031#define ASSERT_CRYPTO(cd, s, cs) \
32 ASSERT_EQ(s, cd->cryptos().size()); \
Steve Antone38a5a12018-11-21 16:05:15 -080033 ASSERT_EQ(cs, cd->cryptos()[0].cipher_suite)
henrike@webrtc.org28e20752013-07-10 00:45:36 +000034
35typedef std::vector<cricket::Candidate> Candidates;
36
37using cricket::MediaContentDescription;
38using cricket::MediaSessionDescriptionFactory;
zhihuang1c378ed2017-08-17 14:10:50 -070039using cricket::MediaDescriptionOptions;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000040using cricket::MediaSessionOptions;
41using cricket::MediaType;
Steve Anton5adfafd2017-12-20 16:34:00 -080042using cricket::MediaProtocolType;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000043using cricket::SessionDescription;
44using cricket::SsrcGroup;
45using cricket::StreamParams;
46using cricket::StreamParamsVec;
47using cricket::TransportDescription;
48using cricket::TransportDescriptionFactory;
49using cricket::TransportInfo;
50using cricket::ContentInfo;
51using cricket::CryptoParamsVec;
52using cricket::AudioContentDescription;
53using cricket::VideoContentDescription;
54using cricket::DataContentDescription;
deadbeef44f08192015-12-15 16:20:09 -080055using cricket::GetFirstAudioContent;
56using cricket::GetFirstVideoContent;
57using cricket::GetFirstDataContent;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000058using cricket::GetFirstAudioContentDescription;
59using cricket::GetFirstVideoContentDescription;
60using cricket::GetFirstDataContentDescription;
61using cricket::kAutoBandwidth;
62using cricket::AudioCodec;
63using cricket::VideoCodec;
64using cricket::DataCodec;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000065using cricket::MEDIA_TYPE_AUDIO;
66using cricket::MEDIA_TYPE_VIDEO;
67using cricket::MEDIA_TYPE_DATA;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068using cricket::SEC_DISABLED;
69using cricket::SEC_ENABLED;
70using cricket::SEC_REQUIRED;
Guo-wei Shieh456696a2015-09-30 21:48:54 -070071using rtc::CS_AES_CM_128_HMAC_SHA1_32;
72using rtc::CS_AES_CM_128_HMAC_SHA1_80;
jbauchcb560652016-08-04 05:20:32 -070073using rtc::CS_AEAD_AES_128_GCM;
74using rtc::CS_AEAD_AES_256_GCM;
Steve Antone38a5a12018-11-21 16:05:15 -080075using testing::ElementsAreArray;
isheriff6f8d6862016-05-26 11:24:55 -070076using webrtc::RtpExtension;
Steve Anton4e70a722017-11-28 14:57:10 -080077using webrtc::RtpTransceiverDirection;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000078
79static const AudioCodec kAudioCodecs1[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070080 AudioCodec(103, "ISAC", 16000, -1, 1),
81 AudioCodec(102, "iLBC", 8000, 13300, 1),
82 AudioCodec(0, "PCMU", 8000, 64000, 1),
83 AudioCodec(8, "PCMA", 8000, 64000, 1),
84 AudioCodec(117, "red", 8000, 0, 1),
85 AudioCodec(107, "CN", 48000, 0, 1)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086
87static const AudioCodec kAudioCodecs2[] = {
Henrik Lundinf8ed5612018-05-07 12:05:57 +020088 AudioCodec(126, "foo", 16000, 22000, 1),
deadbeef67cf2c12016-04-13 10:07:16 -070089 AudioCodec(0, "PCMU", 8000, 64000, 1),
90 AudioCodec(127, "iLBC", 8000, 13300, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000091};
92
93static const AudioCodec kAudioCodecsAnswer[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070094 AudioCodec(102, "iLBC", 8000, 13300, 1),
95 AudioCodec(0, "PCMU", 8000, 64000, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000096};
97
perkj26752742016-10-24 01:21:16 -070098static const VideoCodec kVideoCodecs1[] = {VideoCodec(96, "H264-SVC"),
99 VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000100
zhihuang1c378ed2017-08-17 14:10:50 -0700101static const VideoCodec kVideoCodecs1Reverse[] = {VideoCodec(97, "H264"),
102 VideoCodec(96, "H264-SVC")};
103
perkj26752742016-10-24 01:21:16 -0700104static const VideoCodec kVideoCodecs2[] = {VideoCodec(126, "H264"),
105 VideoCodec(127, "H263")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000106
perkj26752742016-10-24 01:21:16 -0700107static const VideoCodec kVideoCodecsAnswer[] = {VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108
deadbeef67cf2c12016-04-13 10:07:16 -0700109static const DataCodec kDataCodecs1[] = {DataCodec(98, "binary-data"),
110 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000111
deadbeef67cf2c12016-04-13 10:07:16 -0700112static const DataCodec kDataCodecs2[] = {DataCodec(126, "binary-data"),
113 DataCodec(127, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000114
deadbeef67cf2c12016-04-13 10:07:16 -0700115static const DataCodec kDataCodecsAnswer[] = {DataCodec(98, "binary-data"),
116 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000117
isheriff6f8d6862016-05-26 11:24:55 -0700118static const RtpExtension kAudioRtpExtension1[] = {
119 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
120 RtpExtension("http://google.com/testing/audio_something", 10),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000121};
122
jbauch5869f502017-06-29 12:31:36 -0700123static const RtpExtension kAudioRtpExtensionEncrypted1[] = {
124 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
125 RtpExtension("http://google.com/testing/audio_something", 10),
126 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 12, true),
127};
128
isheriff6f8d6862016-05-26 11:24:55 -0700129static const RtpExtension kAudioRtpExtension2[] = {
130 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
131 RtpExtension("http://google.com/testing/audio_something_else", 8),
132 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000133};
134
isheriff6f8d6862016-05-26 11:24:55 -0700135static const RtpExtension kAudioRtpExtension3[] = {
136 RtpExtension("http://google.com/testing/audio_something", 2),
137 RtpExtension("http://google.com/testing/both_audio_and_video", 3),
deadbeefa5b273a2015-08-20 17:30:13 -0700138};
139
jbauch5869f502017-06-29 12:31:36 -0700140static const RtpExtension kAudioRtpExtension3ForEncryption[] = {
141 RtpExtension("http://google.com/testing/audio_something", 2),
142 // Use RTP extension that supports encryption.
143 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 3),
144};
145
146static const RtpExtension kAudioRtpExtension3ForEncryptionOffer[] = {
147 RtpExtension("http://google.com/testing/audio_something", 2),
148 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 3),
149 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14, true),
150};
151
isheriff6f8d6862016-05-26 11:24:55 -0700152static const RtpExtension kAudioRtpExtensionAnswer[] = {
153 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000154};
155
jbauch5869f502017-06-29 12:31:36 -0700156static const RtpExtension kAudioRtpExtensionEncryptedAnswer[] = {
157 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 12, true),
158};
159
isheriff6f8d6862016-05-26 11:24:55 -0700160static const RtpExtension kVideoRtpExtension1[] = {
161 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
162 RtpExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000163};
164
jbauch5869f502017-06-29 12:31:36 -0700165static const RtpExtension kVideoRtpExtensionEncrypted1[] = {
166 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
167 RtpExtension("http://google.com/testing/video_something", 13),
168 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 11, true),
169};
170
isheriff6f8d6862016-05-26 11:24:55 -0700171static const RtpExtension kVideoRtpExtension2[] = {
172 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
173 RtpExtension("http://google.com/testing/video_something_else", 14),
174 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000175};
176
isheriff6f8d6862016-05-26 11:24:55 -0700177static const RtpExtension kVideoRtpExtension3[] = {
178 RtpExtension("http://google.com/testing/video_something", 4),
179 RtpExtension("http://google.com/testing/both_audio_and_video", 5),
deadbeefa5b273a2015-08-20 17:30:13 -0700180};
181
jbauch5869f502017-06-29 12:31:36 -0700182static const RtpExtension kVideoRtpExtension3ForEncryption[] = {
183 RtpExtension("http://google.com/testing/video_something", 4),
184 // Use RTP extension that supports encryption.
185 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 5),
186};
187
isheriff6f8d6862016-05-26 11:24:55 -0700188static const RtpExtension kVideoRtpExtensionAnswer[] = {
189 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000190};
191
jbauch5869f502017-06-29 12:31:36 -0700192static const RtpExtension kVideoRtpExtensionEncryptedAnswer[] = {
193 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 11, true),
194};
195
Peter Boström0c4e06b2015-10-07 12:23:21 +0200196static const uint32_t kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
197static const uint32_t kSimSsrc[] = {10, 20, 30};
198static const uint32_t kFec1Ssrc[] = {10, 11};
199static const uint32_t kFec2Ssrc[] = {20, 21};
200static const uint32_t kFec3Ssrc[] = {30, 31};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000201
202static const char kMediaStream1[] = "stream_1";
203static const char kMediaStream2[] = "stream_2";
204static const char kVideoTrack1[] = "video_1";
205static const char kVideoTrack2[] = "video_2";
206static const char kAudioTrack1[] = "audio_1";
207static const char kAudioTrack2[] = "audio_2";
208static const char kAudioTrack3[] = "audio_3";
209static const char kDataTrack1[] = "data_1";
210static const char kDataTrack2[] = "data_2";
211static const char kDataTrack3[] = "data_3";
212
zhihuangcf5b37c2016-05-05 11:44:35 -0700213static const char* kMediaProtocols[] = {"RTP/AVP", "RTP/SAVP", "RTP/AVPF",
214 "RTP/SAVPF"};
215static const char* kMediaProtocolsDtls[] = {
216 "TCP/TLS/RTP/SAVPF", "TCP/TLS/RTP/SAVP", "UDP/TLS/RTP/SAVPF",
217 "UDP/TLS/RTP/SAVP"};
218
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700219// SRTP cipher name negotiated by the tests. This must be updated if the
220// default changes.
221static const char* kDefaultSrtpCryptoSuite = CS_AES_CM_128_HMAC_SHA1_80;
222static const char* kDefaultSrtpCryptoSuiteGcm = CS_AEAD_AES_256_GCM;
223
zhihuang1c378ed2017-08-17 14:10:50 -0700224// These constants are used to make the code using "AddMediaSection" more
225// readable.
226static constexpr bool kStopped = true;
227static constexpr bool kActive = false;
228
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000229static bool IsMediaContentOfType(const ContentInfo* content,
230 MediaType media_type) {
Steve Antonb1c1de12017-12-21 15:14:30 -0800231 RTC_DCHECK(content);
232 return content->media_description()->type() == media_type;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000233}
234
Steve Anton4e70a722017-11-28 14:57:10 -0800235static RtpTransceiverDirection GetMediaDirection(const ContentInfo* content) {
Steve Antonb1c1de12017-12-21 15:14:30 -0800236 RTC_DCHECK(content);
237 return content->media_description()->direction();
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000238}
239
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000240static void AddRtxCodec(const VideoCodec& rtx_codec,
241 std::vector<VideoCodec>* codecs) {
magjedb05fa242016-11-11 04:00:16 -0800242 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000243 codecs->push_back(rtx_codec);
244}
245
246template <class T>
247static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
248 std::vector<std::string> codec_names;
249 for (const auto& codec : codecs) {
250 codec_names.push_back(codec.name);
251 }
252 return codec_names;
253}
254
zhihuang1c378ed2017-08-17 14:10:50 -0700255// This is used for test only. MIDs are not the identification of the
256// MediaDescriptionOptions since some end points may not support MID and the SDP
257// may not contain 'mid'.
258std::vector<MediaDescriptionOptions>::iterator FindFirstMediaDescriptionByMid(
259 const std::string& mid,
260 MediaSessionOptions* opts) {
261 return std::find_if(
262 opts->media_description_options.begin(),
263 opts->media_description_options.end(),
Steve Anton36b29d12017-10-30 09:57:42 -0700264 [&mid](const MediaDescriptionOptions& t) { return t.mid == mid; });
265}
266
267std::vector<MediaDescriptionOptions>::const_iterator
268FindFirstMediaDescriptionByMid(const std::string& mid,
269 const MediaSessionOptions& opts) {
270 return std::find_if(
271 opts.media_description_options.begin(),
272 opts.media_description_options.end(),
273 [&mid](const MediaDescriptionOptions& t) { return t.mid == mid; });
zhihuang1c378ed2017-08-17 14:10:50 -0700274}
275
276// Add a media section to the |session_options|.
277static void AddMediaSection(MediaType type,
278 const std::string& mid,
Steve Anton4e70a722017-11-28 14:57:10 -0800279 RtpTransceiverDirection direction,
zhihuang1c378ed2017-08-17 14:10:50 -0700280 bool stopped,
281 MediaSessionOptions* opts) {
Steve Anton4e70a722017-11-28 14:57:10 -0800282 opts->media_description_options.push_back(
283 MediaDescriptionOptions(type, mid, direction, stopped));
zhihuang1c378ed2017-08-17 14:10:50 -0700284}
285
Steve Anton4e70a722017-11-28 14:57:10 -0800286static void AddAudioVideoSections(RtpTransceiverDirection direction,
zhihuang1c378ed2017-08-17 14:10:50 -0700287 MediaSessionOptions* opts) {
288 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", direction, kActive, opts);
289 AddMediaSection(MEDIA_TYPE_VIDEO, "video", direction, kActive, opts);
290}
291
292static void AddDataSection(cricket::DataChannelType dct,
Steve Anton4e70a722017-11-28 14:57:10 -0800293 RtpTransceiverDirection direction,
zhihuang1c378ed2017-08-17 14:10:50 -0700294 MediaSessionOptions* opts) {
295 opts->data_channel_type = dct;
296 AddMediaSection(MEDIA_TYPE_DATA, "data", direction, kActive, opts);
297}
298
Steve Anton8ffb9c32017-08-31 15:45:38 -0700299static void AttachSenderToMediaSection(
300 const std::string& mid,
301 MediaType type,
302 const std::string& track_id,
303 const std::vector<std::string>& stream_ids,
304 int num_sim_layer,
305 MediaSessionOptions* session_options) {
zhihuang1c378ed2017-08-17 14:10:50 -0700306 auto it = FindFirstMediaDescriptionByMid(mid, session_options);
307 switch (type) {
308 case MEDIA_TYPE_AUDIO:
Steve Anton8ffb9c32017-08-31 15:45:38 -0700309 it->AddAudioSender(track_id, stream_ids);
zhihuang1c378ed2017-08-17 14:10:50 -0700310 break;
311 case MEDIA_TYPE_VIDEO:
Steve Anton8ffb9c32017-08-31 15:45:38 -0700312 it->AddVideoSender(track_id, stream_ids, num_sim_layer);
zhihuang1c378ed2017-08-17 14:10:50 -0700313 break;
314 case MEDIA_TYPE_DATA:
Steve Anton8ffb9c32017-08-31 15:45:38 -0700315 RTC_CHECK(stream_ids.size() == 1U);
316 it->AddRtpDataChannel(track_id, stream_ids[0]);
zhihuang1c378ed2017-08-17 14:10:50 -0700317 break;
318 default:
319 RTC_NOTREACHED();
320 }
321}
322
323static void DetachSenderFromMediaSection(const std::string& mid,
324 const std::string& track_id,
325 MediaSessionOptions* session_options) {
Steve Anton3a66edf2018-09-10 12:57:37 -0700326 std::vector<cricket::SenderOptions>& sender_options_list =
327 FindFirstMediaDescriptionByMid(mid, session_options)->sender_options;
328 auto sender_it =
329 std::find_if(sender_options_list.begin(), sender_options_list.end(),
330 [track_id](const cricket::SenderOptions& sender_options) {
331 return sender_options.track_id == track_id;
332 });
333 RTC_DCHECK(sender_it != sender_options_list.end());
334 sender_options_list.erase(sender_it);
zhihuang1c378ed2017-08-17 14:10:50 -0700335}
336
337// Helper function used to create a default MediaSessionOptions for Plan B SDP.
338// (https://tools.ietf.org/html/draft-uberti-rtcweb-plan-00).
339static MediaSessionOptions CreatePlanBMediaSessionOptions() {
340 MediaSessionOptions session_options;
Steve Anton4e70a722017-11-28 14:57:10 -0800341 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
342 kActive, &session_options);
zhihuang1c378ed2017-08-17 14:10:50 -0700343 return session_options;
344}
345
346// TODO(zhihuang): Most of these tests were written while MediaSessionOptions
347// was designed for Plan B SDP, where only one audio "m=" section and one video
348// "m=" section could be generated, and ordering couldn't be controlled. Many of
349// these tests may be obsolete as a result, and should be refactored or removed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000350class MediaSessionDescriptionFactoryTest : public testing::Test {
351 public:
zhihuang1c378ed2017-08-17 14:10:50 -0700352 MediaSessionDescriptionFactoryTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -0700353 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
354 MAKE_VECTOR(kAudioCodecs1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000355 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
356 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -0700357 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
358 MAKE_VECTOR(kAudioCodecs2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000359 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
360 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200361 tdf1_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700362 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200363 tdf2_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700364 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000365 }
366
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000367 // Create a video StreamParamsVec object with:
368 // - one video stream with 3 simulcast streams and FEC,
369 StreamParamsVec CreateComplexVideoStreamParamsVec() {
370 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
371 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
372 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
373 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
374
375 std::vector<SsrcGroup> ssrc_groups;
376 ssrc_groups.push_back(sim_group);
377 ssrc_groups.push_back(fec_group1);
378 ssrc_groups.push_back(fec_group2);
379 ssrc_groups.push_back(fec_group3);
380
381 StreamParams simulcast_params;
382 simulcast_params.id = kVideoTrack1;
383 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
384 simulcast_params.ssrc_groups = ssrc_groups;
385 simulcast_params.cname = "Video_SIM_FEC";
Seth Hampson845e8782018-03-02 11:34:10 -0800386 simulcast_params.set_stream_ids({kMediaStream1});
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000387
388 StreamParamsVec video_streams;
389 video_streams.push_back(simulcast_params);
390
391 return video_streams;
392 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000393
394 bool CompareCryptoParams(const CryptoParamsVec& c1,
395 const CryptoParamsVec& c2) {
396 if (c1.size() != c2.size())
397 return false;
398 for (size_t i = 0; i < c1.size(); ++i)
399 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
400 c1[i].key_params != c2[i].key_params ||
401 c1[i].session_params != c2[i].session_params)
402 return false;
403 return true;
404 }
405
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700406 // Returns true if the transport info contains "renomination" as an
407 // ICE option.
408 bool GetIceRenomination(const TransportInfo* transport_info) {
409 const std::vector<std::string>& ice_options =
410 transport_info->description.transport_options;
deadbeef30952b42017-04-21 02:41:29 -0700411 auto iter =
412 std::find(ice_options.begin(), ice_options.end(), "renomination");
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700413 return iter != ice_options.end();
414 }
415
zhihuang1c378ed2017-08-17 14:10:50 -0700416 void TestTransportInfo(bool offer,
Steve Anton36b29d12017-10-30 09:57:42 -0700417 const MediaSessionOptions& options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000418 bool has_current_desc) {
419 const std::string current_audio_ufrag = "current_audio_ufrag";
420 const std::string current_audio_pwd = "current_audio_pwd";
421 const std::string current_video_ufrag = "current_video_ufrag";
422 const std::string current_video_pwd = "current_video_pwd";
423 const std::string current_data_ufrag = "current_data_ufrag";
424 const std::string current_data_pwd = "current_data_pwd";
kwiberg31022942016-03-11 14:18:21 -0800425 std::unique_ptr<SessionDescription> current_desc;
426 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000427 if (has_current_desc) {
428 current_desc.reset(new SessionDescription());
Yves Gerey665174f2018-06-19 15:03:05 +0200429 EXPECT_TRUE(current_desc->AddTransportInfo(TransportInfo(
430 "audio",
431 TransportDescription(current_audio_ufrag, current_audio_pwd))));
432 EXPECT_TRUE(current_desc->AddTransportInfo(TransportInfo(
433 "video",
434 TransportDescription(current_video_ufrag, current_video_pwd))));
435 EXPECT_TRUE(current_desc->AddTransportInfo(TransportInfo(
436 "data", TransportDescription(current_data_ufrag, current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000437 }
438 if (offer) {
439 desc.reset(f1_.CreateOffer(options, current_desc.get()));
440 } else {
kwiberg31022942016-03-11 14:18:21 -0800441 std::unique_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000442 offer.reset(f1_.CreateOffer(options, NULL));
443 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
444 }
445 ASSERT_TRUE(desc.get() != NULL);
446 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000447 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000448 EXPECT_TRUE(ti_audio != NULL);
449 if (has_current_desc) {
450 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
451 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
452 } else {
453 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
454 ti_audio->description.ice_ufrag.size());
455 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
456 ti_audio->description.ice_pwd.size());
457 }
zhihuang1c378ed2017-08-17 14:10:50 -0700458 auto media_desc_options_it =
Steve Anton36b29d12017-10-30 09:57:42 -0700459 FindFirstMediaDescriptionByMid("audio", options);
zhihuang1c378ed2017-08-17 14:10:50 -0700460 EXPECT_EQ(
461 media_desc_options_it->transport_options.enable_ice_renomination,
462 GetIceRenomination(ti_audio));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000463
464 } else {
465 EXPECT_TRUE(ti_audio == NULL);
466 }
467 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000468 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000469 EXPECT_TRUE(ti_video != NULL);
470 if (options.bundle_enabled) {
471 EXPECT_EQ(ti_audio->description.ice_ufrag,
472 ti_video->description.ice_ufrag);
Yves Gerey665174f2018-06-19 15:03:05 +0200473 EXPECT_EQ(ti_audio->description.ice_pwd, ti_video->description.ice_pwd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000474 } else {
475 if (has_current_desc) {
476 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
477 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
478 } else {
479 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
480 ti_video->description.ice_ufrag.size());
481 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
482 ti_video->description.ice_pwd.size());
483 }
484 }
zhihuang1c378ed2017-08-17 14:10:50 -0700485 auto media_desc_options_it =
Steve Anton36b29d12017-10-30 09:57:42 -0700486 FindFirstMediaDescriptionByMid("video", options);
zhihuang1c378ed2017-08-17 14:10:50 -0700487 EXPECT_EQ(
488 media_desc_options_it->transport_options.enable_ice_renomination,
489 GetIceRenomination(ti_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000490 } else {
491 EXPECT_TRUE(ti_video == NULL);
492 }
493 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
494 if (options.has_data()) {
495 EXPECT_TRUE(ti_data != NULL);
496 if (options.bundle_enabled) {
497 EXPECT_EQ(ti_audio->description.ice_ufrag,
498 ti_data->description.ice_ufrag);
Yves Gerey665174f2018-06-19 15:03:05 +0200499 EXPECT_EQ(ti_audio->description.ice_pwd, ti_data->description.ice_pwd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000500 } else {
501 if (has_current_desc) {
502 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
503 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
504 } else {
505 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
506 ti_data->description.ice_ufrag.size());
507 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
508 ti_data->description.ice_pwd.size());
509 }
510 }
zhihuang1c378ed2017-08-17 14:10:50 -0700511 auto media_desc_options_it =
Steve Anton36b29d12017-10-30 09:57:42 -0700512 FindFirstMediaDescriptionByMid("data", options);
zhihuang1c378ed2017-08-17 14:10:50 -0700513 EXPECT_EQ(
514 media_desc_options_it->transport_options.enable_ice_renomination,
515 GetIceRenomination(ti_data));
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700516
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000517 } else {
518 EXPECT_TRUE(ti_video == NULL);
519 }
520 }
521
522 void TestCryptoWithBundle(bool offer) {
523 f1_.set_secure(SEC_ENABLED);
524 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -0800525 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
526 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
527 &options);
kwiberg31022942016-03-11 14:18:21 -0800528 std::unique_ptr<SessionDescription> ref_desc;
529 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000530 if (offer) {
531 options.bundle_enabled = false;
532 ref_desc.reset(f1_.CreateOffer(options, NULL));
533 options.bundle_enabled = true;
534 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
535 } else {
536 options.bundle_enabled = true;
537 ref_desc.reset(f1_.CreateOffer(options, NULL));
538 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
539 }
Steve Antonb1c1de12017-12-21 15:14:30 -0800540 ASSERT_TRUE(desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000541 const cricket::MediaContentDescription* audio_media_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -0800542 desc->GetContentDescriptionByName("audio");
543 ASSERT_TRUE(audio_media_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000544 const cricket::MediaContentDescription* video_media_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -0800545 desc->GetContentDescriptionByName("video");
546 ASSERT_TRUE(video_media_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000547 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
548 video_media_desc->cryptos()));
549 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
Steve Antone38a5a12018-11-21 16:05:15 -0800550 EXPECT_EQ(kDefaultSrtpCryptoSuite,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000551 audio_media_desc->cryptos()[0].cipher_suite);
552
553 // Verify the selected crypto is one from the reference audio
554 // media content.
555 const cricket::MediaContentDescription* ref_audio_media_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -0800556 ref_desc->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000557 bool found = false;
558 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
559 if (ref_audio_media_desc->cryptos()[i].Matches(
Yves Gerey665174f2018-06-19 15:03:05 +0200560 audio_media_desc->cryptos()[0])) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000561 found = true;
562 break;
563 }
564 }
565 EXPECT_TRUE(found);
566 }
567
568 // This test that the audio and video media direction is set to
569 // |expected_direction_in_answer| in an answer if the offer direction is set
zhihuang1c378ed2017-08-17 14:10:50 -0700570 // to |direction_in_offer| and the answer is willing to both send and receive.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000571 void TestMediaDirectionInAnswer(
Steve Anton4e70a722017-11-28 14:57:10 -0800572 RtpTransceiverDirection direction_in_offer,
573 RtpTransceiverDirection expected_direction_in_answer) {
zhihuang1c378ed2017-08-17 14:10:50 -0700574 MediaSessionOptions offer_opts;
575 AddAudioVideoSections(direction_in_offer, &offer_opts);
576
577 std::unique_ptr<SessionDescription> offer(
578 f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000579 ASSERT_TRUE(offer.get() != NULL);
terelius8c011e52016-04-26 05:28:11 -0700580 ContentInfo* ac_offer = offer->GetContentByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000581 ASSERT_TRUE(ac_offer != NULL);
terelius8c011e52016-04-26 05:28:11 -0700582 ContentInfo* vc_offer = offer->GetContentByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000583 ASSERT_TRUE(vc_offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000584
zhihuang1c378ed2017-08-17 14:10:50 -0700585 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800586 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &answer_opts);
kwiberg31022942016-03-11 14:18:21 -0800587 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -0700588 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000589 const AudioContentDescription* acd_answer =
590 GetFirstAudioContentDescription(answer.get());
591 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
592 const VideoContentDescription* vcd_answer =
593 GetFirstVideoContentDescription(answer.get());
594 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
595 }
596
597 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
Steve Antonb1c1de12017-12-21 15:14:30 -0800598 RTC_DCHECK(content);
599 RTC_CHECK(content->media_description());
600 const cricket::AudioContentDescription* audio_desc =
601 content->media_description()->as_audio();
602 RTC_CHECK(audio_desc);
603 for (const cricket::AudioCodec& codec : audio_desc->codecs()) {
604 if (codec.name == "CN") {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000605 return false;
Steve Antonb1c1de12017-12-21 15:14:30 -0800606 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000607 }
608 return true;
609 }
610
jbauchcb560652016-08-04 05:20:32 -0700611 void TestVideoGcmCipher(bool gcm_offer, bool gcm_answer) {
612 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800613 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &offer_opts);
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700614 offer_opts.crypto_options.srtp.enable_gcm_crypto_suites = gcm_offer;
zhihuang1c378ed2017-08-17 14:10:50 -0700615
jbauchcb560652016-08-04 05:20:32 -0700616 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800617 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &answer_opts);
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700618 answer_opts.crypto_options.srtp.enable_gcm_crypto_suites = gcm_answer;
zhihuang1c378ed2017-08-17 14:10:50 -0700619
jbauchcb560652016-08-04 05:20:32 -0700620 f1_.set_secure(SEC_ENABLED);
621 f2_.set_secure(SEC_ENABLED);
622 std::unique_ptr<SessionDescription> offer(
623 f1_.CreateOffer(offer_opts, NULL));
624 ASSERT_TRUE(offer.get() != NULL);
625 std::unique_ptr<SessionDescription> answer(
626 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
627 const ContentInfo* ac = answer->GetContentByName("audio");
628 const ContentInfo* vc = answer->GetContentByName("video");
629 ASSERT_TRUE(ac != NULL);
630 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800631 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
632 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800633 const AudioContentDescription* acd = ac->media_description()->as_audio();
634 const VideoContentDescription* vcd = vc->media_description()->as_video();
jbauchcb560652016-08-04 05:20:32 -0700635 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
Steve Antone38a5a12018-11-21 16:05:15 -0800636 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
jbauchcb560652016-08-04 05:20:32 -0700637 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -0700638 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -0700639 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
640 if (gcm_offer && gcm_answer) {
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700641 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
jbauchcb560652016-08-04 05:20:32 -0700642 } else {
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700643 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
jbauchcb560652016-08-04 05:20:32 -0700644 }
645 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
Steve Antone38a5a12018-11-21 16:05:15 -0800646 EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer));
Yves Gerey665174f2018-06-19 15:03:05 +0200647 EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
648 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
jbauchcb560652016-08-04 05:20:32 -0700649 if (gcm_offer && gcm_answer) {
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700650 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuiteGcm);
jbauchcb560652016-08-04 05:20:32 -0700651 } else {
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700652 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
jbauchcb560652016-08-04 05:20:32 -0700653 }
Steve Antone38a5a12018-11-21 16:05:15 -0800654 EXPECT_EQ(cricket::kMediaProtocolSavpf, vcd->protocol());
jbauchcb560652016-08-04 05:20:32 -0700655 }
656
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000657 protected:
658 MediaSessionDescriptionFactory f1_;
659 MediaSessionDescriptionFactory f2_;
660 TransportDescriptionFactory tdf1_;
661 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000662};
663
664// Create a typical audio offer, and ensure it matches what we expect.
665TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
666 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800667 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -0700668 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669 ASSERT_TRUE(offer.get() != NULL);
670 const ContentInfo* ac = offer->GetContentByName("audio");
671 const ContentInfo* vc = offer->GetContentByName("video");
672 ASSERT_TRUE(ac != NULL);
673 ASSERT_TRUE(vc == NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800674 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800675 const AudioContentDescription* acd = ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000676 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700677 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700678 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
680 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700681 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
Steve Antone38a5a12018-11-21 16:05:15 -0800682 EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000683}
684
685// Create a typical video offer, and ensure it matches what we expect.
686TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
687 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800688 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000689 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800690 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000691 ASSERT_TRUE(offer.get() != NULL);
692 const ContentInfo* ac = offer->GetContentByName("audio");
693 const ContentInfo* vc = offer->GetContentByName("video");
694 ASSERT_TRUE(ac != NULL);
695 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800696 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
697 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800698 const AudioContentDescription* acd = ac->media_description()->as_audio();
699 const VideoContentDescription* vcd = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000700 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700701 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700702 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000703 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
704 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700705 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
Steve Antone38a5a12018-11-21 16:05:15 -0800706 EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000707 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
708 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700709 EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000710 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
711 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700712 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
Steve Antone38a5a12018-11-21 16:05:15 -0800713 EXPECT_EQ(cricket::kMediaProtocolSavpf, vcd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000714}
715
716// Test creating an offer with bundle where the Codecs have the same dynamic
717// RTP playlod type. The test verifies that the offer don't contain the
718// duplicate RTP payload types.
719TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
720 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
ossudedfd282016-06-14 07:12:39 -0700721 const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000722 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
723 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
724 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
725
726 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800727 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
728 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000729 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800730 std::unique_ptr<SessionDescription> offer(f2_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000731 const VideoContentDescription* vcd =
732 GetFirstVideoContentDescription(offer.get());
733 const AudioContentDescription* acd =
734 GetFirstAudioContentDescription(offer.get());
735 const DataContentDescription* dcd =
736 GetFirstDataContentDescription(offer.get());
737 ASSERT_TRUE(NULL != vcd);
738 ASSERT_TRUE(NULL != acd);
739 ASSERT_TRUE(NULL != dcd);
740 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
741 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
742 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
743 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
744 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
745 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
746}
747
zhihuang1c378ed2017-08-17 14:10:50 -0700748// Test creating an updated offer with bundle, audio, video and data
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000749// after an audio only session has been negotiated.
750TEST_F(MediaSessionDescriptionFactoryTest,
751 TestCreateUpdatedVideoOfferWithBundle) {
752 f1_.set_secure(SEC_ENABLED);
753 f2_.set_secure(SEC_ENABLED);
754 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800755 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
756 kActive, &opts);
757 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kInactive,
758 kStopped, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000759 opts.data_channel_type = cricket::DCT_NONE;
760 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800761 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
762 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000763 f2_.CreateAnswer(offer.get(), opts, NULL));
764
765 MediaSessionOptions updated_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800766 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &updated_opts);
767 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
768 &updated_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000769 updated_opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800770 std::unique_ptr<SessionDescription> updated_offer(
771 f1_.CreateOffer(updated_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000772
773 const AudioContentDescription* acd =
774 GetFirstAudioContentDescription(updated_offer.get());
775 const VideoContentDescription* vcd =
776 GetFirstVideoContentDescription(updated_offer.get());
777 const DataContentDescription* dcd =
778 GetFirstDataContentDescription(updated_offer.get());
779 EXPECT_TRUE(NULL != vcd);
780 EXPECT_TRUE(NULL != acd);
781 EXPECT_TRUE(NULL != dcd);
782
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700783 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
Steve Antone38a5a12018-11-21 16:05:15 -0800784 EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700785 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
Steve Antone38a5a12018-11-21 16:05:15 -0800786 EXPECT_EQ(cricket::kMediaProtocolSavpf, vcd->protocol());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700787 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
Steve Antone38a5a12018-11-21 16:05:15 -0800788 EXPECT_EQ(cricket::kMediaProtocolSavpf, dcd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000789}
deadbeef44f08192015-12-15 16:20:09 -0800790
wu@webrtc.org78187522013-10-07 23:32:02 +0000791// Create a RTP data offer, and ensure it matches what we expect.
792TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000793 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800794 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
795 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000796 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800797 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000798 ASSERT_TRUE(offer.get() != NULL);
799 const ContentInfo* ac = offer->GetContentByName("audio");
800 const ContentInfo* dc = offer->GetContentByName("data");
801 ASSERT_TRUE(ac != NULL);
802 ASSERT_TRUE(dc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800803 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
804 EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800805 const AudioContentDescription* acd = ac->media_description()->as_audio();
806 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000807 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700808 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700809 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attched.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000810 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
811 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700812 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
Steve Antone38a5a12018-11-21 16:05:15 -0800813 EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000814 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
815 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700816 EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000817 EXPECT_EQ(cricket::kDataMaxBandwidth,
Yves Gerey665174f2018-06-19 15:03:05 +0200818 dcd->bandwidth()); // default bandwidth (auto)
819 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700820 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
Steve Antone38a5a12018-11-21 16:05:15 -0800821 EXPECT_EQ(cricket::kMediaProtocolSavpf, dcd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000822}
823
wu@webrtc.org78187522013-10-07 23:32:02 +0000824// Create an SCTP data offer with bundle without error.
825TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
826 MediaSessionOptions opts;
wu@webrtc.org78187522013-10-07 23:32:02 +0000827 opts.bundle_enabled = true;
Steve Anton4e70a722017-11-28 14:57:10 -0800828 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
wu@webrtc.org78187522013-10-07 23:32:02 +0000829 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800830 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000831 EXPECT_TRUE(offer.get() != NULL);
832 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
833}
834
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000835// Test creating an sctp data channel from an already generated offer.
836TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
837 MediaSessionOptions opts;
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000838 opts.bundle_enabled = true;
Steve Anton4e70a722017-11-28 14:57:10 -0800839 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000840 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800841 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000842 ASSERT_TRUE(offer1.get() != NULL);
843 const ContentInfo* data = offer1->GetContentByName("data");
844 ASSERT_TRUE(data != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -0800845 ASSERT_EQ(cricket::kMediaProtocolSctp, data->media_description()->protocol());
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000846
847 // Now set data_channel_type to 'none' (default) and make sure that the
848 // datachannel type that gets generated from the previous offer, is of the
849 // same type.
850 opts.data_channel_type = cricket::DCT_NONE;
kwiberg31022942016-03-11 14:18:21 -0800851 std::unique_ptr<SessionDescription> offer2(
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000852 f1_.CreateOffer(opts, offer1.get()));
853 data = offer2->GetContentByName("data");
854 ASSERT_TRUE(data != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -0800855 EXPECT_EQ(cricket::kMediaProtocolSctp, data->media_description()->protocol());
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000856}
857
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000858// Create an audio, video offer without legacy StreamParams.
859TEST_F(MediaSessionDescriptionFactoryTest,
860 TestCreateOfferWithoutLegacyStreams) {
861 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800862 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
kwiberg31022942016-03-11 14:18:21 -0800863 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000864 ASSERT_TRUE(offer.get() != NULL);
865 const ContentInfo* ac = offer->GetContentByName("audio");
866 const ContentInfo* vc = offer->GetContentByName("video");
867 ASSERT_TRUE(ac != NULL);
868 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -0800869 const AudioContentDescription* acd = ac->media_description()->as_audio();
870 const VideoContentDescription* vcd = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000871
Yves Gerey665174f2018-06-19 15:03:05 +0200872 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
873 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000874}
875
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000876// Creates an audio+video sendonly offer.
877TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -0700878 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800879 AddAudioVideoSections(RtpTransceiverDirection::kSendOnly, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -0700880 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -0700881 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -0700882 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -0700883 {kMediaStream1}, 1, &opts);
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000884
zhihuang1c378ed2017-08-17 14:10:50 -0700885 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000886 ASSERT_TRUE(offer.get() != NULL);
887 EXPECT_EQ(2u, offer->contents().size());
888 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
889 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
890
Steve Anton4e70a722017-11-28 14:57:10 -0800891 EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
892 GetMediaDirection(&offer->contents()[0]));
893 EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
894 GetMediaDirection(&offer->contents()[1]));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000895}
896
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000897// Verifies that the order of the media contents in the current
898// SessionDescription is preserved in the new SessionDescription.
899TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
900 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800901 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000902
kwiberg31022942016-03-11 14:18:21 -0800903 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000904 ASSERT_TRUE(offer1.get() != NULL);
905 EXPECT_EQ(1u, offer1->contents().size());
906 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
907
Steve Anton4e70a722017-11-28 14:57:10 -0800908 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
909 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -0800910 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000911 f1_.CreateOffer(opts, offer1.get()));
912 ASSERT_TRUE(offer2.get() != NULL);
913 EXPECT_EQ(2u, offer2->contents().size());
914 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
915 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
916
Steve Anton4e70a722017-11-28 14:57:10 -0800917 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
918 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -0800919 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000920 f1_.CreateOffer(opts, offer2.get()));
921 ASSERT_TRUE(offer3.get() != NULL);
922 EXPECT_EQ(3u, offer3->contents().size());
923 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
924 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
925 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000926}
927
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000928// Create a typical audio answer, and ensure it matches what we expect.
929TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
930 f1_.set_secure(SEC_ENABLED);
931 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800932 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -0700933 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000934 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800935 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -0700936 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000937 const ContentInfo* ac = answer->GetContentByName("audio");
938 const ContentInfo* vc = answer->GetContentByName("video");
939 ASSERT_TRUE(ac != NULL);
940 ASSERT_TRUE(vc == NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800941 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800942 const AudioContentDescription* acd = ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000943 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
Steve Antone38a5a12018-11-21 16:05:15 -0800944 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
zhihuang1c378ed2017-08-17 14:10:50 -0700945 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000946 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
947 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700948 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
Steve Antone38a5a12018-11-21 16:05:15 -0800949 EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000950}
951
jbauchcb560652016-08-04 05:20:32 -0700952// Create a typical audio answer with GCM ciphers enabled, and ensure it
953// matches what we expect.
954TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
955 f1_.set_secure(SEC_ENABLED);
956 f2_.set_secure(SEC_ENABLED);
zhihuang1c378ed2017-08-17 14:10:50 -0700957 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700958 opts.crypto_options.srtp.enable_gcm_crypto_suites = true;
zhihuang1c378ed2017-08-17 14:10:50 -0700959 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
jbauchcb560652016-08-04 05:20:32 -0700960 ASSERT_TRUE(offer.get() != NULL);
961 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -0700962 f2_.CreateAnswer(offer.get(), opts, NULL));
jbauchcb560652016-08-04 05:20:32 -0700963 const ContentInfo* ac = answer->GetContentByName("audio");
964 const ContentInfo* vc = answer->GetContentByName("video");
965 ASSERT_TRUE(ac != NULL);
966 ASSERT_TRUE(vc == NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800967 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800968 const AudioContentDescription* acd = ac->media_description()->as_audio();
jbauchcb560652016-08-04 05:20:32 -0700969 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
Steve Antone38a5a12018-11-21 16:05:15 -0800970 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
zhihuang1c378ed2017-08-17 14:10:50 -0700971 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -0700972 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
973 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700974 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
Steve Antone38a5a12018-11-21 16:05:15 -0800975 EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
jbauchcb560652016-08-04 05:20:32 -0700976}
977
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000978// Create a typical video answer, and ensure it matches what we expect.
979TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
980 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800981 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000982 f1_.set_secure(SEC_ENABLED);
983 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800984 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000985 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800986 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000987 f2_.CreateAnswer(offer.get(), opts, NULL));
988 const ContentInfo* ac = answer->GetContentByName("audio");
989 const ContentInfo* vc = answer->GetContentByName("video");
990 ASSERT_TRUE(ac != NULL);
991 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800992 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
993 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800994 const AudioContentDescription* acd = ac->media_description()->as_audio();
995 const VideoContentDescription* vcd = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000996 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
Steve Antone38a5a12018-11-21 16:05:15 -0800997 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000998 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -0700999 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001000 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001001 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001002 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
Steve Antone38a5a12018-11-21 16:05:15 -08001003 EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer));
Yves Gerey665174f2018-06-19 15:03:05 +02001004 EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
1005 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001006 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
Steve Antone38a5a12018-11-21 16:05:15 -08001007 EXPECT_EQ(cricket::kMediaProtocolSavpf, vcd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001008}
1009
jbauchcb560652016-08-04 05:20:32 -07001010// Create a typical video answer with GCM ciphers enabled, and ensure it
1011// matches what we expect.
1012TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcm) {
1013 TestVideoGcmCipher(true, true);
1014}
1015
1016// Create a typical video answer with GCM ciphers enabled for the offer only,
1017// and ensure it matches what we expect.
1018TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmOffer) {
1019 TestVideoGcmCipher(true, false);
1020}
1021
1022// Create a typical video answer with GCM ciphers enabled for the answer only,
1023// and ensure it matches what we expect.
1024TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmAnswer) {
1025 TestVideoGcmCipher(false, true);
1026}
1027
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001028TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
zhihuang1c378ed2017-08-17 14:10:50 -07001029 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
Steve Anton4e70a722017-11-28 14:57:10 -08001030 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001031 f1_.set_secure(SEC_ENABLED);
1032 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001033 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001034 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001035 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001036 f2_.CreateAnswer(offer.get(), opts, NULL));
1037 const ContentInfo* ac = answer->GetContentByName("audio");
zstein4b2e0822017-02-17 19:48:38 -08001038 const ContentInfo* dc = answer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001039 ASSERT_TRUE(ac != NULL);
zstein4b2e0822017-02-17 19:48:38 -08001040 ASSERT_TRUE(dc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08001041 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
1042 EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08001043 const AudioContentDescription* acd = ac->media_description()->as_audio();
1044 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001045 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
Steve Antone38a5a12018-11-21 16:05:15 -08001046 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001047 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -07001048 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001049 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001050 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
zstein4b2e0822017-02-17 19:48:38 -08001051 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
Steve Antone38a5a12018-11-21 16:05:15 -08001052 EXPECT_THAT(dcd->codecs(), ElementsAreArray(kDataCodecsAnswer));
zhihuang1c378ed2017-08-17 14:10:50 -07001053 EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached
zstein4b2e0822017-02-17 19:48:38 -08001054 EXPECT_TRUE(dcd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001055 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
Steve Antone38a5a12018-11-21 16:05:15 -08001056 EXPECT_EQ(cricket::kMediaProtocolSavpf, dcd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001057}
1058
jbauchcb560652016-08-04 05:20:32 -07001059TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerGcm) {
zhihuang1c378ed2017-08-17 14:10:50 -07001060 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
Steve Anton4e70a722017-11-28 14:57:10 -08001061 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
Benjamin Wrighta54daf12018-10-11 15:33:17 -07001062 opts.crypto_options.srtp.enable_gcm_crypto_suites = true;
jbauchcb560652016-08-04 05:20:32 -07001063 f1_.set_secure(SEC_ENABLED);
1064 f2_.set_secure(SEC_ENABLED);
1065 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1066 ASSERT_TRUE(offer.get() != NULL);
1067 std::unique_ptr<SessionDescription> answer(
1068 f2_.CreateAnswer(offer.get(), opts, NULL));
1069 const ContentInfo* ac = answer->GetContentByName("audio");
zstein4b2e0822017-02-17 19:48:38 -08001070 const ContentInfo* dc = answer->GetContentByName("data");
jbauchcb560652016-08-04 05:20:32 -07001071 ASSERT_TRUE(ac != NULL);
zstein4b2e0822017-02-17 19:48:38 -08001072 ASSERT_TRUE(dc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08001073 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
1074 EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08001075 const AudioContentDescription* acd = ac->media_description()->as_audio();
1076 const DataContentDescription* dcd = dc->media_description()->as_data();
jbauchcb560652016-08-04 05:20:32 -07001077 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
Steve Antone38a5a12018-11-21 16:05:15 -08001078 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
jbauchcb560652016-08-04 05:20:32 -07001079 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -07001080 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -07001081 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001082 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
zstein4b2e0822017-02-17 19:48:38 -08001083 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
Steve Antone38a5a12018-11-21 16:05:15 -08001084 EXPECT_THAT(dcd->codecs(), ElementsAreArray(kDataCodecsAnswer));
zhihuang1c378ed2017-08-17 14:10:50 -07001085 EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached
zstein4b2e0822017-02-17 19:48:38 -08001086 EXPECT_TRUE(dcd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001087 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuiteGcm);
Steve Antone38a5a12018-11-21 16:05:15 -08001088 EXPECT_EQ(cricket::kMediaProtocolSavpf, dcd->protocol());
zstein4b2e0822017-02-17 19:48:38 -08001089}
1090
1091// The use_sctpmap flag should be set in a DataContentDescription by default.
1092// The answer's use_sctpmap flag should match the offer's.
1093TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerUsesSctpmap) {
1094 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001095 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
zstein4b2e0822017-02-17 19:48:38 -08001096 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1097 ASSERT_TRUE(offer.get() != NULL);
1098 ContentInfo* dc_offer = offer->GetContentByName("data");
1099 ASSERT_TRUE(dc_offer != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001100 DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
zstein4b2e0822017-02-17 19:48:38 -08001101 EXPECT_TRUE(dcd_offer->use_sctpmap());
1102
1103 std::unique_ptr<SessionDescription> answer(
1104 f2_.CreateAnswer(offer.get(), opts, NULL));
1105 const ContentInfo* dc_answer = answer->GetContentByName("data");
1106 ASSERT_TRUE(dc_answer != NULL);
1107 const DataContentDescription* dcd_answer =
Steve Antonb1c1de12017-12-21 15:14:30 -08001108 dc_answer->media_description()->as_data();
zstein4b2e0822017-02-17 19:48:38 -08001109 EXPECT_TRUE(dcd_answer->use_sctpmap());
1110}
1111
1112// The answer's use_sctpmap flag should match the offer's.
1113TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerWithoutSctpmap) {
1114 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001115 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
zstein4b2e0822017-02-17 19:48:38 -08001116 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1117 ASSERT_TRUE(offer.get() != NULL);
1118 ContentInfo* dc_offer = offer->GetContentByName("data");
1119 ASSERT_TRUE(dc_offer != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001120 DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
zstein4b2e0822017-02-17 19:48:38 -08001121 dcd_offer->set_use_sctpmap(false);
1122
1123 std::unique_ptr<SessionDescription> answer(
1124 f2_.CreateAnswer(offer.get(), opts, NULL));
1125 const ContentInfo* dc_answer = answer->GetContentByName("data");
1126 ASSERT_TRUE(dc_answer != NULL);
1127 const DataContentDescription* dcd_answer =
Steve Antonb1c1de12017-12-21 15:14:30 -08001128 dc_answer->media_description()->as_data();
zstein4b2e0822017-02-17 19:48:38 -08001129 EXPECT_FALSE(dcd_answer->use_sctpmap());
jbauchcb560652016-08-04 05:20:32 -07001130}
1131
deadbeef8b7e9ad2017-05-25 09:38:55 -07001132// Test that a valid answer will be created for "DTLS/SCTP", "UDP/DTLS/SCTP"
1133// and "TCP/DTLS/SCTP" offers.
1134TEST_F(MediaSessionDescriptionFactoryTest,
1135 TestCreateDataAnswerToDifferentOfferedProtos) {
1136 // Need to enable DTLS offer/answer generation (disabled by default in this
1137 // test).
1138 f1_.set_secure(SEC_ENABLED);
1139 f2_.set_secure(SEC_ENABLED);
1140 tdf1_.set_secure(SEC_ENABLED);
1141 tdf2_.set_secure(SEC_ENABLED);
1142
1143 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001144 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
deadbeef8b7e9ad2017-05-25 09:38:55 -07001145 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
1146 ASSERT_TRUE(offer.get() != nullptr);
1147 ContentInfo* dc_offer = offer->GetContentByName("data");
1148 ASSERT_TRUE(dc_offer != nullptr);
Steve Antonb1c1de12017-12-21 15:14:30 -08001149 DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
deadbeef8b7e9ad2017-05-25 09:38:55 -07001150
1151 std::vector<std::string> protos = {"DTLS/SCTP", "UDP/DTLS/SCTP",
1152 "TCP/DTLS/SCTP"};
1153 for (const std::string& proto : protos) {
1154 dcd_offer->set_protocol(proto);
1155 std::unique_ptr<SessionDescription> answer(
1156 f2_.CreateAnswer(offer.get(), opts, nullptr));
1157 const ContentInfo* dc_answer = answer->GetContentByName("data");
1158 ASSERT_TRUE(dc_answer != nullptr);
1159 const DataContentDescription* dcd_answer =
Steve Antonb1c1de12017-12-21 15:14:30 -08001160 dc_answer->media_description()->as_data();
deadbeef8b7e9ad2017-05-25 09:38:55 -07001161 EXPECT_FALSE(dc_answer->rejected);
1162 EXPECT_EQ(proto, dcd_answer->protocol());
1163 }
1164}
1165
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001166// Verifies that the order of the media contents in the offer is preserved in
1167// the answer.
1168TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
1169 MediaSessionOptions opts;
1170
1171 // Creates a data only offer.
Steve Anton4e70a722017-11-28 14:57:10 -08001172 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
kwiberg31022942016-03-11 14:18:21 -08001173 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001174 ASSERT_TRUE(offer1.get() != NULL);
1175
1176 // Appends audio to the offer.
Steve Anton4e70a722017-11-28 14:57:10 -08001177 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1178 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001179 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001180 f1_.CreateOffer(opts, offer1.get()));
1181 ASSERT_TRUE(offer2.get() != NULL);
1182
1183 // Appends video to the offer.
Steve Anton4e70a722017-11-28 14:57:10 -08001184 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1185 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001186 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001187 f1_.CreateOffer(opts, offer2.get()));
1188 ASSERT_TRUE(offer3.get() != NULL);
1189
kwiberg31022942016-03-11 14:18:21 -08001190 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001191 f2_.CreateAnswer(offer3.get(), opts, NULL));
1192 ASSERT_TRUE(answer.get() != NULL);
1193 EXPECT_EQ(3u, answer->contents().size());
1194 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
1195 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
1196 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
1197}
1198
ossu075af922016-06-14 03:29:38 -07001199// TODO(deadbeef): Extend these tests to ensure the correct direction with other
1200// answerer settings.
1201
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001202// This test that the media direction is set to send/receive in an answer if
1203// the offer is send receive.
1204TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001205 TestMediaDirectionInAnswer(RtpTransceiverDirection::kSendRecv,
1206 RtpTransceiverDirection::kSendRecv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001207}
1208
1209// This test that the media direction is set to receive only in an answer if
1210// the offer is send only.
1211TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001212 TestMediaDirectionInAnswer(RtpTransceiverDirection::kSendOnly,
1213 RtpTransceiverDirection::kRecvOnly);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001214}
1215
1216// This test that the media direction is set to send only in an answer if
1217// the offer is recv only.
1218TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001219 TestMediaDirectionInAnswer(RtpTransceiverDirection::kRecvOnly,
1220 RtpTransceiverDirection::kSendOnly);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001221}
1222
1223// This test that the media direction is set to inactive in an answer if
1224// the offer is inactive.
1225TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001226 TestMediaDirectionInAnswer(RtpTransceiverDirection::kInactive,
1227 RtpTransceiverDirection::kInactive);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001228}
1229
1230// Test that a data content with an unknown protocol is rejected in an answer.
1231TEST_F(MediaSessionDescriptionFactoryTest,
1232 CreateDataAnswerToOfferWithUnknownProtocol) {
1233 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001234 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001235 f1_.set_secure(SEC_ENABLED);
1236 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001237 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
terelius8c011e52016-04-26 05:28:11 -07001238 ContentInfo* dc_offer = offer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001239 ASSERT_TRUE(dc_offer != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001240 DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001241 ASSERT_TRUE(dcd_offer != NULL);
1242 std::string protocol = "a weird unknown protocol";
1243 dcd_offer->set_protocol(protocol);
1244
kwiberg31022942016-03-11 14:18:21 -08001245 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001246 f2_.CreateAnswer(offer.get(), opts, NULL));
1247
1248 const ContentInfo* dc_answer = answer->GetContentByName("data");
1249 ASSERT_TRUE(dc_answer != NULL);
1250 EXPECT_TRUE(dc_answer->rejected);
1251 const DataContentDescription* dcd_answer =
Steve Antonb1c1de12017-12-21 15:14:30 -08001252 dc_answer->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001253 ASSERT_TRUE(dcd_answer != NULL);
1254 EXPECT_EQ(protocol, dcd_answer->protocol());
1255}
1256
1257// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
1258TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
zhihuang1c378ed2017-08-17 14:10:50 -07001259 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001260 f1_.set_secure(SEC_DISABLED);
1261 f2_.set_secure(SEC_DISABLED);
1262 tdf1_.set_secure(SEC_DISABLED);
1263 tdf2_.set_secure(SEC_DISABLED);
1264
kwiberg31022942016-03-11 14:18:21 -08001265 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001266 const AudioContentDescription* offer_acd =
1267 GetFirstAudioContentDescription(offer.get());
1268 ASSERT_TRUE(offer_acd != NULL);
Steve Antone38a5a12018-11-21 16:05:15 -08001269 EXPECT_EQ(cricket::kMediaProtocolAvpf, offer_acd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001270
kwiberg31022942016-03-11 14:18:21 -08001271 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001272 f2_.CreateAnswer(offer.get(), opts, NULL));
1273
1274 const ContentInfo* ac_answer = answer->GetContentByName("audio");
1275 ASSERT_TRUE(ac_answer != NULL);
1276 EXPECT_FALSE(ac_answer->rejected);
1277
1278 const AudioContentDescription* answer_acd =
1279 GetFirstAudioContentDescription(answer.get());
1280 ASSERT_TRUE(answer_acd != NULL);
Steve Antone38a5a12018-11-21 16:05:15 -08001281 EXPECT_EQ(cricket::kMediaProtocolAvpf, answer_acd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001282}
1283
1284// Create a video offer and answer and ensure the RTP header extensions
1285// matches what we expect.
1286TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
1287 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001288 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001289 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1290 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1291 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1292 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1293
kwiberg31022942016-03-11 14:18:21 -08001294 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001295 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001296 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001297 f2_.CreateAnswer(offer.get(), opts, NULL));
1298
Yves Gerey665174f2018-06-19 15:03:05 +02001299 EXPECT_EQ(
1300 MAKE_VECTOR(kAudioRtpExtension1),
1301 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1302 EXPECT_EQ(
1303 MAKE_VECTOR(kVideoRtpExtension1),
1304 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1305 EXPECT_EQ(
1306 MAKE_VECTOR(kAudioRtpExtensionAnswer),
1307 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1308 EXPECT_EQ(
1309 MAKE_VECTOR(kVideoRtpExtensionAnswer),
1310 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001311}
1312
jbauch5869f502017-06-29 12:31:36 -07001313TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02001314 TestOfferAnswerWithEncryptedRtpExtensionsBoth) {
jbauch5869f502017-06-29 12:31:36 -07001315 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001316 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07001317
1318 f1_.set_enable_encrypted_rtp_header_extensions(true);
1319 f2_.set_enable_encrypted_rtp_header_extensions(true);
1320
Yves Gerey665174f2018-06-19 15:03:05 +02001321 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1322 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1323 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1324 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
jbauch5869f502017-06-29 12:31:36 -07001325
1326 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1327 ASSERT_TRUE(offer.get() != NULL);
1328 std::unique_ptr<SessionDescription> answer(
1329 f2_.CreateAnswer(offer.get(), opts, NULL));
1330
Yves Gerey665174f2018-06-19 15:03:05 +02001331 EXPECT_EQ(
1332 MAKE_VECTOR(kAudioRtpExtensionEncrypted1),
1333 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1334 EXPECT_EQ(
1335 MAKE_VECTOR(kVideoRtpExtensionEncrypted1),
1336 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1337 EXPECT_EQ(
1338 MAKE_VECTOR(kAudioRtpExtensionEncryptedAnswer),
1339 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1340 EXPECT_EQ(
1341 MAKE_VECTOR(kVideoRtpExtensionEncryptedAnswer),
1342 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07001343}
1344
1345TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02001346 TestOfferAnswerWithEncryptedRtpExtensionsOffer) {
jbauch5869f502017-06-29 12:31:36 -07001347 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001348 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07001349
1350 f1_.set_enable_encrypted_rtp_header_extensions(true);
1351
Yves Gerey665174f2018-06-19 15:03:05 +02001352 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1353 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1354 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1355 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
jbauch5869f502017-06-29 12:31:36 -07001356
1357 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1358 ASSERT_TRUE(offer.get() != NULL);
1359 std::unique_ptr<SessionDescription> answer(
1360 f2_.CreateAnswer(offer.get(), opts, NULL));
1361
Yves Gerey665174f2018-06-19 15:03:05 +02001362 EXPECT_EQ(
1363 MAKE_VECTOR(kAudioRtpExtensionEncrypted1),
1364 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1365 EXPECT_EQ(
1366 MAKE_VECTOR(kVideoRtpExtensionEncrypted1),
1367 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1368 EXPECT_EQ(
1369 MAKE_VECTOR(kAudioRtpExtensionAnswer),
1370 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1371 EXPECT_EQ(
1372 MAKE_VECTOR(kVideoRtpExtensionAnswer),
1373 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07001374}
1375
1376TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02001377 TestOfferAnswerWithEncryptedRtpExtensionsAnswer) {
jbauch5869f502017-06-29 12:31:36 -07001378 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001379 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07001380
1381 f2_.set_enable_encrypted_rtp_header_extensions(true);
1382
Yves Gerey665174f2018-06-19 15:03:05 +02001383 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1384 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1385 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1386 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
jbauch5869f502017-06-29 12:31:36 -07001387
1388 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1389 ASSERT_TRUE(offer.get() != NULL);
1390 std::unique_ptr<SessionDescription> answer(
1391 f2_.CreateAnswer(offer.get(), opts, NULL));
1392
Yves Gerey665174f2018-06-19 15:03:05 +02001393 EXPECT_EQ(
1394 MAKE_VECTOR(kAudioRtpExtension1),
1395 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1396 EXPECT_EQ(
1397 MAKE_VECTOR(kVideoRtpExtension1),
1398 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1399 EXPECT_EQ(
1400 MAKE_VECTOR(kAudioRtpExtensionAnswer),
1401 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1402 EXPECT_EQ(
1403 MAKE_VECTOR(kVideoRtpExtensionAnswer),
1404 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07001405}
1406
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001407// Create an audio, video, data answer without legacy StreamParams.
1408TEST_F(MediaSessionDescriptionFactoryTest,
1409 TestCreateAnswerWithoutLegacyStreams) {
1410 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001411 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1412 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
kwiberg31022942016-03-11 14:18:21 -08001413 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001414 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001415 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001416 f2_.CreateAnswer(offer.get(), opts, NULL));
1417 const ContentInfo* ac = answer->GetContentByName("audio");
1418 const ContentInfo* vc = answer->GetContentByName("video");
1419 const ContentInfo* dc = answer->GetContentByName("data");
1420 ASSERT_TRUE(ac != NULL);
1421 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001422 const AudioContentDescription* acd = ac->media_description()->as_audio();
1423 const VideoContentDescription* vcd = vc->media_description()->as_video();
1424 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001425
1426 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1427 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1428 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1429}
1430
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001431// Create a typical video answer, and ensure it matches what we expect.
1432TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1433 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001434 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &offer_opts);
1435 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv,
1436 &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001437
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001438 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001439 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &answer_opts);
1440 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv,
1441 &answer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001442
kwiberg31022942016-03-11 14:18:21 -08001443 std::unique_ptr<SessionDescription> offer;
1444 std::unique_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001445
1446 offer_opts.rtcp_mux_enabled = true;
1447 answer_opts.rtcp_mux_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001448 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1449 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1450 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1451 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1452 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1453 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1454 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1455 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1456 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1457 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1458 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1459 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1460 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1461 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1462
1463 offer_opts.rtcp_mux_enabled = true;
1464 answer_opts.rtcp_mux_enabled = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001465 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1466 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1467 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1468 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1469 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1470 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1471 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1472 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1473 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1474 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1475 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1476 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1477 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1478 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1479
1480 offer_opts.rtcp_mux_enabled = false;
1481 answer_opts.rtcp_mux_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001482 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1483 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1484 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1485 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1486 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1487 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1488 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1489 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1490 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1491 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1492 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1493 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1494 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1495 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1496
1497 offer_opts.rtcp_mux_enabled = false;
1498 answer_opts.rtcp_mux_enabled = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001499 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1500 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1501 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1502 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1503 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1504 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1505 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1506 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1507 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1508 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1509 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1510 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1511 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1512 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1513}
1514
1515// Create an audio-only answer to a video offer.
1516TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1517 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001518 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1519 kActive, &opts);
1520 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1521 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001522 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001523 ASSERT_TRUE(offer.get() != NULL);
zhihuang1c378ed2017-08-17 14:10:50 -07001524
1525 opts.media_description_options[1].stopped = true;
kwiberg31022942016-03-11 14:18:21 -08001526 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001527 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001528 const ContentInfo* ac = answer->GetContentByName("audio");
1529 const ContentInfo* vc = answer->GetContentByName("video");
1530 ASSERT_TRUE(ac != NULL);
1531 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001532 ASSERT_TRUE(vc->media_description() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001533 EXPECT_TRUE(vc->rejected);
1534}
1535
1536// Create an audio-only answer to an offer with data.
1537TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07001538 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001539 opts.data_channel_type = cricket::DCT_RTP;
Steve Anton4e70a722017-11-28 14:57:10 -08001540 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kRecvOnly,
1541 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001542 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001543 ASSERT_TRUE(offer.get() != NULL);
zhihuang1c378ed2017-08-17 14:10:50 -07001544
1545 opts.media_description_options[1].stopped = true;
kwiberg31022942016-03-11 14:18:21 -08001546 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001547 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001548 const ContentInfo* ac = answer->GetContentByName("audio");
1549 const ContentInfo* dc = answer->GetContentByName("data");
1550 ASSERT_TRUE(ac != NULL);
1551 ASSERT_TRUE(dc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001552 ASSERT_TRUE(dc->media_description() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001553 EXPECT_TRUE(dc->rejected);
1554}
1555
1556// Create an answer that rejects the contents which are rejected in the offer.
1557TEST_F(MediaSessionDescriptionFactoryTest,
1558 CreateAnswerToOfferWithRejectedMedia) {
1559 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001560 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1561 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
kwiberg31022942016-03-11 14:18:21 -08001562 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001563 ASSERT_TRUE(offer.get() != NULL);
1564 ContentInfo* ac = offer->GetContentByName("audio");
1565 ContentInfo* vc = offer->GetContentByName("video");
1566 ContentInfo* dc = offer->GetContentByName("data");
1567 ASSERT_TRUE(ac != NULL);
1568 ASSERT_TRUE(vc != NULL);
1569 ASSERT_TRUE(dc != NULL);
1570 ac->rejected = true;
1571 vc->rejected = true;
1572 dc->rejected = true;
kwiberg31022942016-03-11 14:18:21 -08001573 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001574 f2_.CreateAnswer(offer.get(), opts, NULL));
1575 ac = answer->GetContentByName("audio");
1576 vc = answer->GetContentByName("video");
1577 dc = answer->GetContentByName("data");
1578 ASSERT_TRUE(ac != NULL);
1579 ASSERT_TRUE(vc != NULL);
1580 ASSERT_TRUE(dc != NULL);
1581 EXPECT_TRUE(ac->rejected);
1582 EXPECT_TRUE(vc->rejected);
1583 EXPECT_TRUE(dc->rejected);
1584}
1585
Johannes Kron0854eb62018-10-10 22:33:20 +02001586TEST_F(MediaSessionDescriptionFactoryTest,
1587 CreateAnswerSupportsMixedOneAndTwoByteHeaderExtensions) {
1588 MediaSessionOptions opts;
1589 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1590 // Offer without request of mixed one- and two-byte header extensions.
Johannes Kron9581bc42018-10-23 10:17:39 +02001591 offer->set_extmap_allow_mixed(false);
Johannes Kron0854eb62018-10-10 22:33:20 +02001592 ASSERT_TRUE(offer.get() != NULL);
1593 std::unique_ptr<SessionDescription> answer_no_support(
1594 f2_.CreateAnswer(offer.get(), opts, NULL));
Johannes Kron9581bc42018-10-23 10:17:39 +02001595 EXPECT_FALSE(answer_no_support->extmap_allow_mixed());
Johannes Kron0854eb62018-10-10 22:33:20 +02001596
1597 // Offer with request of mixed one- and two-byte header extensions.
Johannes Kron9581bc42018-10-23 10:17:39 +02001598 offer->set_extmap_allow_mixed(true);
Johannes Kron0854eb62018-10-10 22:33:20 +02001599 ASSERT_TRUE(offer.get() != NULL);
1600 std::unique_ptr<SessionDescription> answer_support(
1601 f2_.CreateAnswer(offer.get(), opts, NULL));
Johannes Kron9581bc42018-10-23 10:17:39 +02001602 EXPECT_TRUE(answer_support->extmap_allow_mixed());
Johannes Kron0854eb62018-10-10 22:33:20 +02001603}
1604
1605TEST_F(MediaSessionDescriptionFactoryTest,
1606 CreateAnswerSupportsMixedOneAndTwoByteHeaderExtensionsOnMediaLevel) {
1607 MediaSessionOptions opts;
1608 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
1609 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1610 MediaContentDescription* video_offer =
1611 offer->GetContentDescriptionByName("video");
1612 ASSERT_TRUE(video_offer);
1613 MediaContentDescription* audio_offer =
1614 offer->GetContentDescriptionByName("audio");
1615 ASSERT_TRUE(audio_offer);
1616
1617 // Explicit disable of mixed one-two byte header support in offer.
Johannes Kron9581bc42018-10-23 10:17:39 +02001618 video_offer->set_extmap_allow_mixed_enum(MediaContentDescription::kNo);
1619 audio_offer->set_extmap_allow_mixed_enum(MediaContentDescription::kNo);
Johannes Kron0854eb62018-10-10 22:33:20 +02001620
1621 ASSERT_TRUE(offer.get() != NULL);
1622 std::unique_ptr<SessionDescription> answer_no_support(
1623 f2_.CreateAnswer(offer.get(), opts, NULL));
1624 MediaContentDescription* video_answer =
1625 answer_no_support->GetContentDescriptionByName("video");
1626 MediaContentDescription* audio_answer =
1627 answer_no_support->GetContentDescriptionByName("audio");
1628 EXPECT_EQ(MediaContentDescription::kNo,
Johannes Kron9581bc42018-10-23 10:17:39 +02001629 video_answer->extmap_allow_mixed_enum());
Johannes Kron0854eb62018-10-10 22:33:20 +02001630 EXPECT_EQ(MediaContentDescription::kNo,
Johannes Kron9581bc42018-10-23 10:17:39 +02001631 audio_answer->extmap_allow_mixed_enum());
Johannes Kron0854eb62018-10-10 22:33:20 +02001632
1633 // Enable mixed one-two byte header support in offer.
Johannes Kron9581bc42018-10-23 10:17:39 +02001634 video_offer->set_extmap_allow_mixed_enum(MediaContentDescription::kMedia);
1635 audio_offer->set_extmap_allow_mixed_enum(MediaContentDescription::kMedia);
Johannes Kron0854eb62018-10-10 22:33:20 +02001636 ASSERT_TRUE(offer.get() != NULL);
1637 std::unique_ptr<SessionDescription> answer_support(
1638 f2_.CreateAnswer(offer.get(), opts, NULL));
1639 video_answer = answer_support->GetContentDescriptionByName("video");
1640 audio_answer = answer_support->GetContentDescriptionByName("audio");
1641 EXPECT_EQ(MediaContentDescription::kMedia,
Johannes Kron9581bc42018-10-23 10:17:39 +02001642 video_answer->extmap_allow_mixed_enum());
Johannes Kron0854eb62018-10-10 22:33:20 +02001643 EXPECT_EQ(MediaContentDescription::kMedia,
Johannes Kron9581bc42018-10-23 10:17:39 +02001644 audio_answer->extmap_allow_mixed_enum());
Johannes Kron0854eb62018-10-10 22:33:20 +02001645}
1646
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001647// Create an audio and video offer with:
1648// - one video track
1649// - two audio tracks
1650// - two data tracks
1651// and ensure it matches what we expect. Also updates the initial offer by
1652// adding a new video track and replaces one of the audio tracks.
1653TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1654 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001655 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001656 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001657 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001658 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001659 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001660 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001661 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001662
Steve Anton4e70a722017-11-28 14:57:10 -08001663 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001664 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001665 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001666 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001667 {kMediaStream1}, 1, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001668
1669 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001670 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001671
1672 ASSERT_TRUE(offer.get() != NULL);
1673 const ContentInfo* ac = offer->GetContentByName("audio");
1674 const ContentInfo* vc = offer->GetContentByName("video");
1675 const ContentInfo* dc = offer->GetContentByName("data");
1676 ASSERT_TRUE(ac != NULL);
1677 ASSERT_TRUE(vc != NULL);
1678 ASSERT_TRUE(dc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001679 const AudioContentDescription* acd = ac->media_description()->as_audio();
1680 const VideoContentDescription* vcd = vc->media_description()->as_video();
1681 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001682 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -07001683 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001684
1685 const StreamParamsVec& audio_streams = acd->streams();
1686 ASSERT_EQ(2U, audio_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001687 EXPECT_EQ(audio_streams[0].cname, audio_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001688 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1689 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1690 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1691 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1692 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1693 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1694
1695 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1696 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001697 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001698
1699 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1700 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001701 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001702
1703 const StreamParamsVec& video_streams = vcd->streams();
1704 ASSERT_EQ(1U, video_streams.size());
1705 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1706 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1707 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1708 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1709
1710 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1711 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001712 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001713
1714 const StreamParamsVec& data_streams = dcd->streams();
1715 ASSERT_EQ(2U, data_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001716 EXPECT_EQ(data_streams[0].cname, data_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001717 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1718 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1719 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1720 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1721 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1722 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1723
1724 EXPECT_EQ(cricket::kDataMaxBandwidth,
Yves Gerey665174f2018-06-19 15:03:05 +02001725 dcd->bandwidth()); // default bandwidth (auto)
1726 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001727 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001728
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001729 // Update the offer. Add a new video track that is not synched to the
1730 // other tracks and replace audio track 2 with audio track 3.
zhihuang1c378ed2017-08-17 14:10:50 -07001731 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001732 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001733 DetachSenderFromMediaSection("audio", kAudioTrack2, &opts);
1734 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack3,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001735 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001736 DetachSenderFromMediaSection("data", kDataTrack2, &opts);
1737 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack3,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001738 {kMediaStream1}, 1, &opts);
kwiberg31022942016-03-11 14:18:21 -08001739 std::unique_ptr<SessionDescription> updated_offer(
1740 f1_.CreateOffer(opts, offer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001741
1742 ASSERT_TRUE(updated_offer.get() != NULL);
1743 ac = updated_offer->GetContentByName("audio");
1744 vc = updated_offer->GetContentByName("video");
1745 dc = updated_offer->GetContentByName("data");
1746 ASSERT_TRUE(ac != NULL);
1747 ASSERT_TRUE(vc != NULL);
1748 ASSERT_TRUE(dc != NULL);
1749 const AudioContentDescription* updated_acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001750 ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001751 const VideoContentDescription* updated_vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001752 vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001753 const DataContentDescription* updated_dcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001754 dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001755
1756 EXPECT_EQ(acd->type(), updated_acd->type());
1757 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1758 EXPECT_EQ(vcd->type(), updated_vcd->type());
1759 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1760 EXPECT_EQ(dcd->type(), updated_dcd->type());
1761 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001762 ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001763 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001764 ASSERT_CRYPTO(updated_vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001765 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001766 ASSERT_CRYPTO(updated_dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001767 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1768
1769 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1770 ASSERT_EQ(2U, updated_audio_streams.size());
1771 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1772 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1773 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1774 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1775 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1776
1777 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1778 ASSERT_EQ(2U, updated_video_streams.size());
1779 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1780 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001781 // All the media streams in one PeerConnection share one RTCP CNAME.
1782 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001783
1784 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1785 ASSERT_EQ(2U, updated_data_streams.size());
1786 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1787 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1788 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1789 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1790 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
zhihuang8f65cdf2016-05-06 18:40:30 -07001791 // The stream correctly got the CNAME from the MediaSessionOptions.
1792 // The Expected RTCP CNAME is the default one as we are using the default
1793 // MediaSessionOptions.
1794 EXPECT_EQ(updated_data_streams[0].cname, cricket::kDefaultRtcpCname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001795}
1796
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001797// Create an offer with simulcast video stream.
1798TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1799 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001800 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1801 kActive, &opts);
1802 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
1803 kActive, &opts);
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001804 const int num_sim_layers = 3;
zhihuang1c378ed2017-08-17 14:10:50 -07001805 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001806 {kMediaStream1}, num_sim_layers, &opts);
kwiberg31022942016-03-11 14:18:21 -08001807 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001808
1809 ASSERT_TRUE(offer.get() != NULL);
1810 const ContentInfo* vc = offer->GetContentByName("video");
1811 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001812 const VideoContentDescription* vcd = vc->media_description()->as_video();
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001813
1814 const StreamParamsVec& video_streams = vcd->streams();
1815 ASSERT_EQ(1U, video_streams.size());
1816 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1817 const SsrcGroup* sim_ssrc_group =
1818 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1819 ASSERT_TRUE(sim_ssrc_group != NULL);
1820 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1821}
1822
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001823// Create an audio and video answer to a standard video offer with:
1824// - one video track
1825// - two audio tracks
1826// - two data tracks
1827// and ensure it matches what we expect. Also updates the initial answer by
1828// adding a new video track and removes one of the audio tracks.
1829TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1830 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001831 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1832 kActive, &offer_opts);
1833 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1834 kActive, &offer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001835 offer_opts.data_channel_type = cricket::DCT_RTP;
Steve Anton4e70a722017-11-28 14:57:10 -08001836 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kRecvOnly,
1837 kActive, &offer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001838 f1_.set_secure(SEC_ENABLED);
1839 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001840 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001841
zhihuang1c378ed2017-08-17 14:10:50 -07001842 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001843 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
1844 kActive, &answer_opts);
1845 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
1846 kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001847 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001848 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001849 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001850 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001851 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001852 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001853
Steve Anton4e70a722017-11-28 14:57:10 -08001854 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kSendRecv,
1855 kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001856 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001857 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001858 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001859 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001860 answer_opts.data_channel_type = cricket::DCT_RTP;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001861
kwiberg31022942016-03-11 14:18:21 -08001862 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001863 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001864
1865 ASSERT_TRUE(answer.get() != NULL);
1866 const ContentInfo* ac = answer->GetContentByName("audio");
1867 const ContentInfo* vc = answer->GetContentByName("video");
1868 const ContentInfo* dc = answer->GetContentByName("data");
1869 ASSERT_TRUE(ac != NULL);
1870 ASSERT_TRUE(vc != NULL);
1871 ASSERT_TRUE(dc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001872 const AudioContentDescription* acd = ac->media_description()->as_audio();
1873 const VideoContentDescription* vcd = vc->media_description()->as_video();
1874 const DataContentDescription* dcd = dc->media_description()->as_data();
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001875 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
1876 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
1877 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001878
1879 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
Steve Antone38a5a12018-11-21 16:05:15 -08001880 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001881
1882 const StreamParamsVec& audio_streams = acd->streams();
1883 ASSERT_EQ(2U, audio_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001884 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001885 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1886 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1887 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1888 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1889 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1890 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1891
1892 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1893 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1894
1895 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
Steve Antone38a5a12018-11-21 16:05:15 -08001896 EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001897
1898 const StreamParamsVec& video_streams = vcd->streams();
1899 ASSERT_EQ(1U, video_streams.size());
1900 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1901 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1902 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1903 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1904
1905 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
Steve Antone38a5a12018-11-21 16:05:15 -08001906 EXPECT_THAT(dcd->codecs(), ElementsAreArray(kDataCodecsAnswer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001907
1908 const StreamParamsVec& data_streams = dcd->streams();
1909 ASSERT_EQ(2U, data_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001910 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001911 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1912 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1913 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1914 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1915 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1916 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1917
1918 EXPECT_EQ(cricket::kDataMaxBandwidth,
Yves Gerey665174f2018-06-19 15:03:05 +02001919 dcd->bandwidth()); // default bandwidth (auto)
1920 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001921
1922 // Update the answer. Add a new video track that is not synched to the
zhihuang8f65cdf2016-05-06 18:40:30 -07001923 // other tracks and remove 1 audio track.
zhihuang1c378ed2017-08-17 14:10:50 -07001924 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001925 {kMediaStream2}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001926 DetachSenderFromMediaSection("audio", kAudioTrack2, &answer_opts);
1927 DetachSenderFromMediaSection("data", kDataTrack2, &answer_opts);
kwiberg31022942016-03-11 14:18:21 -08001928 std::unique_ptr<SessionDescription> updated_answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001929 f2_.CreateAnswer(offer.get(), answer_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001930
1931 ASSERT_TRUE(updated_answer.get() != NULL);
1932 ac = updated_answer->GetContentByName("audio");
1933 vc = updated_answer->GetContentByName("video");
1934 dc = updated_answer->GetContentByName("data");
1935 ASSERT_TRUE(ac != NULL);
1936 ASSERT_TRUE(vc != NULL);
1937 ASSERT_TRUE(dc != NULL);
1938 const AudioContentDescription* updated_acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001939 ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001940 const VideoContentDescription* updated_vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001941 vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001942 const DataContentDescription* updated_dcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001943 dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001944
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001945 ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001946 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001947 ASSERT_CRYPTO(updated_vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001948 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001949 ASSERT_CRYPTO(updated_dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001950 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1951
1952 EXPECT_EQ(acd->type(), updated_acd->type());
1953 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1954 EXPECT_EQ(vcd->type(), updated_vcd->type());
1955 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1956 EXPECT_EQ(dcd->type(), updated_dcd->type());
1957 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1958
1959 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1960 ASSERT_EQ(1U, updated_audio_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001961 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001962
1963 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1964 ASSERT_EQ(2U, updated_video_streams.size());
1965 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1966 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001967 // All media streams in one PeerConnection share one CNAME.
1968 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001969
1970 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1971 ASSERT_EQ(1U, updated_data_streams.size());
1972 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1973}
1974
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001975// Create an updated offer after creating an answer to the original offer and
1976// verify that the codecs that were part of the original answer are not changed
1977// in the updated offer.
1978TEST_F(MediaSessionDescriptionFactoryTest,
1979 RespondentCreatesOfferAfterCreatingAnswer) {
1980 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001981 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001982
kwiberg31022942016-03-11 14:18:21 -08001983 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1984 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001985 f2_.CreateAnswer(offer.get(), opts, NULL));
1986
1987 const AudioContentDescription* acd =
1988 GetFirstAudioContentDescription(answer.get());
Steve Antone38a5a12018-11-21 16:05:15 -08001989 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001990
1991 const VideoContentDescription* vcd =
1992 GetFirstVideoContentDescription(answer.get());
Steve Antone38a5a12018-11-21 16:05:15 -08001993 EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001994
kwiberg31022942016-03-11 14:18:21 -08001995 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001996 f2_.CreateOffer(opts, answer.get()));
1997
1998 // The expected audio codecs are the common audio codecs from the first
1999 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
2000 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00002001 // TODO(wu): |updated_offer| should not include the codec
2002 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002003 const AudioCodec kUpdatedAudioCodecOffer[] = {
Yves Gerey665174f2018-06-19 15:03:05 +02002004 kAudioCodecsAnswer[0], kAudioCodecsAnswer[1], kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002005 };
2006
2007 // The expected video codecs are the common video codecs from the first
2008 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
2009 // preference order.
2010 const VideoCodec kUpdatedVideoCodecOffer[] = {
Yves Gerey665174f2018-06-19 15:03:05 +02002011 kVideoCodecsAnswer[0], kVideoCodecs2[1],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002012 };
2013
2014 const AudioContentDescription* updated_acd =
2015 GetFirstAudioContentDescription(updated_offer.get());
Steve Antone38a5a12018-11-21 16:05:15 -08002016 EXPECT_THAT(updated_acd->codecs(), ElementsAreArray(kUpdatedAudioCodecOffer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002017
2018 const VideoContentDescription* updated_vcd =
2019 GetFirstVideoContentDescription(updated_offer.get());
Steve Antone38a5a12018-11-21 16:05:15 -08002020 EXPECT_THAT(updated_vcd->codecs(), ElementsAreArray(kUpdatedVideoCodecOffer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002021}
2022
Steve Anton5c72e712018-12-10 14:25:30 -08002023// Test that a reoffer does not reuse audio codecs from a previous media section
2024// that is being recycled.
2025TEST_F(MediaSessionDescriptionFactoryTest,
2026 ReOfferDoesNotReUseRecycledAudioCodecs) {
2027 f1_.set_video_codecs({});
2028 f2_.set_video_codecs({});
2029
2030 MediaSessionOptions opts;
2031 AddMediaSection(MEDIA_TYPE_AUDIO, "a0", RtpTransceiverDirection::kSendRecv,
2032 kActive, &opts);
2033 auto offer = absl::WrapUnique(f1_.CreateOffer(opts, nullptr));
2034 auto answer = absl::WrapUnique(f2_.CreateAnswer(offer.get(), opts, nullptr));
2035
2036 // Recycle the media section by changing its mid.
2037 opts.media_description_options[0].mid = "a1";
2038 auto reoffer = absl::WrapUnique(f2_.CreateOffer(opts, answer.get()));
2039
2040 // Expect that the results of the first negotiation are ignored. If the m=
2041 // section was not recycled the payload types would match the initial offerer.
2042 const AudioContentDescription* acd =
2043 GetFirstAudioContentDescription(reoffer.get());
2044 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecs2));
2045}
2046
2047// Test that a reoffer does not reuse video codecs from a previous media section
2048// that is being recycled.
2049TEST_F(MediaSessionDescriptionFactoryTest,
2050 ReOfferDoesNotReUseRecycledVideoCodecs) {
2051 f1_.set_audio_codecs({}, {});
2052 f2_.set_audio_codecs({}, {});
2053
2054 MediaSessionOptions opts;
2055 AddMediaSection(MEDIA_TYPE_VIDEO, "v0", RtpTransceiverDirection::kSendRecv,
2056 kActive, &opts);
2057 auto offer = absl::WrapUnique(f1_.CreateOffer(opts, nullptr));
2058 auto answer = absl::WrapUnique(f2_.CreateAnswer(offer.get(), opts, nullptr));
2059
2060 // Recycle the media section by changing its mid.
2061 opts.media_description_options[0].mid = "v1";
2062 auto reoffer = absl::WrapUnique(f2_.CreateOffer(opts, answer.get()));
2063
2064 // Expect that the results of the first negotiation are ignored. If the m=
2065 // section was not recycled the payload types would match the initial offerer.
2066 const VideoContentDescription* vcd =
2067 GetFirstVideoContentDescription(reoffer.get());
2068 EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecs2));
2069}
2070
2071// Test that a reanswer does not reuse audio codecs from a previous media
2072// section that is being recycled.
2073TEST_F(MediaSessionDescriptionFactoryTest,
2074 ReAnswerDoesNotReUseRecycledAudioCodecs) {
2075 f1_.set_video_codecs({});
2076 f2_.set_video_codecs({});
2077
2078 // Perform initial offer/answer in reverse (|f2_| as offerer) so that the
2079 // second offer/answer is forward (|f1_| as offerer).
2080 MediaSessionOptions opts;
2081 AddMediaSection(MEDIA_TYPE_AUDIO, "a0", RtpTransceiverDirection::kSendRecv,
2082 kActive, &opts);
2083 auto offer = absl::WrapUnique(f2_.CreateOffer(opts, nullptr));
2084 auto answer = absl::WrapUnique(f1_.CreateAnswer(offer.get(), opts, nullptr));
2085
2086 // Recycle the media section by changing its mid.
2087 opts.media_description_options[0].mid = "a1";
2088 auto reoffer = absl::WrapUnique(f1_.CreateOffer(opts, answer.get()));
2089 auto reanswer =
2090 absl::WrapUnique(f2_.CreateAnswer(reoffer.get(), opts, offer.get()));
2091
2092 // Expect that the results of the first negotiation are ignored. If the m=
2093 // section was not recycled the payload types would match the initial offerer.
2094 const AudioContentDescription* acd =
2095 GetFirstAudioContentDescription(reanswer.get());
2096 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
2097}
2098
2099// Test that a reanswer does not reuse video codecs from a previous media
2100// section that is being recycled.
2101TEST_F(MediaSessionDescriptionFactoryTest,
2102 ReAnswerDoesNotReUseRecycledVideoCodecs) {
2103 f1_.set_audio_codecs({}, {});
2104 f2_.set_audio_codecs({}, {});
2105
2106 // Perform initial offer/answer in reverse (|f2_| as offerer) so that the
2107 // second offer/answer is forward (|f1_| as offerer).
2108 MediaSessionOptions opts;
2109 AddMediaSection(MEDIA_TYPE_VIDEO, "v0", RtpTransceiverDirection::kSendRecv,
2110 kActive, &opts);
2111 auto offer = absl::WrapUnique(f2_.CreateOffer(opts, nullptr));
2112 auto answer = absl::WrapUnique(f1_.CreateAnswer(offer.get(), opts, nullptr));
2113
2114 // Recycle the media section by changing its mid.
2115 opts.media_description_options[0].mid = "v1";
2116 auto reoffer = absl::WrapUnique(f1_.CreateOffer(opts, answer.get()));
2117 auto reanswer =
2118 absl::WrapUnique(f2_.CreateAnswer(reoffer.get(), opts, offer.get()));
2119
2120 // Expect that the results of the first negotiation are ignored. If the m=
2121 // section was not recycled the payload types would match the initial offerer.
2122 const VideoContentDescription* vcd =
2123 GetFirstVideoContentDescription(reanswer.get());
2124 EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer));
2125}
2126
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002127// Create an updated offer after creating an answer to the original offer and
2128// verify that the codecs that were part of the original answer are not changed
2129// in the updated offer. In this test Rtx is enabled.
2130TEST_F(MediaSessionDescriptionFactoryTest,
2131 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
2132 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002133 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2134 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002135 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002136 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002137 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002138 f1_.set_video_codecs(f1_codecs);
2139
2140 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002141 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002142 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002143 f2_.set_video_codecs(f2_codecs);
2144
kwiberg31022942016-03-11 14:18:21 -08002145 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002146 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002147 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002148 f2_.CreateAnswer(offer.get(), opts, NULL));
2149
2150 const VideoContentDescription* vcd =
2151 GetFirstVideoContentDescription(answer.get());
2152
2153 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002154 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2155 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002156
2157 EXPECT_EQ(expected_codecs, vcd->codecs());
2158
deadbeef67cf2c12016-04-13 10:07:16 -07002159 // Now, make sure we get same result (except for the order) if |f2_| creates
2160 // an updated offer even though the default payload types between |f1_| and
2161 // |f2_| are different.
kwiberg31022942016-03-11 14:18:21 -08002162 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002163 f2_.CreateOffer(opts, answer.get()));
2164 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08002165 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002166 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
2167
2168 const VideoContentDescription* updated_vcd =
2169 GetFirstVideoContentDescription(updated_answer.get());
2170
2171 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
2172}
2173
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002174// Regression test for:
2175// https://bugs.chromium.org/p/webrtc/issues/detail?id=8332
2176// Existing codecs should always appear before new codecs in re-offers. But
2177// under a specific set of circumstances, the existing RTX codec was ending up
2178// added to the end of the list.
2179TEST_F(MediaSessionDescriptionFactoryTest,
2180 RespondentCreatesOfferAfterCreatingAnswerWithRemappedRtxPayloadType) {
2181 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002182 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2183 kActive, &opts);
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002184 // We specifically choose different preferred payload types for VP8 to
2185 // trigger the issue.
2186 cricket::VideoCodec vp8_offerer(100, "VP8");
2187 cricket::VideoCodec vp8_offerer_rtx =
2188 VideoCodec::CreateRtxCodec(101, vp8_offerer.id);
2189 cricket::VideoCodec vp8_answerer(110, "VP8");
2190 cricket::VideoCodec vp8_answerer_rtx =
2191 VideoCodec::CreateRtxCodec(111, vp8_answerer.id);
2192 cricket::VideoCodec vp9(120, "VP9");
2193 cricket::VideoCodec vp9_rtx = VideoCodec::CreateRtxCodec(121, vp9.id);
2194
2195 std::vector<VideoCodec> f1_codecs = {vp8_offerer, vp8_offerer_rtx};
2196 // We also specifically cause the answerer to prefer VP9, such that if it
2197 // *doesn't* honor the existing preferred codec (VP8) we'll notice.
2198 std::vector<VideoCodec> f2_codecs = {vp9, vp9_rtx, vp8_answerer,
2199 vp8_answerer_rtx};
2200
2201 f1_.set_video_codecs(f1_codecs);
2202 f2_.set_video_codecs(f2_codecs);
2203 std::vector<AudioCodec> audio_codecs;
2204 f1_.set_audio_codecs(audio_codecs, audio_codecs);
2205 f2_.set_audio_codecs(audio_codecs, audio_codecs);
2206
2207 // Offer will be {VP8, RTX for VP8}. Answer will be the same.
2208 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2209 ASSERT_TRUE(offer.get() != NULL);
2210 std::unique_ptr<SessionDescription> answer(
2211 f2_.CreateAnswer(offer.get(), opts, NULL));
2212
2213 // Updated offer *should* be {VP8, RTX for VP8, VP9, RTX for VP9}.
2214 // But if the bug is triggered, RTX for VP8 ends up last.
2215 std::unique_ptr<SessionDescription> updated_offer(
2216 f2_.CreateOffer(opts, answer.get()));
2217
2218 const VideoContentDescription* vcd =
2219 GetFirstVideoContentDescription(updated_offer.get());
2220 std::vector<cricket::VideoCodec> codecs = vcd->codecs();
2221 ASSERT_EQ(4u, codecs.size());
2222 EXPECT_EQ(vp8_offerer, codecs[0]);
2223 EXPECT_EQ(vp8_offerer_rtx, codecs[1]);
2224 EXPECT_EQ(vp9, codecs[2]);
2225 EXPECT_EQ(vp9_rtx, codecs[3]);
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002226}
2227
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002228// Create an updated offer that adds video after creating an audio only answer
2229// to the original offer. This test verifies that if a video codec and the RTX
2230// codec have the same default payload type as an audio codec that is already in
2231// use, the added codecs payload types are changed.
2232TEST_F(MediaSessionDescriptionFactoryTest,
2233 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
2234 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002235 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002236 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002237 f1_.set_video_codecs(f1_codecs);
2238
2239 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002240 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2241 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002242
kwiberg31022942016-03-11 14:18:21 -08002243 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2244 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002245 f2_.CreateAnswer(offer.get(), opts, NULL));
2246
2247 const AudioContentDescription* acd =
2248 GetFirstAudioContentDescription(answer.get());
Steve Antone38a5a12018-11-21 16:05:15 -08002249 EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002250
2251 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
2252 // reference be the same as an audio codec that was negotiated in the
2253 // first offer/answer exchange.
zhihuang1c378ed2017-08-17 14:10:50 -07002254 opts.media_description_options.clear();
Steve Anton4e70a722017-11-28 14:57:10 -08002255 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002256
2257 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2258 int used_pl_type = acd->codecs()[0].id;
2259 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002260 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002261 f2_.set_video_codecs(f2_codecs);
2262
kwiberg31022942016-03-11 14:18:21 -08002263 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002264 f2_.CreateOffer(opts, answer.get()));
2265 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08002266 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002267 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
2268
2269 const AudioContentDescription* updated_acd =
2270 GetFirstAudioContentDescription(answer.get());
Steve Antone38a5a12018-11-21 16:05:15 -08002271 EXPECT_THAT(updated_acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002272
2273 const VideoContentDescription* updated_vcd =
2274 GetFirstVideoContentDescription(updated_answer.get());
2275
2276 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
Steve Antone38a5a12018-11-21 16:05:15 -08002277 ASSERT_EQ(cricket::kRtxCodecName, updated_vcd->codecs()[1].name);
Yves Gerey665174f2018-06-19 15:03:05 +02002278 int new_h264_pl_type = updated_vcd->codecs()[0].id;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002279 EXPECT_NE(used_pl_type, new_h264_pl_type);
2280 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002281 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002282 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
2283 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
2284}
2285
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002286// Create an updated offer with RTX after creating an answer to an offer
2287// without RTX, and with different default payload types.
2288// Verify that the added RTX codec references the correct payload type.
2289TEST_F(MediaSessionDescriptionFactoryTest,
2290 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
2291 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002292 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002293
2294 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2295 // This creates rtx for H264 with the payload type |f2_| uses.
2296 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
2297 f2_.set_video_codecs(f2_codecs);
2298
kwiberg31022942016-03-11 14:18:21 -08002299 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002300 ASSERT_TRUE(offer.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08002301 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002302 f2_.CreateAnswer(offer.get(), opts, nullptr));
2303
2304 const VideoContentDescription* vcd =
2305 GetFirstVideoContentDescription(answer.get());
2306
2307 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2308 EXPECT_EQ(expected_codecs, vcd->codecs());
2309
2310 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
2311 // updated offer, even though the default payload types are different from
2312 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08002313 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002314 f2_.CreateOffer(opts, answer.get()));
2315 ASSERT_TRUE(updated_offer);
2316
2317 const VideoContentDescription* updated_vcd =
2318 GetFirstVideoContentDescription(updated_offer.get());
2319
2320 // New offer should attempt to add H263, and RTX for H264.
2321 expected_codecs.push_back(kVideoCodecs2[1]);
2322 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
2323 &expected_codecs);
2324 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
2325}
2326
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002327// Test that RTX is ignored when there is no associated payload type parameter.
2328TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
2329 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002330 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2331 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002332 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002333 // This creates RTX without associated payload type parameter.
perkj26752742016-10-24 01:21:16 -07002334 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002335 f1_.set_video_codecs(f1_codecs);
2336
2337 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002338 // This creates RTX for H264 with the payload type |f2_| uses.
2339 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002340 f2_.set_video_codecs(f2_codecs);
2341
kwiberg31022942016-03-11 14:18:21 -08002342 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002343 ASSERT_TRUE(offer.get() != NULL);
2344 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
2345 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
2346 // is possible to test that that RTX is dropped when
2347 // kCodecParamAssociatedPayloadType is missing in the offer.
Steve Antonb1c1de12017-12-21 15:14:30 -08002348 MediaContentDescription* media_desc =
2349 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2350 ASSERT_TRUE(media_desc);
2351 VideoContentDescription* desc = media_desc->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002352 std::vector<VideoCodec> codecs = desc->codecs();
Steve Anton3a66edf2018-09-10 12:57:37 -07002353 for (VideoCodec& codec : codecs) {
2354 if (codec.name.find(cricket::kRtxCodecName) == 0) {
2355 codec.params.clear();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002356 }
2357 }
2358 desc->set_codecs(codecs);
2359
kwiberg31022942016-03-11 14:18:21 -08002360 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002361 f2_.CreateAnswer(offer.get(), opts, NULL));
2362
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002363 std::vector<std::string> codec_names =
2364 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
2365 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
2366 cricket::kRtxCodecName));
2367}
2368
2369// Test that RTX will be filtered out in the answer if its associated payload
2370// type doesn't match the local value.
2371TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
2372 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002373 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2374 kActive, &opts);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002375 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2376 // This creates RTX for H264 in sender.
2377 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2378 f1_.set_video_codecs(f1_codecs);
2379
2380 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2381 // This creates RTX for H263 in receiver.
2382 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
2383 f2_.set_video_codecs(f2_codecs);
2384
kwiberg31022942016-03-11 14:18:21 -08002385 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002386 ASSERT_TRUE(offer.get() != NULL);
2387 // Associated payload type doesn't match, therefore, RTX codec is removed in
2388 // the answer.
kwiberg31022942016-03-11 14:18:21 -08002389 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002390 f2_.CreateAnswer(offer.get(), opts, NULL));
2391
2392 std::vector<std::string> codec_names =
2393 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
2394 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
2395 cricket::kRtxCodecName));
2396}
2397
2398// Test that when multiple RTX codecs are offered, only the matched RTX codec
2399// is added in the answer, and the unsupported RTX codec is filtered out.
2400TEST_F(MediaSessionDescriptionFactoryTest,
2401 FilterOutUnsupportedRtxWhenCreatingAnswer) {
2402 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002403 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2404 kActive, &opts);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002405 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2406 // This creates RTX for H264-SVC in sender.
2407 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
2408 f1_.set_video_codecs(f1_codecs);
2409
2410 // This creates RTX for H264 in sender.
2411 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2412 f1_.set_video_codecs(f1_codecs);
2413
2414 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2415 // This creates RTX for H264 in receiver.
2416 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
2417 f2_.set_video_codecs(f2_codecs);
2418
2419 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
2420 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08002421 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002422 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002423 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002424 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002425 const VideoContentDescription* vcd =
2426 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002427 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2428 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2429 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002430
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002431 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002432}
2433
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002434// Test that after one RTX codec has been negotiated, a new offer can attempt
2435// to add another.
2436TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
2437 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002438 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2439 kActive, &opts);
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002440 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2441 // This creates RTX for H264 for the offerer.
2442 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2443 f1_.set_video_codecs(f1_codecs);
2444
kwiberg31022942016-03-11 14:18:21 -08002445 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002446 ASSERT_TRUE(offer);
2447 const VideoContentDescription* vcd =
2448 GetFirstVideoContentDescription(offer.get());
2449
2450 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
2451 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2452 &expected_codecs);
2453 EXPECT_EQ(expected_codecs, vcd->codecs());
2454
2455 // Now, attempt to add RTX for H264-SVC.
2456 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
2457 f1_.set_video_codecs(f1_codecs);
2458
kwiberg31022942016-03-11 14:18:21 -08002459 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002460 f1_.CreateOffer(opts, offer.get()));
2461 ASSERT_TRUE(updated_offer);
2462 vcd = GetFirstVideoContentDescription(updated_offer.get());
2463
2464 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
2465 &expected_codecs);
2466 EXPECT_EQ(expected_codecs, vcd->codecs());
2467}
2468
Noah Richards2e7a0982015-05-18 14:02:54 -07002469// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
2470// generated for each simulcast ssrc and correctly grouped.
2471TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
2472 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002473 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2474 kActive, &opts);
Noah Richards2e7a0982015-05-18 14:02:54 -07002475 // Add simulcast streams.
zhihuang1c378ed2017-08-17 14:10:50 -07002476 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002477 {"stream1label"}, 3, &opts);
Noah Richards2e7a0982015-05-18 14:02:54 -07002478
2479 // Use a single real codec, and then add RTX for it.
2480 std::vector<VideoCodec> f1_codecs;
perkj26752742016-10-24 01:21:16 -07002481 f1_codecs.push_back(VideoCodec(97, "H264"));
Noah Richards2e7a0982015-05-18 14:02:54 -07002482 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
2483 f1_.set_video_codecs(f1_codecs);
2484
2485 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
2486 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08002487 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07002488 ASSERT_TRUE(offer.get() != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002489 MediaContentDescription* media_desc =
2490 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2491 ASSERT_TRUE(media_desc);
2492 VideoContentDescription* desc = media_desc->as_video();
Noah Richards2e7a0982015-05-18 14:02:54 -07002493 const StreamParamsVec& streams = desc->streams();
2494 // Single stream.
2495 ASSERT_EQ(1u, streams.size());
2496 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
2497 EXPECT_EQ(6u, streams[0].ssrcs.size());
2498 // And should have a SIM group for the simulcast.
2499 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2500 // And a FID group for RTX.
2501 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02002502 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002503 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2504 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02002505 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002506 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
2507 EXPECT_EQ(3u, fid_ssrcs.size());
2508}
2509
brandtr03d5fb12016-11-22 03:37:59 -08002510// Test that, when the FlexFEC codec is added, a FlexFEC ssrc is created
2511// together with a FEC-FR grouping.
2512TEST_F(MediaSessionDescriptionFactoryTest, GenerateFlexfecSsrc) {
2513 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002514 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2515 kActive, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002516 // Add single stream.
zhihuang1c378ed2017-08-17 14:10:50 -07002517 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002518 {"stream1label"}, 1, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002519
2520 // Use a single real codec, and then add FlexFEC for it.
2521 std::vector<VideoCodec> f1_codecs;
2522 f1_codecs.push_back(VideoCodec(97, "H264"));
2523 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2524 f1_.set_video_codecs(f1_codecs);
2525
2526 // Ensure that the offer has a single FlexFEC ssrc and that
2527 // there is no FEC-FR ssrc + grouping for each.
2528 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2529 ASSERT_TRUE(offer.get() != nullptr);
Steve Antonb1c1de12017-12-21 15:14:30 -08002530 MediaContentDescription* media_desc =
2531 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2532 ASSERT_TRUE(media_desc);
2533 VideoContentDescription* desc = media_desc->as_video();
brandtr03d5fb12016-11-22 03:37:59 -08002534 const StreamParamsVec& streams = desc->streams();
2535 // Single stream.
2536 ASSERT_EQ(1u, streams.size());
2537 // Stream should have 2 ssrcs: 1 for video, 1 for FlexFEC.
2538 EXPECT_EQ(2u, streams[0].ssrcs.size());
2539 // And should have a FEC-FR group for FlexFEC.
2540 EXPECT_TRUE(streams[0].has_ssrc_group("FEC-FR"));
2541 std::vector<uint32_t> primary_ssrcs;
2542 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2543 ASSERT_EQ(1u, primary_ssrcs.size());
2544 uint32_t flexfec_ssrc;
2545 EXPECT_TRUE(streams[0].GetFecFrSsrc(primary_ssrcs[0], &flexfec_ssrc));
2546 EXPECT_NE(flexfec_ssrc, 0u);
2547}
2548
2549// Test that FlexFEC is disabled for simulcast.
2550// TODO(brandtr): Remove this test when we support simulcast, either through
2551// multiple FlexfecSenders, or through multistream protection.
2552TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateNoFlexfecSsrcs) {
2553 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002554 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2555 kActive, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002556 // Add simulcast streams.
zhihuang1c378ed2017-08-17 14:10:50 -07002557 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002558 {"stream1label"}, 3, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002559
2560 // Use a single real codec, and then add FlexFEC for it.
2561 std::vector<VideoCodec> f1_codecs;
2562 f1_codecs.push_back(VideoCodec(97, "H264"));
2563 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2564 f1_.set_video_codecs(f1_codecs);
2565
2566 // Ensure that the offer has no FlexFEC ssrcs for each regular ssrc, and that
2567 // there is no FEC-FR ssrc + grouping for each.
2568 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2569 ASSERT_TRUE(offer.get() != nullptr);
Steve Antonb1c1de12017-12-21 15:14:30 -08002570 MediaContentDescription* media_desc =
2571 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2572 ASSERT_TRUE(media_desc);
2573 VideoContentDescription* desc = media_desc->as_video();
brandtr03d5fb12016-11-22 03:37:59 -08002574 const StreamParamsVec& streams = desc->streams();
2575 // Single stream.
2576 ASSERT_EQ(1u, streams.size());
2577 // Stream should have 3 ssrcs: 3 for video, 0 for FlexFEC.
2578 EXPECT_EQ(3u, streams[0].ssrcs.size());
2579 // And should have a SIM group for the simulcast.
2580 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2581 // And not a FEC-FR group for FlexFEC.
2582 EXPECT_FALSE(streams[0].has_ssrc_group("FEC-FR"));
2583 std::vector<uint32_t> primary_ssrcs;
2584 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2585 EXPECT_EQ(3u, primary_ssrcs.size());
2586 for (uint32_t primary_ssrc : primary_ssrcs) {
2587 uint32_t flexfec_ssrc;
2588 EXPECT_FALSE(streams[0].GetFecFrSsrc(primary_ssrc, &flexfec_ssrc));
2589 }
2590}
2591
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002592// Create an updated offer after creating an answer to the original offer and
2593// verify that the RTP header extensions that were part of the original answer
2594// are not changed in the updated offer.
2595TEST_F(MediaSessionDescriptionFactoryTest,
2596 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
2597 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002598 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002599
2600 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
2601 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
2602 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
2603 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
2604
kwiberg31022942016-03-11 14:18:21 -08002605 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2606 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002607 f2_.CreateAnswer(offer.get(), opts, NULL));
2608
Yves Gerey665174f2018-06-19 15:03:05 +02002609 EXPECT_EQ(
2610 MAKE_VECTOR(kAudioRtpExtensionAnswer),
2611 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
2612 EXPECT_EQ(
2613 MAKE_VECTOR(kVideoRtpExtensionAnswer),
2614 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002615
kwiberg31022942016-03-11 14:18:21 -08002616 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002617 f2_.CreateOffer(opts, answer.get()));
2618
2619 // The expected RTP header extensions in the new offer are the resulting
2620 // extensions from the first offer/answer exchange plus the extensions only
2621 // |f2_| offer.
2622 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002623 // |f1_| for another extensions, it is changed to 13.
isheriff6f8d6862016-05-26 11:24:55 -07002624 const RtpExtension kUpdatedAudioRtpExtensions[] = {
2625 kAudioRtpExtensionAnswer[0], RtpExtension(kAudioRtpExtension2[1].uri, 13),
2626 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002627 };
2628
2629 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002630 // |f1_| for another extensions, is is changed to 12.
isheriff6f8d6862016-05-26 11:24:55 -07002631 const RtpExtension kUpdatedVideoRtpExtensions[] = {
2632 kVideoRtpExtensionAnswer[0], RtpExtension(kVideoRtpExtension2[1].uri, 12),
2633 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002634 };
2635
2636 const AudioContentDescription* updated_acd =
2637 GetFirstAudioContentDescription(updated_offer.get());
2638 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
2639 updated_acd->rtp_header_extensions());
2640
2641 const VideoContentDescription* updated_vcd =
2642 GetFirstVideoContentDescription(updated_offer.get());
2643 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
2644 updated_vcd->rtp_header_extensions());
2645}
2646
deadbeefa5b273a2015-08-20 17:30:13 -07002647// Verify that if the same RTP extension URI is used for audio and video, the
2648// same ID is used. Also verify that the ID isn't changed when creating an
2649// updated offer (this was previously a bug).
isheriff6f8d6862016-05-26 11:24:55 -07002650TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) {
deadbeefa5b273a2015-08-20 17:30:13 -07002651 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002652 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
deadbeefa5b273a2015-08-20 17:30:13 -07002653
2654 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
2655 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
2656
kwiberg31022942016-03-11 14:18:21 -08002657 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07002658
2659 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
2660 // the video extensions.
isheriff6f8d6862016-05-26 11:24:55 -07002661 const RtpExtension kExpectedVideoRtpExtension[] = {
2662 kVideoRtpExtension3[0], kAudioRtpExtension3[1],
deadbeefa5b273a2015-08-20 17:30:13 -07002663 };
2664
Yves Gerey665174f2018-06-19 15:03:05 +02002665 EXPECT_EQ(
2666 MAKE_VECTOR(kAudioRtpExtension3),
2667 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
2668 EXPECT_EQ(
2669 MAKE_VECTOR(kExpectedVideoRtpExtension),
2670 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
deadbeefa5b273a2015-08-20 17:30:13 -07002671
2672 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08002673 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07002674 f1_.CreateOffer(opts, offer.get()));
2675
2676 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
Yves Gerey665174f2018-06-19 15:03:05 +02002677 GetFirstAudioContentDescription(updated_offer.get())
2678 ->rtp_header_extensions());
deadbeefa5b273a2015-08-20 17:30:13 -07002679 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
Yves Gerey665174f2018-06-19 15:03:05 +02002680 GetFirstVideoContentDescription(updated_offer.get())
2681 ->rtp_header_extensions());
deadbeefa5b273a2015-08-20 17:30:13 -07002682}
2683
jbauch5869f502017-06-29 12:31:36 -07002684// Same as "RtpExtensionIdReused" above for encrypted RTP extensions.
2685TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReusedEncrypted) {
2686 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002687 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07002688
2689 f1_.set_enable_encrypted_rtp_header_extensions(true);
2690 f2_.set_enable_encrypted_rtp_header_extensions(true);
2691
2692 f1_.set_audio_rtp_header_extensions(
2693 MAKE_VECTOR(kAudioRtpExtension3ForEncryption));
2694 f1_.set_video_rtp_header_extensions(
2695 MAKE_VECTOR(kVideoRtpExtension3ForEncryption));
2696
2697 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2698
2699 // The extensions that are shared between audio and video should use the same
2700 // id.
2701 const RtpExtension kExpectedVideoRtpExtension[] = {
2702 kVideoRtpExtension3ForEncryption[0],
2703 kAudioRtpExtension3ForEncryptionOffer[1],
2704 kAudioRtpExtension3ForEncryptionOffer[2],
2705 };
2706
Yves Gerey665174f2018-06-19 15:03:05 +02002707 EXPECT_EQ(
2708 MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
2709 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
2710 EXPECT_EQ(
2711 MAKE_VECTOR(kExpectedVideoRtpExtension),
2712 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07002713
2714 // Nothing should change when creating a new offer
2715 std::unique_ptr<SessionDescription> updated_offer(
2716 f1_.CreateOffer(opts, offer.get()));
2717
2718 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
Yves Gerey665174f2018-06-19 15:03:05 +02002719 GetFirstAudioContentDescription(updated_offer.get())
2720 ->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07002721 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
Yves Gerey665174f2018-06-19 15:03:05 +02002722 GetFirstVideoContentDescription(updated_offer.get())
2723 ->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07002724}
2725
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002726TEST(MediaSessionDescription, CopySessionDescription) {
2727 SessionDescription source;
2728 cricket::ContentGroup group(cricket::CN_AUDIO);
2729 source.AddGroup(group);
2730 AudioContentDescription* acd(new AudioContentDescription());
2731 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
2732 acd->AddLegacyStream(1);
Steve Anton5adfafd2017-12-20 16:34:00 -08002733 source.AddContent(cricket::CN_AUDIO, MediaProtocolType::kRtp, acd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002734 VideoContentDescription* vcd(new VideoContentDescription());
2735 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
2736 vcd->AddLegacyStream(2);
Steve Anton5adfafd2017-12-20 16:34:00 -08002737 source.AddContent(cricket::CN_VIDEO, MediaProtocolType::kRtp, vcd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002738
kwiberg31022942016-03-11 14:18:21 -08002739 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002740 ASSERT_TRUE(copy.get() != NULL);
2741 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
2742 const ContentInfo* ac = copy->GetContentByName("audio");
2743 const ContentInfo* vc = copy->GetContentByName("video");
2744 ASSERT_TRUE(ac != NULL);
2745 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08002746 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08002747 const AudioContentDescription* acd_copy = ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002748 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
2749 EXPECT_EQ(1u, acd->first_ssrc());
2750
Steve Anton5adfafd2017-12-20 16:34:00 -08002751 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08002752 const VideoContentDescription* vcd_copy = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002753 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
2754 EXPECT_EQ(2u, vcd->first_ssrc());
2755}
2756
2757// The below TestTransportInfoXXX tests create different offers/answers, and
2758// ensure the TransportInfo in the SessionDescription matches what we expect.
2759TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
2760 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002761 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2762 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002763 TestTransportInfo(true, options, false);
2764}
2765
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002766TEST_F(MediaSessionDescriptionFactoryTest,
2767 TestTransportInfoOfferIceRenomination) {
2768 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002769 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2770 kActive, &options);
zhihuang1c378ed2017-08-17 14:10:50 -07002771 options.media_description_options[0]
2772 .transport_options.enable_ice_renomination = true;
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002773 TestTransportInfo(true, options, false);
2774}
2775
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002776TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
2777 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002778 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2779 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002780 TestTransportInfo(true, options, true);
2781}
2782
2783TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2784 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002785 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2786 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2787 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002788 TestTransportInfo(true, options, false);
2789}
2790
2791TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02002792 TestTransportInfoOfferMultimediaCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002793 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002794 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2795 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2796 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002797 TestTransportInfo(true, options, true);
2798}
2799
2800TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2801 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002802 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2803 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2804 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002805 options.bundle_enabled = true;
2806 TestTransportInfo(true, options, false);
2807}
2808
2809TEST_F(MediaSessionDescriptionFactoryTest,
2810 TestTransportInfoOfferBundleCurrent) {
2811 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002812 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2813 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2814 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002815 options.bundle_enabled = true;
2816 TestTransportInfo(true, options, true);
2817}
2818
2819TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2820 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002821 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2822 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002823 TestTransportInfo(false, options, false);
2824}
2825
2826TEST_F(MediaSessionDescriptionFactoryTest,
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002827 TestTransportInfoAnswerIceRenomination) {
2828 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002829 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2830 kActive, &options);
zhihuang1c378ed2017-08-17 14:10:50 -07002831 options.media_description_options[0]
2832 .transport_options.enable_ice_renomination = true;
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002833 TestTransportInfo(false, options, false);
2834}
2835
2836TEST_F(MediaSessionDescriptionFactoryTest,
2837 TestTransportInfoAnswerAudioCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002838 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002839 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2840 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002841 TestTransportInfo(false, options, true);
2842}
2843
2844TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2845 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002846 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2847 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2848 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002849 TestTransportInfo(false, options, false);
2850}
2851
2852TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02002853 TestTransportInfoAnswerMultimediaCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002854 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002855 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2856 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2857 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002858 TestTransportInfo(false, options, true);
2859}
2860
2861TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2862 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002863 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2864 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2865 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002866 options.bundle_enabled = true;
2867 TestTransportInfo(false, options, false);
2868}
2869
2870TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02002871 TestTransportInfoAnswerBundleCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002872 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002873 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2874 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2875 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002876 options.bundle_enabled = true;
2877 TestTransportInfo(false, options, true);
2878}
2879
2880// Create an offer with bundle enabled and verify the crypto parameters are
2881// the common set of the available cryptos.
2882TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2883 TestCryptoWithBundle(true);
2884}
2885
2886// Create an answer with bundle enabled and verify the crypto parameters are
2887// the common set of the available cryptos.
2888TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2889 TestCryptoWithBundle(false);
2890}
2891
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002892// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2893// DTLS is not enabled locally.
2894TEST_F(MediaSessionDescriptionFactoryTest,
2895 TestOfferDtlsSavpfWithoutDtlsFailed) {
2896 f1_.set_secure(SEC_ENABLED);
2897 f2_.set_secure(SEC_ENABLED);
2898 tdf1_.set_secure(SEC_DISABLED);
2899 tdf2_.set_secure(SEC_DISABLED);
2900
kwiberg31022942016-03-11 14:18:21 -08002901 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -07002902 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002903 ASSERT_TRUE(offer.get() != NULL);
2904 ContentInfo* offer_content = offer->GetContentByName("audio");
2905 ASSERT_TRUE(offer_content != NULL);
2906 AudioContentDescription* offer_audio_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -08002907 offer_content->media_description()->as_audio();
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002908 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2909
kwiberg31022942016-03-11 14:18:21 -08002910 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07002911 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002912 ASSERT_TRUE(answer != NULL);
2913 ContentInfo* answer_content = answer->GetContentByName("audio");
2914 ASSERT_TRUE(answer_content != NULL);
2915
2916 ASSERT_TRUE(answer_content->rejected);
2917}
2918
2919// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2920// UDP/TLS/RTP/SAVPF.
2921TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2922 f1_.set_secure(SEC_ENABLED);
2923 f2_.set_secure(SEC_ENABLED);
2924 tdf1_.set_secure(SEC_ENABLED);
2925 tdf2_.set_secure(SEC_ENABLED);
2926
kwiberg31022942016-03-11 14:18:21 -08002927 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -07002928 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002929 ASSERT_TRUE(offer.get() != NULL);
2930 ContentInfo* offer_content = offer->GetContentByName("audio");
2931 ASSERT_TRUE(offer_content != NULL);
2932 AudioContentDescription* offer_audio_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -08002933 offer_content->media_description()->as_audio();
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002934 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2935
kwiberg31022942016-03-11 14:18:21 -08002936 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07002937 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002938 ASSERT_TRUE(answer != NULL);
2939
2940 const ContentInfo* answer_content = answer->GetContentByName("audio");
2941 ASSERT_TRUE(answer_content != NULL);
2942 ASSERT_FALSE(answer_content->rejected);
2943
2944 const AudioContentDescription* answer_audio_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -08002945 answer_content->media_description()->as_audio();
Steve Antone38a5a12018-11-21 16:05:15 -08002946 EXPECT_EQ(cricket::kMediaProtocolDtlsSavpf, answer_audio_desc->protocol());
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002947}
2948
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002949// Test that we include both SDES and DTLS in the offer, but only include SDES
2950// in the answer if DTLS isn't negotiated.
2951TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2952 f1_.set_secure(SEC_ENABLED);
2953 f2_.set_secure(SEC_ENABLED);
2954 tdf1_.set_secure(SEC_ENABLED);
2955 tdf2_.set_secure(SEC_DISABLED);
2956 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002957 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
kwiberg31022942016-03-11 14:18:21 -08002958 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002959 const cricket::MediaContentDescription* audio_media_desc;
2960 const cricket::MediaContentDescription* video_media_desc;
2961 const cricket::TransportDescription* audio_trans_desc;
2962 const cricket::TransportDescription* video_trans_desc;
2963
2964 // Generate an offer with SDES and DTLS support.
2965 offer.reset(f1_.CreateOffer(options, NULL));
2966 ASSERT_TRUE(offer.get() != NULL);
2967
Steve Antonb1c1de12017-12-21 15:14:30 -08002968 audio_media_desc = offer->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002969 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002970 video_media_desc = offer->GetContentDescriptionByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002971 ASSERT_TRUE(video_media_desc != NULL);
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07002972 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002973 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2974
2975 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2976 ASSERT_TRUE(audio_trans_desc != NULL);
2977 video_trans_desc = offer->GetTransportDescriptionByName("video");
2978 ASSERT_TRUE(video_trans_desc != NULL);
2979 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2980 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2981
2982 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2983 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2984 ASSERT_TRUE(answer.get() != NULL);
2985
Steve Antonb1c1de12017-12-21 15:14:30 -08002986 audio_media_desc = answer->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002987 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002988 video_media_desc = answer->GetContentDescriptionByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002989 ASSERT_TRUE(video_media_desc != NULL);
2990 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2991 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2992
2993 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2994 ASSERT_TRUE(audio_trans_desc != NULL);
2995 video_trans_desc = answer->GetTransportDescriptionByName("video");
2996 ASSERT_TRUE(video_trans_desc != NULL);
2997 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2998 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2999
3000 // Enable DTLS; the answer should now only have DTLS support.
3001 tdf2_.set_secure(SEC_ENABLED);
3002 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
3003 ASSERT_TRUE(answer.get() != NULL);
3004
Steve Antonb1c1de12017-12-21 15:14:30 -08003005 audio_media_desc = answer->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003006 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08003007 video_media_desc = answer->GetContentDescriptionByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003008 ASSERT_TRUE(video_media_desc != NULL);
3009 EXPECT_TRUE(audio_media_desc->cryptos().empty());
3010 EXPECT_TRUE(video_media_desc->cryptos().empty());
Steve Antone38a5a12018-11-21 16:05:15 -08003011 EXPECT_EQ(cricket::kMediaProtocolSavpf, audio_media_desc->protocol());
3012 EXPECT_EQ(cricket::kMediaProtocolSavpf, video_media_desc->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003013
3014 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
3015 ASSERT_TRUE(audio_trans_desc != NULL);
3016 video_trans_desc = answer->GetTransportDescriptionByName("video");
3017 ASSERT_TRUE(video_trans_desc != NULL);
3018 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
3019 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003020
3021 // Try creating offer again. DTLS enabled now, crypto's should be empty
3022 // in new offer.
3023 offer.reset(f1_.CreateOffer(options, offer.get()));
3024 ASSERT_TRUE(offer.get() != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08003025 audio_media_desc = offer->GetContentDescriptionByName("audio");
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003026 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08003027 video_media_desc = offer->GetContentDescriptionByName("video");
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003028 ASSERT_TRUE(video_media_desc != NULL);
3029 EXPECT_TRUE(audio_media_desc->cryptos().empty());
3030 EXPECT_TRUE(video_media_desc->cryptos().empty());
3031
3032 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
3033 ASSERT_TRUE(audio_trans_desc != NULL);
3034 video_trans_desc = offer->GetTransportDescriptionByName("video");
3035 ASSERT_TRUE(video_trans_desc != NULL);
3036 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
3037 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003038}
3039
3040// Test that an answer can't be created if cryptos are required but the offer is
3041// unsecure.
3042TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07003043 MediaSessionOptions options = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003044 f1_.set_secure(SEC_DISABLED);
3045 tdf1_.set_secure(SEC_DISABLED);
3046 f2_.set_secure(SEC_REQUIRED);
3047 tdf1_.set_secure(SEC_ENABLED);
3048
kwiberg31022942016-03-11 14:18:21 -08003049 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003050 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08003051 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003052 f2_.CreateAnswer(offer.get(), options, NULL));
3053 EXPECT_TRUE(answer.get() == NULL);
3054}
3055
3056// Test that we accept a DTLS offer without SDES and create an appropriate
3057// answer.
3058TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
3059 f1_.set_secure(SEC_DISABLED);
3060 f2_.set_secure(SEC_ENABLED);
3061 tdf1_.set_secure(SEC_ENABLED);
3062 tdf2_.set_secure(SEC_ENABLED);
3063 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08003064 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
3065 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
3066 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003067
kwiberg31022942016-03-11 14:18:21 -08003068 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003069
3070 // Generate an offer with DTLS but without SDES.
3071 offer.reset(f1_.CreateOffer(options, NULL));
3072 ASSERT_TRUE(offer.get() != NULL);
3073
3074 const AudioContentDescription* audio_offer =
3075 GetFirstAudioContentDescription(offer.get());
3076 ASSERT_TRUE(audio_offer->cryptos().empty());
3077 const VideoContentDescription* video_offer =
3078 GetFirstVideoContentDescription(offer.get());
3079 ASSERT_TRUE(video_offer->cryptos().empty());
3080 const DataContentDescription* data_offer =
3081 GetFirstDataContentDescription(offer.get());
3082 ASSERT_TRUE(data_offer->cryptos().empty());
3083
3084 const cricket::TransportDescription* audio_offer_trans_desc =
3085 offer->GetTransportDescriptionByName("audio");
3086 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
3087 const cricket::TransportDescription* video_offer_trans_desc =
3088 offer->GetTransportDescriptionByName("video");
3089 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
3090 const cricket::TransportDescription* data_offer_trans_desc =
3091 offer->GetTransportDescriptionByName("data");
3092 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
3093
3094 // Generate an answer with DTLS.
3095 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
3096 ASSERT_TRUE(answer.get() != NULL);
3097
3098 const cricket::TransportDescription* audio_answer_trans_desc =
3099 answer->GetTransportDescriptionByName("audio");
3100 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
3101 const cricket::TransportDescription* video_answer_trans_desc =
3102 answer->GetTransportDescriptionByName("video");
3103 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
3104 const cricket::TransportDescription* data_answer_trans_desc =
3105 answer->GetTransportDescriptionByName("data");
3106 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
3107}
3108
3109// Verifies if vad_enabled option is set to false, CN codecs are not present in
3110// offer or answer.
3111TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
3112 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08003113 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
kwiberg31022942016-03-11 14:18:21 -08003114 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003115 ASSERT_TRUE(offer.get() != NULL);
3116 const ContentInfo* audio_content = offer->GetContentByName("audio");
3117 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
3118
3119 options.vad_enabled = false;
3120 offer.reset(f1_.CreateOffer(options, NULL));
3121 ASSERT_TRUE(offer.get() != NULL);
3122 audio_content = offer->GetContentByName("audio");
3123 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08003124 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003125 f1_.CreateAnswer(offer.get(), options, NULL));
3126 ASSERT_TRUE(answer.get() != NULL);
3127 audio_content = answer->GetContentByName("audio");
3128 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
3129}
deadbeef44f08192015-12-15 16:20:09 -08003130
zhihuang1c378ed2017-08-17 14:10:50 -07003131// Test that the generated MIDs match the existing offer.
3132TEST_F(MediaSessionDescriptionFactoryTest, TestMIDsMatchesExistingOffer) {
deadbeef44f08192015-12-15 16:20:09 -08003133 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003134 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_modified",
3135 RtpTransceiverDirection::kRecvOnly, kActive, &opts);
3136 AddMediaSection(MEDIA_TYPE_VIDEO, "video_modified",
3137 RtpTransceiverDirection::kRecvOnly, kActive, &opts);
deadbeef44f08192015-12-15 16:20:09 -08003138 opts.data_channel_type = cricket::DCT_SCTP;
Steve Anton4e70a722017-11-28 14:57:10 -08003139 AddMediaSection(MEDIA_TYPE_DATA, "data_modified",
3140 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003141 // Create offer.
kwiberg31022942016-03-11 14:18:21 -08003142 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
kwiberg31022942016-03-11 14:18:21 -08003143 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08003144 f1_.CreateOffer(opts, offer.get()));
zhihuang1c378ed2017-08-17 14:10:50 -07003145
deadbeef44f08192015-12-15 16:20:09 -08003146 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
3147 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
3148 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
3149 ASSERT_TRUE(audio_content != nullptr);
3150 ASSERT_TRUE(video_content != nullptr);
3151 ASSERT_TRUE(data_content != nullptr);
3152 EXPECT_EQ("audio_modified", audio_content->name);
3153 EXPECT_EQ("video_modified", video_content->name);
3154 EXPECT_EQ("data_modified", data_content->name);
3155}
zhihuangcf5b37c2016-05-05 11:44:35 -07003156
zhihuang1c378ed2017-08-17 14:10:50 -07003157// The following tests verify that the unified plan SDP is supported.
3158// Test that we can create an offer with multiple media sections of same media
3159// type.
3160TEST_F(MediaSessionDescriptionFactoryTest,
3161 CreateOfferWithMultipleAVMediaSections) {
3162 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003163 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_1",
3164 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003165 AttachSenderToMediaSection("audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003166 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003167
Steve Anton4e70a722017-11-28 14:57:10 -08003168 AddMediaSection(MEDIA_TYPE_VIDEO, "video_1",
3169 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003170 AttachSenderToMediaSection("video_1", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003171 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003172
Steve Anton4e70a722017-11-28 14:57:10 -08003173 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_2",
3174 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003175 AttachSenderToMediaSection("audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003176 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003177
Steve Anton4e70a722017-11-28 14:57:10 -08003178 AddMediaSection(MEDIA_TYPE_VIDEO, "video_2",
3179 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003180 AttachSenderToMediaSection("video_2", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003181 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003182 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3183 ASSERT_TRUE(offer);
3184
3185 ASSERT_EQ(4u, offer->contents().size());
3186 EXPECT_FALSE(offer->contents()[0].rejected);
3187 const AudioContentDescription* acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003188 offer->contents()[0].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003189 ASSERT_EQ(1u, acd->streams().size());
3190 EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003191 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003192
3193 EXPECT_FALSE(offer->contents()[1].rejected);
3194 const VideoContentDescription* vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003195 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003196 ASSERT_EQ(1u, vcd->streams().size());
3197 EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003198 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003199
3200 EXPECT_FALSE(offer->contents()[2].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003201 acd = offer->contents()[2].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003202 ASSERT_EQ(1u, acd->streams().size());
3203 EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003204 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003205
3206 EXPECT_FALSE(offer->contents()[3].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003207 vcd = offer->contents()[3].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003208 ASSERT_EQ(1u, vcd->streams().size());
3209 EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003210 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003211}
3212
3213// Test that we can create an answer with multiple media sections of same media
3214// type.
3215TEST_F(MediaSessionDescriptionFactoryTest,
3216 CreateAnswerWithMultipleAVMediaSections) {
3217 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003218 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_1",
3219 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003220 AttachSenderToMediaSection("audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003221 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003222
Steve Anton4e70a722017-11-28 14:57:10 -08003223 AddMediaSection(MEDIA_TYPE_VIDEO, "video_1",
3224 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003225 AttachSenderToMediaSection("video_1", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003226 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003227
Steve Anton4e70a722017-11-28 14:57:10 -08003228 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_2",
3229 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003230 AttachSenderToMediaSection("audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003231 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003232
Steve Anton4e70a722017-11-28 14:57:10 -08003233 AddMediaSection(MEDIA_TYPE_VIDEO, "video_2",
3234 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003235 AttachSenderToMediaSection("video_2", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003236 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003237
3238 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3239 ASSERT_TRUE(offer);
3240 std::unique_ptr<SessionDescription> answer(
3241 f2_.CreateAnswer(offer.get(), opts, nullptr));
3242
3243 ASSERT_EQ(4u, answer->contents().size());
3244 EXPECT_FALSE(answer->contents()[0].rejected);
3245 const AudioContentDescription* acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003246 answer->contents()[0].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003247 ASSERT_EQ(1u, acd->streams().size());
3248 EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003249 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003250
3251 EXPECT_FALSE(answer->contents()[1].rejected);
3252 const VideoContentDescription* vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003253 answer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003254 ASSERT_EQ(1u, vcd->streams().size());
3255 EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003256 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003257
3258 EXPECT_FALSE(answer->contents()[2].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003259 acd = answer->contents()[2].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003260 ASSERT_EQ(1u, acd->streams().size());
3261 EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003262 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003263
3264 EXPECT_FALSE(answer->contents()[3].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003265 vcd = answer->contents()[3].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003266 ASSERT_EQ(1u, vcd->streams().size());
3267 EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003268 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003269}
3270
3271// Test that the media section will be rejected in offer if the corresponding
3272// MediaDescriptionOptions is stopped by the offerer.
3273TEST_F(MediaSessionDescriptionFactoryTest,
3274 CreateOfferWithMediaSectionStoppedByOfferer) {
3275 // Create an offer with two audio sections and one of them is stopped.
3276 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003277 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3278 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3279 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3280 RtpTransceiverDirection::kInactive, kStopped, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003281 std::unique_ptr<SessionDescription> offer(
3282 f1_.CreateOffer(offer_opts, nullptr));
3283 ASSERT_TRUE(offer);
3284 ASSERT_EQ(2u, offer->contents().size());
3285 EXPECT_FALSE(offer->contents()[0].rejected);
3286 EXPECT_TRUE(offer->contents()[1].rejected);
3287}
3288
3289// Test that the media section will be rejected in answer if the corresponding
3290// MediaDescriptionOptions is stopped by the offerer.
3291TEST_F(MediaSessionDescriptionFactoryTest,
3292 CreateAnswerWithMediaSectionStoppedByOfferer) {
3293 // Create an offer with two audio sections and one of them is stopped.
3294 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003295 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3296 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3297 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3298 RtpTransceiverDirection::kInactive, kStopped, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003299 std::unique_ptr<SessionDescription> offer(
3300 f1_.CreateOffer(offer_opts, nullptr));
3301 ASSERT_TRUE(offer);
3302 ASSERT_EQ(2u, offer->contents().size());
3303 EXPECT_FALSE(offer->contents()[0].rejected);
3304 EXPECT_TRUE(offer->contents()[1].rejected);
3305
3306 // Create an answer based on the offer.
3307 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003308 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3309 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
3310 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3311 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003312 std::unique_ptr<SessionDescription> answer(
3313 f2_.CreateAnswer(offer.get(), answer_opts, nullptr));
3314 ASSERT_EQ(2u, answer->contents().size());
3315 EXPECT_FALSE(answer->contents()[0].rejected);
3316 EXPECT_TRUE(answer->contents()[1].rejected);
3317}
3318
3319// Test that the media section will be rejected in answer if the corresponding
3320// MediaDescriptionOptions is stopped by the answerer.
3321TEST_F(MediaSessionDescriptionFactoryTest,
3322 CreateAnswerWithMediaSectionRejectedByAnswerer) {
3323 // Create an offer with two audio sections.
3324 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003325 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3326 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3327 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3328 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003329 std::unique_ptr<SessionDescription> offer(
3330 f1_.CreateOffer(offer_opts, nullptr));
3331 ASSERT_TRUE(offer);
3332 ASSERT_EQ(2u, offer->contents().size());
3333 ASSERT_FALSE(offer->contents()[0].rejected);
3334 ASSERT_FALSE(offer->contents()[1].rejected);
3335
3336 // The answerer rejects one of the audio sections.
3337 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003338 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3339 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
3340 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3341 RtpTransceiverDirection::kInactive, kStopped, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003342 std::unique_ptr<SessionDescription> answer(
3343 f2_.CreateAnswer(offer.get(), answer_opts, nullptr));
3344 ASSERT_EQ(2u, answer->contents().size());
3345 EXPECT_FALSE(answer->contents()[0].rejected);
3346 EXPECT_TRUE(answer->contents()[1].rejected);
Zhi Huang3518e7b2018-01-30 13:20:35 -08003347
3348 // The TransportInfo of the rejected m= section is expected to be added in the
3349 // answer.
3350 EXPECT_EQ(offer->transport_infos().size(), answer->transport_infos().size());
zhihuang1c378ed2017-08-17 14:10:50 -07003351}
3352
3353// Test the generated media sections has the same order of the
3354// corresponding MediaDescriptionOptions.
3355TEST_F(MediaSessionDescriptionFactoryTest,
3356 CreateOfferRespectsMediaDescriptionOptionsOrder) {
3357 MediaSessionOptions opts;
3358 // This tests put video section first because normally audio comes first by
3359 // default.
Steve Anton4e70a722017-11-28 14:57:10 -08003360 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3361 kActive, &opts);
3362 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
3363 kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003364 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3365
3366 ASSERT_TRUE(offer);
3367 ASSERT_EQ(2u, offer->contents().size());
3368 EXPECT_EQ("video", offer->contents()[0].name);
3369 EXPECT_EQ("audio", offer->contents()[1].name);
3370}
3371
3372// Test that different media sections using the same codec have same payload
3373// type.
3374TEST_F(MediaSessionDescriptionFactoryTest,
3375 PayloadTypesSharedByMediaSectionsOfSameType) {
3376 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003377 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3378 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3379 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3380 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003381 // Create an offer with two video sections using same codecs.
3382 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3383 ASSERT_TRUE(offer);
3384 ASSERT_EQ(2u, offer->contents().size());
3385 const VideoContentDescription* vcd1 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003386 offer->contents()[0].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003387 const VideoContentDescription* vcd2 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003388 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003389 EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
3390 ASSERT_EQ(2u, vcd1->codecs().size());
3391 EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
3392 EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
3393 EXPECT_EQ(vcd1->codecs()[1].name, vcd2->codecs()[1].name);
3394 EXPECT_EQ(vcd1->codecs()[1].id, vcd2->codecs()[1].id);
3395
3396 // Create answer and negotiate the codecs.
3397 std::unique_ptr<SessionDescription> answer(
3398 f2_.CreateAnswer(offer.get(), opts, nullptr));
3399 ASSERT_TRUE(answer);
3400 ASSERT_EQ(2u, answer->contents().size());
Steve Antonb1c1de12017-12-21 15:14:30 -08003401 vcd1 = answer->contents()[0].media_description()->as_video();
3402 vcd2 = answer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003403 EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
3404 ASSERT_EQ(1u, vcd1->codecs().size());
3405 EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
3406 EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
3407}
3408
3409// Test that the codec preference order per media section is respected in
3410// subsequent offer.
3411TEST_F(MediaSessionDescriptionFactoryTest,
3412 CreateOfferRespectsCodecPreferenceOrder) {
3413 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003414 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3415 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3416 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3417 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003418 // Create an offer with two video sections using same codecs.
3419 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3420 ASSERT_TRUE(offer);
3421 ASSERT_EQ(2u, offer->contents().size());
3422 VideoContentDescription* vcd1 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003423 offer->contents()[0].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003424 const VideoContentDescription* vcd2 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003425 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003426 auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
3427 EXPECT_EQ(video_codecs, vcd1->codecs());
3428 EXPECT_EQ(video_codecs, vcd2->codecs());
3429
3430 // Change the codec preference of the first video section and create a
3431 // follow-up offer.
3432 auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
3433 vcd1->set_codecs(video_codecs_reverse);
3434 std::unique_ptr<SessionDescription> updated_offer(
3435 f1_.CreateOffer(opts, offer.get()));
Steve Antonb1c1de12017-12-21 15:14:30 -08003436 vcd1 = updated_offer->contents()[0].media_description()->as_video();
3437 vcd2 = updated_offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003438 // The video codec preference order should be respected.
3439 EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
3440 EXPECT_EQ(video_codecs, vcd2->codecs());
3441}
3442
3443// Test that the codec preference order per media section is respected in
3444// the answer.
3445TEST_F(MediaSessionDescriptionFactoryTest,
3446 CreateAnswerRespectsCodecPreferenceOrder) {
3447 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003448 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3449 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3450 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3451 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003452 // Create an offer with two video sections using same codecs.
3453 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3454 ASSERT_TRUE(offer);
3455 ASSERT_EQ(2u, offer->contents().size());
3456 VideoContentDescription* vcd1 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003457 offer->contents()[0].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003458 const VideoContentDescription* vcd2 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003459 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003460 auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
3461 EXPECT_EQ(video_codecs, vcd1->codecs());
3462 EXPECT_EQ(video_codecs, vcd2->codecs());
3463
3464 // Change the codec preference of the first video section and create an
3465 // answer.
3466 auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
3467 vcd1->set_codecs(video_codecs_reverse);
3468 std::unique_ptr<SessionDescription> answer(
3469 f1_.CreateAnswer(offer.get(), opts, nullptr));
Steve Antonb1c1de12017-12-21 15:14:30 -08003470 vcd1 = answer->contents()[0].media_description()->as_video();
3471 vcd2 = answer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003472 // The video codec preference order should be respected.
3473 EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
3474 EXPECT_EQ(video_codecs, vcd2->codecs());
3475}
3476
Zhi Huang6f367472017-11-22 13:20:02 -08003477// Test that when creating an answer, the codecs use local parameters instead of
3478// the remote ones.
3479TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerWithLocalCodecParams) {
3480 const std::string audio_param_name = "audio_param";
3481 const std::string audio_value1 = "audio_v1";
3482 const std::string audio_value2 = "audio_v2";
3483 const std::string video_param_name = "video_param";
3484 const std::string video_value1 = "video_v1";
3485 const std::string video_value2 = "video_v2";
3486
3487 auto audio_codecs1 = MAKE_VECTOR(kAudioCodecs1);
3488 auto audio_codecs2 = MAKE_VECTOR(kAudioCodecs1);
3489 auto video_codecs1 = MAKE_VECTOR(kVideoCodecs1);
3490 auto video_codecs2 = MAKE_VECTOR(kVideoCodecs1);
3491
3492 // Set the parameters for codecs.
3493 audio_codecs1[0].SetParam(audio_param_name, audio_value1);
3494 video_codecs1[0].SetParam(video_param_name, video_value1);
3495 audio_codecs2[0].SetParam(audio_param_name, audio_value2);
3496 video_codecs2[0].SetParam(video_param_name, video_value2);
3497
3498 f1_.set_audio_codecs(audio_codecs1, audio_codecs1);
3499 f1_.set_video_codecs(video_codecs1);
3500 f2_.set_audio_codecs(audio_codecs2, audio_codecs2);
3501 f2_.set_video_codecs(video_codecs2);
3502
3503 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003504 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
3505 kActive, &opts);
3506 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3507 kActive, &opts);
Zhi Huang6f367472017-11-22 13:20:02 -08003508
3509 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3510 ASSERT_TRUE(offer);
Steve Antonb1c1de12017-12-21 15:14:30 -08003511 auto offer_acd = offer->contents()[0].media_description()->as_audio();
3512 auto offer_vcd = offer->contents()[1].media_description()->as_video();
Zhi Huang6f367472017-11-22 13:20:02 -08003513 std::string value;
3514 EXPECT_TRUE(offer_acd->codecs()[0].GetParam(audio_param_name, &value));
3515 EXPECT_EQ(audio_value1, value);
3516 EXPECT_TRUE(offer_vcd->codecs()[0].GetParam(video_param_name, &value));
3517 EXPECT_EQ(video_value1, value);
3518
3519 std::unique_ptr<SessionDescription> answer(
3520 f2_.CreateAnswer(offer.get(), opts, nullptr));
3521 ASSERT_TRUE(answer);
Steve Antonb1c1de12017-12-21 15:14:30 -08003522 auto answer_acd = answer->contents()[0].media_description()->as_audio();
3523 auto answer_vcd = answer->contents()[1].media_description()->as_video();
Zhi Huang6f367472017-11-22 13:20:02 -08003524 // Use the parameters from the local codecs.
3525 EXPECT_TRUE(answer_acd->codecs()[0].GetParam(audio_param_name, &value));
3526 EXPECT_EQ(audio_value2, value);
3527 EXPECT_TRUE(answer_vcd->codecs()[0].GetParam(video_param_name, &value));
3528 EXPECT_EQ(video_value2, value);
3529}
3530
Steve Anton9c1fb1e2018-02-26 15:09:41 -08003531// Test that matching packetization-mode is part of the criteria for matching
3532// H264 codecs (in addition to profile-level-id). Previously, this was not the
3533// case, so the first H264 codec with the same profile-level-id would match and
3534// the payload type in the answer would be incorrect.
3535// This is a regression test for bugs.webrtc.org/8808
3536TEST_F(MediaSessionDescriptionFactoryTest,
3537 H264MatchCriteriaIncludesPacketizationMode) {
3538 // Create two H264 codecs with the same profile level ID and different
3539 // packetization modes.
3540 VideoCodec h264_pm0(96, "H264");
3541 h264_pm0.params[cricket::kH264FmtpProfileLevelId] = "42c01f";
3542 h264_pm0.params[cricket::kH264FmtpPacketizationMode] = "0";
3543 VideoCodec h264_pm1(97, "H264");
3544 h264_pm1.params[cricket::kH264FmtpProfileLevelId] = "42c01f";
3545 h264_pm1.params[cricket::kH264FmtpPacketizationMode] = "1";
3546
3547 // Offerer will send both codecs, answerer should choose the one with matching
3548 // packetization mode (and not the first one it sees).
3549 f1_.set_video_codecs({h264_pm0, h264_pm1});
3550 f2_.set_video_codecs({h264_pm1});
3551
3552 MediaSessionOptions opts;
3553 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3554 kActive, &opts);
3555
3556 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3557 ASSERT_TRUE(offer);
3558
3559 std::unique_ptr<SessionDescription> answer(
3560 f2_.CreateAnswer(offer.get(), opts, nullptr));
3561 ASSERT_TRUE(answer);
3562
3563 // Answer should have one negotiated codec with packetization-mode=1 using the
3564 // offered payload type.
3565 ASSERT_EQ(1u, answer->contents().size());
3566 auto answer_vcd = answer->contents()[0].media_description()->as_video();
3567 ASSERT_EQ(1u, answer_vcd->codecs().size());
3568 auto answer_codec = answer_vcd->codecs()[0];
3569 EXPECT_EQ(h264_pm1.id, answer_codec.id);
3570}
3571
zhihuangcf5b37c2016-05-05 11:44:35 -07003572class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
3573 public:
3574 MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -07003575 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
3576 MAKE_VECTOR(kAudioCodecs1));
zhihuangcf5b37c2016-05-05 11:44:35 -07003577 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
3578 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -07003579 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
3580 MAKE_VECTOR(kAudioCodecs2));
zhihuangcf5b37c2016-05-05 11:44:35 -07003581 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
3582 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
3583 f1_.set_secure(SEC_ENABLED);
3584 f2_.set_secure(SEC_ENABLED);
3585 tdf1_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07003586 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07003587 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07003588 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07003589 tdf1_.set_secure(SEC_ENABLED);
3590 tdf2_.set_secure(SEC_ENABLED);
3591 }
3592
3593 protected:
3594 MediaSessionDescriptionFactory f1_;
3595 MediaSessionDescriptionFactory f2_;
3596 TransportDescriptionFactory tdf1_;
3597 TransportDescriptionFactory tdf2_;
3598};
3599
3600TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
3601 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003602 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
zhihuangcf5b37c2016-05-05 11:44:35 -07003603 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3604 ASSERT_TRUE(offer.get() != nullptr);
3605 // Set the protocol for all the contents.
3606 for (auto content : offer.get()->contents()) {
Steve Antonb1c1de12017-12-21 15:14:30 -08003607 content.media_description()->set_protocol(GetParam());
zhihuangcf5b37c2016-05-05 11:44:35 -07003608 }
3609 std::unique_ptr<SessionDescription> answer(
3610 f2_.CreateAnswer(offer.get(), opts, nullptr));
3611 const ContentInfo* ac = answer->GetContentByName("audio");
3612 const ContentInfo* vc = answer->GetContentByName("video");
3613 ASSERT_TRUE(ac != nullptr);
3614 ASSERT_TRUE(vc != nullptr);
3615 EXPECT_FALSE(ac->rejected); // the offer is accepted
3616 EXPECT_FALSE(vc->rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003617 const AudioContentDescription* acd = ac->media_description()->as_audio();
3618 const VideoContentDescription* vcd = vc->media_description()->as_video();
zhihuangcf5b37c2016-05-05 11:44:35 -07003619 EXPECT_EQ(GetParam(), acd->protocol());
3620 EXPECT_EQ(GetParam(), vcd->protocol());
3621}
3622
3623INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest,
3624 MediaProtocolTest,
3625 ::testing::ValuesIn(kMediaProtocols));
3626INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest,
3627 MediaProtocolTest,
3628 ::testing::ValuesIn(kMediaProtocolsDtls));
ossu075af922016-06-14 03:29:38 -07003629
3630TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) {
3631 TransportDescriptionFactory tdf;
3632 MediaSessionDescriptionFactory sf(&tdf);
3633 std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
3634 std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
3635
3636 // The merged list of codecs should contain any send codecs that are also
3637 // nominally in the recieve codecs list. Payload types should be picked from
3638 // the send codecs and a number-of-channels of 0 and 1 should be equivalent
3639 // (set to 1). This equals what happens when the send codecs are used in an
3640 // offer and the receive codecs are used in the following answer.
3641 const std::vector<AudioCodec> sendrecv_codecs =
3642 MAKE_VECTOR(kAudioCodecsAnswer);
3643 const std::vector<AudioCodec> no_codecs;
3644
3645 RTC_CHECK_EQ(send_codecs[1].name, "iLBC")
3646 << "Please don't change shared test data!";
3647 RTC_CHECK_EQ(recv_codecs[2].name, "iLBC")
3648 << "Please don't change shared test data!";
3649 // Alter iLBC send codec to have zero channels, to test that that is handled
3650 // properly.
3651 send_codecs[1].channels = 0;
3652
3653 // Alther iLBC receive codec to be lowercase, to test that case conversions
3654 // are handled properly.
3655 recv_codecs[2].name = "ilbc";
3656
3657 // Test proper merge
3658 sf.set_audio_codecs(send_codecs, recv_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003659 EXPECT_EQ(send_codecs, sf.audio_send_codecs());
3660 EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
3661 EXPECT_EQ(sendrecv_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003662
3663 // Test empty send codecs list
3664 sf.set_audio_codecs(no_codecs, recv_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003665 EXPECT_EQ(no_codecs, sf.audio_send_codecs());
3666 EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
3667 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003668
3669 // Test empty recv codecs list
3670 sf.set_audio_codecs(send_codecs, no_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003671 EXPECT_EQ(send_codecs, sf.audio_send_codecs());
3672 EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
3673 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003674
3675 // Test all empty codec lists
3676 sf.set_audio_codecs(no_codecs, no_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003677 EXPECT_EQ(no_codecs, sf.audio_send_codecs());
3678 EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
3679 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003680}
3681
3682namespace {
zhihuang1c378ed2017-08-17 14:10:50 -07003683// Compare the two vectors of codecs ignoring the payload type.
3684template <class Codec>
3685bool CodecsMatch(const std::vector<Codec>& codecs1,
3686 const std::vector<Codec>& codecs2) {
3687 if (codecs1.size() != codecs2.size()) {
3688 return false;
3689 }
3690
3691 for (size_t i = 0; i < codecs1.size(); ++i) {
3692 if (!codecs1[i].Matches(codecs2[i])) {
3693 return false;
3694 }
3695 }
3696 return true;
3697}
3698
Steve Anton4e70a722017-11-28 14:57:10 -08003699void TestAudioCodecsOffer(RtpTransceiverDirection direction) {
ossu075af922016-06-14 03:29:38 -07003700 TransportDescriptionFactory tdf;
3701 MediaSessionDescriptionFactory sf(&tdf);
3702 const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
3703 const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
3704 const std::vector<AudioCodec> sendrecv_codecs =
3705 MAKE_VECTOR(kAudioCodecsAnswer);
3706 sf.set_audio_codecs(send_codecs, recv_codecs);
ossu075af922016-06-14 03:29:38 -07003707
3708 MediaSessionOptions opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003709 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", direction, kActive, &opts);
3710
Steve Anton4e70a722017-11-28 14:57:10 -08003711 if (direction == RtpTransceiverDirection::kSendRecv ||
3712 direction == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003713 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003714 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003715 }
ossu075af922016-06-14 03:29:38 -07003716
3717 std::unique_ptr<SessionDescription> offer(sf.CreateOffer(opts, NULL));
3718 ASSERT_TRUE(offer.get() != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08003719 ContentInfo* ac = offer->GetContentByName("audio");
ossu075af922016-06-14 03:29:38 -07003720
3721 // If the factory didn't add any audio content to the offer, we cannot check
zhihuang1c378ed2017-08-17 14:10:50 -07003722 // that the codecs put in are right. This happens when we neither want to
3723 // send nor receive audio. The checks are still in place if at some point
3724 // we'd instead create an inactive stream.
ossu075af922016-06-14 03:29:38 -07003725 if (ac) {
Steve Antonb1c1de12017-12-21 15:14:30 -08003726 AudioContentDescription* acd = ac->media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003727 // sendrecv and inactive should both present lists as if the channel was
3728 // to be used for sending and receiving. Inactive essentially means it
3729 // might eventually be used anything, but we don't know more at this
3730 // moment.
Steve Anton4e70a722017-11-28 14:57:10 -08003731 if (acd->direction() == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003732 EXPECT_TRUE(CodecsMatch<AudioCodec>(send_codecs, acd->codecs()));
Steve Anton4e70a722017-11-28 14:57:10 -08003733 } else if (acd->direction() == RtpTransceiverDirection::kRecvOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003734 EXPECT_TRUE(CodecsMatch<AudioCodec>(recv_codecs, acd->codecs()));
ossu075af922016-06-14 03:29:38 -07003735 } else {
zhihuang1c378ed2017-08-17 14:10:50 -07003736 EXPECT_TRUE(CodecsMatch<AudioCodec>(sendrecv_codecs, acd->codecs()));
ossu075af922016-06-14 03:29:38 -07003737 }
3738 }
3739}
3740
3741static const AudioCodec kOfferAnswerCodecs[] = {
zhihuang1c378ed2017-08-17 14:10:50 -07003742 AudioCodec(0, "codec0", 16000, -1, 1),
3743 AudioCodec(1, "codec1", 8000, 13300, 1),
3744 AudioCodec(2, "codec2", 8000, 64000, 1),
3745 AudioCodec(3, "codec3", 8000, 64000, 1),
3746 AudioCodec(4, "codec4", 8000, 0, 2),
3747 AudioCodec(5, "codec5", 32000, 0, 1),
3748 AudioCodec(6, "codec6", 48000, 0, 1)};
ossu075af922016-06-14 03:29:38 -07003749
zhihuang1c378ed2017-08-17 14:10:50 -07003750/* The codecs groups below are chosen as per the matrix below. The objective
3751 * is to have different sets of codecs in the inputs, to get unique sets of
3752 * codecs after negotiation, depending on offer and answer communication
3753 * directions. One-way directions in the offer should either result in the
3754 * opposite direction in the answer, or an inactive answer. Regardless, the
3755 * choice of codecs should be as if the answer contained the opposite
3756 * direction. Inactive offers should be treated as sendrecv/sendrecv.
ossu075af922016-06-14 03:29:38 -07003757 *
3758 * | Offer | Answer | Result
3759 * codec|send recv sr | send recv sr | s/r r/s sr/s sr/r sr/sr
3760 * 0 | x - - | - x - | x - - - -
3761 * 1 | x x x | - x - | x - - x -
3762 * 2 | - x - | x - - | - x - - -
3763 * 3 | x x x | x - - | - x x - -
3764 * 4 | - x - | x x x | - x - - -
3765 * 5 | x - - | x x x | x - - - -
3766 * 6 | x x x | x x x | x x x x x
3767 */
3768// Codecs used by offerer in the AudioCodecsAnswerTest
zhihuang1c378ed2017-08-17 14:10:50 -07003769static const int kOfferSendCodecs[] = {0, 1, 3, 5, 6};
3770static const int kOfferRecvCodecs[] = {1, 2, 3, 4, 6};
ossu075af922016-06-14 03:29:38 -07003771// Codecs used in the answerer in the AudioCodecsAnswerTest. The order is
3772// jumbled to catch the answer not following the order in the offer.
zhihuang1c378ed2017-08-17 14:10:50 -07003773static const int kAnswerSendCodecs[] = {6, 5, 2, 3, 4};
3774static const int kAnswerRecvCodecs[] = {6, 5, 4, 1, 0};
ossu075af922016-06-14 03:29:38 -07003775// The resulting sets of codecs in the answer in the AudioCodecsAnswerTest
zhihuang1c378ed2017-08-17 14:10:50 -07003776static const int kResultSend_RecvCodecs[] = {0, 1, 5, 6};
3777static const int kResultRecv_SendCodecs[] = {2, 3, 4, 6};
3778static const int kResultSendrecv_SendCodecs[] = {3, 6};
3779static const int kResultSendrecv_RecvCodecs[] = {1, 6};
3780static const int kResultSendrecv_SendrecvCodecs[] = {6};
ossu075af922016-06-14 03:29:38 -07003781
3782template <typename T, int IDXS>
3783std::vector<T> VectorFromIndices(const T* array, const int (&indices)[IDXS]) {
3784 std::vector<T> out;
3785 out.reserve(IDXS);
3786 for (int idx : indices)
3787 out.push_back(array[idx]);
3788
3789 return out;
3790}
3791
Steve Anton4e70a722017-11-28 14:57:10 -08003792void TestAudioCodecsAnswer(RtpTransceiverDirection offer_direction,
3793 RtpTransceiverDirection answer_direction,
ossu075af922016-06-14 03:29:38 -07003794 bool add_legacy_stream) {
3795 TransportDescriptionFactory offer_tdf;
3796 TransportDescriptionFactory answer_tdf;
3797 MediaSessionDescriptionFactory offer_factory(&offer_tdf);
3798 MediaSessionDescriptionFactory answer_factory(&answer_tdf);
3799 offer_factory.set_audio_codecs(
3800 VectorFromIndices(kOfferAnswerCodecs, kOfferSendCodecs),
3801 VectorFromIndices(kOfferAnswerCodecs, kOfferRecvCodecs));
3802 answer_factory.set_audio_codecs(
3803 VectorFromIndices(kOfferAnswerCodecs, kAnswerSendCodecs),
3804 VectorFromIndices(kOfferAnswerCodecs, kAnswerRecvCodecs));
3805
ossu075af922016-06-14 03:29:38 -07003806 MediaSessionOptions offer_opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003807 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", offer_direction, kActive,
3808 &offer_opts);
3809
Steve Anton4e70a722017-11-28 14:57:10 -08003810 if (webrtc::RtpTransceiverDirectionHasSend(offer_direction)) {
zhihuang1c378ed2017-08-17 14:10:50 -07003811 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003812 {kMediaStream1}, 1, &offer_opts);
ossu075af922016-06-14 03:29:38 -07003813 }
3814
3815 std::unique_ptr<SessionDescription> offer(
3816 offer_factory.CreateOffer(offer_opts, NULL));
3817 ASSERT_TRUE(offer.get() != NULL);
3818
3819 MediaSessionOptions answer_opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003820 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", answer_direction, kActive,
3821 &answer_opts);
3822
Steve Anton4e70a722017-11-28 14:57:10 -08003823 if (webrtc::RtpTransceiverDirectionHasSend(answer_direction)) {
zhihuang1c378ed2017-08-17 14:10:50 -07003824 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003825 {kMediaStream1}, 1, &answer_opts);
ossu075af922016-06-14 03:29:38 -07003826 }
3827 std::unique_ptr<SessionDescription> answer(
3828 answer_factory.CreateAnswer(offer.get(), answer_opts, NULL));
3829 const ContentInfo* ac = answer->GetContentByName("audio");
3830
zhihuang1c378ed2017-08-17 14:10:50 -07003831 // If the factory didn't add any audio content to the answer, we cannot
3832 // check that the codecs put in are right. This happens when we neither want
3833 // to send nor receive audio. The checks are still in place if at some point
3834 // we'd instead create an inactive stream.
ossu075af922016-06-14 03:29:38 -07003835 if (ac) {
Steve Antonb1c1de12017-12-21 15:14:30 -08003836 ASSERT_EQ(MEDIA_TYPE_AUDIO, ac->media_description()->type());
3837 const AudioContentDescription* acd = ac->media_description()->as_audio();
ossu075af922016-06-14 03:29:38 -07003838
ossu075af922016-06-14 03:29:38 -07003839 std::vector<AudioCodec> target_codecs;
3840 // For offers with sendrecv or inactive, we should never reply with more
3841 // codecs than offered, with these codec sets.
3842 switch (offer_direction) {
Steve Anton4e70a722017-11-28 14:57:10 -08003843 case RtpTransceiverDirection::kInactive:
ossu075af922016-06-14 03:29:38 -07003844 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3845 kResultSendrecv_SendrecvCodecs);
3846 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003847 case RtpTransceiverDirection::kSendOnly:
zhihuang1c378ed2017-08-17 14:10:50 -07003848 target_codecs =
3849 VectorFromIndices(kOfferAnswerCodecs, kResultSend_RecvCodecs);
ossu075af922016-06-14 03:29:38 -07003850 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003851 case RtpTransceiverDirection::kRecvOnly:
zhihuang1c378ed2017-08-17 14:10:50 -07003852 target_codecs =
3853 VectorFromIndices(kOfferAnswerCodecs, kResultRecv_SendCodecs);
ossu075af922016-06-14 03:29:38 -07003854 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003855 case RtpTransceiverDirection::kSendRecv:
3856 if (acd->direction() == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003857 target_codecs =
3858 VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_SendCodecs);
Steve Anton4e70a722017-11-28 14:57:10 -08003859 } else if (acd->direction() == RtpTransceiverDirection::kRecvOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003860 target_codecs =
3861 VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_RecvCodecs);
ossu075af922016-06-14 03:29:38 -07003862 } else {
3863 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3864 kResultSendrecv_SendrecvCodecs);
3865 }
3866 break;
3867 }
3868
zhihuang1c378ed2017-08-17 14:10:50 -07003869 auto format_codecs = [](const std::vector<AudioCodec>& codecs) {
Jonas Olsson366a50c2018-09-06 13:41:30 +02003870 rtc::StringBuilder os;
ossu075af922016-06-14 03:29:38 -07003871 bool first = true;
3872 os << "{";
3873 for (const auto& c : codecs) {
3874 os << (first ? " " : ", ") << c.id;
3875 first = false;
3876 }
3877 os << " }";
Jonas Olsson84df1c72018-09-14 16:59:32 +02003878 return os.Release();
ossu075af922016-06-14 03:29:38 -07003879 };
3880
3881 EXPECT_TRUE(acd->codecs() == target_codecs)
3882 << "Expected: " << format_codecs(target_codecs)
Steve Anton4e70a722017-11-28 14:57:10 -08003883 << ", got: " << format_codecs(acd->codecs()) << "; Offered: "
3884 << webrtc::RtpTransceiverDirectionToString(offer_direction)
ossu075af922016-06-14 03:29:38 -07003885 << ", answerer wants: "
Steve Anton4e70a722017-11-28 14:57:10 -08003886 << webrtc::RtpTransceiverDirectionToString(answer_direction)
3887 << "; got: "
3888 << webrtc::RtpTransceiverDirectionToString(acd->direction());
ossu075af922016-06-14 03:29:38 -07003889 } else {
Steve Anton4e70a722017-11-28 14:57:10 -08003890 EXPECT_EQ(offer_direction, RtpTransceiverDirection::kInactive)
zhihuang1c378ed2017-08-17 14:10:50 -07003891 << "Only inactive offers are allowed to not generate any audio "
3892 "content";
ossu075af922016-06-14 03:29:38 -07003893 }
3894}
brandtr03d5fb12016-11-22 03:37:59 -08003895
3896} // namespace
ossu075af922016-06-14 03:29:38 -07003897
3898class AudioCodecsOfferTest
Steve Anton4e70a722017-11-28 14:57:10 -08003899 : public ::testing::TestWithParam<RtpTransceiverDirection> {};
ossu075af922016-06-14 03:29:38 -07003900
3901TEST_P(AudioCodecsOfferTest, TestCodecsInOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07003902 TestAudioCodecsOffer(GetParam());
ossu075af922016-06-14 03:29:38 -07003903}
3904
3905INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
3906 AudioCodecsOfferTest,
Steve Anton4e70a722017-11-28 14:57:10 -08003907 ::testing::Values(RtpTransceiverDirection::kSendOnly,
3908 RtpTransceiverDirection::kRecvOnly,
3909 RtpTransceiverDirection::kSendRecv,
3910 RtpTransceiverDirection::kInactive));
ossu075af922016-06-14 03:29:38 -07003911
3912class AudioCodecsAnswerTest
Steve Anton4e70a722017-11-28 14:57:10 -08003913 : public ::testing::TestWithParam<::testing::tuple<RtpTransceiverDirection,
3914 RtpTransceiverDirection,
zhihuang1c378ed2017-08-17 14:10:50 -07003915 bool>> {};
ossu075af922016-06-14 03:29:38 -07003916
3917TEST_P(AudioCodecsAnswerTest, TestCodecsInAnswer) {
ehmaldonadoabcef5d2017-02-08 04:07:11 -08003918 TestAudioCodecsAnswer(::testing::get<0>(GetParam()),
3919 ::testing::get<1>(GetParam()),
3920 ::testing::get<2>(GetParam()));
ossu075af922016-06-14 03:29:38 -07003921}
3922
zhihuang1c378ed2017-08-17 14:10:50 -07003923INSTANTIATE_TEST_CASE_P(
3924 MediaSessionDescriptionFactoryTest,
3925 AudioCodecsAnswerTest,
Steve Anton4e70a722017-11-28 14:57:10 -08003926 ::testing::Combine(::testing::Values(RtpTransceiverDirection::kSendOnly,
3927 RtpTransceiverDirection::kRecvOnly,
3928 RtpTransceiverDirection::kSendRecv,
3929 RtpTransceiverDirection::kInactive),
3930 ::testing::Values(RtpTransceiverDirection::kSendOnly,
3931 RtpTransceiverDirection::kRecvOnly,
3932 RtpTransceiverDirection::kSendRecv,
3933 RtpTransceiverDirection::kInactive),
zhihuang1c378ed2017-08-17 14:10:50 -07003934 ::testing::Bool()));