blob: 269ad78a708361b288b6dcee585a6cb95076c935 [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"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000028
Yves Gerey665174f2018-06-19 15:03:05 +020029#define ASSERT_CRYPTO(cd, s, cs) \
30 ASSERT_EQ(s, cd->cryptos().size()); \
31 ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
henrike@webrtc.org28e20752013-07-10 00:45:36 +000032
33typedef std::vector<cricket::Candidate> Candidates;
34
35using cricket::MediaContentDescription;
36using cricket::MediaSessionDescriptionFactory;
zhihuang1c378ed2017-08-17 14:10:50 -070037using cricket::MediaDescriptionOptions;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000038using cricket::MediaSessionOptions;
39using cricket::MediaType;
Steve Anton5adfafd2017-12-20 16:34:00 -080040using cricket::MediaProtocolType;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000041using cricket::SessionDescription;
42using cricket::SsrcGroup;
43using cricket::StreamParams;
44using cricket::StreamParamsVec;
45using cricket::TransportDescription;
46using cricket::TransportDescriptionFactory;
47using cricket::TransportInfo;
48using cricket::ContentInfo;
49using cricket::CryptoParamsVec;
50using cricket::AudioContentDescription;
51using cricket::VideoContentDescription;
52using cricket::DataContentDescription;
deadbeef44f08192015-12-15 16:20:09 -080053using cricket::GetFirstAudioContent;
54using cricket::GetFirstVideoContent;
55using cricket::GetFirstDataContent;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000056using cricket::GetFirstAudioContentDescription;
57using cricket::GetFirstVideoContentDescription;
58using cricket::GetFirstDataContentDescription;
59using cricket::kAutoBandwidth;
60using cricket::AudioCodec;
61using cricket::VideoCodec;
62using cricket::DataCodec;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000063using cricket::MEDIA_TYPE_AUDIO;
64using cricket::MEDIA_TYPE_VIDEO;
65using cricket::MEDIA_TYPE_DATA;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066using cricket::SEC_DISABLED;
67using cricket::SEC_ENABLED;
68using cricket::SEC_REQUIRED;
Guo-wei Shieh456696a2015-09-30 21:48:54 -070069using rtc::CS_AES_CM_128_HMAC_SHA1_32;
70using rtc::CS_AES_CM_128_HMAC_SHA1_80;
jbauchcb560652016-08-04 05:20:32 -070071using rtc::CS_AEAD_AES_128_GCM;
72using rtc::CS_AEAD_AES_256_GCM;
isheriff6f8d6862016-05-26 11:24:55 -070073using webrtc::RtpExtension;
Steve Anton4e70a722017-11-28 14:57:10 -080074using webrtc::RtpTransceiverDirection;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075
76static const AudioCodec kAudioCodecs1[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070077 AudioCodec(103, "ISAC", 16000, -1, 1),
78 AudioCodec(102, "iLBC", 8000, 13300, 1),
79 AudioCodec(0, "PCMU", 8000, 64000, 1),
80 AudioCodec(8, "PCMA", 8000, 64000, 1),
81 AudioCodec(117, "red", 8000, 0, 1),
82 AudioCodec(107, "CN", 48000, 0, 1)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000083
84static const AudioCodec kAudioCodecs2[] = {
Henrik Lundinf8ed5612018-05-07 12:05:57 +020085 AudioCodec(126, "foo", 16000, 22000, 1),
deadbeef67cf2c12016-04-13 10:07:16 -070086 AudioCodec(0, "PCMU", 8000, 64000, 1),
87 AudioCodec(127, "iLBC", 8000, 13300, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000088};
89
90static const AudioCodec kAudioCodecsAnswer[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070091 AudioCodec(102, "iLBC", 8000, 13300, 1),
92 AudioCodec(0, "PCMU", 8000, 64000, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000093};
94
perkj26752742016-10-24 01:21:16 -070095static const VideoCodec kVideoCodecs1[] = {VideoCodec(96, "H264-SVC"),
96 VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097
zhihuang1c378ed2017-08-17 14:10:50 -070098static const VideoCodec kVideoCodecs1Reverse[] = {VideoCodec(97, "H264"),
99 VideoCodec(96, "H264-SVC")};
100
perkj26752742016-10-24 01:21:16 -0700101static const VideoCodec kVideoCodecs2[] = {VideoCodec(126, "H264"),
102 VideoCodec(127, "H263")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103
perkj26752742016-10-24 01:21:16 -0700104static const VideoCodec kVideoCodecsAnswer[] = {VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000105
deadbeef67cf2c12016-04-13 10:07:16 -0700106static const DataCodec kDataCodecs1[] = {DataCodec(98, "binary-data"),
107 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108
deadbeef67cf2c12016-04-13 10:07:16 -0700109static const DataCodec kDataCodecs2[] = {DataCodec(126, "binary-data"),
110 DataCodec(127, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000111
deadbeef67cf2c12016-04-13 10:07:16 -0700112static const DataCodec kDataCodecsAnswer[] = {DataCodec(98, "binary-data"),
113 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000114
isheriff6f8d6862016-05-26 11:24:55 -0700115static const RtpExtension kAudioRtpExtension1[] = {
116 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
117 RtpExtension("http://google.com/testing/audio_something", 10),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000118};
119
jbauch5869f502017-06-29 12:31:36 -0700120static const RtpExtension kAudioRtpExtensionEncrypted1[] = {
121 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
122 RtpExtension("http://google.com/testing/audio_something", 10),
123 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 12, true),
124};
125
isheriff6f8d6862016-05-26 11:24:55 -0700126static const RtpExtension kAudioRtpExtension2[] = {
127 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
128 RtpExtension("http://google.com/testing/audio_something_else", 8),
129 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000130};
131
isheriff6f8d6862016-05-26 11:24:55 -0700132static const RtpExtension kAudioRtpExtension3[] = {
133 RtpExtension("http://google.com/testing/audio_something", 2),
134 RtpExtension("http://google.com/testing/both_audio_and_video", 3),
deadbeefa5b273a2015-08-20 17:30:13 -0700135};
136
jbauch5869f502017-06-29 12:31:36 -0700137static const RtpExtension kAudioRtpExtension3ForEncryption[] = {
138 RtpExtension("http://google.com/testing/audio_something", 2),
139 // Use RTP extension that supports encryption.
140 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 3),
141};
142
143static const RtpExtension kAudioRtpExtension3ForEncryptionOffer[] = {
144 RtpExtension("http://google.com/testing/audio_something", 2),
145 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 3),
146 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14, true),
147};
148
isheriff6f8d6862016-05-26 11:24:55 -0700149static const RtpExtension kAudioRtpExtensionAnswer[] = {
150 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000151};
152
jbauch5869f502017-06-29 12:31:36 -0700153static const RtpExtension kAudioRtpExtensionEncryptedAnswer[] = {
154 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 12, true),
155};
156
isheriff6f8d6862016-05-26 11:24:55 -0700157static const RtpExtension kVideoRtpExtension1[] = {
158 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
159 RtpExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000160};
161
jbauch5869f502017-06-29 12:31:36 -0700162static const RtpExtension kVideoRtpExtensionEncrypted1[] = {
163 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
164 RtpExtension("http://google.com/testing/video_something", 13),
165 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 11, true),
166};
167
isheriff6f8d6862016-05-26 11:24:55 -0700168static const RtpExtension kVideoRtpExtension2[] = {
169 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
170 RtpExtension("http://google.com/testing/video_something_else", 14),
171 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000172};
173
isheriff6f8d6862016-05-26 11:24:55 -0700174static const RtpExtension kVideoRtpExtension3[] = {
175 RtpExtension("http://google.com/testing/video_something", 4),
176 RtpExtension("http://google.com/testing/both_audio_and_video", 5),
deadbeefa5b273a2015-08-20 17:30:13 -0700177};
178
jbauch5869f502017-06-29 12:31:36 -0700179static const RtpExtension kVideoRtpExtension3ForEncryption[] = {
180 RtpExtension("http://google.com/testing/video_something", 4),
181 // Use RTP extension that supports encryption.
182 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 5),
183};
184
isheriff6f8d6862016-05-26 11:24:55 -0700185static const RtpExtension kVideoRtpExtensionAnswer[] = {
186 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000187};
188
jbauch5869f502017-06-29 12:31:36 -0700189static const RtpExtension kVideoRtpExtensionEncryptedAnswer[] = {
190 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 11, true),
191};
192
Peter Boström0c4e06b2015-10-07 12:23:21 +0200193static const uint32_t kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
194static const uint32_t kSimSsrc[] = {10, 20, 30};
195static const uint32_t kFec1Ssrc[] = {10, 11};
196static const uint32_t kFec2Ssrc[] = {20, 21};
197static const uint32_t kFec3Ssrc[] = {30, 31};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000198
199static const char kMediaStream1[] = "stream_1";
200static const char kMediaStream2[] = "stream_2";
201static const char kVideoTrack1[] = "video_1";
202static const char kVideoTrack2[] = "video_2";
203static const char kAudioTrack1[] = "audio_1";
204static const char kAudioTrack2[] = "audio_2";
205static const char kAudioTrack3[] = "audio_3";
206static const char kDataTrack1[] = "data_1";
207static const char kDataTrack2[] = "data_2";
208static const char kDataTrack3[] = "data_3";
209
zhihuangcf5b37c2016-05-05 11:44:35 -0700210static const char* kMediaProtocols[] = {"RTP/AVP", "RTP/SAVP", "RTP/AVPF",
211 "RTP/SAVPF"};
212static const char* kMediaProtocolsDtls[] = {
213 "TCP/TLS/RTP/SAVPF", "TCP/TLS/RTP/SAVP", "UDP/TLS/RTP/SAVPF",
214 "UDP/TLS/RTP/SAVP"};
215
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700216// SRTP cipher name negotiated by the tests. This must be updated if the
217// default changes.
218static const char* kDefaultSrtpCryptoSuite = CS_AES_CM_128_HMAC_SHA1_80;
219static const char* kDefaultSrtpCryptoSuiteGcm = CS_AEAD_AES_256_GCM;
220
zhihuang1c378ed2017-08-17 14:10:50 -0700221// These constants are used to make the code using "AddMediaSection" more
222// readable.
223static constexpr bool kStopped = true;
224static constexpr bool kActive = false;
225
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000226static bool IsMediaContentOfType(const ContentInfo* content,
227 MediaType media_type) {
Steve Antonb1c1de12017-12-21 15:14:30 -0800228 RTC_DCHECK(content);
229 return content->media_description()->type() == media_type;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000230}
231
Steve Anton4e70a722017-11-28 14:57:10 -0800232static RtpTransceiverDirection GetMediaDirection(const ContentInfo* content) {
Steve Antonb1c1de12017-12-21 15:14:30 -0800233 RTC_DCHECK(content);
234 return content->media_description()->direction();
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000235}
236
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000237static void AddRtxCodec(const VideoCodec& rtx_codec,
238 std::vector<VideoCodec>* codecs) {
magjedb05fa242016-11-11 04:00:16 -0800239 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000240 codecs->push_back(rtx_codec);
241}
242
243template <class T>
244static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
245 std::vector<std::string> codec_names;
246 for (const auto& codec : codecs) {
247 codec_names.push_back(codec.name);
248 }
249 return codec_names;
250}
251
zhihuang1c378ed2017-08-17 14:10:50 -0700252// This is used for test only. MIDs are not the identification of the
253// MediaDescriptionOptions since some end points may not support MID and the SDP
254// may not contain 'mid'.
255std::vector<MediaDescriptionOptions>::iterator FindFirstMediaDescriptionByMid(
256 const std::string& mid,
257 MediaSessionOptions* opts) {
258 return std::find_if(
259 opts->media_description_options.begin(),
260 opts->media_description_options.end(),
Steve Anton36b29d12017-10-30 09:57:42 -0700261 [&mid](const MediaDescriptionOptions& t) { return t.mid == mid; });
262}
263
264std::vector<MediaDescriptionOptions>::const_iterator
265FindFirstMediaDescriptionByMid(const std::string& mid,
266 const MediaSessionOptions& opts) {
267 return std::find_if(
268 opts.media_description_options.begin(),
269 opts.media_description_options.end(),
270 [&mid](const MediaDescriptionOptions& t) { return t.mid == mid; });
zhihuang1c378ed2017-08-17 14:10:50 -0700271}
272
273// Add a media section to the |session_options|.
274static void AddMediaSection(MediaType type,
275 const std::string& mid,
Steve Anton4e70a722017-11-28 14:57:10 -0800276 RtpTransceiverDirection direction,
zhihuang1c378ed2017-08-17 14:10:50 -0700277 bool stopped,
278 MediaSessionOptions* opts) {
Steve Anton4e70a722017-11-28 14:57:10 -0800279 opts->media_description_options.push_back(
280 MediaDescriptionOptions(type, mid, direction, stopped));
zhihuang1c378ed2017-08-17 14:10:50 -0700281}
282
Steve Anton4e70a722017-11-28 14:57:10 -0800283static void AddAudioVideoSections(RtpTransceiverDirection direction,
zhihuang1c378ed2017-08-17 14:10:50 -0700284 MediaSessionOptions* opts) {
285 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", direction, kActive, opts);
286 AddMediaSection(MEDIA_TYPE_VIDEO, "video", direction, kActive, opts);
287}
288
289static void AddDataSection(cricket::DataChannelType dct,
Steve Anton4e70a722017-11-28 14:57:10 -0800290 RtpTransceiverDirection direction,
zhihuang1c378ed2017-08-17 14:10:50 -0700291 MediaSessionOptions* opts) {
292 opts->data_channel_type = dct;
293 AddMediaSection(MEDIA_TYPE_DATA, "data", direction, kActive, opts);
294}
295
Steve Anton8ffb9c32017-08-31 15:45:38 -0700296static void AttachSenderToMediaSection(
297 const std::string& mid,
298 MediaType type,
299 const std::string& track_id,
300 const std::vector<std::string>& stream_ids,
301 int num_sim_layer,
302 MediaSessionOptions* session_options) {
zhihuang1c378ed2017-08-17 14:10:50 -0700303 auto it = FindFirstMediaDescriptionByMid(mid, session_options);
304 switch (type) {
305 case MEDIA_TYPE_AUDIO:
Steve Anton8ffb9c32017-08-31 15:45:38 -0700306 it->AddAudioSender(track_id, stream_ids);
zhihuang1c378ed2017-08-17 14:10:50 -0700307 break;
308 case MEDIA_TYPE_VIDEO:
Steve Anton8ffb9c32017-08-31 15:45:38 -0700309 it->AddVideoSender(track_id, stream_ids, num_sim_layer);
zhihuang1c378ed2017-08-17 14:10:50 -0700310 break;
311 case MEDIA_TYPE_DATA:
Steve Anton8ffb9c32017-08-31 15:45:38 -0700312 RTC_CHECK(stream_ids.size() == 1U);
313 it->AddRtpDataChannel(track_id, stream_ids[0]);
zhihuang1c378ed2017-08-17 14:10:50 -0700314 break;
315 default:
316 RTC_NOTREACHED();
317 }
318}
319
320static void DetachSenderFromMediaSection(const std::string& mid,
321 const std::string& track_id,
322 MediaSessionOptions* session_options) {
323 auto it = FindFirstMediaDescriptionByMid(mid, session_options);
324 auto sender_it = it->sender_options.begin();
325 for (; sender_it != it->sender_options.end(); ++sender_it) {
326 if (sender_it->track_id == track_id) {
327 it->sender_options.erase(sender_it);
328 return;
329 }
330 }
331 RTC_NOTREACHED();
332}
333
334// Helper function used to create a default MediaSessionOptions for Plan B SDP.
335// (https://tools.ietf.org/html/draft-uberti-rtcweb-plan-00).
336static MediaSessionOptions CreatePlanBMediaSessionOptions() {
337 MediaSessionOptions session_options;
Steve Anton4e70a722017-11-28 14:57:10 -0800338 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
339 kActive, &session_options);
zhihuang1c378ed2017-08-17 14:10:50 -0700340 return session_options;
341}
342
343// TODO(zhihuang): Most of these tests were written while MediaSessionOptions
344// was designed for Plan B SDP, where only one audio "m=" section and one video
345// "m=" section could be generated, and ordering couldn't be controlled. Many of
346// these tests may be obsolete as a result, and should be refactored or removed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000347class MediaSessionDescriptionFactoryTest : public testing::Test {
348 public:
zhihuang1c378ed2017-08-17 14:10:50 -0700349 MediaSessionDescriptionFactoryTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -0700350 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
351 MAKE_VECTOR(kAudioCodecs1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000352 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
353 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -0700354 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
355 MAKE_VECTOR(kAudioCodecs2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000356 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
357 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200358 tdf1_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700359 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200360 tdf2_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700361 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000362 }
363
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000364 // Create a video StreamParamsVec object with:
365 // - one video stream with 3 simulcast streams and FEC,
366 StreamParamsVec CreateComplexVideoStreamParamsVec() {
367 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
368 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
369 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
370 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
371
372 std::vector<SsrcGroup> ssrc_groups;
373 ssrc_groups.push_back(sim_group);
374 ssrc_groups.push_back(fec_group1);
375 ssrc_groups.push_back(fec_group2);
376 ssrc_groups.push_back(fec_group3);
377
378 StreamParams simulcast_params;
379 simulcast_params.id = kVideoTrack1;
380 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
381 simulcast_params.ssrc_groups = ssrc_groups;
382 simulcast_params.cname = "Video_SIM_FEC";
Seth Hampson845e8782018-03-02 11:34:10 -0800383 simulcast_params.set_stream_ids({kMediaStream1});
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000384
385 StreamParamsVec video_streams;
386 video_streams.push_back(simulcast_params);
387
388 return video_streams;
389 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000390
391 bool CompareCryptoParams(const CryptoParamsVec& c1,
392 const CryptoParamsVec& c2) {
393 if (c1.size() != c2.size())
394 return false;
395 for (size_t i = 0; i < c1.size(); ++i)
396 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
397 c1[i].key_params != c2[i].key_params ||
398 c1[i].session_params != c2[i].session_params)
399 return false;
400 return true;
401 }
402
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700403 // Returns true if the transport info contains "renomination" as an
404 // ICE option.
405 bool GetIceRenomination(const TransportInfo* transport_info) {
406 const std::vector<std::string>& ice_options =
407 transport_info->description.transport_options;
deadbeef30952b42017-04-21 02:41:29 -0700408 auto iter =
409 std::find(ice_options.begin(), ice_options.end(), "renomination");
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700410 return iter != ice_options.end();
411 }
412
zhihuang1c378ed2017-08-17 14:10:50 -0700413 void TestTransportInfo(bool offer,
Steve Anton36b29d12017-10-30 09:57:42 -0700414 const MediaSessionOptions& options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000415 bool has_current_desc) {
416 const std::string current_audio_ufrag = "current_audio_ufrag";
417 const std::string current_audio_pwd = "current_audio_pwd";
418 const std::string current_video_ufrag = "current_video_ufrag";
419 const std::string current_video_pwd = "current_video_pwd";
420 const std::string current_data_ufrag = "current_data_ufrag";
421 const std::string current_data_pwd = "current_data_pwd";
kwiberg31022942016-03-11 14:18:21 -0800422 std::unique_ptr<SessionDescription> current_desc;
423 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000424 if (has_current_desc) {
425 current_desc.reset(new SessionDescription());
Yves Gerey665174f2018-06-19 15:03:05 +0200426 EXPECT_TRUE(current_desc->AddTransportInfo(TransportInfo(
427 "audio",
428 TransportDescription(current_audio_ufrag, current_audio_pwd))));
429 EXPECT_TRUE(current_desc->AddTransportInfo(TransportInfo(
430 "video",
431 TransportDescription(current_video_ufrag, current_video_pwd))));
432 EXPECT_TRUE(current_desc->AddTransportInfo(TransportInfo(
433 "data", TransportDescription(current_data_ufrag, current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000434 }
435 if (offer) {
436 desc.reset(f1_.CreateOffer(options, current_desc.get()));
437 } else {
kwiberg31022942016-03-11 14:18:21 -0800438 std::unique_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000439 offer.reset(f1_.CreateOffer(options, NULL));
440 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
441 }
442 ASSERT_TRUE(desc.get() != NULL);
443 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000444 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000445 EXPECT_TRUE(ti_audio != NULL);
446 if (has_current_desc) {
447 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
448 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
449 } else {
450 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
451 ti_audio->description.ice_ufrag.size());
452 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
453 ti_audio->description.ice_pwd.size());
454 }
zhihuang1c378ed2017-08-17 14:10:50 -0700455 auto media_desc_options_it =
Steve Anton36b29d12017-10-30 09:57:42 -0700456 FindFirstMediaDescriptionByMid("audio", options);
zhihuang1c378ed2017-08-17 14:10:50 -0700457 EXPECT_EQ(
458 media_desc_options_it->transport_options.enable_ice_renomination,
459 GetIceRenomination(ti_audio));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000460
461 } else {
462 EXPECT_TRUE(ti_audio == NULL);
463 }
464 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000465 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000466 EXPECT_TRUE(ti_video != NULL);
467 if (options.bundle_enabled) {
468 EXPECT_EQ(ti_audio->description.ice_ufrag,
469 ti_video->description.ice_ufrag);
Yves Gerey665174f2018-06-19 15:03:05 +0200470 EXPECT_EQ(ti_audio->description.ice_pwd, ti_video->description.ice_pwd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000471 } else {
472 if (has_current_desc) {
473 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
474 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
475 } else {
476 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
477 ti_video->description.ice_ufrag.size());
478 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
479 ti_video->description.ice_pwd.size());
480 }
481 }
zhihuang1c378ed2017-08-17 14:10:50 -0700482 auto media_desc_options_it =
Steve Anton36b29d12017-10-30 09:57:42 -0700483 FindFirstMediaDescriptionByMid("video", options);
zhihuang1c378ed2017-08-17 14:10:50 -0700484 EXPECT_EQ(
485 media_desc_options_it->transport_options.enable_ice_renomination,
486 GetIceRenomination(ti_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000487 } else {
488 EXPECT_TRUE(ti_video == NULL);
489 }
490 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
491 if (options.has_data()) {
492 EXPECT_TRUE(ti_data != NULL);
493 if (options.bundle_enabled) {
494 EXPECT_EQ(ti_audio->description.ice_ufrag,
495 ti_data->description.ice_ufrag);
Yves Gerey665174f2018-06-19 15:03:05 +0200496 EXPECT_EQ(ti_audio->description.ice_pwd, ti_data->description.ice_pwd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000497 } else {
498 if (has_current_desc) {
499 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
500 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
501 } else {
502 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
503 ti_data->description.ice_ufrag.size());
504 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
505 ti_data->description.ice_pwd.size());
506 }
507 }
zhihuang1c378ed2017-08-17 14:10:50 -0700508 auto media_desc_options_it =
Steve Anton36b29d12017-10-30 09:57:42 -0700509 FindFirstMediaDescriptionByMid("data", options);
zhihuang1c378ed2017-08-17 14:10:50 -0700510 EXPECT_EQ(
511 media_desc_options_it->transport_options.enable_ice_renomination,
512 GetIceRenomination(ti_data));
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700513
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000514 } else {
515 EXPECT_TRUE(ti_video == NULL);
516 }
517 }
518
519 void TestCryptoWithBundle(bool offer) {
520 f1_.set_secure(SEC_ENABLED);
521 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -0800522 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
523 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
524 &options);
kwiberg31022942016-03-11 14:18:21 -0800525 std::unique_ptr<SessionDescription> ref_desc;
526 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000527 if (offer) {
528 options.bundle_enabled = false;
529 ref_desc.reset(f1_.CreateOffer(options, NULL));
530 options.bundle_enabled = true;
531 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
532 } else {
533 options.bundle_enabled = true;
534 ref_desc.reset(f1_.CreateOffer(options, NULL));
535 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
536 }
Steve Antonb1c1de12017-12-21 15:14:30 -0800537 ASSERT_TRUE(desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000538 const cricket::MediaContentDescription* audio_media_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -0800539 desc->GetContentDescriptionByName("audio");
540 ASSERT_TRUE(audio_media_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000541 const cricket::MediaContentDescription* video_media_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -0800542 desc->GetContentDescriptionByName("video");
543 ASSERT_TRUE(video_media_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000544 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
545 video_media_desc->cryptos()));
546 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700547 EXPECT_EQ(std::string(kDefaultSrtpCryptoSuite),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000548 audio_media_desc->cryptos()[0].cipher_suite);
549
550 // Verify the selected crypto is one from the reference audio
551 // media content.
552 const cricket::MediaContentDescription* ref_audio_media_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -0800553 ref_desc->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000554 bool found = false;
555 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
556 if (ref_audio_media_desc->cryptos()[i].Matches(
Yves Gerey665174f2018-06-19 15:03:05 +0200557 audio_media_desc->cryptos()[0])) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000558 found = true;
559 break;
560 }
561 }
562 EXPECT_TRUE(found);
563 }
564
565 // This test that the audio and video media direction is set to
566 // |expected_direction_in_answer| in an answer if the offer direction is set
zhihuang1c378ed2017-08-17 14:10:50 -0700567 // to |direction_in_offer| and the answer is willing to both send and receive.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000568 void TestMediaDirectionInAnswer(
Steve Anton4e70a722017-11-28 14:57:10 -0800569 RtpTransceiverDirection direction_in_offer,
570 RtpTransceiverDirection expected_direction_in_answer) {
zhihuang1c378ed2017-08-17 14:10:50 -0700571 MediaSessionOptions offer_opts;
572 AddAudioVideoSections(direction_in_offer, &offer_opts);
573
574 std::unique_ptr<SessionDescription> offer(
575 f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000576 ASSERT_TRUE(offer.get() != NULL);
terelius8c011e52016-04-26 05:28:11 -0700577 ContentInfo* ac_offer = offer->GetContentByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000578 ASSERT_TRUE(ac_offer != NULL);
terelius8c011e52016-04-26 05:28:11 -0700579 ContentInfo* vc_offer = offer->GetContentByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000580 ASSERT_TRUE(vc_offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000581
zhihuang1c378ed2017-08-17 14:10:50 -0700582 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800583 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &answer_opts);
kwiberg31022942016-03-11 14:18:21 -0800584 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -0700585 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000586 const AudioContentDescription* acd_answer =
587 GetFirstAudioContentDescription(answer.get());
588 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
589 const VideoContentDescription* vcd_answer =
590 GetFirstVideoContentDescription(answer.get());
591 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
592 }
593
594 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
Steve Antonb1c1de12017-12-21 15:14:30 -0800595 RTC_DCHECK(content);
596 RTC_CHECK(content->media_description());
597 const cricket::AudioContentDescription* audio_desc =
598 content->media_description()->as_audio();
599 RTC_CHECK(audio_desc);
600 for (const cricket::AudioCodec& codec : audio_desc->codecs()) {
601 if (codec.name == "CN") {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000602 return false;
Steve Antonb1c1de12017-12-21 15:14:30 -0800603 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000604 }
605 return true;
606 }
607
jbauchcb560652016-08-04 05:20:32 -0700608 void TestVideoGcmCipher(bool gcm_offer, bool gcm_answer) {
609 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800610 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &offer_opts);
jbauchcb560652016-08-04 05:20:32 -0700611 offer_opts.crypto_options.enable_gcm_crypto_suites = gcm_offer;
zhihuang1c378ed2017-08-17 14:10:50 -0700612
jbauchcb560652016-08-04 05:20:32 -0700613 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800614 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &answer_opts);
jbauchcb560652016-08-04 05:20:32 -0700615 answer_opts.crypto_options.enable_gcm_crypto_suites = gcm_answer;
zhihuang1c378ed2017-08-17 14:10:50 -0700616
jbauchcb560652016-08-04 05:20:32 -0700617 f1_.set_secure(SEC_ENABLED);
618 f2_.set_secure(SEC_ENABLED);
619 std::unique_ptr<SessionDescription> offer(
620 f1_.CreateOffer(offer_opts, NULL));
621 ASSERT_TRUE(offer.get() != NULL);
622 std::unique_ptr<SessionDescription> answer(
623 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
624 const ContentInfo* ac = answer->GetContentByName("audio");
625 const ContentInfo* vc = answer->GetContentByName("video");
626 ASSERT_TRUE(ac != NULL);
627 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800628 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
629 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800630 const AudioContentDescription* acd = ac->media_description()->as_audio();
631 const VideoContentDescription* vcd = vc->media_description()->as_video();
jbauchcb560652016-08-04 05:20:32 -0700632 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
633 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
634 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -0700635 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -0700636 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
637 if (gcm_offer && gcm_answer) {
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700638 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
jbauchcb560652016-08-04 05:20:32 -0700639 } else {
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700640 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
jbauchcb560652016-08-04 05:20:32 -0700641 }
642 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
643 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
Yves Gerey665174f2018-06-19 15:03:05 +0200644 EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
645 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
jbauchcb560652016-08-04 05:20:32 -0700646 if (gcm_offer && gcm_answer) {
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700647 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuiteGcm);
jbauchcb560652016-08-04 05:20:32 -0700648 } else {
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700649 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
jbauchcb560652016-08-04 05:20:32 -0700650 }
651 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
652 }
653
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000654 protected:
655 MediaSessionDescriptionFactory f1_;
656 MediaSessionDescriptionFactory f2_;
657 TransportDescriptionFactory tdf1_;
658 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000659};
660
661// Create a typical audio offer, and ensure it matches what we expect.
662TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
663 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800664 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -0700665 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666 ASSERT_TRUE(offer.get() != NULL);
667 const ContentInfo* ac = offer->GetContentByName("audio");
668 const ContentInfo* vc = offer->GetContentByName("video");
669 ASSERT_TRUE(ac != NULL);
670 ASSERT_TRUE(vc == NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800671 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800672 const AudioContentDescription* acd = ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000673 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700674 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700675 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000676 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
677 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700678 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
680}
681
682// Create a typical video offer, and ensure it matches what we expect.
683TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
684 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800685 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000686 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800687 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000688 ASSERT_TRUE(offer.get() != NULL);
689 const ContentInfo* ac = offer->GetContentByName("audio");
690 const ContentInfo* vc = offer->GetContentByName("video");
691 ASSERT_TRUE(ac != NULL);
692 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800693 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
694 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800695 const AudioContentDescription* acd = ac->media_description()->as_audio();
696 const VideoContentDescription* vcd = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000697 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700698 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700699 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000700 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
701 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700702 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000703 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
704 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
705 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700706 EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000707 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
708 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700709 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000710 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
711}
712
713// Test creating an offer with bundle where the Codecs have the same dynamic
714// RTP playlod type. The test verifies that the offer don't contain the
715// duplicate RTP payload types.
716TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
717 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
ossudedfd282016-06-14 07:12:39 -0700718 const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000719 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
720 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
721 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
722
723 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800724 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
725 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000726 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800727 std::unique_ptr<SessionDescription> offer(f2_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000728 const VideoContentDescription* vcd =
729 GetFirstVideoContentDescription(offer.get());
730 const AudioContentDescription* acd =
731 GetFirstAudioContentDescription(offer.get());
732 const DataContentDescription* dcd =
733 GetFirstDataContentDescription(offer.get());
734 ASSERT_TRUE(NULL != vcd);
735 ASSERT_TRUE(NULL != acd);
736 ASSERT_TRUE(NULL != dcd);
737 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
738 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
739 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
740 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
741 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
742 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
743}
744
zhihuang1c378ed2017-08-17 14:10:50 -0700745// Test creating an updated offer with bundle, audio, video and data
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000746// after an audio only session has been negotiated.
747TEST_F(MediaSessionDescriptionFactoryTest,
748 TestCreateUpdatedVideoOfferWithBundle) {
749 f1_.set_secure(SEC_ENABLED);
750 f2_.set_secure(SEC_ENABLED);
751 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800752 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
753 kActive, &opts);
754 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kInactive,
755 kStopped, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000756 opts.data_channel_type = cricket::DCT_NONE;
757 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800758 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
759 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000760 f2_.CreateAnswer(offer.get(), opts, NULL));
761
762 MediaSessionOptions updated_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800763 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &updated_opts);
764 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
765 &updated_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000766 updated_opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800767 std::unique_ptr<SessionDescription> updated_offer(
768 f1_.CreateOffer(updated_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000769
770 const AudioContentDescription* acd =
771 GetFirstAudioContentDescription(updated_offer.get());
772 const VideoContentDescription* vcd =
773 GetFirstVideoContentDescription(updated_offer.get());
774 const DataContentDescription* dcd =
775 GetFirstDataContentDescription(updated_offer.get());
776 EXPECT_TRUE(NULL != vcd);
777 EXPECT_TRUE(NULL != acd);
778 EXPECT_TRUE(NULL != dcd);
779
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700780 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000781 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700782 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000783 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700784 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000785 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
786}
deadbeef44f08192015-12-15 16:20:09 -0800787
wu@webrtc.org78187522013-10-07 23:32:02 +0000788// Create a RTP data offer, and ensure it matches what we expect.
789TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000790 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800791 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
792 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000793 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800794 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000795 ASSERT_TRUE(offer.get() != NULL);
796 const ContentInfo* ac = offer->GetContentByName("audio");
797 const ContentInfo* dc = offer->GetContentByName("data");
798 ASSERT_TRUE(ac != NULL);
799 ASSERT_TRUE(dc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800800 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
801 EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800802 const AudioContentDescription* acd = ac->media_description()->as_audio();
803 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000804 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700805 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700806 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attched.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000807 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
808 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700809 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000810 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
811 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
812 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700813 EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000814 EXPECT_EQ(cricket::kDataMaxBandwidth,
Yves Gerey665174f2018-06-19 15:03:05 +0200815 dcd->bandwidth()); // default bandwidth (auto)
816 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700817 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000818 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
819}
820
wu@webrtc.org78187522013-10-07 23:32:02 +0000821// Create an SCTP data offer with bundle without error.
822TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
823 MediaSessionOptions opts;
wu@webrtc.org78187522013-10-07 23:32:02 +0000824 opts.bundle_enabled = true;
Steve Anton4e70a722017-11-28 14:57:10 -0800825 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
wu@webrtc.org78187522013-10-07 23:32:02 +0000826 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800827 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000828 EXPECT_TRUE(offer.get() != NULL);
829 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
830}
831
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000832// Test creating an sctp data channel from an already generated offer.
833TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
834 MediaSessionOptions opts;
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000835 opts.bundle_enabled = true;
Steve Anton4e70a722017-11-28 14:57:10 -0800836 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000837 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800838 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000839 ASSERT_TRUE(offer1.get() != NULL);
840 const ContentInfo* data = offer1->GetContentByName("data");
841 ASSERT_TRUE(data != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -0800842 ASSERT_EQ(cricket::kMediaProtocolSctp, data->media_description()->protocol());
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000843
844 // Now set data_channel_type to 'none' (default) and make sure that the
845 // datachannel type that gets generated from the previous offer, is of the
846 // same type.
847 opts.data_channel_type = cricket::DCT_NONE;
kwiberg31022942016-03-11 14:18:21 -0800848 std::unique_ptr<SessionDescription> offer2(
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000849 f1_.CreateOffer(opts, offer1.get()));
850 data = offer2->GetContentByName("data");
851 ASSERT_TRUE(data != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -0800852 EXPECT_EQ(cricket::kMediaProtocolSctp, data->media_description()->protocol());
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000853}
854
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000855// Create an audio, video offer without legacy StreamParams.
856TEST_F(MediaSessionDescriptionFactoryTest,
857 TestCreateOfferWithoutLegacyStreams) {
858 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800859 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
kwiberg31022942016-03-11 14:18:21 -0800860 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861 ASSERT_TRUE(offer.get() != NULL);
862 const ContentInfo* ac = offer->GetContentByName("audio");
863 const ContentInfo* vc = offer->GetContentByName("video");
864 ASSERT_TRUE(ac != NULL);
865 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -0800866 const AudioContentDescription* acd = ac->media_description()->as_audio();
867 const VideoContentDescription* vcd = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000868
Yves Gerey665174f2018-06-19 15:03:05 +0200869 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
870 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000871}
872
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000873// Creates an audio+video sendonly offer.
874TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -0700875 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800876 AddAudioVideoSections(RtpTransceiverDirection::kSendOnly, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -0700877 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -0700878 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -0700879 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -0700880 {kMediaStream1}, 1, &opts);
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000881
zhihuang1c378ed2017-08-17 14:10:50 -0700882 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000883 ASSERT_TRUE(offer.get() != NULL);
884 EXPECT_EQ(2u, offer->contents().size());
885 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
886 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
887
Steve Anton4e70a722017-11-28 14:57:10 -0800888 EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
889 GetMediaDirection(&offer->contents()[0]));
890 EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
891 GetMediaDirection(&offer->contents()[1]));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000892}
893
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000894// Verifies that the order of the media contents in the current
895// SessionDescription is preserved in the new SessionDescription.
896TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
897 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800898 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000899
kwiberg31022942016-03-11 14:18:21 -0800900 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000901 ASSERT_TRUE(offer1.get() != NULL);
902 EXPECT_EQ(1u, offer1->contents().size());
903 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
904
Steve Anton4e70a722017-11-28 14:57:10 -0800905 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
906 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -0800907 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000908 f1_.CreateOffer(opts, offer1.get()));
909 ASSERT_TRUE(offer2.get() != NULL);
910 EXPECT_EQ(2u, offer2->contents().size());
911 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
912 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
913
Steve Anton4e70a722017-11-28 14:57:10 -0800914 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
915 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -0800916 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000917 f1_.CreateOffer(opts, offer2.get()));
918 ASSERT_TRUE(offer3.get() != NULL);
919 EXPECT_EQ(3u, offer3->contents().size());
920 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
921 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
922 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000923}
924
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000925// Create a typical audio answer, and ensure it matches what we expect.
926TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
927 f1_.set_secure(SEC_ENABLED);
928 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800929 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -0700930 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000931 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800932 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -0700933 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000934 const ContentInfo* ac = answer->GetContentByName("audio");
935 const ContentInfo* vc = answer->GetContentByName("video");
936 ASSERT_TRUE(ac != NULL);
937 ASSERT_TRUE(vc == NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800938 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800939 const AudioContentDescription* acd = ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000940 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
941 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700942 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000943 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
944 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700945 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000946 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
947}
948
jbauchcb560652016-08-04 05:20:32 -0700949// Create a typical audio answer with GCM ciphers enabled, and ensure it
950// matches what we expect.
951TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
952 f1_.set_secure(SEC_ENABLED);
953 f2_.set_secure(SEC_ENABLED);
zhihuang1c378ed2017-08-17 14:10:50 -0700954 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
955 opts.crypto_options.enable_gcm_crypto_suites = true;
956 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
jbauchcb560652016-08-04 05:20:32 -0700957 ASSERT_TRUE(offer.get() != NULL);
958 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -0700959 f2_.CreateAnswer(offer.get(), opts, NULL));
jbauchcb560652016-08-04 05:20:32 -0700960 const ContentInfo* ac = answer->GetContentByName("audio");
961 const ContentInfo* vc = answer->GetContentByName("video");
962 ASSERT_TRUE(ac != NULL);
963 ASSERT_TRUE(vc == NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800964 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800965 const AudioContentDescription* acd = ac->media_description()->as_audio();
jbauchcb560652016-08-04 05:20:32 -0700966 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
967 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700968 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -0700969 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
970 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700971 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
jbauchcb560652016-08-04 05:20:32 -0700972 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
973}
974
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000975// Create a typical video answer, and ensure it matches what we expect.
976TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
977 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800978 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000979 f1_.set_secure(SEC_ENABLED);
980 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800981 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000982 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800983 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000984 f2_.CreateAnswer(offer.get(), opts, NULL));
985 const ContentInfo* ac = answer->GetContentByName("audio");
986 const ContentInfo* vc = answer->GetContentByName("video");
987 ASSERT_TRUE(ac != NULL);
988 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800989 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
990 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -0800991 const AudioContentDescription* acd = ac->media_description()->as_audio();
992 const VideoContentDescription* vcd = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000993 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
994 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
995 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -0700996 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000997 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -0700998 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000999 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1000 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
Yves Gerey665174f2018-06-19 15:03:05 +02001001 EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
1002 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001003 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001004 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
1005}
1006
jbauchcb560652016-08-04 05:20:32 -07001007// Create a typical video answer with GCM ciphers enabled, and ensure it
1008// matches what we expect.
1009TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcm) {
1010 TestVideoGcmCipher(true, true);
1011}
1012
1013// Create a typical video answer with GCM ciphers enabled for the offer only,
1014// and ensure it matches what we expect.
1015TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmOffer) {
1016 TestVideoGcmCipher(true, false);
1017}
1018
1019// Create a typical video answer with GCM ciphers enabled for the answer only,
1020// and ensure it matches what we expect.
1021TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmAnswer) {
1022 TestVideoGcmCipher(false, true);
1023}
1024
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001025TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
zhihuang1c378ed2017-08-17 14:10:50 -07001026 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
Steve Anton4e70a722017-11-28 14:57:10 -08001027 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001028 f1_.set_secure(SEC_ENABLED);
1029 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001030 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001031 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001032 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001033 f2_.CreateAnswer(offer.get(), opts, NULL));
1034 const ContentInfo* ac = answer->GetContentByName("audio");
zstein4b2e0822017-02-17 19:48:38 -08001035 const ContentInfo* dc = answer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001036 ASSERT_TRUE(ac != NULL);
zstein4b2e0822017-02-17 19:48:38 -08001037 ASSERT_TRUE(dc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08001038 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
1039 EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08001040 const AudioContentDescription* acd = ac->media_description()->as_audio();
1041 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001042 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1043 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1044 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -07001045 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001046 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001047 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
zstein4b2e0822017-02-17 19:48:38 -08001048 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1049 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -07001050 EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached
zstein4b2e0822017-02-17 19:48:38 -08001051 EXPECT_TRUE(dcd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001052 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
zstein4b2e0822017-02-17 19:48:38 -08001053 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001054}
1055
jbauchcb560652016-08-04 05:20:32 -07001056TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerGcm) {
zhihuang1c378ed2017-08-17 14:10:50 -07001057 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
Steve Anton4e70a722017-11-28 14:57:10 -08001058 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
jbauchcb560652016-08-04 05:20:32 -07001059 opts.crypto_options.enable_gcm_crypto_suites = true;
1060 f1_.set_secure(SEC_ENABLED);
1061 f2_.set_secure(SEC_ENABLED);
1062 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1063 ASSERT_TRUE(offer.get() != NULL);
1064 std::unique_ptr<SessionDescription> answer(
1065 f2_.CreateAnswer(offer.get(), opts, NULL));
1066 const ContentInfo* ac = answer->GetContentByName("audio");
zstein4b2e0822017-02-17 19:48:38 -08001067 const ContentInfo* dc = answer->GetContentByName("data");
jbauchcb560652016-08-04 05:20:32 -07001068 ASSERT_TRUE(ac != NULL);
zstein4b2e0822017-02-17 19:48:38 -08001069 ASSERT_TRUE(dc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08001070 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
1071 EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08001072 const AudioContentDescription* acd = ac->media_description()->as_audio();
1073 const DataContentDescription* dcd = dc->media_description()->as_data();
jbauchcb560652016-08-04 05:20:32 -07001074 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1075 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1076 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -07001077 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -07001078 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001079 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
zstein4b2e0822017-02-17 19:48:38 -08001080 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1081 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -07001082 EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached
zstein4b2e0822017-02-17 19:48:38 -08001083 EXPECT_TRUE(dcd->rtcp_mux()); // negotiated rtcp-mux
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001084 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuiteGcm);
zstein4b2e0822017-02-17 19:48:38 -08001085 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
1086}
1087
1088// The use_sctpmap flag should be set in a DataContentDescription by default.
1089// The answer's use_sctpmap flag should match the offer's.
1090TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerUsesSctpmap) {
1091 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001092 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
zstein4b2e0822017-02-17 19:48:38 -08001093 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1094 ASSERT_TRUE(offer.get() != NULL);
1095 ContentInfo* dc_offer = offer->GetContentByName("data");
1096 ASSERT_TRUE(dc_offer != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001097 DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
zstein4b2e0822017-02-17 19:48:38 -08001098 EXPECT_TRUE(dcd_offer->use_sctpmap());
1099
1100 std::unique_ptr<SessionDescription> answer(
1101 f2_.CreateAnswer(offer.get(), opts, NULL));
1102 const ContentInfo* dc_answer = answer->GetContentByName("data");
1103 ASSERT_TRUE(dc_answer != NULL);
1104 const DataContentDescription* dcd_answer =
Steve Antonb1c1de12017-12-21 15:14:30 -08001105 dc_answer->media_description()->as_data();
zstein4b2e0822017-02-17 19:48:38 -08001106 EXPECT_TRUE(dcd_answer->use_sctpmap());
1107}
1108
1109// The answer's use_sctpmap flag should match the offer's.
1110TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerWithoutSctpmap) {
1111 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001112 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
zstein4b2e0822017-02-17 19:48:38 -08001113 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1114 ASSERT_TRUE(offer.get() != NULL);
1115 ContentInfo* dc_offer = offer->GetContentByName("data");
1116 ASSERT_TRUE(dc_offer != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001117 DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
zstein4b2e0822017-02-17 19:48:38 -08001118 dcd_offer->set_use_sctpmap(false);
1119
1120 std::unique_ptr<SessionDescription> answer(
1121 f2_.CreateAnswer(offer.get(), opts, NULL));
1122 const ContentInfo* dc_answer = answer->GetContentByName("data");
1123 ASSERT_TRUE(dc_answer != NULL);
1124 const DataContentDescription* dcd_answer =
Steve Antonb1c1de12017-12-21 15:14:30 -08001125 dc_answer->media_description()->as_data();
zstein4b2e0822017-02-17 19:48:38 -08001126 EXPECT_FALSE(dcd_answer->use_sctpmap());
jbauchcb560652016-08-04 05:20:32 -07001127}
1128
deadbeef8b7e9ad2017-05-25 09:38:55 -07001129// Test that a valid answer will be created for "DTLS/SCTP", "UDP/DTLS/SCTP"
1130// and "TCP/DTLS/SCTP" offers.
1131TEST_F(MediaSessionDescriptionFactoryTest,
1132 TestCreateDataAnswerToDifferentOfferedProtos) {
1133 // Need to enable DTLS offer/answer generation (disabled by default in this
1134 // test).
1135 f1_.set_secure(SEC_ENABLED);
1136 f2_.set_secure(SEC_ENABLED);
1137 tdf1_.set_secure(SEC_ENABLED);
1138 tdf2_.set_secure(SEC_ENABLED);
1139
1140 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001141 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
deadbeef8b7e9ad2017-05-25 09:38:55 -07001142 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
1143 ASSERT_TRUE(offer.get() != nullptr);
1144 ContentInfo* dc_offer = offer->GetContentByName("data");
1145 ASSERT_TRUE(dc_offer != nullptr);
Steve Antonb1c1de12017-12-21 15:14:30 -08001146 DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
deadbeef8b7e9ad2017-05-25 09:38:55 -07001147
1148 std::vector<std::string> protos = {"DTLS/SCTP", "UDP/DTLS/SCTP",
1149 "TCP/DTLS/SCTP"};
1150 for (const std::string& proto : protos) {
1151 dcd_offer->set_protocol(proto);
1152 std::unique_ptr<SessionDescription> answer(
1153 f2_.CreateAnswer(offer.get(), opts, nullptr));
1154 const ContentInfo* dc_answer = answer->GetContentByName("data");
1155 ASSERT_TRUE(dc_answer != nullptr);
1156 const DataContentDescription* dcd_answer =
Steve Antonb1c1de12017-12-21 15:14:30 -08001157 dc_answer->media_description()->as_data();
deadbeef8b7e9ad2017-05-25 09:38:55 -07001158 EXPECT_FALSE(dc_answer->rejected);
1159 EXPECT_EQ(proto, dcd_answer->protocol());
1160 }
1161}
1162
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001163// Verifies that the order of the media contents in the offer is preserved in
1164// the answer.
1165TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
1166 MediaSessionOptions opts;
1167
1168 // Creates a data only offer.
Steve Anton4e70a722017-11-28 14:57:10 -08001169 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
kwiberg31022942016-03-11 14:18:21 -08001170 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001171 ASSERT_TRUE(offer1.get() != NULL);
1172
1173 // Appends audio to the offer.
Steve Anton4e70a722017-11-28 14:57:10 -08001174 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1175 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001176 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001177 f1_.CreateOffer(opts, offer1.get()));
1178 ASSERT_TRUE(offer2.get() != NULL);
1179
1180 // Appends video to the offer.
Steve Anton4e70a722017-11-28 14:57:10 -08001181 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1182 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001183 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001184 f1_.CreateOffer(opts, offer2.get()));
1185 ASSERT_TRUE(offer3.get() != NULL);
1186
kwiberg31022942016-03-11 14:18:21 -08001187 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001188 f2_.CreateAnswer(offer3.get(), opts, NULL));
1189 ASSERT_TRUE(answer.get() != NULL);
1190 EXPECT_EQ(3u, answer->contents().size());
1191 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
1192 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
1193 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
1194}
1195
ossu075af922016-06-14 03:29:38 -07001196// TODO(deadbeef): Extend these tests to ensure the correct direction with other
1197// answerer settings.
1198
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001199// This test that the media direction is set to send/receive in an answer if
1200// the offer is send receive.
1201TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001202 TestMediaDirectionInAnswer(RtpTransceiverDirection::kSendRecv,
1203 RtpTransceiverDirection::kSendRecv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001204}
1205
1206// This test that the media direction is set to receive only in an answer if
1207// the offer is send only.
1208TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001209 TestMediaDirectionInAnswer(RtpTransceiverDirection::kSendOnly,
1210 RtpTransceiverDirection::kRecvOnly);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001211}
1212
1213// This test that the media direction is set to send only in an answer if
1214// the offer is recv only.
1215TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001216 TestMediaDirectionInAnswer(RtpTransceiverDirection::kRecvOnly,
1217 RtpTransceiverDirection::kSendOnly);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001218}
1219
1220// This test that the media direction is set to inactive in an answer if
1221// the offer is inactive.
1222TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001223 TestMediaDirectionInAnswer(RtpTransceiverDirection::kInactive,
1224 RtpTransceiverDirection::kInactive);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001225}
1226
1227// Test that a data content with an unknown protocol is rejected in an answer.
1228TEST_F(MediaSessionDescriptionFactoryTest,
1229 CreateDataAnswerToOfferWithUnknownProtocol) {
1230 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001231 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001232 f1_.set_secure(SEC_ENABLED);
1233 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001234 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
terelius8c011e52016-04-26 05:28:11 -07001235 ContentInfo* dc_offer = offer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001236 ASSERT_TRUE(dc_offer != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001237 DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001238 ASSERT_TRUE(dcd_offer != NULL);
1239 std::string protocol = "a weird unknown protocol";
1240 dcd_offer->set_protocol(protocol);
1241
kwiberg31022942016-03-11 14:18:21 -08001242 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001243 f2_.CreateAnswer(offer.get(), opts, NULL));
1244
1245 const ContentInfo* dc_answer = answer->GetContentByName("data");
1246 ASSERT_TRUE(dc_answer != NULL);
1247 EXPECT_TRUE(dc_answer->rejected);
1248 const DataContentDescription* dcd_answer =
Steve Antonb1c1de12017-12-21 15:14:30 -08001249 dc_answer->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001250 ASSERT_TRUE(dcd_answer != NULL);
1251 EXPECT_EQ(protocol, dcd_answer->protocol());
1252}
1253
1254// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
1255TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
zhihuang1c378ed2017-08-17 14:10:50 -07001256 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001257 f1_.set_secure(SEC_DISABLED);
1258 f2_.set_secure(SEC_DISABLED);
1259 tdf1_.set_secure(SEC_DISABLED);
1260 tdf2_.set_secure(SEC_DISABLED);
1261
kwiberg31022942016-03-11 14:18:21 -08001262 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001263 const AudioContentDescription* offer_acd =
1264 GetFirstAudioContentDescription(offer.get());
1265 ASSERT_TRUE(offer_acd != NULL);
1266 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
1267
kwiberg31022942016-03-11 14:18:21 -08001268 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001269 f2_.CreateAnswer(offer.get(), opts, NULL));
1270
1271 const ContentInfo* ac_answer = answer->GetContentByName("audio");
1272 ASSERT_TRUE(ac_answer != NULL);
1273 EXPECT_FALSE(ac_answer->rejected);
1274
1275 const AudioContentDescription* answer_acd =
1276 GetFirstAudioContentDescription(answer.get());
1277 ASSERT_TRUE(answer_acd != NULL);
1278 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
1279}
1280
1281// Create a video offer and answer and ensure the RTP header extensions
1282// matches what we expect.
1283TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
1284 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001285 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001286 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1287 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1288 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1289 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1290
kwiberg31022942016-03-11 14:18:21 -08001291 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001292 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001293 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001294 f2_.CreateAnswer(offer.get(), opts, NULL));
1295
Yves Gerey665174f2018-06-19 15:03:05 +02001296 EXPECT_EQ(
1297 MAKE_VECTOR(kAudioRtpExtension1),
1298 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1299 EXPECT_EQ(
1300 MAKE_VECTOR(kVideoRtpExtension1),
1301 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1302 EXPECT_EQ(
1303 MAKE_VECTOR(kAudioRtpExtensionAnswer),
1304 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1305 EXPECT_EQ(
1306 MAKE_VECTOR(kVideoRtpExtensionAnswer),
1307 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001308}
1309
jbauch5869f502017-06-29 12:31:36 -07001310TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02001311 TestOfferAnswerWithEncryptedRtpExtensionsBoth) {
jbauch5869f502017-06-29 12:31:36 -07001312 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001313 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07001314
1315 f1_.set_enable_encrypted_rtp_header_extensions(true);
1316 f2_.set_enable_encrypted_rtp_header_extensions(true);
1317
Yves Gerey665174f2018-06-19 15:03:05 +02001318 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1319 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1320 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1321 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
jbauch5869f502017-06-29 12:31:36 -07001322
1323 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1324 ASSERT_TRUE(offer.get() != NULL);
1325 std::unique_ptr<SessionDescription> answer(
1326 f2_.CreateAnswer(offer.get(), opts, NULL));
1327
Yves Gerey665174f2018-06-19 15:03:05 +02001328 EXPECT_EQ(
1329 MAKE_VECTOR(kAudioRtpExtensionEncrypted1),
1330 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1331 EXPECT_EQ(
1332 MAKE_VECTOR(kVideoRtpExtensionEncrypted1),
1333 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1334 EXPECT_EQ(
1335 MAKE_VECTOR(kAudioRtpExtensionEncryptedAnswer),
1336 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1337 EXPECT_EQ(
1338 MAKE_VECTOR(kVideoRtpExtensionEncryptedAnswer),
1339 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07001340}
1341
1342TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02001343 TestOfferAnswerWithEncryptedRtpExtensionsOffer) {
jbauch5869f502017-06-29 12:31:36 -07001344 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001345 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07001346
1347 f1_.set_enable_encrypted_rtp_header_extensions(true);
1348
Yves Gerey665174f2018-06-19 15:03:05 +02001349 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1350 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1351 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1352 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
jbauch5869f502017-06-29 12:31:36 -07001353
1354 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1355 ASSERT_TRUE(offer.get() != NULL);
1356 std::unique_ptr<SessionDescription> answer(
1357 f2_.CreateAnswer(offer.get(), opts, NULL));
1358
Yves Gerey665174f2018-06-19 15:03:05 +02001359 EXPECT_EQ(
1360 MAKE_VECTOR(kAudioRtpExtensionEncrypted1),
1361 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1362 EXPECT_EQ(
1363 MAKE_VECTOR(kVideoRtpExtensionEncrypted1),
1364 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1365 EXPECT_EQ(
1366 MAKE_VECTOR(kAudioRtpExtensionAnswer),
1367 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1368 EXPECT_EQ(
1369 MAKE_VECTOR(kVideoRtpExtensionAnswer),
1370 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07001371}
1372
1373TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02001374 TestOfferAnswerWithEncryptedRtpExtensionsAnswer) {
jbauch5869f502017-06-29 12:31:36 -07001375 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001376 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07001377
1378 f2_.set_enable_encrypted_rtp_header_extensions(true);
1379
Yves Gerey665174f2018-06-19 15:03:05 +02001380 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1381 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1382 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1383 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
jbauch5869f502017-06-29 12:31:36 -07001384
1385 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1386 ASSERT_TRUE(offer.get() != NULL);
1387 std::unique_ptr<SessionDescription> answer(
1388 f2_.CreateAnswer(offer.get(), opts, NULL));
1389
Yves Gerey665174f2018-06-19 15:03:05 +02001390 EXPECT_EQ(
1391 MAKE_VECTOR(kAudioRtpExtension1),
1392 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1393 EXPECT_EQ(
1394 MAKE_VECTOR(kVideoRtpExtension1),
1395 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1396 EXPECT_EQ(
1397 MAKE_VECTOR(kAudioRtpExtensionAnswer),
1398 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1399 EXPECT_EQ(
1400 MAKE_VECTOR(kVideoRtpExtensionAnswer),
1401 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07001402}
1403
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001404// Create an audio, video, data answer without legacy StreamParams.
1405TEST_F(MediaSessionDescriptionFactoryTest,
1406 TestCreateAnswerWithoutLegacyStreams) {
1407 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001408 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1409 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
kwiberg31022942016-03-11 14:18:21 -08001410 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001411 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001412 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001413 f2_.CreateAnswer(offer.get(), opts, NULL));
1414 const ContentInfo* ac = answer->GetContentByName("audio");
1415 const ContentInfo* vc = answer->GetContentByName("video");
1416 const ContentInfo* dc = answer->GetContentByName("data");
1417 ASSERT_TRUE(ac != NULL);
1418 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001419 const AudioContentDescription* acd = ac->media_description()->as_audio();
1420 const VideoContentDescription* vcd = vc->media_description()->as_video();
1421 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001422
1423 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1424 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1425 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1426}
1427
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001428// Create a typical video answer, and ensure it matches what we expect.
1429TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1430 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001431 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &offer_opts);
1432 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv,
1433 &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001434
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001435 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001436 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &answer_opts);
1437 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv,
1438 &answer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001439
kwiberg31022942016-03-11 14:18:21 -08001440 std::unique_ptr<SessionDescription> offer;
1441 std::unique_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001442
1443 offer_opts.rtcp_mux_enabled = true;
1444 answer_opts.rtcp_mux_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001445 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1446 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1447 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1448 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1449 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1450 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1451 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1452 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1453 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1454 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1455 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1456 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1457 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1458 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1459
1460 offer_opts.rtcp_mux_enabled = true;
1461 answer_opts.rtcp_mux_enabled = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001462 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1463 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1464 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1465 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1466 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1467 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1468 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1469 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1470 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1471 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1472 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1473 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1474 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1475 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1476
1477 offer_opts.rtcp_mux_enabled = false;
1478 answer_opts.rtcp_mux_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001479 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1480 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1481 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1482 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1483 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1484 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1485 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1486 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1487 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1488 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1489 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1490 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1491 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1492 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1493
1494 offer_opts.rtcp_mux_enabled = false;
1495 answer_opts.rtcp_mux_enabled = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001496 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1497 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1498 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1499 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1500 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1501 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1502 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1503 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1504 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1505 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1506 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1507 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1508 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1509 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1510}
1511
1512// Create an audio-only answer to a video offer.
1513TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1514 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001515 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1516 kActive, &opts);
1517 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1518 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001519 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001520 ASSERT_TRUE(offer.get() != NULL);
zhihuang1c378ed2017-08-17 14:10:50 -07001521
1522 opts.media_description_options[1].stopped = true;
kwiberg31022942016-03-11 14:18:21 -08001523 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001524 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001525 const ContentInfo* ac = answer->GetContentByName("audio");
1526 const ContentInfo* vc = answer->GetContentByName("video");
1527 ASSERT_TRUE(ac != NULL);
1528 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001529 ASSERT_TRUE(vc->media_description() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001530 EXPECT_TRUE(vc->rejected);
1531}
1532
1533// Create an audio-only answer to an offer with data.
1534TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07001535 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001536 opts.data_channel_type = cricket::DCT_RTP;
Steve Anton4e70a722017-11-28 14:57:10 -08001537 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kRecvOnly,
1538 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001539 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001540 ASSERT_TRUE(offer.get() != NULL);
zhihuang1c378ed2017-08-17 14:10:50 -07001541
1542 opts.media_description_options[1].stopped = true;
kwiberg31022942016-03-11 14:18:21 -08001543 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001544 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001545 const ContentInfo* ac = answer->GetContentByName("audio");
1546 const ContentInfo* dc = answer->GetContentByName("data");
1547 ASSERT_TRUE(ac != NULL);
1548 ASSERT_TRUE(dc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001549 ASSERT_TRUE(dc->media_description() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001550 EXPECT_TRUE(dc->rejected);
1551}
1552
1553// Create an answer that rejects the contents which are rejected in the offer.
1554TEST_F(MediaSessionDescriptionFactoryTest,
1555 CreateAnswerToOfferWithRejectedMedia) {
1556 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001557 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1558 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
kwiberg31022942016-03-11 14:18:21 -08001559 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001560 ASSERT_TRUE(offer.get() != NULL);
1561 ContentInfo* ac = offer->GetContentByName("audio");
1562 ContentInfo* vc = offer->GetContentByName("video");
1563 ContentInfo* dc = offer->GetContentByName("data");
1564 ASSERT_TRUE(ac != NULL);
1565 ASSERT_TRUE(vc != NULL);
1566 ASSERT_TRUE(dc != NULL);
1567 ac->rejected = true;
1568 vc->rejected = true;
1569 dc->rejected = true;
kwiberg31022942016-03-11 14:18:21 -08001570 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001571 f2_.CreateAnswer(offer.get(), opts, NULL));
1572 ac = answer->GetContentByName("audio");
1573 vc = answer->GetContentByName("video");
1574 dc = answer->GetContentByName("data");
1575 ASSERT_TRUE(ac != NULL);
1576 ASSERT_TRUE(vc != NULL);
1577 ASSERT_TRUE(dc != NULL);
1578 EXPECT_TRUE(ac->rejected);
1579 EXPECT_TRUE(vc->rejected);
1580 EXPECT_TRUE(dc->rejected);
1581}
1582
1583// Create an audio and video offer with:
1584// - one video track
1585// - two audio tracks
1586// - two data tracks
1587// and ensure it matches what we expect. Also updates the initial offer by
1588// adding a new video track and replaces one of the audio tracks.
1589TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1590 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001591 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001592 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001593 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001594 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001595 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001596 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001597 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001598
Steve Anton4e70a722017-11-28 14:57:10 -08001599 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001600 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001601 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001602 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001603 {kMediaStream1}, 1, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001604
1605 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001606 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001607
1608 ASSERT_TRUE(offer.get() != NULL);
1609 const ContentInfo* ac = offer->GetContentByName("audio");
1610 const ContentInfo* vc = offer->GetContentByName("video");
1611 const ContentInfo* dc = offer->GetContentByName("data");
1612 ASSERT_TRUE(ac != NULL);
1613 ASSERT_TRUE(vc != NULL);
1614 ASSERT_TRUE(dc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001615 const AudioContentDescription* acd = ac->media_description()->as_audio();
1616 const VideoContentDescription* vcd = vc->media_description()->as_video();
1617 const DataContentDescription* dcd = dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001618 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -07001619 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001620
1621 const StreamParamsVec& audio_streams = acd->streams();
1622 ASSERT_EQ(2U, audio_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001623 EXPECT_EQ(audio_streams[0].cname, audio_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001624 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1625 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1626 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1627 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1628 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1629 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1630
1631 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1632 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001633 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001634
1635 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1636 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001637 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001638
1639 const StreamParamsVec& video_streams = vcd->streams();
1640 ASSERT_EQ(1U, video_streams.size());
1641 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1642 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1643 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1644 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1645
1646 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1647 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001648 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001649
1650 const StreamParamsVec& data_streams = dcd->streams();
1651 ASSERT_EQ(2U, data_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001652 EXPECT_EQ(data_streams[0].cname, data_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001653 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1654 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1655 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1656 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1657 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1658 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1659
1660 EXPECT_EQ(cricket::kDataMaxBandwidth,
Yves Gerey665174f2018-06-19 15:03:05 +02001661 dcd->bandwidth()); // default bandwidth (auto)
1662 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001663 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001664
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001665 // Update the offer. Add a new video track that is not synched to the
1666 // other tracks and replace audio track 2 with audio track 3.
zhihuang1c378ed2017-08-17 14:10:50 -07001667 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001668 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001669 DetachSenderFromMediaSection("audio", kAudioTrack2, &opts);
1670 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack3,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001671 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001672 DetachSenderFromMediaSection("data", kDataTrack2, &opts);
1673 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack3,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001674 {kMediaStream1}, 1, &opts);
kwiberg31022942016-03-11 14:18:21 -08001675 std::unique_ptr<SessionDescription> updated_offer(
1676 f1_.CreateOffer(opts, offer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001677
1678 ASSERT_TRUE(updated_offer.get() != NULL);
1679 ac = updated_offer->GetContentByName("audio");
1680 vc = updated_offer->GetContentByName("video");
1681 dc = updated_offer->GetContentByName("data");
1682 ASSERT_TRUE(ac != NULL);
1683 ASSERT_TRUE(vc != NULL);
1684 ASSERT_TRUE(dc != NULL);
1685 const AudioContentDescription* updated_acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001686 ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001687 const VideoContentDescription* updated_vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001688 vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001689 const DataContentDescription* updated_dcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001690 dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001691
1692 EXPECT_EQ(acd->type(), updated_acd->type());
1693 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1694 EXPECT_EQ(vcd->type(), updated_vcd->type());
1695 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1696 EXPECT_EQ(dcd->type(), updated_dcd->type());
1697 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001698 ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001699 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001700 ASSERT_CRYPTO(updated_vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001701 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001702 ASSERT_CRYPTO(updated_dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001703 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1704
1705 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1706 ASSERT_EQ(2U, updated_audio_streams.size());
1707 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1708 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1709 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1710 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1711 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1712
1713 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1714 ASSERT_EQ(2U, updated_video_streams.size());
1715 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1716 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001717 // All the media streams in one PeerConnection share one RTCP CNAME.
1718 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001719
1720 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1721 ASSERT_EQ(2U, updated_data_streams.size());
1722 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1723 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1724 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1725 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1726 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
zhihuang8f65cdf2016-05-06 18:40:30 -07001727 // The stream correctly got the CNAME from the MediaSessionOptions.
1728 // The Expected RTCP CNAME is the default one as we are using the default
1729 // MediaSessionOptions.
1730 EXPECT_EQ(updated_data_streams[0].cname, cricket::kDefaultRtcpCname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001731}
1732
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001733// Create an offer with simulcast video stream.
1734TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1735 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001736 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1737 kActive, &opts);
1738 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
1739 kActive, &opts);
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001740 const int num_sim_layers = 3;
zhihuang1c378ed2017-08-17 14:10:50 -07001741 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001742 {kMediaStream1}, num_sim_layers, &opts);
kwiberg31022942016-03-11 14:18:21 -08001743 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001744
1745 ASSERT_TRUE(offer.get() != NULL);
1746 const ContentInfo* vc = offer->GetContentByName("video");
1747 ASSERT_TRUE(vc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001748 const VideoContentDescription* vcd = vc->media_description()->as_video();
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001749
1750 const StreamParamsVec& video_streams = vcd->streams();
1751 ASSERT_EQ(1U, video_streams.size());
1752 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1753 const SsrcGroup* sim_ssrc_group =
1754 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1755 ASSERT_TRUE(sim_ssrc_group != NULL);
1756 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1757}
1758
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001759// Create an audio and video answer to a standard video offer with:
1760// - one video track
1761// - two audio tracks
1762// - two data tracks
1763// and ensure it matches what we expect. Also updates the initial answer by
1764// adding a new video track and removes one of the audio tracks.
1765TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1766 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001767 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1768 kActive, &offer_opts);
1769 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1770 kActive, &offer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001771 offer_opts.data_channel_type = cricket::DCT_RTP;
Steve Anton4e70a722017-11-28 14:57:10 -08001772 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kRecvOnly,
1773 kActive, &offer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001774 f1_.set_secure(SEC_ENABLED);
1775 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001776 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001777
zhihuang1c378ed2017-08-17 14:10:50 -07001778 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001779 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
1780 kActive, &answer_opts);
1781 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
1782 kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001783 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001784 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001785 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001786 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001787 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001788 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001789
Steve Anton4e70a722017-11-28 14:57:10 -08001790 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kSendRecv,
1791 kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001792 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001793 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001794 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001795 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001796 answer_opts.data_channel_type = cricket::DCT_RTP;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001797
kwiberg31022942016-03-11 14:18:21 -08001798 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001799 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001800
1801 ASSERT_TRUE(answer.get() != NULL);
1802 const ContentInfo* ac = answer->GetContentByName("audio");
1803 const ContentInfo* vc = answer->GetContentByName("video");
1804 const ContentInfo* dc = answer->GetContentByName("data");
1805 ASSERT_TRUE(ac != NULL);
1806 ASSERT_TRUE(vc != NULL);
1807 ASSERT_TRUE(dc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08001808 const AudioContentDescription* acd = ac->media_description()->as_audio();
1809 const VideoContentDescription* vcd = vc->media_description()->as_video();
1810 const DataContentDescription* dcd = dc->media_description()->as_data();
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001811 ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
1812 ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
1813 ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001814
1815 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1816 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1817
1818 const StreamParamsVec& audio_streams = acd->streams();
1819 ASSERT_EQ(2U, audio_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001820 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001821 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1822 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1823 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1824 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1825 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1826 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1827
1828 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1829 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1830
1831 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1832 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1833
1834 const StreamParamsVec& video_streams = vcd->streams();
1835 ASSERT_EQ(1U, video_streams.size());
1836 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1837 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1838 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1839 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1840
1841 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1842 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1843
1844 const StreamParamsVec& data_streams = dcd->streams();
1845 ASSERT_EQ(2U, data_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001846 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001847 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1848 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1849 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1850 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1851 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1852 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1853
1854 EXPECT_EQ(cricket::kDataMaxBandwidth,
Yves Gerey665174f2018-06-19 15:03:05 +02001855 dcd->bandwidth()); // default bandwidth (auto)
1856 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001857
1858 // Update the answer. Add a new video track that is not synched to the
zhihuang8f65cdf2016-05-06 18:40:30 -07001859 // other tracks and remove 1 audio track.
zhihuang1c378ed2017-08-17 14:10:50 -07001860 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001861 {kMediaStream2}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001862 DetachSenderFromMediaSection("audio", kAudioTrack2, &answer_opts);
1863 DetachSenderFromMediaSection("data", kDataTrack2, &answer_opts);
kwiberg31022942016-03-11 14:18:21 -08001864 std::unique_ptr<SessionDescription> updated_answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001865 f2_.CreateAnswer(offer.get(), answer_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001866
1867 ASSERT_TRUE(updated_answer.get() != NULL);
1868 ac = updated_answer->GetContentByName("audio");
1869 vc = updated_answer->GetContentByName("video");
1870 dc = updated_answer->GetContentByName("data");
1871 ASSERT_TRUE(ac != NULL);
1872 ASSERT_TRUE(vc != NULL);
1873 ASSERT_TRUE(dc != NULL);
1874 const AudioContentDescription* updated_acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001875 ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001876 const VideoContentDescription* updated_vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001877 vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001878 const DataContentDescription* updated_dcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08001879 dc->media_description()->as_data();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001880
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001881 ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001882 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001883 ASSERT_CRYPTO(updated_vcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001884 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07001885 ASSERT_CRYPTO(updated_dcd, 1U, kDefaultSrtpCryptoSuite);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001886 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1887
1888 EXPECT_EQ(acd->type(), updated_acd->type());
1889 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1890 EXPECT_EQ(vcd->type(), updated_vcd->type());
1891 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1892 EXPECT_EQ(dcd->type(), updated_dcd->type());
1893 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1894
1895 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1896 ASSERT_EQ(1U, updated_audio_streams.size());
Yves Gerey665174f2018-06-19 15:03:05 +02001897 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001898
1899 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1900 ASSERT_EQ(2U, updated_video_streams.size());
1901 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1902 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001903 // All media streams in one PeerConnection share one CNAME.
1904 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001905
1906 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1907 ASSERT_EQ(1U, updated_data_streams.size());
1908 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1909}
1910
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001911// Create an updated offer after creating an answer to the original offer and
1912// verify that the codecs that were part of the original answer are not changed
1913// in the updated offer.
1914TEST_F(MediaSessionDescriptionFactoryTest,
1915 RespondentCreatesOfferAfterCreatingAnswer) {
1916 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001917 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001918
kwiberg31022942016-03-11 14:18:21 -08001919 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1920 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001921 f2_.CreateAnswer(offer.get(), opts, NULL));
1922
1923 const AudioContentDescription* acd =
1924 GetFirstAudioContentDescription(answer.get());
1925 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1926
1927 const VideoContentDescription* vcd =
1928 GetFirstVideoContentDescription(answer.get());
1929 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1930
kwiberg31022942016-03-11 14:18:21 -08001931 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001932 f2_.CreateOffer(opts, answer.get()));
1933
1934 // The expected audio codecs are the common audio codecs from the first
1935 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1936 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001937 // TODO(wu): |updated_offer| should not include the codec
1938 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001939 const AudioCodec kUpdatedAudioCodecOffer[] = {
Yves Gerey665174f2018-06-19 15:03:05 +02001940 kAudioCodecsAnswer[0], kAudioCodecsAnswer[1], kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001941 };
1942
1943 // The expected video codecs are the common video codecs from the first
1944 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1945 // preference order.
1946 const VideoCodec kUpdatedVideoCodecOffer[] = {
Yves Gerey665174f2018-06-19 15:03:05 +02001947 kVideoCodecsAnswer[0], kVideoCodecs2[1],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001948 };
1949
1950 const AudioContentDescription* updated_acd =
1951 GetFirstAudioContentDescription(updated_offer.get());
1952 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1953
1954 const VideoContentDescription* updated_vcd =
1955 GetFirstVideoContentDescription(updated_offer.get());
1956 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1957}
1958
1959// Create an updated offer after creating an answer to the original offer and
1960// verify that the codecs that were part of the original answer are not changed
1961// in the updated offer. In this test Rtx is enabled.
1962TEST_F(MediaSessionDescriptionFactoryTest,
1963 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1964 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001965 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1966 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001967 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001968 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001969 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001970 f1_.set_video_codecs(f1_codecs);
1971
1972 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001973 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001974 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001975 f2_.set_video_codecs(f2_codecs);
1976
kwiberg31022942016-03-11 14:18:21 -08001977 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001978 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001979 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001980 f2_.CreateAnswer(offer.get(), opts, NULL));
1981
1982 const VideoContentDescription* vcd =
1983 GetFirstVideoContentDescription(answer.get());
1984
1985 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001986 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1987 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001988
1989 EXPECT_EQ(expected_codecs, vcd->codecs());
1990
deadbeef67cf2c12016-04-13 10:07:16 -07001991 // Now, make sure we get same result (except for the order) if |f2_| creates
1992 // an updated offer even though the default payload types between |f1_| and
1993 // |f2_| are different.
kwiberg31022942016-03-11 14:18:21 -08001994 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001995 f2_.CreateOffer(opts, answer.get()));
1996 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001997 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001998 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1999
2000 const VideoContentDescription* updated_vcd =
2001 GetFirstVideoContentDescription(updated_answer.get());
2002
2003 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
2004}
2005
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002006// Regression test for:
2007// https://bugs.chromium.org/p/webrtc/issues/detail?id=8332
2008// Existing codecs should always appear before new codecs in re-offers. But
2009// under a specific set of circumstances, the existing RTX codec was ending up
2010// added to the end of the list.
2011TEST_F(MediaSessionDescriptionFactoryTest,
2012 RespondentCreatesOfferAfterCreatingAnswerWithRemappedRtxPayloadType) {
2013 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002014 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2015 kActive, &opts);
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002016 // We specifically choose different preferred payload types for VP8 to
2017 // trigger the issue.
2018 cricket::VideoCodec vp8_offerer(100, "VP8");
2019 cricket::VideoCodec vp8_offerer_rtx =
2020 VideoCodec::CreateRtxCodec(101, vp8_offerer.id);
2021 cricket::VideoCodec vp8_answerer(110, "VP8");
2022 cricket::VideoCodec vp8_answerer_rtx =
2023 VideoCodec::CreateRtxCodec(111, vp8_answerer.id);
2024 cricket::VideoCodec vp9(120, "VP9");
2025 cricket::VideoCodec vp9_rtx = VideoCodec::CreateRtxCodec(121, vp9.id);
2026
2027 std::vector<VideoCodec> f1_codecs = {vp8_offerer, vp8_offerer_rtx};
2028 // We also specifically cause the answerer to prefer VP9, such that if it
2029 // *doesn't* honor the existing preferred codec (VP8) we'll notice.
2030 std::vector<VideoCodec> f2_codecs = {vp9, vp9_rtx, vp8_answerer,
2031 vp8_answerer_rtx};
2032
2033 f1_.set_video_codecs(f1_codecs);
2034 f2_.set_video_codecs(f2_codecs);
2035 std::vector<AudioCodec> audio_codecs;
2036 f1_.set_audio_codecs(audio_codecs, audio_codecs);
2037 f2_.set_audio_codecs(audio_codecs, audio_codecs);
2038
2039 // Offer will be {VP8, RTX for VP8}. Answer will be the same.
2040 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2041 ASSERT_TRUE(offer.get() != NULL);
2042 std::unique_ptr<SessionDescription> answer(
2043 f2_.CreateAnswer(offer.get(), opts, NULL));
2044
2045 // Updated offer *should* be {VP8, RTX for VP8, VP9, RTX for VP9}.
2046 // But if the bug is triggered, RTX for VP8 ends up last.
2047 std::unique_ptr<SessionDescription> updated_offer(
2048 f2_.CreateOffer(opts, answer.get()));
2049
2050 const VideoContentDescription* vcd =
2051 GetFirstVideoContentDescription(updated_offer.get());
2052 std::vector<cricket::VideoCodec> codecs = vcd->codecs();
2053 ASSERT_EQ(4u, codecs.size());
2054 EXPECT_EQ(vp8_offerer, codecs[0]);
2055 EXPECT_EQ(vp8_offerer_rtx, codecs[1]);
2056 EXPECT_EQ(vp9, codecs[2]);
2057 EXPECT_EQ(vp9_rtx, codecs[3]);
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002058}
2059
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002060// Create an updated offer that adds video after creating an audio only answer
2061// to the original offer. This test verifies that if a video codec and the RTX
2062// codec have the same default payload type as an audio codec that is already in
2063// use, the added codecs payload types are changed.
2064TEST_F(MediaSessionDescriptionFactoryTest,
2065 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
2066 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002067 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002068 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002069 f1_.set_video_codecs(f1_codecs);
2070
2071 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002072 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2073 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002074
kwiberg31022942016-03-11 14:18:21 -08002075 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2076 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002077 f2_.CreateAnswer(offer.get(), opts, NULL));
2078
2079 const AudioContentDescription* acd =
2080 GetFirstAudioContentDescription(answer.get());
2081 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
2082
2083 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
2084 // reference be the same as an audio codec that was negotiated in the
2085 // first offer/answer exchange.
zhihuang1c378ed2017-08-17 14:10:50 -07002086 opts.media_description_options.clear();
Steve Anton4e70a722017-11-28 14:57:10 -08002087 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002088
2089 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2090 int used_pl_type = acd->codecs()[0].id;
2091 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002092 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002093 f2_.set_video_codecs(f2_codecs);
2094
kwiberg31022942016-03-11 14:18:21 -08002095 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002096 f2_.CreateOffer(opts, answer.get()));
2097 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08002098 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002099 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
2100
2101 const AudioContentDescription* updated_acd =
2102 GetFirstAudioContentDescription(answer.get());
2103 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
2104
2105 const VideoContentDescription* updated_vcd =
2106 GetFirstVideoContentDescription(updated_answer.get());
2107
2108 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00002109 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
Yves Gerey665174f2018-06-19 15:03:05 +02002110 int new_h264_pl_type = updated_vcd->codecs()[0].id;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002111 EXPECT_NE(used_pl_type, new_h264_pl_type);
2112 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002113 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002114 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
2115 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
2116}
2117
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002118// Create an updated offer with RTX after creating an answer to an offer
2119// without RTX, and with different default payload types.
2120// Verify that the added RTX codec references the correct payload type.
2121TEST_F(MediaSessionDescriptionFactoryTest,
2122 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
2123 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002124 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002125
2126 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2127 // This creates rtx for H264 with the payload type |f2_| uses.
2128 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
2129 f2_.set_video_codecs(f2_codecs);
2130
kwiberg31022942016-03-11 14:18:21 -08002131 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002132 ASSERT_TRUE(offer.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08002133 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002134 f2_.CreateAnswer(offer.get(), opts, nullptr));
2135
2136 const VideoContentDescription* vcd =
2137 GetFirstVideoContentDescription(answer.get());
2138
2139 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2140 EXPECT_EQ(expected_codecs, vcd->codecs());
2141
2142 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
2143 // updated offer, even though the default payload types are different from
2144 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08002145 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002146 f2_.CreateOffer(opts, answer.get()));
2147 ASSERT_TRUE(updated_offer);
2148
2149 const VideoContentDescription* updated_vcd =
2150 GetFirstVideoContentDescription(updated_offer.get());
2151
2152 // New offer should attempt to add H263, and RTX for H264.
2153 expected_codecs.push_back(kVideoCodecs2[1]);
2154 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
2155 &expected_codecs);
2156 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
2157}
2158
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002159// Test that RTX is ignored when there is no associated payload type parameter.
2160TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
2161 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002162 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2163 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002164 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002165 // This creates RTX without associated payload type parameter.
perkj26752742016-10-24 01:21:16 -07002166 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002167 f1_.set_video_codecs(f1_codecs);
2168
2169 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002170 // This creates RTX for H264 with the payload type |f2_| uses.
2171 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002172 f2_.set_video_codecs(f2_codecs);
2173
kwiberg31022942016-03-11 14:18:21 -08002174 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002175 ASSERT_TRUE(offer.get() != NULL);
2176 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
2177 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
2178 // is possible to test that that RTX is dropped when
2179 // kCodecParamAssociatedPayloadType is missing in the offer.
Steve Antonb1c1de12017-12-21 15:14:30 -08002180 MediaContentDescription* media_desc =
2181 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2182 ASSERT_TRUE(media_desc);
2183 VideoContentDescription* desc = media_desc->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002184 std::vector<VideoCodec> codecs = desc->codecs();
2185 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
2186 iter != codecs.end(); ++iter) {
2187 if (iter->name.find(cricket::kRtxCodecName) == 0) {
2188 iter->params.clear();
2189 }
2190 }
2191 desc->set_codecs(codecs);
2192
kwiberg31022942016-03-11 14:18:21 -08002193 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002194 f2_.CreateAnswer(offer.get(), opts, NULL));
2195
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002196 std::vector<std::string> codec_names =
2197 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
2198 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
2199 cricket::kRtxCodecName));
2200}
2201
2202// Test that RTX will be filtered out in the answer if its associated payload
2203// type doesn't match the local value.
2204TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
2205 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002206 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2207 kActive, &opts);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002208 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2209 // This creates RTX for H264 in sender.
2210 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2211 f1_.set_video_codecs(f1_codecs);
2212
2213 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2214 // This creates RTX for H263 in receiver.
2215 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
2216 f2_.set_video_codecs(f2_codecs);
2217
kwiberg31022942016-03-11 14:18:21 -08002218 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002219 ASSERT_TRUE(offer.get() != NULL);
2220 // Associated payload type doesn't match, therefore, RTX codec is removed in
2221 // the answer.
kwiberg31022942016-03-11 14:18:21 -08002222 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002223 f2_.CreateAnswer(offer.get(), opts, NULL));
2224
2225 std::vector<std::string> codec_names =
2226 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
2227 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
2228 cricket::kRtxCodecName));
2229}
2230
2231// Test that when multiple RTX codecs are offered, only the matched RTX codec
2232// is added in the answer, and the unsupported RTX codec is filtered out.
2233TEST_F(MediaSessionDescriptionFactoryTest,
2234 FilterOutUnsupportedRtxWhenCreatingAnswer) {
2235 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002236 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2237 kActive, &opts);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002238 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2239 // This creates RTX for H264-SVC in sender.
2240 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
2241 f1_.set_video_codecs(f1_codecs);
2242
2243 // This creates RTX for H264 in sender.
2244 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2245 f1_.set_video_codecs(f1_codecs);
2246
2247 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2248 // This creates RTX for H264 in receiver.
2249 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
2250 f2_.set_video_codecs(f2_codecs);
2251
2252 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
2253 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08002254 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002255 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002256 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002257 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002258 const VideoContentDescription* vcd =
2259 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002260 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2261 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2262 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002263
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002264 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002265}
2266
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002267// Test that after one RTX codec has been negotiated, a new offer can attempt
2268// to add another.
2269TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
2270 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002271 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2272 kActive, &opts);
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002273 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2274 // This creates RTX for H264 for the offerer.
2275 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2276 f1_.set_video_codecs(f1_codecs);
2277
kwiberg31022942016-03-11 14:18:21 -08002278 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002279 ASSERT_TRUE(offer);
2280 const VideoContentDescription* vcd =
2281 GetFirstVideoContentDescription(offer.get());
2282
2283 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
2284 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2285 &expected_codecs);
2286 EXPECT_EQ(expected_codecs, vcd->codecs());
2287
2288 // Now, attempt to add RTX for H264-SVC.
2289 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
2290 f1_.set_video_codecs(f1_codecs);
2291
kwiberg31022942016-03-11 14:18:21 -08002292 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002293 f1_.CreateOffer(opts, offer.get()));
2294 ASSERT_TRUE(updated_offer);
2295 vcd = GetFirstVideoContentDescription(updated_offer.get());
2296
2297 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
2298 &expected_codecs);
2299 EXPECT_EQ(expected_codecs, vcd->codecs());
2300}
2301
Noah Richards2e7a0982015-05-18 14:02:54 -07002302// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
2303// generated for each simulcast ssrc and correctly grouped.
2304TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
2305 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002306 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2307 kActive, &opts);
Noah Richards2e7a0982015-05-18 14:02:54 -07002308 // Add simulcast streams.
zhihuang1c378ed2017-08-17 14:10:50 -07002309 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002310 {"stream1label"}, 3, &opts);
Noah Richards2e7a0982015-05-18 14:02:54 -07002311
2312 // Use a single real codec, and then add RTX for it.
2313 std::vector<VideoCodec> f1_codecs;
perkj26752742016-10-24 01:21:16 -07002314 f1_codecs.push_back(VideoCodec(97, "H264"));
Noah Richards2e7a0982015-05-18 14:02:54 -07002315 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
2316 f1_.set_video_codecs(f1_codecs);
2317
2318 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
2319 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08002320 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07002321 ASSERT_TRUE(offer.get() != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002322 MediaContentDescription* media_desc =
2323 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2324 ASSERT_TRUE(media_desc);
2325 VideoContentDescription* desc = media_desc->as_video();
Noah Richards2e7a0982015-05-18 14:02:54 -07002326 const StreamParamsVec& streams = desc->streams();
2327 // Single stream.
2328 ASSERT_EQ(1u, streams.size());
2329 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
2330 EXPECT_EQ(6u, streams[0].ssrcs.size());
2331 // And should have a SIM group for the simulcast.
2332 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2333 // And a FID group for RTX.
2334 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02002335 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002336 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2337 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02002338 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002339 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
2340 EXPECT_EQ(3u, fid_ssrcs.size());
2341}
2342
brandtr03d5fb12016-11-22 03:37:59 -08002343// Test that, when the FlexFEC codec is added, a FlexFEC ssrc is created
2344// together with a FEC-FR grouping.
2345TEST_F(MediaSessionDescriptionFactoryTest, GenerateFlexfecSsrc) {
2346 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002347 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2348 kActive, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002349 // Add single stream.
zhihuang1c378ed2017-08-17 14:10:50 -07002350 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002351 {"stream1label"}, 1, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002352
2353 // Use a single real codec, and then add FlexFEC for it.
2354 std::vector<VideoCodec> f1_codecs;
2355 f1_codecs.push_back(VideoCodec(97, "H264"));
2356 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2357 f1_.set_video_codecs(f1_codecs);
2358
2359 // Ensure that the offer has a single FlexFEC ssrc and that
2360 // there is no FEC-FR ssrc + grouping for each.
2361 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2362 ASSERT_TRUE(offer.get() != nullptr);
Steve Antonb1c1de12017-12-21 15:14:30 -08002363 MediaContentDescription* media_desc =
2364 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2365 ASSERT_TRUE(media_desc);
2366 VideoContentDescription* desc = media_desc->as_video();
brandtr03d5fb12016-11-22 03:37:59 -08002367 const StreamParamsVec& streams = desc->streams();
2368 // Single stream.
2369 ASSERT_EQ(1u, streams.size());
2370 // Stream should have 2 ssrcs: 1 for video, 1 for FlexFEC.
2371 EXPECT_EQ(2u, streams[0].ssrcs.size());
2372 // And should have a FEC-FR group for FlexFEC.
2373 EXPECT_TRUE(streams[0].has_ssrc_group("FEC-FR"));
2374 std::vector<uint32_t> primary_ssrcs;
2375 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2376 ASSERT_EQ(1u, primary_ssrcs.size());
2377 uint32_t flexfec_ssrc;
2378 EXPECT_TRUE(streams[0].GetFecFrSsrc(primary_ssrcs[0], &flexfec_ssrc));
2379 EXPECT_NE(flexfec_ssrc, 0u);
2380}
2381
2382// Test that FlexFEC is disabled for simulcast.
2383// TODO(brandtr): Remove this test when we support simulcast, either through
2384// multiple FlexfecSenders, or through multistream protection.
2385TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateNoFlexfecSsrcs) {
2386 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002387 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2388 kActive, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002389 // Add simulcast streams.
zhihuang1c378ed2017-08-17 14:10:50 -07002390 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002391 {"stream1label"}, 3, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002392
2393 // Use a single real codec, and then add FlexFEC for it.
2394 std::vector<VideoCodec> f1_codecs;
2395 f1_codecs.push_back(VideoCodec(97, "H264"));
2396 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2397 f1_.set_video_codecs(f1_codecs);
2398
2399 // Ensure that the offer has no FlexFEC ssrcs for each regular ssrc, and that
2400 // there is no FEC-FR ssrc + grouping for each.
2401 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2402 ASSERT_TRUE(offer.get() != nullptr);
Steve Antonb1c1de12017-12-21 15:14:30 -08002403 MediaContentDescription* media_desc =
2404 offer->GetContentDescriptionByName(cricket::CN_VIDEO);
2405 ASSERT_TRUE(media_desc);
2406 VideoContentDescription* desc = media_desc->as_video();
brandtr03d5fb12016-11-22 03:37:59 -08002407 const StreamParamsVec& streams = desc->streams();
2408 // Single stream.
2409 ASSERT_EQ(1u, streams.size());
2410 // Stream should have 3 ssrcs: 3 for video, 0 for FlexFEC.
2411 EXPECT_EQ(3u, streams[0].ssrcs.size());
2412 // And should have a SIM group for the simulcast.
2413 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2414 // And not a FEC-FR group for FlexFEC.
2415 EXPECT_FALSE(streams[0].has_ssrc_group("FEC-FR"));
2416 std::vector<uint32_t> primary_ssrcs;
2417 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2418 EXPECT_EQ(3u, primary_ssrcs.size());
2419 for (uint32_t primary_ssrc : primary_ssrcs) {
2420 uint32_t flexfec_ssrc;
2421 EXPECT_FALSE(streams[0].GetFecFrSsrc(primary_ssrc, &flexfec_ssrc));
2422 }
2423}
2424
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002425// Create an updated offer after creating an answer to the original offer and
2426// verify that the RTP header extensions that were part of the original answer
2427// are not changed in the updated offer.
2428TEST_F(MediaSessionDescriptionFactoryTest,
2429 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
2430 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002431 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002432
2433 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
2434 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
2435 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
2436 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
2437
kwiberg31022942016-03-11 14:18:21 -08002438 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2439 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002440 f2_.CreateAnswer(offer.get(), opts, NULL));
2441
Yves Gerey665174f2018-06-19 15:03:05 +02002442 EXPECT_EQ(
2443 MAKE_VECTOR(kAudioRtpExtensionAnswer),
2444 GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
2445 EXPECT_EQ(
2446 MAKE_VECTOR(kVideoRtpExtensionAnswer),
2447 GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002448
kwiberg31022942016-03-11 14:18:21 -08002449 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002450 f2_.CreateOffer(opts, answer.get()));
2451
2452 // The expected RTP header extensions in the new offer are the resulting
2453 // extensions from the first offer/answer exchange plus the extensions only
2454 // |f2_| offer.
2455 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002456 // |f1_| for another extensions, it is changed to 13.
isheriff6f8d6862016-05-26 11:24:55 -07002457 const RtpExtension kUpdatedAudioRtpExtensions[] = {
2458 kAudioRtpExtensionAnswer[0], RtpExtension(kAudioRtpExtension2[1].uri, 13),
2459 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002460 };
2461
2462 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002463 // |f1_| for another extensions, is is changed to 12.
isheriff6f8d6862016-05-26 11:24:55 -07002464 const RtpExtension kUpdatedVideoRtpExtensions[] = {
2465 kVideoRtpExtensionAnswer[0], RtpExtension(kVideoRtpExtension2[1].uri, 12),
2466 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002467 };
2468
2469 const AudioContentDescription* updated_acd =
2470 GetFirstAudioContentDescription(updated_offer.get());
2471 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
2472 updated_acd->rtp_header_extensions());
2473
2474 const VideoContentDescription* updated_vcd =
2475 GetFirstVideoContentDescription(updated_offer.get());
2476 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
2477 updated_vcd->rtp_header_extensions());
2478}
2479
deadbeefa5b273a2015-08-20 17:30:13 -07002480// Verify that if the same RTP extension URI is used for audio and video, the
2481// same ID is used. Also verify that the ID isn't changed when creating an
2482// updated offer (this was previously a bug).
isheriff6f8d6862016-05-26 11:24:55 -07002483TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) {
deadbeefa5b273a2015-08-20 17:30:13 -07002484 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002485 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
deadbeefa5b273a2015-08-20 17:30:13 -07002486
2487 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
2488 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
2489
kwiberg31022942016-03-11 14:18:21 -08002490 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07002491
2492 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
2493 // the video extensions.
isheriff6f8d6862016-05-26 11:24:55 -07002494 const RtpExtension kExpectedVideoRtpExtension[] = {
2495 kVideoRtpExtension3[0], kAudioRtpExtension3[1],
deadbeefa5b273a2015-08-20 17:30:13 -07002496 };
2497
Yves Gerey665174f2018-06-19 15:03:05 +02002498 EXPECT_EQ(
2499 MAKE_VECTOR(kAudioRtpExtension3),
2500 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
2501 EXPECT_EQ(
2502 MAKE_VECTOR(kExpectedVideoRtpExtension),
2503 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
deadbeefa5b273a2015-08-20 17:30:13 -07002504
2505 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08002506 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07002507 f1_.CreateOffer(opts, offer.get()));
2508
2509 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
Yves Gerey665174f2018-06-19 15:03:05 +02002510 GetFirstAudioContentDescription(updated_offer.get())
2511 ->rtp_header_extensions());
deadbeefa5b273a2015-08-20 17:30:13 -07002512 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
Yves Gerey665174f2018-06-19 15:03:05 +02002513 GetFirstVideoContentDescription(updated_offer.get())
2514 ->rtp_header_extensions());
deadbeefa5b273a2015-08-20 17:30:13 -07002515}
2516
jbauch5869f502017-06-29 12:31:36 -07002517// Same as "RtpExtensionIdReused" above for encrypted RTP extensions.
2518TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReusedEncrypted) {
2519 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002520 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07002521
2522 f1_.set_enable_encrypted_rtp_header_extensions(true);
2523 f2_.set_enable_encrypted_rtp_header_extensions(true);
2524
2525 f1_.set_audio_rtp_header_extensions(
2526 MAKE_VECTOR(kAudioRtpExtension3ForEncryption));
2527 f1_.set_video_rtp_header_extensions(
2528 MAKE_VECTOR(kVideoRtpExtension3ForEncryption));
2529
2530 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2531
2532 // The extensions that are shared between audio and video should use the same
2533 // id.
2534 const RtpExtension kExpectedVideoRtpExtension[] = {
2535 kVideoRtpExtension3ForEncryption[0],
2536 kAudioRtpExtension3ForEncryptionOffer[1],
2537 kAudioRtpExtension3ForEncryptionOffer[2],
2538 };
2539
Yves Gerey665174f2018-06-19 15:03:05 +02002540 EXPECT_EQ(
2541 MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
2542 GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
2543 EXPECT_EQ(
2544 MAKE_VECTOR(kExpectedVideoRtpExtension),
2545 GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07002546
2547 // Nothing should change when creating a new offer
2548 std::unique_ptr<SessionDescription> updated_offer(
2549 f1_.CreateOffer(opts, offer.get()));
2550
2551 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
Yves Gerey665174f2018-06-19 15:03:05 +02002552 GetFirstAudioContentDescription(updated_offer.get())
2553 ->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07002554 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
Yves Gerey665174f2018-06-19 15:03:05 +02002555 GetFirstVideoContentDescription(updated_offer.get())
2556 ->rtp_header_extensions());
jbauch5869f502017-06-29 12:31:36 -07002557}
2558
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002559TEST(MediaSessionDescription, CopySessionDescription) {
2560 SessionDescription source;
2561 cricket::ContentGroup group(cricket::CN_AUDIO);
2562 source.AddGroup(group);
2563 AudioContentDescription* acd(new AudioContentDescription());
2564 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
2565 acd->AddLegacyStream(1);
Steve Anton5adfafd2017-12-20 16:34:00 -08002566 source.AddContent(cricket::CN_AUDIO, MediaProtocolType::kRtp, acd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002567 VideoContentDescription* vcd(new VideoContentDescription());
2568 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
2569 vcd->AddLegacyStream(2);
Steve Anton5adfafd2017-12-20 16:34:00 -08002570 source.AddContent(cricket::CN_VIDEO, MediaProtocolType::kRtp, vcd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002571
kwiberg31022942016-03-11 14:18:21 -08002572 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002573 ASSERT_TRUE(copy.get() != NULL);
2574 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
2575 const ContentInfo* ac = copy->GetContentByName("audio");
2576 const ContentInfo* vc = copy->GetContentByName("video");
2577 ASSERT_TRUE(ac != NULL);
2578 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08002579 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08002580 const AudioContentDescription* acd_copy = ac->media_description()->as_audio();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002581 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
2582 EXPECT_EQ(1u, acd->first_ssrc());
2583
Steve Anton5adfafd2017-12-20 16:34:00 -08002584 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
Steve Antonb1c1de12017-12-21 15:14:30 -08002585 const VideoContentDescription* vcd_copy = vc->media_description()->as_video();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002586 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
2587 EXPECT_EQ(2u, vcd->first_ssrc());
2588}
2589
2590// The below TestTransportInfoXXX tests create different offers/answers, and
2591// ensure the TransportInfo in the SessionDescription matches what we expect.
2592TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
2593 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002594 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2595 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002596 TestTransportInfo(true, options, false);
2597}
2598
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002599TEST_F(MediaSessionDescriptionFactoryTest,
2600 TestTransportInfoOfferIceRenomination) {
2601 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002602 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2603 kActive, &options);
zhihuang1c378ed2017-08-17 14:10:50 -07002604 options.media_description_options[0]
2605 .transport_options.enable_ice_renomination = true;
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002606 TestTransportInfo(true, options, false);
2607}
2608
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002609TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
2610 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002611 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2612 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002613 TestTransportInfo(true, options, true);
2614}
2615
2616TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2617 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002618 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2619 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2620 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002621 TestTransportInfo(true, options, false);
2622}
2623
2624TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02002625 TestTransportInfoOfferMultimediaCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002626 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002627 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2628 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2629 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002630 TestTransportInfo(true, options, true);
2631}
2632
2633TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2634 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002635 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2636 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2637 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002638 options.bundle_enabled = true;
2639 TestTransportInfo(true, options, false);
2640}
2641
2642TEST_F(MediaSessionDescriptionFactoryTest,
2643 TestTransportInfoOfferBundleCurrent) {
2644 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002645 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2646 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2647 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002648 options.bundle_enabled = true;
2649 TestTransportInfo(true, options, true);
2650}
2651
2652TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2653 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002654 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2655 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002656 TestTransportInfo(false, options, false);
2657}
2658
2659TEST_F(MediaSessionDescriptionFactoryTest,
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002660 TestTransportInfoAnswerIceRenomination) {
2661 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002662 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2663 kActive, &options);
zhihuang1c378ed2017-08-17 14:10:50 -07002664 options.media_description_options[0]
2665 .transport_options.enable_ice_renomination = true;
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002666 TestTransportInfo(false, options, false);
2667}
2668
2669TEST_F(MediaSessionDescriptionFactoryTest,
2670 TestTransportInfoAnswerAudioCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002671 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002672 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2673 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002674 TestTransportInfo(false, options, true);
2675}
2676
2677TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2678 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002679 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2680 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2681 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002682 TestTransportInfo(false, options, false);
2683}
2684
2685TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02002686 TestTransportInfoAnswerMultimediaCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002687 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002688 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2689 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2690 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002691 TestTransportInfo(false, options, true);
2692}
2693
2694TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2695 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002696 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2697 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2698 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002699 options.bundle_enabled = true;
2700 TestTransportInfo(false, options, false);
2701}
2702
2703TEST_F(MediaSessionDescriptionFactoryTest,
Yves Gerey665174f2018-06-19 15:03:05 +02002704 TestTransportInfoAnswerBundleCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002705 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002706 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2707 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2708 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002709 options.bundle_enabled = true;
2710 TestTransportInfo(false, options, true);
2711}
2712
2713// Create an offer with bundle enabled and verify the crypto parameters are
2714// the common set of the available cryptos.
2715TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2716 TestCryptoWithBundle(true);
2717}
2718
2719// Create an answer with bundle enabled and verify the crypto parameters are
2720// the common set of the available cryptos.
2721TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2722 TestCryptoWithBundle(false);
2723}
2724
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002725// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2726// DTLS is not enabled locally.
2727TEST_F(MediaSessionDescriptionFactoryTest,
2728 TestOfferDtlsSavpfWithoutDtlsFailed) {
2729 f1_.set_secure(SEC_ENABLED);
2730 f2_.set_secure(SEC_ENABLED);
2731 tdf1_.set_secure(SEC_DISABLED);
2732 tdf2_.set_secure(SEC_DISABLED);
2733
kwiberg31022942016-03-11 14:18:21 -08002734 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -07002735 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002736 ASSERT_TRUE(offer.get() != NULL);
2737 ContentInfo* offer_content = offer->GetContentByName("audio");
2738 ASSERT_TRUE(offer_content != NULL);
2739 AudioContentDescription* offer_audio_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -08002740 offer_content->media_description()->as_audio();
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002741 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2742
kwiberg31022942016-03-11 14:18:21 -08002743 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07002744 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002745 ASSERT_TRUE(answer != NULL);
2746 ContentInfo* answer_content = answer->GetContentByName("audio");
2747 ASSERT_TRUE(answer_content != NULL);
2748
2749 ASSERT_TRUE(answer_content->rejected);
2750}
2751
2752// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2753// UDP/TLS/RTP/SAVPF.
2754TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2755 f1_.set_secure(SEC_ENABLED);
2756 f2_.set_secure(SEC_ENABLED);
2757 tdf1_.set_secure(SEC_ENABLED);
2758 tdf2_.set_secure(SEC_ENABLED);
2759
kwiberg31022942016-03-11 14:18:21 -08002760 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -07002761 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002762 ASSERT_TRUE(offer.get() != NULL);
2763 ContentInfo* offer_content = offer->GetContentByName("audio");
2764 ASSERT_TRUE(offer_content != NULL);
2765 AudioContentDescription* offer_audio_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -08002766 offer_content->media_description()->as_audio();
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002767 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2768
kwiberg31022942016-03-11 14:18:21 -08002769 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07002770 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002771 ASSERT_TRUE(answer != NULL);
2772
2773 const ContentInfo* answer_content = answer->GetContentByName("audio");
2774 ASSERT_TRUE(answer_content != NULL);
2775 ASSERT_FALSE(answer_content->rejected);
2776
2777 const AudioContentDescription* answer_audio_desc =
Steve Antonb1c1de12017-12-21 15:14:30 -08002778 answer_content->media_description()->as_audio();
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002779 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
Yves Gerey665174f2018-06-19 15:03:05 +02002780 answer_audio_desc->protocol());
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002781}
2782
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002783// Test that we include both SDES and DTLS in the offer, but only include SDES
2784// in the answer if DTLS isn't negotiated.
2785TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2786 f1_.set_secure(SEC_ENABLED);
2787 f2_.set_secure(SEC_ENABLED);
2788 tdf1_.set_secure(SEC_ENABLED);
2789 tdf2_.set_secure(SEC_DISABLED);
2790 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002791 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
kwiberg31022942016-03-11 14:18:21 -08002792 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002793 const cricket::MediaContentDescription* audio_media_desc;
2794 const cricket::MediaContentDescription* video_media_desc;
2795 const cricket::TransportDescription* audio_trans_desc;
2796 const cricket::TransportDescription* video_trans_desc;
2797
2798 // Generate an offer with SDES and DTLS support.
2799 offer.reset(f1_.CreateOffer(options, NULL));
2800 ASSERT_TRUE(offer.get() != NULL);
2801
Steve Antonb1c1de12017-12-21 15:14:30 -08002802 audio_media_desc = offer->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002803 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002804 video_media_desc = offer->GetContentDescriptionByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002805 ASSERT_TRUE(video_media_desc != NULL);
Taylor Brandstetterfd350d72018-04-03 16:29:26 -07002806 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002807 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2808
2809 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2810 ASSERT_TRUE(audio_trans_desc != NULL);
2811 video_trans_desc = offer->GetTransportDescriptionByName("video");
2812 ASSERT_TRUE(video_trans_desc != NULL);
2813 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2814 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2815
2816 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2817 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2818 ASSERT_TRUE(answer.get() != NULL);
2819
Steve Antonb1c1de12017-12-21 15:14:30 -08002820 audio_media_desc = answer->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002821 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002822 video_media_desc = answer->GetContentDescriptionByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002823 ASSERT_TRUE(video_media_desc != NULL);
2824 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2825 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2826
2827 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2828 ASSERT_TRUE(audio_trans_desc != NULL);
2829 video_trans_desc = answer->GetTransportDescriptionByName("video");
2830 ASSERT_TRUE(video_trans_desc != NULL);
2831 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2832 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2833
2834 // Enable DTLS; the answer should now only have DTLS support.
2835 tdf2_.set_secure(SEC_ENABLED);
2836 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2837 ASSERT_TRUE(answer.get() != NULL);
2838
Steve Antonb1c1de12017-12-21 15:14:30 -08002839 audio_media_desc = answer->GetContentDescriptionByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002840 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002841 video_media_desc = answer->GetContentDescriptionByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002842 ASSERT_TRUE(video_media_desc != NULL);
2843 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2844 EXPECT_TRUE(video_media_desc->cryptos().empty());
2845 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2846 audio_media_desc->protocol());
2847 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2848 video_media_desc->protocol());
2849
2850 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2851 ASSERT_TRUE(audio_trans_desc != NULL);
2852 video_trans_desc = answer->GetTransportDescriptionByName("video");
2853 ASSERT_TRUE(video_trans_desc != NULL);
2854 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2855 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002856
2857 // Try creating offer again. DTLS enabled now, crypto's should be empty
2858 // in new offer.
2859 offer.reset(f1_.CreateOffer(options, offer.get()));
2860 ASSERT_TRUE(offer.get() != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002861 audio_media_desc = offer->GetContentDescriptionByName("audio");
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002862 ASSERT_TRUE(audio_media_desc != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08002863 video_media_desc = offer->GetContentDescriptionByName("video");
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002864 ASSERT_TRUE(video_media_desc != NULL);
2865 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2866 EXPECT_TRUE(video_media_desc->cryptos().empty());
2867
2868 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2869 ASSERT_TRUE(audio_trans_desc != NULL);
2870 video_trans_desc = offer->GetTransportDescriptionByName("video");
2871 ASSERT_TRUE(video_trans_desc != NULL);
2872 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2873 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002874}
2875
2876// Test that an answer can't be created if cryptos are required but the offer is
2877// unsecure.
2878TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07002879 MediaSessionOptions options = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002880 f1_.set_secure(SEC_DISABLED);
2881 tdf1_.set_secure(SEC_DISABLED);
2882 f2_.set_secure(SEC_REQUIRED);
2883 tdf1_.set_secure(SEC_ENABLED);
2884
kwiberg31022942016-03-11 14:18:21 -08002885 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002886 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002887 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002888 f2_.CreateAnswer(offer.get(), options, NULL));
2889 EXPECT_TRUE(answer.get() == NULL);
2890}
2891
2892// Test that we accept a DTLS offer without SDES and create an appropriate
2893// answer.
2894TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2895 f1_.set_secure(SEC_DISABLED);
2896 f2_.set_secure(SEC_ENABLED);
2897 tdf1_.set_secure(SEC_ENABLED);
2898 tdf2_.set_secure(SEC_ENABLED);
2899 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002900 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2901 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2902 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002903
kwiberg31022942016-03-11 14:18:21 -08002904 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002905
2906 // Generate an offer with DTLS but without SDES.
2907 offer.reset(f1_.CreateOffer(options, NULL));
2908 ASSERT_TRUE(offer.get() != NULL);
2909
2910 const AudioContentDescription* audio_offer =
2911 GetFirstAudioContentDescription(offer.get());
2912 ASSERT_TRUE(audio_offer->cryptos().empty());
2913 const VideoContentDescription* video_offer =
2914 GetFirstVideoContentDescription(offer.get());
2915 ASSERT_TRUE(video_offer->cryptos().empty());
2916 const DataContentDescription* data_offer =
2917 GetFirstDataContentDescription(offer.get());
2918 ASSERT_TRUE(data_offer->cryptos().empty());
2919
2920 const cricket::TransportDescription* audio_offer_trans_desc =
2921 offer->GetTransportDescriptionByName("audio");
2922 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2923 const cricket::TransportDescription* video_offer_trans_desc =
2924 offer->GetTransportDescriptionByName("video");
2925 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2926 const cricket::TransportDescription* data_offer_trans_desc =
2927 offer->GetTransportDescriptionByName("data");
2928 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2929
2930 // Generate an answer with DTLS.
2931 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2932 ASSERT_TRUE(answer.get() != NULL);
2933
2934 const cricket::TransportDescription* audio_answer_trans_desc =
2935 answer->GetTransportDescriptionByName("audio");
2936 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2937 const cricket::TransportDescription* video_answer_trans_desc =
2938 answer->GetTransportDescriptionByName("video");
2939 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2940 const cricket::TransportDescription* data_answer_trans_desc =
2941 answer->GetTransportDescriptionByName("data");
2942 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2943}
2944
2945// Verifies if vad_enabled option is set to false, CN codecs are not present in
2946// offer or answer.
2947TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2948 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002949 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
kwiberg31022942016-03-11 14:18:21 -08002950 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002951 ASSERT_TRUE(offer.get() != NULL);
2952 const ContentInfo* audio_content = offer->GetContentByName("audio");
2953 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2954
2955 options.vad_enabled = false;
2956 offer.reset(f1_.CreateOffer(options, NULL));
2957 ASSERT_TRUE(offer.get() != NULL);
2958 audio_content = offer->GetContentByName("audio");
2959 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08002960 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002961 f1_.CreateAnswer(offer.get(), options, NULL));
2962 ASSERT_TRUE(answer.get() != NULL);
2963 audio_content = answer->GetContentByName("audio");
2964 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2965}
deadbeef44f08192015-12-15 16:20:09 -08002966
zhihuang1c378ed2017-08-17 14:10:50 -07002967// Test that the generated MIDs match the existing offer.
2968TEST_F(MediaSessionDescriptionFactoryTest, TestMIDsMatchesExistingOffer) {
deadbeef44f08192015-12-15 16:20:09 -08002969 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002970 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_modified",
2971 RtpTransceiverDirection::kRecvOnly, kActive, &opts);
2972 AddMediaSection(MEDIA_TYPE_VIDEO, "video_modified",
2973 RtpTransceiverDirection::kRecvOnly, kActive, &opts);
deadbeef44f08192015-12-15 16:20:09 -08002974 opts.data_channel_type = cricket::DCT_SCTP;
Steve Anton4e70a722017-11-28 14:57:10 -08002975 AddMediaSection(MEDIA_TYPE_DATA, "data_modified",
2976 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07002977 // Create offer.
kwiberg31022942016-03-11 14:18:21 -08002978 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
kwiberg31022942016-03-11 14:18:21 -08002979 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08002980 f1_.CreateOffer(opts, offer.get()));
zhihuang1c378ed2017-08-17 14:10:50 -07002981
deadbeef44f08192015-12-15 16:20:09 -08002982 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
2983 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
2984 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
2985 ASSERT_TRUE(audio_content != nullptr);
2986 ASSERT_TRUE(video_content != nullptr);
2987 ASSERT_TRUE(data_content != nullptr);
2988 EXPECT_EQ("audio_modified", audio_content->name);
2989 EXPECT_EQ("video_modified", video_content->name);
2990 EXPECT_EQ("data_modified", data_content->name);
2991}
zhihuangcf5b37c2016-05-05 11:44:35 -07002992
zhihuang1c378ed2017-08-17 14:10:50 -07002993// The following tests verify that the unified plan SDP is supported.
2994// Test that we can create an offer with multiple media sections of same media
2995// type.
2996TEST_F(MediaSessionDescriptionFactoryTest,
2997 CreateOfferWithMultipleAVMediaSections) {
2998 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002999 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_1",
3000 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003001 AttachSenderToMediaSection("audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003002 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003003
Steve Anton4e70a722017-11-28 14:57:10 -08003004 AddMediaSection(MEDIA_TYPE_VIDEO, "video_1",
3005 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003006 AttachSenderToMediaSection("video_1", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003007 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003008
Steve Anton4e70a722017-11-28 14:57:10 -08003009 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_2",
3010 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003011 AttachSenderToMediaSection("audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003012 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003013
Steve Anton4e70a722017-11-28 14:57:10 -08003014 AddMediaSection(MEDIA_TYPE_VIDEO, "video_2",
3015 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003016 AttachSenderToMediaSection("video_2", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003017 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003018 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3019 ASSERT_TRUE(offer);
3020
3021 ASSERT_EQ(4u, offer->contents().size());
3022 EXPECT_FALSE(offer->contents()[0].rejected);
3023 const AudioContentDescription* acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003024 offer->contents()[0].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003025 ASSERT_EQ(1u, acd->streams().size());
3026 EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003027 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003028
3029 EXPECT_FALSE(offer->contents()[1].rejected);
3030 const VideoContentDescription* vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003031 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003032 ASSERT_EQ(1u, vcd->streams().size());
3033 EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003034 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003035
3036 EXPECT_FALSE(offer->contents()[2].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003037 acd = offer->contents()[2].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003038 ASSERT_EQ(1u, acd->streams().size());
3039 EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003040 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003041
3042 EXPECT_FALSE(offer->contents()[3].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003043 vcd = offer->contents()[3].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003044 ASSERT_EQ(1u, vcd->streams().size());
3045 EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003046 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003047}
3048
3049// Test that we can create an answer with multiple media sections of same media
3050// type.
3051TEST_F(MediaSessionDescriptionFactoryTest,
3052 CreateAnswerWithMultipleAVMediaSections) {
3053 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003054 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_1",
3055 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003056 AttachSenderToMediaSection("audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003057 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003058
Steve Anton4e70a722017-11-28 14:57:10 -08003059 AddMediaSection(MEDIA_TYPE_VIDEO, "video_1",
3060 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003061 AttachSenderToMediaSection("video_1", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003062 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003063
Steve Anton4e70a722017-11-28 14:57:10 -08003064 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_2",
3065 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003066 AttachSenderToMediaSection("audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003067 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003068
Steve Anton4e70a722017-11-28 14:57:10 -08003069 AddMediaSection(MEDIA_TYPE_VIDEO, "video_2",
3070 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003071 AttachSenderToMediaSection("video_2", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003072 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003073
3074 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3075 ASSERT_TRUE(offer);
3076 std::unique_ptr<SessionDescription> answer(
3077 f2_.CreateAnswer(offer.get(), opts, nullptr));
3078
3079 ASSERT_EQ(4u, answer->contents().size());
3080 EXPECT_FALSE(answer->contents()[0].rejected);
3081 const AudioContentDescription* acd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003082 answer->contents()[0].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003083 ASSERT_EQ(1u, acd->streams().size());
3084 EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003085 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003086
3087 EXPECT_FALSE(answer->contents()[1].rejected);
3088 const VideoContentDescription* vcd =
Steve Antonb1c1de12017-12-21 15:14:30 -08003089 answer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003090 ASSERT_EQ(1u, vcd->streams().size());
3091 EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003092 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003093
3094 EXPECT_FALSE(answer->contents()[2].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003095 acd = answer->contents()[2].media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003096 ASSERT_EQ(1u, acd->streams().size());
3097 EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003098 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003099
3100 EXPECT_FALSE(answer->contents()[3].rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003101 vcd = answer->contents()[3].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003102 ASSERT_EQ(1u, vcd->streams().size());
3103 EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003104 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003105}
3106
3107// Test that the media section will be rejected in offer if the corresponding
3108// MediaDescriptionOptions is stopped by the offerer.
3109TEST_F(MediaSessionDescriptionFactoryTest,
3110 CreateOfferWithMediaSectionStoppedByOfferer) {
3111 // Create an offer with two audio sections and one of them is stopped.
3112 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003113 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3114 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3115 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3116 RtpTransceiverDirection::kInactive, kStopped, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003117 std::unique_ptr<SessionDescription> offer(
3118 f1_.CreateOffer(offer_opts, nullptr));
3119 ASSERT_TRUE(offer);
3120 ASSERT_EQ(2u, offer->contents().size());
3121 EXPECT_FALSE(offer->contents()[0].rejected);
3122 EXPECT_TRUE(offer->contents()[1].rejected);
3123}
3124
3125// Test that the media section will be rejected in answer if the corresponding
3126// MediaDescriptionOptions is stopped by the offerer.
3127TEST_F(MediaSessionDescriptionFactoryTest,
3128 CreateAnswerWithMediaSectionStoppedByOfferer) {
3129 // Create an offer with two audio sections and one of them is stopped.
3130 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003131 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3132 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3133 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3134 RtpTransceiverDirection::kInactive, kStopped, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003135 std::unique_ptr<SessionDescription> offer(
3136 f1_.CreateOffer(offer_opts, nullptr));
3137 ASSERT_TRUE(offer);
3138 ASSERT_EQ(2u, offer->contents().size());
3139 EXPECT_FALSE(offer->contents()[0].rejected);
3140 EXPECT_TRUE(offer->contents()[1].rejected);
3141
3142 // Create an answer based on the offer.
3143 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003144 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3145 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
3146 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3147 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003148 std::unique_ptr<SessionDescription> answer(
3149 f2_.CreateAnswer(offer.get(), answer_opts, nullptr));
3150 ASSERT_EQ(2u, answer->contents().size());
3151 EXPECT_FALSE(answer->contents()[0].rejected);
3152 EXPECT_TRUE(answer->contents()[1].rejected);
3153}
3154
3155// Test that the media section will be rejected in answer if the corresponding
3156// MediaDescriptionOptions is stopped by the answerer.
3157TEST_F(MediaSessionDescriptionFactoryTest,
3158 CreateAnswerWithMediaSectionRejectedByAnswerer) {
3159 // Create an offer with two audio sections.
3160 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003161 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3162 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3163 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3164 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003165 std::unique_ptr<SessionDescription> offer(
3166 f1_.CreateOffer(offer_opts, nullptr));
3167 ASSERT_TRUE(offer);
3168 ASSERT_EQ(2u, offer->contents().size());
3169 ASSERT_FALSE(offer->contents()[0].rejected);
3170 ASSERT_FALSE(offer->contents()[1].rejected);
3171
3172 // The answerer rejects one of the audio sections.
3173 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003174 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3175 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
3176 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3177 RtpTransceiverDirection::kInactive, kStopped, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003178 std::unique_ptr<SessionDescription> answer(
3179 f2_.CreateAnswer(offer.get(), answer_opts, nullptr));
3180 ASSERT_EQ(2u, answer->contents().size());
3181 EXPECT_FALSE(answer->contents()[0].rejected);
3182 EXPECT_TRUE(answer->contents()[1].rejected);
Zhi Huang3518e7b2018-01-30 13:20:35 -08003183
3184 // The TransportInfo of the rejected m= section is expected to be added in the
3185 // answer.
3186 EXPECT_EQ(offer->transport_infos().size(), answer->transport_infos().size());
zhihuang1c378ed2017-08-17 14:10:50 -07003187}
3188
3189// Test the generated media sections has the same order of the
3190// corresponding MediaDescriptionOptions.
3191TEST_F(MediaSessionDescriptionFactoryTest,
3192 CreateOfferRespectsMediaDescriptionOptionsOrder) {
3193 MediaSessionOptions opts;
3194 // This tests put video section first because normally audio comes first by
3195 // default.
Steve Anton4e70a722017-11-28 14:57:10 -08003196 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3197 kActive, &opts);
3198 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
3199 kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003200 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3201
3202 ASSERT_TRUE(offer);
3203 ASSERT_EQ(2u, offer->contents().size());
3204 EXPECT_EQ("video", offer->contents()[0].name);
3205 EXPECT_EQ("audio", offer->contents()[1].name);
3206}
3207
3208// Test that different media sections using the same codec have same payload
3209// type.
3210TEST_F(MediaSessionDescriptionFactoryTest,
3211 PayloadTypesSharedByMediaSectionsOfSameType) {
3212 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003213 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3214 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3215 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3216 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003217 // Create an offer with two video sections using same codecs.
3218 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3219 ASSERT_TRUE(offer);
3220 ASSERT_EQ(2u, offer->contents().size());
3221 const VideoContentDescription* vcd1 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003222 offer->contents()[0].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003223 const VideoContentDescription* vcd2 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003224 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003225 EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
3226 ASSERT_EQ(2u, vcd1->codecs().size());
3227 EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
3228 EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
3229 EXPECT_EQ(vcd1->codecs()[1].name, vcd2->codecs()[1].name);
3230 EXPECT_EQ(vcd1->codecs()[1].id, vcd2->codecs()[1].id);
3231
3232 // Create answer and negotiate the codecs.
3233 std::unique_ptr<SessionDescription> answer(
3234 f2_.CreateAnswer(offer.get(), opts, nullptr));
3235 ASSERT_TRUE(answer);
3236 ASSERT_EQ(2u, answer->contents().size());
Steve Antonb1c1de12017-12-21 15:14:30 -08003237 vcd1 = answer->contents()[0].media_description()->as_video();
3238 vcd2 = answer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003239 EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
3240 ASSERT_EQ(1u, vcd1->codecs().size());
3241 EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
3242 EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
3243}
3244
3245// Test that the codec preference order per media section is respected in
3246// subsequent offer.
3247TEST_F(MediaSessionDescriptionFactoryTest,
3248 CreateOfferRespectsCodecPreferenceOrder) {
3249 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003250 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3251 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3252 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3253 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003254 // Create an offer with two video sections using same codecs.
3255 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3256 ASSERT_TRUE(offer);
3257 ASSERT_EQ(2u, offer->contents().size());
3258 VideoContentDescription* vcd1 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003259 offer->contents()[0].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003260 const VideoContentDescription* vcd2 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003261 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003262 auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
3263 EXPECT_EQ(video_codecs, vcd1->codecs());
3264 EXPECT_EQ(video_codecs, vcd2->codecs());
3265
3266 // Change the codec preference of the first video section and create a
3267 // follow-up offer.
3268 auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
3269 vcd1->set_codecs(video_codecs_reverse);
3270 std::unique_ptr<SessionDescription> updated_offer(
3271 f1_.CreateOffer(opts, offer.get()));
Steve Antonb1c1de12017-12-21 15:14:30 -08003272 vcd1 = updated_offer->contents()[0].media_description()->as_video();
3273 vcd2 = updated_offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003274 // The video codec preference order should be respected.
3275 EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
3276 EXPECT_EQ(video_codecs, vcd2->codecs());
3277}
3278
3279// Test that the codec preference order per media section is respected in
3280// the answer.
3281TEST_F(MediaSessionDescriptionFactoryTest,
3282 CreateAnswerRespectsCodecPreferenceOrder) {
3283 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003284 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3285 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3286 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3287 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003288 // Create an offer with two video sections using same codecs.
3289 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3290 ASSERT_TRUE(offer);
3291 ASSERT_EQ(2u, offer->contents().size());
3292 VideoContentDescription* vcd1 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003293 offer->contents()[0].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003294 const VideoContentDescription* vcd2 =
Steve Antonb1c1de12017-12-21 15:14:30 -08003295 offer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003296 auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
3297 EXPECT_EQ(video_codecs, vcd1->codecs());
3298 EXPECT_EQ(video_codecs, vcd2->codecs());
3299
3300 // Change the codec preference of the first video section and create an
3301 // answer.
3302 auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
3303 vcd1->set_codecs(video_codecs_reverse);
3304 std::unique_ptr<SessionDescription> answer(
3305 f1_.CreateAnswer(offer.get(), opts, nullptr));
Steve Antonb1c1de12017-12-21 15:14:30 -08003306 vcd1 = answer->contents()[0].media_description()->as_video();
3307 vcd2 = answer->contents()[1].media_description()->as_video();
zhihuang1c378ed2017-08-17 14:10:50 -07003308 // The video codec preference order should be respected.
3309 EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
3310 EXPECT_EQ(video_codecs, vcd2->codecs());
3311}
3312
Zhi Huang6f367472017-11-22 13:20:02 -08003313// Test that when creating an answer, the codecs use local parameters instead of
3314// the remote ones.
3315TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerWithLocalCodecParams) {
3316 const std::string audio_param_name = "audio_param";
3317 const std::string audio_value1 = "audio_v1";
3318 const std::string audio_value2 = "audio_v2";
3319 const std::string video_param_name = "video_param";
3320 const std::string video_value1 = "video_v1";
3321 const std::string video_value2 = "video_v2";
3322
3323 auto audio_codecs1 = MAKE_VECTOR(kAudioCodecs1);
3324 auto audio_codecs2 = MAKE_VECTOR(kAudioCodecs1);
3325 auto video_codecs1 = MAKE_VECTOR(kVideoCodecs1);
3326 auto video_codecs2 = MAKE_VECTOR(kVideoCodecs1);
3327
3328 // Set the parameters for codecs.
3329 audio_codecs1[0].SetParam(audio_param_name, audio_value1);
3330 video_codecs1[0].SetParam(video_param_name, video_value1);
3331 audio_codecs2[0].SetParam(audio_param_name, audio_value2);
3332 video_codecs2[0].SetParam(video_param_name, video_value2);
3333
3334 f1_.set_audio_codecs(audio_codecs1, audio_codecs1);
3335 f1_.set_video_codecs(video_codecs1);
3336 f2_.set_audio_codecs(audio_codecs2, audio_codecs2);
3337 f2_.set_video_codecs(video_codecs2);
3338
3339 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003340 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
3341 kActive, &opts);
3342 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3343 kActive, &opts);
Zhi Huang6f367472017-11-22 13:20:02 -08003344
3345 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3346 ASSERT_TRUE(offer);
Steve Antonb1c1de12017-12-21 15:14:30 -08003347 auto offer_acd = offer->contents()[0].media_description()->as_audio();
3348 auto offer_vcd = offer->contents()[1].media_description()->as_video();
Zhi Huang6f367472017-11-22 13:20:02 -08003349 std::string value;
3350 EXPECT_TRUE(offer_acd->codecs()[0].GetParam(audio_param_name, &value));
3351 EXPECT_EQ(audio_value1, value);
3352 EXPECT_TRUE(offer_vcd->codecs()[0].GetParam(video_param_name, &value));
3353 EXPECT_EQ(video_value1, value);
3354
3355 std::unique_ptr<SessionDescription> answer(
3356 f2_.CreateAnswer(offer.get(), opts, nullptr));
3357 ASSERT_TRUE(answer);
Steve Antonb1c1de12017-12-21 15:14:30 -08003358 auto answer_acd = answer->contents()[0].media_description()->as_audio();
3359 auto answer_vcd = answer->contents()[1].media_description()->as_video();
Zhi Huang6f367472017-11-22 13:20:02 -08003360 // Use the parameters from the local codecs.
3361 EXPECT_TRUE(answer_acd->codecs()[0].GetParam(audio_param_name, &value));
3362 EXPECT_EQ(audio_value2, value);
3363 EXPECT_TRUE(answer_vcd->codecs()[0].GetParam(video_param_name, &value));
3364 EXPECT_EQ(video_value2, value);
3365}
3366
Steve Anton9c1fb1e2018-02-26 15:09:41 -08003367// Test that matching packetization-mode is part of the criteria for matching
3368// H264 codecs (in addition to profile-level-id). Previously, this was not the
3369// case, so the first H264 codec with the same profile-level-id would match and
3370// the payload type in the answer would be incorrect.
3371// This is a regression test for bugs.webrtc.org/8808
3372TEST_F(MediaSessionDescriptionFactoryTest,
3373 H264MatchCriteriaIncludesPacketizationMode) {
3374 // Create two H264 codecs with the same profile level ID and different
3375 // packetization modes.
3376 VideoCodec h264_pm0(96, "H264");
3377 h264_pm0.params[cricket::kH264FmtpProfileLevelId] = "42c01f";
3378 h264_pm0.params[cricket::kH264FmtpPacketizationMode] = "0";
3379 VideoCodec h264_pm1(97, "H264");
3380 h264_pm1.params[cricket::kH264FmtpProfileLevelId] = "42c01f";
3381 h264_pm1.params[cricket::kH264FmtpPacketizationMode] = "1";
3382
3383 // Offerer will send both codecs, answerer should choose the one with matching
3384 // packetization mode (and not the first one it sees).
3385 f1_.set_video_codecs({h264_pm0, h264_pm1});
3386 f2_.set_video_codecs({h264_pm1});
3387
3388 MediaSessionOptions opts;
3389 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3390 kActive, &opts);
3391
3392 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3393 ASSERT_TRUE(offer);
3394
3395 std::unique_ptr<SessionDescription> answer(
3396 f2_.CreateAnswer(offer.get(), opts, nullptr));
3397 ASSERT_TRUE(answer);
3398
3399 // Answer should have one negotiated codec with packetization-mode=1 using the
3400 // offered payload type.
3401 ASSERT_EQ(1u, answer->contents().size());
3402 auto answer_vcd = answer->contents()[0].media_description()->as_video();
3403 ASSERT_EQ(1u, answer_vcd->codecs().size());
3404 auto answer_codec = answer_vcd->codecs()[0];
3405 EXPECT_EQ(h264_pm1.id, answer_codec.id);
3406}
3407
zhihuangcf5b37c2016-05-05 11:44:35 -07003408class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
3409 public:
3410 MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -07003411 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
3412 MAKE_VECTOR(kAudioCodecs1));
zhihuangcf5b37c2016-05-05 11:44:35 -07003413 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
3414 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -07003415 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
3416 MAKE_VECTOR(kAudioCodecs2));
zhihuangcf5b37c2016-05-05 11:44:35 -07003417 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
3418 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
3419 f1_.set_secure(SEC_ENABLED);
3420 f2_.set_secure(SEC_ENABLED);
3421 tdf1_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07003422 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07003423 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07003424 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07003425 tdf1_.set_secure(SEC_ENABLED);
3426 tdf2_.set_secure(SEC_ENABLED);
3427 }
3428
3429 protected:
3430 MediaSessionDescriptionFactory f1_;
3431 MediaSessionDescriptionFactory f2_;
3432 TransportDescriptionFactory tdf1_;
3433 TransportDescriptionFactory tdf2_;
3434};
3435
3436TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
3437 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003438 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
zhihuangcf5b37c2016-05-05 11:44:35 -07003439 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3440 ASSERT_TRUE(offer.get() != nullptr);
3441 // Set the protocol for all the contents.
3442 for (auto content : offer.get()->contents()) {
Steve Antonb1c1de12017-12-21 15:14:30 -08003443 content.media_description()->set_protocol(GetParam());
zhihuangcf5b37c2016-05-05 11:44:35 -07003444 }
3445 std::unique_ptr<SessionDescription> answer(
3446 f2_.CreateAnswer(offer.get(), opts, nullptr));
3447 const ContentInfo* ac = answer->GetContentByName("audio");
3448 const ContentInfo* vc = answer->GetContentByName("video");
3449 ASSERT_TRUE(ac != nullptr);
3450 ASSERT_TRUE(vc != nullptr);
3451 EXPECT_FALSE(ac->rejected); // the offer is accepted
3452 EXPECT_FALSE(vc->rejected);
Steve Antonb1c1de12017-12-21 15:14:30 -08003453 const AudioContentDescription* acd = ac->media_description()->as_audio();
3454 const VideoContentDescription* vcd = vc->media_description()->as_video();
zhihuangcf5b37c2016-05-05 11:44:35 -07003455 EXPECT_EQ(GetParam(), acd->protocol());
3456 EXPECT_EQ(GetParam(), vcd->protocol());
3457}
3458
3459INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest,
3460 MediaProtocolTest,
3461 ::testing::ValuesIn(kMediaProtocols));
3462INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest,
3463 MediaProtocolTest,
3464 ::testing::ValuesIn(kMediaProtocolsDtls));
ossu075af922016-06-14 03:29:38 -07003465
3466TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) {
3467 TransportDescriptionFactory tdf;
3468 MediaSessionDescriptionFactory sf(&tdf);
3469 std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
3470 std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
3471
3472 // The merged list of codecs should contain any send codecs that are also
3473 // nominally in the recieve codecs list. Payload types should be picked from
3474 // the send codecs and a number-of-channels of 0 and 1 should be equivalent
3475 // (set to 1). This equals what happens when the send codecs are used in an
3476 // offer and the receive codecs are used in the following answer.
3477 const std::vector<AudioCodec> sendrecv_codecs =
3478 MAKE_VECTOR(kAudioCodecsAnswer);
3479 const std::vector<AudioCodec> no_codecs;
3480
3481 RTC_CHECK_EQ(send_codecs[1].name, "iLBC")
3482 << "Please don't change shared test data!";
3483 RTC_CHECK_EQ(recv_codecs[2].name, "iLBC")
3484 << "Please don't change shared test data!";
3485 // Alter iLBC send codec to have zero channels, to test that that is handled
3486 // properly.
3487 send_codecs[1].channels = 0;
3488
3489 // Alther iLBC receive codec to be lowercase, to test that case conversions
3490 // are handled properly.
3491 recv_codecs[2].name = "ilbc";
3492
3493 // Test proper merge
3494 sf.set_audio_codecs(send_codecs, recv_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003495 EXPECT_EQ(send_codecs, sf.audio_send_codecs());
3496 EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
3497 EXPECT_EQ(sendrecv_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003498
3499 // Test empty send codecs list
3500 sf.set_audio_codecs(no_codecs, recv_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003501 EXPECT_EQ(no_codecs, sf.audio_send_codecs());
3502 EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
3503 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003504
3505 // Test empty recv codecs list
3506 sf.set_audio_codecs(send_codecs, no_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003507 EXPECT_EQ(send_codecs, sf.audio_send_codecs());
3508 EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
3509 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003510
3511 // Test all empty codec lists
3512 sf.set_audio_codecs(no_codecs, no_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003513 EXPECT_EQ(no_codecs, sf.audio_send_codecs());
3514 EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
3515 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003516}
3517
3518namespace {
zhihuang1c378ed2017-08-17 14:10:50 -07003519// Compare the two vectors of codecs ignoring the payload type.
3520template <class Codec>
3521bool CodecsMatch(const std::vector<Codec>& codecs1,
3522 const std::vector<Codec>& codecs2) {
3523 if (codecs1.size() != codecs2.size()) {
3524 return false;
3525 }
3526
3527 for (size_t i = 0; i < codecs1.size(); ++i) {
3528 if (!codecs1[i].Matches(codecs2[i])) {
3529 return false;
3530 }
3531 }
3532 return true;
3533}
3534
Steve Anton4e70a722017-11-28 14:57:10 -08003535void TestAudioCodecsOffer(RtpTransceiverDirection direction) {
ossu075af922016-06-14 03:29:38 -07003536 TransportDescriptionFactory tdf;
3537 MediaSessionDescriptionFactory sf(&tdf);
3538 const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
3539 const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
3540 const std::vector<AudioCodec> sendrecv_codecs =
3541 MAKE_VECTOR(kAudioCodecsAnswer);
3542 sf.set_audio_codecs(send_codecs, recv_codecs);
ossu075af922016-06-14 03:29:38 -07003543
3544 MediaSessionOptions opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003545 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", direction, kActive, &opts);
3546
Steve Anton4e70a722017-11-28 14:57:10 -08003547 if (direction == RtpTransceiverDirection::kSendRecv ||
3548 direction == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003549 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003550 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003551 }
ossu075af922016-06-14 03:29:38 -07003552
3553 std::unique_ptr<SessionDescription> offer(sf.CreateOffer(opts, NULL));
3554 ASSERT_TRUE(offer.get() != NULL);
Steve Antonb1c1de12017-12-21 15:14:30 -08003555 ContentInfo* ac = offer->GetContentByName("audio");
ossu075af922016-06-14 03:29:38 -07003556
3557 // If the factory didn't add any audio content to the offer, we cannot check
zhihuang1c378ed2017-08-17 14:10:50 -07003558 // that the codecs put in are right. This happens when we neither want to
3559 // send nor receive audio. The checks are still in place if at some point
3560 // we'd instead create an inactive stream.
ossu075af922016-06-14 03:29:38 -07003561 if (ac) {
Steve Antonb1c1de12017-12-21 15:14:30 -08003562 AudioContentDescription* acd = ac->media_description()->as_audio();
zhihuang1c378ed2017-08-17 14:10:50 -07003563 // sendrecv and inactive should both present lists as if the channel was
3564 // to be used for sending and receiving. Inactive essentially means it
3565 // might eventually be used anything, but we don't know more at this
3566 // moment.
Steve Anton4e70a722017-11-28 14:57:10 -08003567 if (acd->direction() == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003568 EXPECT_TRUE(CodecsMatch<AudioCodec>(send_codecs, acd->codecs()));
Steve Anton4e70a722017-11-28 14:57:10 -08003569 } else if (acd->direction() == RtpTransceiverDirection::kRecvOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003570 EXPECT_TRUE(CodecsMatch<AudioCodec>(recv_codecs, acd->codecs()));
ossu075af922016-06-14 03:29:38 -07003571 } else {
zhihuang1c378ed2017-08-17 14:10:50 -07003572 EXPECT_TRUE(CodecsMatch<AudioCodec>(sendrecv_codecs, acd->codecs()));
ossu075af922016-06-14 03:29:38 -07003573 }
3574 }
3575}
3576
3577static const AudioCodec kOfferAnswerCodecs[] = {
zhihuang1c378ed2017-08-17 14:10:50 -07003578 AudioCodec(0, "codec0", 16000, -1, 1),
3579 AudioCodec(1, "codec1", 8000, 13300, 1),
3580 AudioCodec(2, "codec2", 8000, 64000, 1),
3581 AudioCodec(3, "codec3", 8000, 64000, 1),
3582 AudioCodec(4, "codec4", 8000, 0, 2),
3583 AudioCodec(5, "codec5", 32000, 0, 1),
3584 AudioCodec(6, "codec6", 48000, 0, 1)};
ossu075af922016-06-14 03:29:38 -07003585
zhihuang1c378ed2017-08-17 14:10:50 -07003586/* The codecs groups below are chosen as per the matrix below. The objective
3587 * is to have different sets of codecs in the inputs, to get unique sets of
3588 * codecs after negotiation, depending on offer and answer communication
3589 * directions. One-way directions in the offer should either result in the
3590 * opposite direction in the answer, or an inactive answer. Regardless, the
3591 * choice of codecs should be as if the answer contained the opposite
3592 * direction. Inactive offers should be treated as sendrecv/sendrecv.
ossu075af922016-06-14 03:29:38 -07003593 *
3594 * | Offer | Answer | Result
3595 * codec|send recv sr | send recv sr | s/r r/s sr/s sr/r sr/sr
3596 * 0 | x - - | - x - | x - - - -
3597 * 1 | x x x | - x - | x - - x -
3598 * 2 | - x - | x - - | - x - - -
3599 * 3 | x x x | x - - | - x x - -
3600 * 4 | - x - | x x x | - x - - -
3601 * 5 | x - - | x x x | x - - - -
3602 * 6 | x x x | x x x | x x x x x
3603 */
3604// Codecs used by offerer in the AudioCodecsAnswerTest
zhihuang1c378ed2017-08-17 14:10:50 -07003605static const int kOfferSendCodecs[] = {0, 1, 3, 5, 6};
3606static const int kOfferRecvCodecs[] = {1, 2, 3, 4, 6};
ossu075af922016-06-14 03:29:38 -07003607// Codecs used in the answerer in the AudioCodecsAnswerTest. The order is
3608// jumbled to catch the answer not following the order in the offer.
zhihuang1c378ed2017-08-17 14:10:50 -07003609static const int kAnswerSendCodecs[] = {6, 5, 2, 3, 4};
3610static const int kAnswerRecvCodecs[] = {6, 5, 4, 1, 0};
ossu075af922016-06-14 03:29:38 -07003611// The resulting sets of codecs in the answer in the AudioCodecsAnswerTest
zhihuang1c378ed2017-08-17 14:10:50 -07003612static const int kResultSend_RecvCodecs[] = {0, 1, 5, 6};
3613static const int kResultRecv_SendCodecs[] = {2, 3, 4, 6};
3614static const int kResultSendrecv_SendCodecs[] = {3, 6};
3615static const int kResultSendrecv_RecvCodecs[] = {1, 6};
3616static const int kResultSendrecv_SendrecvCodecs[] = {6};
ossu075af922016-06-14 03:29:38 -07003617
3618template <typename T, int IDXS>
3619std::vector<T> VectorFromIndices(const T* array, const int (&indices)[IDXS]) {
3620 std::vector<T> out;
3621 out.reserve(IDXS);
3622 for (int idx : indices)
3623 out.push_back(array[idx]);
3624
3625 return out;
3626}
3627
Steve Anton4e70a722017-11-28 14:57:10 -08003628void TestAudioCodecsAnswer(RtpTransceiverDirection offer_direction,
3629 RtpTransceiverDirection answer_direction,
ossu075af922016-06-14 03:29:38 -07003630 bool add_legacy_stream) {
3631 TransportDescriptionFactory offer_tdf;
3632 TransportDescriptionFactory answer_tdf;
3633 MediaSessionDescriptionFactory offer_factory(&offer_tdf);
3634 MediaSessionDescriptionFactory answer_factory(&answer_tdf);
3635 offer_factory.set_audio_codecs(
3636 VectorFromIndices(kOfferAnswerCodecs, kOfferSendCodecs),
3637 VectorFromIndices(kOfferAnswerCodecs, kOfferRecvCodecs));
3638 answer_factory.set_audio_codecs(
3639 VectorFromIndices(kOfferAnswerCodecs, kAnswerSendCodecs),
3640 VectorFromIndices(kOfferAnswerCodecs, kAnswerRecvCodecs));
3641
ossu075af922016-06-14 03:29:38 -07003642 MediaSessionOptions offer_opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003643 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", offer_direction, kActive,
3644 &offer_opts);
3645
Steve Anton4e70a722017-11-28 14:57:10 -08003646 if (webrtc::RtpTransceiverDirectionHasSend(offer_direction)) {
zhihuang1c378ed2017-08-17 14:10:50 -07003647 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003648 {kMediaStream1}, 1, &offer_opts);
ossu075af922016-06-14 03:29:38 -07003649 }
3650
3651 std::unique_ptr<SessionDescription> offer(
3652 offer_factory.CreateOffer(offer_opts, NULL));
3653 ASSERT_TRUE(offer.get() != NULL);
3654
3655 MediaSessionOptions answer_opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003656 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", answer_direction, kActive,
3657 &answer_opts);
3658
Steve Anton4e70a722017-11-28 14:57:10 -08003659 if (webrtc::RtpTransceiverDirectionHasSend(answer_direction)) {
zhihuang1c378ed2017-08-17 14:10:50 -07003660 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003661 {kMediaStream1}, 1, &answer_opts);
ossu075af922016-06-14 03:29:38 -07003662 }
3663 std::unique_ptr<SessionDescription> answer(
3664 answer_factory.CreateAnswer(offer.get(), answer_opts, NULL));
3665 const ContentInfo* ac = answer->GetContentByName("audio");
3666
zhihuang1c378ed2017-08-17 14:10:50 -07003667 // If the factory didn't add any audio content to the answer, we cannot
3668 // check that the codecs put in are right. This happens when we neither want
3669 // to send nor receive audio. The checks are still in place if at some point
3670 // we'd instead create an inactive stream.
ossu075af922016-06-14 03:29:38 -07003671 if (ac) {
Steve Antonb1c1de12017-12-21 15:14:30 -08003672 ASSERT_EQ(MEDIA_TYPE_AUDIO, ac->media_description()->type());
3673 const AudioContentDescription* acd = ac->media_description()->as_audio();
ossu075af922016-06-14 03:29:38 -07003674
ossu075af922016-06-14 03:29:38 -07003675 std::vector<AudioCodec> target_codecs;
3676 // For offers with sendrecv or inactive, we should never reply with more
3677 // codecs than offered, with these codec sets.
3678 switch (offer_direction) {
Steve Anton4e70a722017-11-28 14:57:10 -08003679 case RtpTransceiverDirection::kInactive:
ossu075af922016-06-14 03:29:38 -07003680 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3681 kResultSendrecv_SendrecvCodecs);
3682 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003683 case RtpTransceiverDirection::kSendOnly:
zhihuang1c378ed2017-08-17 14:10:50 -07003684 target_codecs =
3685 VectorFromIndices(kOfferAnswerCodecs, kResultSend_RecvCodecs);
ossu075af922016-06-14 03:29:38 -07003686 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003687 case RtpTransceiverDirection::kRecvOnly:
zhihuang1c378ed2017-08-17 14:10:50 -07003688 target_codecs =
3689 VectorFromIndices(kOfferAnswerCodecs, kResultRecv_SendCodecs);
ossu075af922016-06-14 03:29:38 -07003690 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003691 case RtpTransceiverDirection::kSendRecv:
3692 if (acd->direction() == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003693 target_codecs =
3694 VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_SendCodecs);
Steve Anton4e70a722017-11-28 14:57:10 -08003695 } else if (acd->direction() == RtpTransceiverDirection::kRecvOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003696 target_codecs =
3697 VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_RecvCodecs);
ossu075af922016-06-14 03:29:38 -07003698 } else {
3699 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3700 kResultSendrecv_SendrecvCodecs);
3701 }
3702 break;
3703 }
3704
zhihuang1c378ed2017-08-17 14:10:50 -07003705 auto format_codecs = [](const std::vector<AudioCodec>& codecs) {
ossu075af922016-06-14 03:29:38 -07003706 std::stringstream os;
3707 bool first = true;
3708 os << "{";
3709 for (const auto& c : codecs) {
3710 os << (first ? " " : ", ") << c.id;
3711 first = false;
3712 }
3713 os << " }";
3714 return os.str();
3715 };
3716
3717 EXPECT_TRUE(acd->codecs() == target_codecs)
3718 << "Expected: " << format_codecs(target_codecs)
Steve Anton4e70a722017-11-28 14:57:10 -08003719 << ", got: " << format_codecs(acd->codecs()) << "; Offered: "
3720 << webrtc::RtpTransceiverDirectionToString(offer_direction)
ossu075af922016-06-14 03:29:38 -07003721 << ", answerer wants: "
Steve Anton4e70a722017-11-28 14:57:10 -08003722 << webrtc::RtpTransceiverDirectionToString(answer_direction)
3723 << "; got: "
3724 << webrtc::RtpTransceiverDirectionToString(acd->direction());
ossu075af922016-06-14 03:29:38 -07003725 } else {
Steve Anton4e70a722017-11-28 14:57:10 -08003726 EXPECT_EQ(offer_direction, RtpTransceiverDirection::kInactive)
zhihuang1c378ed2017-08-17 14:10:50 -07003727 << "Only inactive offers are allowed to not generate any audio "
3728 "content";
ossu075af922016-06-14 03:29:38 -07003729 }
3730}
brandtr03d5fb12016-11-22 03:37:59 -08003731
3732} // namespace
ossu075af922016-06-14 03:29:38 -07003733
3734class AudioCodecsOfferTest
Steve Anton4e70a722017-11-28 14:57:10 -08003735 : public ::testing::TestWithParam<RtpTransceiverDirection> {};
ossu075af922016-06-14 03:29:38 -07003736
3737TEST_P(AudioCodecsOfferTest, TestCodecsInOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07003738 TestAudioCodecsOffer(GetParam());
ossu075af922016-06-14 03:29:38 -07003739}
3740
3741INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
3742 AudioCodecsOfferTest,
Steve Anton4e70a722017-11-28 14:57:10 -08003743 ::testing::Values(RtpTransceiverDirection::kSendOnly,
3744 RtpTransceiverDirection::kRecvOnly,
3745 RtpTransceiverDirection::kSendRecv,
3746 RtpTransceiverDirection::kInactive));
ossu075af922016-06-14 03:29:38 -07003747
3748class AudioCodecsAnswerTest
Steve Anton4e70a722017-11-28 14:57:10 -08003749 : public ::testing::TestWithParam<::testing::tuple<RtpTransceiverDirection,
3750 RtpTransceiverDirection,
zhihuang1c378ed2017-08-17 14:10:50 -07003751 bool>> {};
ossu075af922016-06-14 03:29:38 -07003752
3753TEST_P(AudioCodecsAnswerTest, TestCodecsInAnswer) {
ehmaldonadoabcef5d2017-02-08 04:07:11 -08003754 TestAudioCodecsAnswer(::testing::get<0>(GetParam()),
3755 ::testing::get<1>(GetParam()),
3756 ::testing::get<2>(GetParam()));
ossu075af922016-06-14 03:29:38 -07003757}
3758
zhihuang1c378ed2017-08-17 14:10:50 -07003759INSTANTIATE_TEST_CASE_P(
3760 MediaSessionDescriptionFactoryTest,
3761 AudioCodecsAnswerTest,
Steve Anton4e70a722017-11-28 14:57:10 -08003762 ::testing::Combine(::testing::Values(RtpTransceiverDirection::kSendOnly,
3763 RtpTransceiverDirection::kRecvOnly,
3764 RtpTransceiverDirection::kSendRecv,
3765 RtpTransceiverDirection::kInactive),
3766 ::testing::Values(RtpTransceiverDirection::kSendOnly,
3767 RtpTransceiverDirection::kRecvOnly,
3768 RtpTransceiverDirection::kSendRecv,
3769 RtpTransceiverDirection::kInactive),
zhihuang1c378ed2017-08-17 14:10:50 -07003770 ::testing::Bool()));