blob: d83d87d8218aea4e4d82d7f2a881085363326e6e [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
henrike@webrtc.org28e20752013-07-10 00:45:36 +000029#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000030 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[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070085 AudioCodec(126, "speex", 16000, 22000, 1),
86 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
zhihuang1c378ed2017-08-17 14:10:50 -0700216// These constants are used to make the code using "AddMediaSection" more
217// readable.
218static constexpr bool kStopped = true;
219static constexpr bool kActive = false;
220
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000221static bool IsMediaContentOfType(const ContentInfo* content,
222 MediaType media_type) {
223 const MediaContentDescription* mdesc =
224 static_cast<const MediaContentDescription*>(content->description);
225 return mdesc && mdesc->type() == media_type;
226}
227
Steve Anton4e70a722017-11-28 14:57:10 -0800228static RtpTransceiverDirection GetMediaDirection(const ContentInfo* content) {
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000229 cricket::MediaContentDescription* desc =
230 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
231 return desc->direction();
232}
233
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000234static void AddRtxCodec(const VideoCodec& rtx_codec,
235 std::vector<VideoCodec>* codecs) {
magjedb05fa242016-11-11 04:00:16 -0800236 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000237 codecs->push_back(rtx_codec);
238}
239
240template <class T>
241static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
242 std::vector<std::string> codec_names;
243 for (const auto& codec : codecs) {
244 codec_names.push_back(codec.name);
245 }
246 return codec_names;
247}
248
zhihuang1c378ed2017-08-17 14:10:50 -0700249// This is used for test only. MIDs are not the identification of the
250// MediaDescriptionOptions since some end points may not support MID and the SDP
251// may not contain 'mid'.
252std::vector<MediaDescriptionOptions>::iterator FindFirstMediaDescriptionByMid(
253 const std::string& mid,
254 MediaSessionOptions* opts) {
255 return std::find_if(
256 opts->media_description_options.begin(),
257 opts->media_description_options.end(),
Steve Anton36b29d12017-10-30 09:57:42 -0700258 [&mid](const MediaDescriptionOptions& t) { return t.mid == mid; });
259}
260
261std::vector<MediaDescriptionOptions>::const_iterator
262FindFirstMediaDescriptionByMid(const std::string& mid,
263 const MediaSessionOptions& opts) {
264 return std::find_if(
265 opts.media_description_options.begin(),
266 opts.media_description_options.end(),
267 [&mid](const MediaDescriptionOptions& t) { return t.mid == mid; });
zhihuang1c378ed2017-08-17 14:10:50 -0700268}
269
270// Add a media section to the |session_options|.
271static void AddMediaSection(MediaType type,
272 const std::string& mid,
Steve Anton4e70a722017-11-28 14:57:10 -0800273 RtpTransceiverDirection direction,
zhihuang1c378ed2017-08-17 14:10:50 -0700274 bool stopped,
275 MediaSessionOptions* opts) {
Steve Anton4e70a722017-11-28 14:57:10 -0800276 opts->media_description_options.push_back(
277 MediaDescriptionOptions(type, mid, direction, stopped));
zhihuang1c378ed2017-08-17 14:10:50 -0700278}
279
Steve Anton4e70a722017-11-28 14:57:10 -0800280static void AddAudioVideoSections(RtpTransceiverDirection direction,
zhihuang1c378ed2017-08-17 14:10:50 -0700281 MediaSessionOptions* opts) {
282 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", direction, kActive, opts);
283 AddMediaSection(MEDIA_TYPE_VIDEO, "video", direction, kActive, opts);
284}
285
286static void AddDataSection(cricket::DataChannelType dct,
Steve Anton4e70a722017-11-28 14:57:10 -0800287 RtpTransceiverDirection direction,
zhihuang1c378ed2017-08-17 14:10:50 -0700288 MediaSessionOptions* opts) {
289 opts->data_channel_type = dct;
290 AddMediaSection(MEDIA_TYPE_DATA, "data", direction, kActive, opts);
291}
292
Steve Anton8ffb9c32017-08-31 15:45:38 -0700293static void AttachSenderToMediaSection(
294 const std::string& mid,
295 MediaType type,
296 const std::string& track_id,
297 const std::vector<std::string>& stream_ids,
298 int num_sim_layer,
299 MediaSessionOptions* session_options) {
zhihuang1c378ed2017-08-17 14:10:50 -0700300 auto it = FindFirstMediaDescriptionByMid(mid, session_options);
301 switch (type) {
302 case MEDIA_TYPE_AUDIO:
Steve Anton8ffb9c32017-08-31 15:45:38 -0700303 it->AddAudioSender(track_id, stream_ids);
zhihuang1c378ed2017-08-17 14:10:50 -0700304 break;
305 case MEDIA_TYPE_VIDEO:
Steve Anton8ffb9c32017-08-31 15:45:38 -0700306 it->AddVideoSender(track_id, stream_ids, num_sim_layer);
zhihuang1c378ed2017-08-17 14:10:50 -0700307 break;
308 case MEDIA_TYPE_DATA:
Steve Anton8ffb9c32017-08-31 15:45:38 -0700309 RTC_CHECK(stream_ids.size() == 1U);
310 it->AddRtpDataChannel(track_id, stream_ids[0]);
zhihuang1c378ed2017-08-17 14:10:50 -0700311 break;
312 default:
313 RTC_NOTREACHED();
314 }
315}
316
317static void DetachSenderFromMediaSection(const std::string& mid,
318 const std::string& track_id,
319 MediaSessionOptions* session_options) {
320 auto it = FindFirstMediaDescriptionByMid(mid, session_options);
321 auto sender_it = it->sender_options.begin();
322 for (; sender_it != it->sender_options.end(); ++sender_it) {
323 if (sender_it->track_id == track_id) {
324 it->sender_options.erase(sender_it);
325 return;
326 }
327 }
328 RTC_NOTREACHED();
329}
330
331// Helper function used to create a default MediaSessionOptions for Plan B SDP.
332// (https://tools.ietf.org/html/draft-uberti-rtcweb-plan-00).
333static MediaSessionOptions CreatePlanBMediaSessionOptions() {
334 MediaSessionOptions session_options;
Steve Anton4e70a722017-11-28 14:57:10 -0800335 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
336 kActive, &session_options);
zhihuang1c378ed2017-08-17 14:10:50 -0700337 return session_options;
338}
339
340// TODO(zhihuang): Most of these tests were written while MediaSessionOptions
341// was designed for Plan B SDP, where only one audio "m=" section and one video
342// "m=" section could be generated, and ordering couldn't be controlled. Many of
343// these tests may be obsolete as a result, and should be refactored or removed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000344class MediaSessionDescriptionFactoryTest : public testing::Test {
345 public:
zhihuang1c378ed2017-08-17 14:10:50 -0700346 MediaSessionDescriptionFactoryTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -0700347 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
348 MAKE_VECTOR(kAudioCodecs1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000349 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
350 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -0700351 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
352 MAKE_VECTOR(kAudioCodecs2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000353 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
354 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200355 tdf1_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700356 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200357 tdf2_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700358 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000359 }
360
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000361 // Create a video StreamParamsVec object with:
362 // - one video stream with 3 simulcast streams and FEC,
363 StreamParamsVec CreateComplexVideoStreamParamsVec() {
364 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
365 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
366 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
367 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
368
369 std::vector<SsrcGroup> ssrc_groups;
370 ssrc_groups.push_back(sim_group);
371 ssrc_groups.push_back(fec_group1);
372 ssrc_groups.push_back(fec_group2);
373 ssrc_groups.push_back(fec_group3);
374
375 StreamParams simulcast_params;
376 simulcast_params.id = kVideoTrack1;
377 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
378 simulcast_params.ssrc_groups = ssrc_groups;
379 simulcast_params.cname = "Video_SIM_FEC";
380 simulcast_params.sync_label = kMediaStream1;
381
382 StreamParamsVec video_streams;
383 video_streams.push_back(simulcast_params);
384
385 return video_streams;
386 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000387
388 bool CompareCryptoParams(const CryptoParamsVec& c1,
389 const CryptoParamsVec& c2) {
390 if (c1.size() != c2.size())
391 return false;
392 for (size_t i = 0; i < c1.size(); ++i)
393 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
394 c1[i].key_params != c2[i].key_params ||
395 c1[i].session_params != c2[i].session_params)
396 return false;
397 return true;
398 }
399
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700400 // Returns true if the transport info contains "renomination" as an
401 // ICE option.
402 bool GetIceRenomination(const TransportInfo* transport_info) {
403 const std::vector<std::string>& ice_options =
404 transport_info->description.transport_options;
deadbeef30952b42017-04-21 02:41:29 -0700405 auto iter =
406 std::find(ice_options.begin(), ice_options.end(), "renomination");
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700407 return iter != ice_options.end();
408 }
409
zhihuang1c378ed2017-08-17 14:10:50 -0700410 void TestTransportInfo(bool offer,
Steve Anton36b29d12017-10-30 09:57:42 -0700411 const MediaSessionOptions& options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000412 bool has_current_desc) {
413 const std::string current_audio_ufrag = "current_audio_ufrag";
414 const std::string current_audio_pwd = "current_audio_pwd";
415 const std::string current_video_ufrag = "current_video_ufrag";
416 const std::string current_video_pwd = "current_video_pwd";
417 const std::string current_data_ufrag = "current_data_ufrag";
418 const std::string current_data_pwd = "current_data_pwd";
kwiberg31022942016-03-11 14:18:21 -0800419 std::unique_ptr<SessionDescription> current_desc;
420 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000421 if (has_current_desc) {
422 current_desc.reset(new SessionDescription());
423 EXPECT_TRUE(current_desc->AddTransportInfo(
424 TransportInfo("audio",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700425 TransportDescription(current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000426 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000427 EXPECT_TRUE(current_desc->AddTransportInfo(
428 TransportInfo("video",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700429 TransportDescription(current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000430 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000431 EXPECT_TRUE(current_desc->AddTransportInfo(
432 TransportInfo("data",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700433 TransportDescription(current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000434 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000435 }
436 if (offer) {
437 desc.reset(f1_.CreateOffer(options, current_desc.get()));
438 } else {
kwiberg31022942016-03-11 14:18:21 -0800439 std::unique_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000440 offer.reset(f1_.CreateOffer(options, NULL));
441 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
442 }
443 ASSERT_TRUE(desc.get() != NULL);
444 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000445 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000446 EXPECT_TRUE(ti_audio != NULL);
447 if (has_current_desc) {
448 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
449 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
450 } else {
451 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
452 ti_audio->description.ice_ufrag.size());
453 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
454 ti_audio->description.ice_pwd.size());
455 }
zhihuang1c378ed2017-08-17 14:10:50 -0700456 auto media_desc_options_it =
Steve Anton36b29d12017-10-30 09:57:42 -0700457 FindFirstMediaDescriptionByMid("audio", options);
zhihuang1c378ed2017-08-17 14:10:50 -0700458 EXPECT_EQ(
459 media_desc_options_it->transport_options.enable_ice_renomination,
460 GetIceRenomination(ti_audio));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000461
462 } else {
463 EXPECT_TRUE(ti_audio == NULL);
464 }
465 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000466 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000467 EXPECT_TRUE(ti_video != NULL);
468 if (options.bundle_enabled) {
469 EXPECT_EQ(ti_audio->description.ice_ufrag,
470 ti_video->description.ice_ufrag);
471 EXPECT_EQ(ti_audio->description.ice_pwd,
472 ti_video->description.ice_pwd);
473 } else {
474 if (has_current_desc) {
475 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
476 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
477 } else {
478 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
479 ti_video->description.ice_ufrag.size());
480 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
481 ti_video->description.ice_pwd.size());
482 }
483 }
zhihuang1c378ed2017-08-17 14:10:50 -0700484 auto media_desc_options_it =
Steve Anton36b29d12017-10-30 09:57:42 -0700485 FindFirstMediaDescriptionByMid("video", options);
zhihuang1c378ed2017-08-17 14:10:50 -0700486 EXPECT_EQ(
487 media_desc_options_it->transport_options.enable_ice_renomination,
488 GetIceRenomination(ti_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000489 } else {
490 EXPECT_TRUE(ti_video == NULL);
491 }
492 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
493 if (options.has_data()) {
494 EXPECT_TRUE(ti_data != NULL);
495 if (options.bundle_enabled) {
496 EXPECT_EQ(ti_audio->description.ice_ufrag,
497 ti_data->description.ice_ufrag);
498 EXPECT_EQ(ti_audio->description.ice_pwd,
499 ti_data->description.ice_pwd);
500 } else {
501 if (has_current_desc) {
502 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
503 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
504 } else {
505 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
506 ti_data->description.ice_ufrag.size());
507 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
508 ti_data->description.ice_pwd.size());
509 }
510 }
zhihuang1c378ed2017-08-17 14:10:50 -0700511 auto media_desc_options_it =
Steve Anton36b29d12017-10-30 09:57:42 -0700512 FindFirstMediaDescriptionByMid("data", options);
zhihuang1c378ed2017-08-17 14:10:50 -0700513 EXPECT_EQ(
514 media_desc_options_it->transport_options.enable_ice_renomination,
515 GetIceRenomination(ti_data));
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700516
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000517 } else {
518 EXPECT_TRUE(ti_video == NULL);
519 }
520 }
521
522 void TestCryptoWithBundle(bool offer) {
523 f1_.set_secure(SEC_ENABLED);
524 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -0800525 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
526 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
527 &options);
kwiberg31022942016-03-11 14:18:21 -0800528 std::unique_ptr<SessionDescription> ref_desc;
529 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000530 if (offer) {
531 options.bundle_enabled = false;
532 ref_desc.reset(f1_.CreateOffer(options, NULL));
533 options.bundle_enabled = true;
534 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
535 } else {
536 options.bundle_enabled = true;
537 ref_desc.reset(f1_.CreateOffer(options, NULL));
538 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
539 }
540 ASSERT_TRUE(desc.get() != NULL);
541 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000542 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000543 desc.get()->GetContentDescriptionByName("audio"));
544 ASSERT_TRUE(audio_media_desc != NULL);
545 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000546 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000547 desc.get()->GetContentDescriptionByName("video"));
548 ASSERT_TRUE(video_media_desc != NULL);
549 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
550 video_media_desc->cryptos()));
551 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
552 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
553 audio_media_desc->cryptos()[0].cipher_suite);
554
555 // Verify the selected crypto is one from the reference audio
556 // media content.
557 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000558 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000559 ref_desc.get()->GetContentDescriptionByName("audio"));
560 bool found = false;
561 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
562 if (ref_audio_media_desc->cryptos()[i].Matches(
563 audio_media_desc->cryptos()[0])) {
564 found = true;
565 break;
566 }
567 }
568 EXPECT_TRUE(found);
569 }
570
571 // This test that the audio and video media direction is set to
572 // |expected_direction_in_answer| in an answer if the offer direction is set
zhihuang1c378ed2017-08-17 14:10:50 -0700573 // to |direction_in_offer| and the answer is willing to both send and receive.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000574 void TestMediaDirectionInAnswer(
Steve Anton4e70a722017-11-28 14:57:10 -0800575 RtpTransceiverDirection direction_in_offer,
576 RtpTransceiverDirection expected_direction_in_answer) {
zhihuang1c378ed2017-08-17 14:10:50 -0700577 MediaSessionOptions offer_opts;
578 AddAudioVideoSections(direction_in_offer, &offer_opts);
579
580 std::unique_ptr<SessionDescription> offer(
581 f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000582 ASSERT_TRUE(offer.get() != NULL);
terelius8c011e52016-04-26 05:28:11 -0700583 ContentInfo* ac_offer = offer->GetContentByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000584 ASSERT_TRUE(ac_offer != NULL);
terelius8c011e52016-04-26 05:28:11 -0700585 ContentInfo* vc_offer = offer->GetContentByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000586 ASSERT_TRUE(vc_offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000587
zhihuang1c378ed2017-08-17 14:10:50 -0700588 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800589 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &answer_opts);
kwiberg31022942016-03-11 14:18:21 -0800590 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -0700591 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000592 const AudioContentDescription* acd_answer =
593 GetFirstAudioContentDescription(answer.get());
594 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
595 const VideoContentDescription* vcd_answer =
596 GetFirstVideoContentDescription(answer.get());
597 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
598 }
599
600 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
601 const cricket::ContentDescription* description = content->description;
nissec8ee8822017-01-18 07:20:55 -0800602 RTC_CHECK(description != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000603 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000604 static_cast<const cricket::AudioContentDescription*>(description);
nissec8ee8822017-01-18 07:20:55 -0800605 RTC_CHECK(audio_content_desc != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000606 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
607 if (audio_content_desc->codecs()[i].name == "CN")
608 return false;
609 }
610 return true;
611 }
612
jbauchcb560652016-08-04 05:20:32 -0700613 void TestVideoGcmCipher(bool gcm_offer, bool gcm_answer) {
614 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800615 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &offer_opts);
jbauchcb560652016-08-04 05:20:32 -0700616 offer_opts.crypto_options.enable_gcm_crypto_suites = gcm_offer;
zhihuang1c378ed2017-08-17 14:10:50 -0700617
jbauchcb560652016-08-04 05:20:32 -0700618 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800619 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &answer_opts);
jbauchcb560652016-08-04 05:20:32 -0700620 answer_opts.crypto_options.enable_gcm_crypto_suites = gcm_answer;
zhihuang1c378ed2017-08-17 14:10:50 -0700621
jbauchcb560652016-08-04 05:20:32 -0700622 f1_.set_secure(SEC_ENABLED);
623 f2_.set_secure(SEC_ENABLED);
624 std::unique_ptr<SessionDescription> offer(
625 f1_.CreateOffer(offer_opts, NULL));
626 ASSERT_TRUE(offer.get() != NULL);
627 std::unique_ptr<SessionDescription> answer(
628 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
629 const ContentInfo* ac = answer->GetContentByName("audio");
630 const ContentInfo* vc = answer->GetContentByName("video");
631 ASSERT_TRUE(ac != NULL);
632 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800633 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
634 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
jbauchcb560652016-08-04 05:20:32 -0700635 const AudioContentDescription* acd =
636 static_cast<const AudioContentDescription*>(ac->description);
637 const VideoContentDescription* vcd =
638 static_cast<const VideoContentDescription*>(vc->description);
639 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
640 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
641 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -0700642 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -0700643 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
644 if (gcm_offer && gcm_answer) {
645 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
646 } else {
647 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
648 }
649 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
650 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700651 EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -0700652 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
653 if (gcm_offer && gcm_answer) {
654 ASSERT_CRYPTO(vcd, 1U, CS_AEAD_AES_256_GCM);
655 } else {
656 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
657 }
658 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
659 }
660
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000661 protected:
662 MediaSessionDescriptionFactory f1_;
663 MediaSessionDescriptionFactory f2_;
664 TransportDescriptionFactory tdf1_;
665 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666};
667
668// Create a typical audio offer, and ensure it matches what we expect.
669TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
670 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800671 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -0700672 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000673 ASSERT_TRUE(offer.get() != NULL);
674 const ContentInfo* ac = offer->GetContentByName("audio");
675 const ContentInfo* vc = offer->GetContentByName("video");
676 ASSERT_TRUE(ac != NULL);
677 ASSERT_TRUE(vc == NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800678 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679 const AudioContentDescription* acd =
680 static_cast<const AudioContentDescription*>(ac->description);
681 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700682 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700683 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
685 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
686 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
687 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
688}
689
690// Create a typical video offer, and ensure it matches what we expect.
691TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
692 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800693 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000694 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800695 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000696 ASSERT_TRUE(offer.get() != NULL);
697 const ContentInfo* ac = offer->GetContentByName("audio");
698 const ContentInfo* vc = offer->GetContentByName("video");
699 ASSERT_TRUE(ac != NULL);
700 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800701 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
702 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000703 const AudioContentDescription* acd =
704 static_cast<const AudioContentDescription*>(ac->description);
705 const VideoContentDescription* vcd =
706 static_cast<const VideoContentDescription*>(vc->description);
707 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700708 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700709 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000710 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
711 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
712 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
713 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
714 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
715 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700716 EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000717 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
718 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
719 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
720 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
721}
722
723// Test creating an offer with bundle where the Codecs have the same dynamic
724// RTP playlod type. The test verifies that the offer don't contain the
725// duplicate RTP payload types.
726TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
727 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
ossudedfd282016-06-14 07:12:39 -0700728 const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000729 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
730 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
731 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
732
733 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800734 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
735 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000736 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800737 std::unique_ptr<SessionDescription> offer(f2_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000738 const VideoContentDescription* vcd =
739 GetFirstVideoContentDescription(offer.get());
740 const AudioContentDescription* acd =
741 GetFirstAudioContentDescription(offer.get());
742 const DataContentDescription* dcd =
743 GetFirstDataContentDescription(offer.get());
744 ASSERT_TRUE(NULL != vcd);
745 ASSERT_TRUE(NULL != acd);
746 ASSERT_TRUE(NULL != dcd);
747 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
748 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
749 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
750 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
751 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
752 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
753}
754
zhihuang1c378ed2017-08-17 14:10:50 -0700755// Test creating an updated offer with bundle, audio, video and data
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000756// after an audio only session has been negotiated.
757TEST_F(MediaSessionDescriptionFactoryTest,
758 TestCreateUpdatedVideoOfferWithBundle) {
759 f1_.set_secure(SEC_ENABLED);
760 f2_.set_secure(SEC_ENABLED);
761 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800762 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
763 kActive, &opts);
764 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kInactive,
765 kStopped, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000766 opts.data_channel_type = cricket::DCT_NONE;
767 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800768 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
769 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000770 f2_.CreateAnswer(offer.get(), opts, NULL));
771
772 MediaSessionOptions updated_opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800773 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &updated_opts);
774 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
775 &updated_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000776 updated_opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800777 std::unique_ptr<SessionDescription> updated_offer(
778 f1_.CreateOffer(updated_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000779
780 const AudioContentDescription* acd =
781 GetFirstAudioContentDescription(updated_offer.get());
782 const VideoContentDescription* vcd =
783 GetFirstVideoContentDescription(updated_offer.get());
784 const DataContentDescription* dcd =
785 GetFirstDataContentDescription(updated_offer.get());
786 EXPECT_TRUE(NULL != vcd);
787 EXPECT_TRUE(NULL != acd);
788 EXPECT_TRUE(NULL != dcd);
789
790 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
791 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
792 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
793 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
794 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
795 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
796}
deadbeef44f08192015-12-15 16:20:09 -0800797
wu@webrtc.org78187522013-10-07 23:32:02 +0000798// Create a RTP data offer, and ensure it matches what we expect.
799TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000800 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800801 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
802 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000803 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800804 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000805 ASSERT_TRUE(offer.get() != NULL);
806 const ContentInfo* ac = offer->GetContentByName("audio");
807 const ContentInfo* dc = offer->GetContentByName("data");
808 ASSERT_TRUE(ac != NULL);
809 ASSERT_TRUE(dc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800810 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
811 EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000812 const AudioContentDescription* acd =
813 static_cast<const AudioContentDescription*>(ac->description);
814 const DataContentDescription* dcd =
815 static_cast<const DataContentDescription*>(dc->description);
816 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700817 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700818 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attched.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000819 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
820 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
821 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
822 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
823 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
824 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700825 EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000826 EXPECT_EQ(cricket::kDataMaxBandwidth,
827 dcd->bandwidth()); // default bandwidth (auto)
828 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
829 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
830 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
831}
832
wu@webrtc.org78187522013-10-07 23:32:02 +0000833// Create an SCTP data offer with bundle without error.
834TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
835 MediaSessionOptions opts;
wu@webrtc.org78187522013-10-07 23:32:02 +0000836 opts.bundle_enabled = true;
Steve Anton4e70a722017-11-28 14:57:10 -0800837 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
wu@webrtc.org78187522013-10-07 23:32:02 +0000838 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800839 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000840 EXPECT_TRUE(offer.get() != NULL);
841 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
842}
843
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000844// Test creating an sctp data channel from an already generated offer.
845TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
846 MediaSessionOptions opts;
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000847 opts.bundle_enabled = true;
Steve Anton4e70a722017-11-28 14:57:10 -0800848 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000849 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800850 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000851 ASSERT_TRUE(offer1.get() != NULL);
852 const ContentInfo* data = offer1->GetContentByName("data");
853 ASSERT_TRUE(data != NULL);
854 const MediaContentDescription* mdesc =
855 static_cast<const MediaContentDescription*>(data->description);
856 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
857
858 // Now set data_channel_type to 'none' (default) and make sure that the
859 // datachannel type that gets generated from the previous offer, is of the
860 // same type.
861 opts.data_channel_type = cricket::DCT_NONE;
kwiberg31022942016-03-11 14:18:21 -0800862 std::unique_ptr<SessionDescription> offer2(
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000863 f1_.CreateOffer(opts, offer1.get()));
864 data = offer2->GetContentByName("data");
865 ASSERT_TRUE(data != NULL);
866 mdesc = static_cast<const MediaContentDescription*>(data->description);
867 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
868}
869
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000870// Create an audio, video offer without legacy StreamParams.
871TEST_F(MediaSessionDescriptionFactoryTest,
872 TestCreateOfferWithoutLegacyStreams) {
873 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800874 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
kwiberg31022942016-03-11 14:18:21 -0800875 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000876 ASSERT_TRUE(offer.get() != NULL);
877 const ContentInfo* ac = offer->GetContentByName("audio");
878 const ContentInfo* vc = offer->GetContentByName("video");
879 ASSERT_TRUE(ac != NULL);
880 ASSERT_TRUE(vc != NULL);
881 const AudioContentDescription* acd =
882 static_cast<const AudioContentDescription*>(ac->description);
883 const VideoContentDescription* vcd =
884 static_cast<const VideoContentDescription*>(vc->description);
885
886 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
887 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
888}
889
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000890// Creates an audio+video sendonly offer.
891TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -0700892 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800893 AddAudioVideoSections(RtpTransceiverDirection::kSendOnly, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -0700894 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -0700895 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -0700896 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -0700897 {kMediaStream1}, 1, &opts);
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000898
zhihuang1c378ed2017-08-17 14:10:50 -0700899 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000900 ASSERT_TRUE(offer.get() != NULL);
901 EXPECT_EQ(2u, offer->contents().size());
902 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
903 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
904
Steve Anton4e70a722017-11-28 14:57:10 -0800905 EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
906 GetMediaDirection(&offer->contents()[0]));
907 EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
908 GetMediaDirection(&offer->contents()[1]));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000909}
910
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000911// Verifies that the order of the media contents in the current
912// SessionDescription is preserved in the new SessionDescription.
913TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
914 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800915 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000916
kwiberg31022942016-03-11 14:18:21 -0800917 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000918 ASSERT_TRUE(offer1.get() != NULL);
919 EXPECT_EQ(1u, offer1->contents().size());
920 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
921
Steve Anton4e70a722017-11-28 14:57:10 -0800922 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
923 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -0800924 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000925 f1_.CreateOffer(opts, offer1.get()));
926 ASSERT_TRUE(offer2.get() != NULL);
927 EXPECT_EQ(2u, offer2->contents().size());
928 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
929 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
930
Steve Anton4e70a722017-11-28 14:57:10 -0800931 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
932 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -0800933 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000934 f1_.CreateOffer(opts, offer2.get()));
935 ASSERT_TRUE(offer3.get() != NULL);
936 EXPECT_EQ(3u, offer3->contents().size());
937 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
938 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
939 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000940}
941
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000942// Create a typical audio answer, and ensure it matches what we expect.
943TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
944 f1_.set_secure(SEC_ENABLED);
945 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800946 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -0700947 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000948 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800949 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -0700950 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000951 const ContentInfo* ac = answer->GetContentByName("audio");
952 const ContentInfo* vc = answer->GetContentByName("video");
953 ASSERT_TRUE(ac != NULL);
954 ASSERT_TRUE(vc == NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800955 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000956 const AudioContentDescription* acd =
957 static_cast<const AudioContentDescription*>(ac->description);
958 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
959 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700960 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000961 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
962 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
963 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
964 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
965}
966
jbauchcb560652016-08-04 05:20:32 -0700967// Create a typical audio answer with GCM ciphers enabled, and ensure it
968// matches what we expect.
969TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
970 f1_.set_secure(SEC_ENABLED);
971 f2_.set_secure(SEC_ENABLED);
zhihuang1c378ed2017-08-17 14:10:50 -0700972 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
973 opts.crypto_options.enable_gcm_crypto_suites = true;
974 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
jbauchcb560652016-08-04 05:20:32 -0700975 ASSERT_TRUE(offer.get() != NULL);
976 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -0700977 f2_.CreateAnswer(offer.get(), opts, NULL));
jbauchcb560652016-08-04 05:20:32 -0700978 const ContentInfo* ac = answer->GetContentByName("audio");
979 const ContentInfo* vc = answer->GetContentByName("video");
980 ASSERT_TRUE(ac != NULL);
981 ASSERT_TRUE(vc == NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -0800982 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
jbauchcb560652016-08-04 05:20:32 -0700983 const AudioContentDescription* acd =
984 static_cast<const AudioContentDescription*>(ac->description);
985 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
986 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -0700987 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -0700988 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
989 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
990 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
991 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
992}
993
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000994// Create a typical video answer, and ensure it matches what we expect.
995TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
996 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -0800997 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000998 f1_.set_secure(SEC_ENABLED);
999 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001000 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001001 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001002 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001003 f2_.CreateAnswer(offer.get(), opts, NULL));
1004 const ContentInfo* ac = answer->GetContentByName("audio");
1005 const ContentInfo* vc = answer->GetContentByName("video");
1006 ASSERT_TRUE(ac != NULL);
1007 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08001008 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
1009 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001010 const AudioContentDescription* acd =
1011 static_cast<const AudioContentDescription*>(ac->description);
1012 const VideoContentDescription* vcd =
1013 static_cast<const VideoContentDescription*>(vc->description);
1014 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1015 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1016 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -07001017 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001018 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
1019 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1020 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1021 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -07001022 EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001023 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
1024 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1025 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
1026}
1027
jbauchcb560652016-08-04 05:20:32 -07001028// Create a typical video answer with GCM ciphers enabled, and ensure it
1029// matches what we expect.
1030TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcm) {
1031 TestVideoGcmCipher(true, true);
1032}
1033
1034// Create a typical video answer with GCM ciphers enabled for the offer only,
1035// and ensure it matches what we expect.
1036TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmOffer) {
1037 TestVideoGcmCipher(true, false);
1038}
1039
1040// Create a typical video answer with GCM ciphers enabled for the answer only,
1041// and ensure it matches what we expect.
1042TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmAnswer) {
1043 TestVideoGcmCipher(false, true);
1044}
1045
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001046TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
zhihuang1c378ed2017-08-17 14:10:50 -07001047 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
Steve Anton4e70a722017-11-28 14:57:10 -08001048 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001049 f1_.set_secure(SEC_ENABLED);
1050 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001051 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001052 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001053 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001054 f2_.CreateAnswer(offer.get(), opts, NULL));
1055 const ContentInfo* ac = answer->GetContentByName("audio");
zstein4b2e0822017-02-17 19:48:38 -08001056 const ContentInfo* dc = answer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001057 ASSERT_TRUE(ac != NULL);
zstein4b2e0822017-02-17 19:48:38 -08001058 ASSERT_TRUE(dc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08001059 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
1060 EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001061 const AudioContentDescription* acd =
1062 static_cast<const AudioContentDescription*>(ac->description);
zstein4b2e0822017-02-17 19:48:38 -08001063 const DataContentDescription* dcd =
1064 static_cast<const DataContentDescription*>(dc->description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001065 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1066 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1067 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -07001068 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001069 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
1070 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
zstein4b2e0822017-02-17 19:48:38 -08001071 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1072 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -07001073 EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached
zstein4b2e0822017-02-17 19:48:38 -08001074 EXPECT_TRUE(dcd->rtcp_mux()); // negotiated rtcp-mux
1075 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1076 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001077}
1078
jbauchcb560652016-08-04 05:20:32 -07001079TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerGcm) {
zhihuang1c378ed2017-08-17 14:10:50 -07001080 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
Steve Anton4e70a722017-11-28 14:57:10 -08001081 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
jbauchcb560652016-08-04 05:20:32 -07001082 opts.crypto_options.enable_gcm_crypto_suites = true;
1083 f1_.set_secure(SEC_ENABLED);
1084 f2_.set_secure(SEC_ENABLED);
1085 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1086 ASSERT_TRUE(offer.get() != NULL);
1087 std::unique_ptr<SessionDescription> answer(
1088 f2_.CreateAnswer(offer.get(), opts, NULL));
1089 const ContentInfo* ac = answer->GetContentByName("audio");
zstein4b2e0822017-02-17 19:48:38 -08001090 const ContentInfo* dc = answer->GetContentByName("data");
jbauchcb560652016-08-04 05:20:32 -07001091 ASSERT_TRUE(ac != NULL);
zstein4b2e0822017-02-17 19:48:38 -08001092 ASSERT_TRUE(dc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08001093 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
1094 EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
jbauchcb560652016-08-04 05:20:32 -07001095 const AudioContentDescription* acd =
1096 static_cast<const AudioContentDescription*>(ac->description);
zstein4b2e0822017-02-17 19:48:38 -08001097 const DataContentDescription* dcd =
1098 static_cast<const DataContentDescription*>(dc->description);
jbauchcb560652016-08-04 05:20:32 -07001099 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1100 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1101 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
zhihuang1c378ed2017-08-17 14:10:50 -07001102 EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
jbauchcb560652016-08-04 05:20:32 -07001103 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
1104 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
zstein4b2e0822017-02-17 19:48:38 -08001105 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1106 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
zhihuang1c378ed2017-08-17 14:10:50 -07001107 EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached
zstein4b2e0822017-02-17 19:48:38 -08001108 EXPECT_TRUE(dcd->rtcp_mux()); // negotiated rtcp-mux
1109 ASSERT_CRYPTO(dcd, 1U, CS_AEAD_AES_256_GCM);
1110 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
1111}
1112
1113// The use_sctpmap flag should be set in a DataContentDescription by default.
1114// The answer's use_sctpmap flag should match the offer's.
1115TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerUsesSctpmap) {
1116 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001117 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
zstein4b2e0822017-02-17 19:48:38 -08001118 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1119 ASSERT_TRUE(offer.get() != NULL);
1120 ContentInfo* dc_offer = offer->GetContentByName("data");
1121 ASSERT_TRUE(dc_offer != NULL);
1122 DataContentDescription* dcd_offer =
1123 static_cast<DataContentDescription*>(dc_offer->description);
1124 EXPECT_TRUE(dcd_offer->use_sctpmap());
1125
1126 std::unique_ptr<SessionDescription> answer(
1127 f2_.CreateAnswer(offer.get(), opts, NULL));
1128 const ContentInfo* dc_answer = answer->GetContentByName("data");
1129 ASSERT_TRUE(dc_answer != NULL);
1130 const DataContentDescription* dcd_answer =
1131 static_cast<const DataContentDescription*>(dc_answer->description);
1132 EXPECT_TRUE(dcd_answer->use_sctpmap());
1133}
1134
1135// The answer's use_sctpmap flag should match the offer's.
1136TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerWithoutSctpmap) {
1137 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001138 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
zstein4b2e0822017-02-17 19:48:38 -08001139 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1140 ASSERT_TRUE(offer.get() != NULL);
1141 ContentInfo* dc_offer = offer->GetContentByName("data");
1142 ASSERT_TRUE(dc_offer != NULL);
1143 DataContentDescription* dcd_offer =
1144 static_cast<DataContentDescription*>(dc_offer->description);
1145 dcd_offer->set_use_sctpmap(false);
1146
1147 std::unique_ptr<SessionDescription> answer(
1148 f2_.CreateAnswer(offer.get(), opts, NULL));
1149 const ContentInfo* dc_answer = answer->GetContentByName("data");
1150 ASSERT_TRUE(dc_answer != NULL);
1151 const DataContentDescription* dcd_answer =
1152 static_cast<const DataContentDescription*>(dc_answer->description);
1153 EXPECT_FALSE(dcd_answer->use_sctpmap());
jbauchcb560652016-08-04 05:20:32 -07001154}
1155
deadbeef8b7e9ad2017-05-25 09:38:55 -07001156// Test that a valid answer will be created for "DTLS/SCTP", "UDP/DTLS/SCTP"
1157// and "TCP/DTLS/SCTP" offers.
1158TEST_F(MediaSessionDescriptionFactoryTest,
1159 TestCreateDataAnswerToDifferentOfferedProtos) {
1160 // Need to enable DTLS offer/answer generation (disabled by default in this
1161 // test).
1162 f1_.set_secure(SEC_ENABLED);
1163 f2_.set_secure(SEC_ENABLED);
1164 tdf1_.set_secure(SEC_ENABLED);
1165 tdf2_.set_secure(SEC_ENABLED);
1166
1167 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001168 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
deadbeef8b7e9ad2017-05-25 09:38:55 -07001169 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
1170 ASSERT_TRUE(offer.get() != nullptr);
1171 ContentInfo* dc_offer = offer->GetContentByName("data");
1172 ASSERT_TRUE(dc_offer != nullptr);
1173 DataContentDescription* dcd_offer =
1174 static_cast<DataContentDescription*>(dc_offer->description);
1175
1176 std::vector<std::string> protos = {"DTLS/SCTP", "UDP/DTLS/SCTP",
1177 "TCP/DTLS/SCTP"};
1178 for (const std::string& proto : protos) {
1179 dcd_offer->set_protocol(proto);
1180 std::unique_ptr<SessionDescription> answer(
1181 f2_.CreateAnswer(offer.get(), opts, nullptr));
1182 const ContentInfo* dc_answer = answer->GetContentByName("data");
1183 ASSERT_TRUE(dc_answer != nullptr);
1184 const DataContentDescription* dcd_answer =
1185 static_cast<const DataContentDescription*>(dc_answer->description);
1186 EXPECT_FALSE(dc_answer->rejected);
1187 EXPECT_EQ(proto, dcd_answer->protocol());
1188 }
1189}
1190
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001191// Verifies that the order of the media contents in the offer is preserved in
1192// the answer.
1193TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
1194 MediaSessionOptions opts;
1195
1196 // Creates a data only offer.
Steve Anton4e70a722017-11-28 14:57:10 -08001197 AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kSendRecv, &opts);
kwiberg31022942016-03-11 14:18:21 -08001198 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001199 ASSERT_TRUE(offer1.get() != NULL);
1200
1201 // Appends audio to the offer.
Steve Anton4e70a722017-11-28 14:57:10 -08001202 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1203 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001204 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001205 f1_.CreateOffer(opts, offer1.get()));
1206 ASSERT_TRUE(offer2.get() != NULL);
1207
1208 // Appends video to the offer.
Steve Anton4e70a722017-11-28 14:57:10 -08001209 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1210 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001211 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001212 f1_.CreateOffer(opts, offer2.get()));
1213 ASSERT_TRUE(offer3.get() != NULL);
1214
kwiberg31022942016-03-11 14:18:21 -08001215 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001216 f2_.CreateAnswer(offer3.get(), opts, NULL));
1217 ASSERT_TRUE(answer.get() != NULL);
1218 EXPECT_EQ(3u, answer->contents().size());
1219 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
1220 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
1221 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
1222}
1223
ossu075af922016-06-14 03:29:38 -07001224// TODO(deadbeef): Extend these tests to ensure the correct direction with other
1225// answerer settings.
1226
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001227// This test that the media direction is set to send/receive in an answer if
1228// the offer is send receive.
1229TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001230 TestMediaDirectionInAnswer(RtpTransceiverDirection::kSendRecv,
1231 RtpTransceiverDirection::kSendRecv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001232}
1233
1234// This test that the media direction is set to receive only in an answer if
1235// the offer is send only.
1236TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001237 TestMediaDirectionInAnswer(RtpTransceiverDirection::kSendOnly,
1238 RtpTransceiverDirection::kRecvOnly);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001239}
1240
1241// This test that the media direction is set to send only in an answer if
1242// the offer is recv only.
1243TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001244 TestMediaDirectionInAnswer(RtpTransceiverDirection::kRecvOnly,
1245 RtpTransceiverDirection::kSendOnly);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001246}
1247
1248// This test that the media direction is set to inactive in an answer if
1249// the offer is inactive.
1250TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
Steve Anton4e70a722017-11-28 14:57:10 -08001251 TestMediaDirectionInAnswer(RtpTransceiverDirection::kInactive,
1252 RtpTransceiverDirection::kInactive);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001253}
1254
1255// Test that a data content with an unknown protocol is rejected in an answer.
1256TEST_F(MediaSessionDescriptionFactoryTest,
1257 CreateDataAnswerToOfferWithUnknownProtocol) {
1258 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001259 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001260 f1_.set_secure(SEC_ENABLED);
1261 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001262 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
terelius8c011e52016-04-26 05:28:11 -07001263 ContentInfo* dc_offer = offer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001264 ASSERT_TRUE(dc_offer != NULL);
1265 DataContentDescription* dcd_offer =
1266 static_cast<DataContentDescription*>(dc_offer->description);
1267 ASSERT_TRUE(dcd_offer != NULL);
1268 std::string protocol = "a weird unknown protocol";
1269 dcd_offer->set_protocol(protocol);
1270
kwiberg31022942016-03-11 14:18:21 -08001271 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001272 f2_.CreateAnswer(offer.get(), opts, NULL));
1273
1274 const ContentInfo* dc_answer = answer->GetContentByName("data");
1275 ASSERT_TRUE(dc_answer != NULL);
1276 EXPECT_TRUE(dc_answer->rejected);
1277 const DataContentDescription* dcd_answer =
1278 static_cast<const DataContentDescription*>(dc_answer->description);
1279 ASSERT_TRUE(dcd_answer != NULL);
1280 EXPECT_EQ(protocol, dcd_answer->protocol());
1281}
1282
1283// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
1284TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
zhihuang1c378ed2017-08-17 14:10:50 -07001285 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001286 f1_.set_secure(SEC_DISABLED);
1287 f2_.set_secure(SEC_DISABLED);
1288 tdf1_.set_secure(SEC_DISABLED);
1289 tdf2_.set_secure(SEC_DISABLED);
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 const AudioContentDescription* offer_acd =
1293 GetFirstAudioContentDescription(offer.get());
1294 ASSERT_TRUE(offer_acd != NULL);
1295 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
1296
kwiberg31022942016-03-11 14:18:21 -08001297 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001298 f2_.CreateAnswer(offer.get(), opts, NULL));
1299
1300 const ContentInfo* ac_answer = answer->GetContentByName("audio");
1301 ASSERT_TRUE(ac_answer != NULL);
1302 EXPECT_FALSE(ac_answer->rejected);
1303
1304 const AudioContentDescription* answer_acd =
1305 GetFirstAudioContentDescription(answer.get());
1306 ASSERT_TRUE(answer_acd != NULL);
1307 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
1308}
1309
1310// Create a video offer and answer and ensure the RTP header extensions
1311// matches what we expect.
1312TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
1313 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001314 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001315 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1316 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1317 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1318 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1319
kwiberg31022942016-03-11 14:18:21 -08001320 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001321 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001322 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001323 f2_.CreateAnswer(offer.get(), opts, NULL));
1324
1325 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
1326 GetFirstAudioContentDescription(
1327 offer.get())->rtp_header_extensions());
1328 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
1329 GetFirstVideoContentDescription(
1330 offer.get())->rtp_header_extensions());
1331 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1332 GetFirstAudioContentDescription(
1333 answer.get())->rtp_header_extensions());
1334 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1335 GetFirstVideoContentDescription(
1336 answer.get())->rtp_header_extensions());
1337}
1338
jbauch5869f502017-06-29 12:31:36 -07001339TEST_F(MediaSessionDescriptionFactoryTest,
1340 TestOfferAnswerWithEncryptedRtpExtensionsBoth) {
1341 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001342 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07001343
1344 f1_.set_enable_encrypted_rtp_header_extensions(true);
1345 f2_.set_enable_encrypted_rtp_header_extensions(true);
1346
1347 f1_.set_audio_rtp_header_extensions(
1348 MAKE_VECTOR(kAudioRtpExtension1));
1349 f1_.set_video_rtp_header_extensions(
1350 MAKE_VECTOR(kVideoRtpExtension1));
1351 f2_.set_audio_rtp_header_extensions(
1352 MAKE_VECTOR(kAudioRtpExtension2));
1353 f2_.set_video_rtp_header_extensions(
1354 MAKE_VECTOR(kVideoRtpExtension2));
1355
1356 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1357 ASSERT_TRUE(offer.get() != NULL);
1358 std::unique_ptr<SessionDescription> answer(
1359 f2_.CreateAnswer(offer.get(), opts, NULL));
1360
1361 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionEncrypted1),
1362 GetFirstAudioContentDescription(
1363 offer.get())->rtp_header_extensions());
1364 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionEncrypted1),
1365 GetFirstVideoContentDescription(
1366 offer.get())->rtp_header_extensions());
1367 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionEncryptedAnswer),
1368 GetFirstAudioContentDescription(
1369 answer.get())->rtp_header_extensions());
1370 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionEncryptedAnswer),
1371 GetFirstVideoContentDescription(
1372 answer.get())->rtp_header_extensions());
1373}
1374
1375TEST_F(MediaSessionDescriptionFactoryTest,
1376 TestOfferAnswerWithEncryptedRtpExtensionsOffer) {
1377 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001378 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07001379
1380 f1_.set_enable_encrypted_rtp_header_extensions(true);
1381
1382 f1_.set_audio_rtp_header_extensions(
1383 MAKE_VECTOR(kAudioRtpExtension1));
1384 f1_.set_video_rtp_header_extensions(
1385 MAKE_VECTOR(kVideoRtpExtension1));
1386 f2_.set_audio_rtp_header_extensions(
1387 MAKE_VECTOR(kAudioRtpExtension2));
1388 f2_.set_video_rtp_header_extensions(
1389 MAKE_VECTOR(kVideoRtpExtension2));
1390
1391 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1392 ASSERT_TRUE(offer.get() != NULL);
1393 std::unique_ptr<SessionDescription> answer(
1394 f2_.CreateAnswer(offer.get(), opts, NULL));
1395
1396 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionEncrypted1),
1397 GetFirstAudioContentDescription(
1398 offer.get())->rtp_header_extensions());
1399 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionEncrypted1),
1400 GetFirstVideoContentDescription(
1401 offer.get())->rtp_header_extensions());
1402 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1403 GetFirstAudioContentDescription(
1404 answer.get())->rtp_header_extensions());
1405 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1406 GetFirstVideoContentDescription(
1407 answer.get())->rtp_header_extensions());
1408}
1409
1410TEST_F(MediaSessionDescriptionFactoryTest,
1411 TestOfferAnswerWithEncryptedRtpExtensionsAnswer) {
1412 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001413 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07001414
1415 f2_.set_enable_encrypted_rtp_header_extensions(true);
1416
1417 f1_.set_audio_rtp_header_extensions(
1418 MAKE_VECTOR(kAudioRtpExtension1));
1419 f1_.set_video_rtp_header_extensions(
1420 MAKE_VECTOR(kVideoRtpExtension1));
1421 f2_.set_audio_rtp_header_extensions(
1422 MAKE_VECTOR(kAudioRtpExtension2));
1423 f2_.set_video_rtp_header_extensions(
1424 MAKE_VECTOR(kVideoRtpExtension2));
1425
1426 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1427 ASSERT_TRUE(offer.get() != NULL);
1428 std::unique_ptr<SessionDescription> answer(
1429 f2_.CreateAnswer(offer.get(), opts, NULL));
1430
1431 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
1432 GetFirstAudioContentDescription(
1433 offer.get())->rtp_header_extensions());
1434 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
1435 GetFirstVideoContentDescription(
1436 offer.get())->rtp_header_extensions());
1437 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1438 GetFirstAudioContentDescription(
1439 answer.get())->rtp_header_extensions());
1440 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1441 GetFirstVideoContentDescription(
1442 answer.get())->rtp_header_extensions());
1443}
1444
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001445// Create an audio, video, data answer without legacy StreamParams.
1446TEST_F(MediaSessionDescriptionFactoryTest,
1447 TestCreateAnswerWithoutLegacyStreams) {
1448 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001449 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1450 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
kwiberg31022942016-03-11 14:18:21 -08001451 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001452 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001453 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001454 f2_.CreateAnswer(offer.get(), opts, NULL));
1455 const ContentInfo* ac = answer->GetContentByName("audio");
1456 const ContentInfo* vc = answer->GetContentByName("video");
1457 const ContentInfo* dc = answer->GetContentByName("data");
1458 ASSERT_TRUE(ac != NULL);
1459 ASSERT_TRUE(vc != NULL);
1460 const AudioContentDescription* acd =
1461 static_cast<const AudioContentDescription*>(ac->description);
1462 const VideoContentDescription* vcd =
1463 static_cast<const VideoContentDescription*>(vc->description);
1464 const DataContentDescription* dcd =
1465 static_cast<const DataContentDescription*>(dc->description);
1466
1467 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1468 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1469 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1470}
1471
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001472// Create a typical video answer, and ensure it matches what we expect.
1473TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1474 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001475 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &offer_opts);
1476 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv,
1477 &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001478
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001479 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001480 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &answer_opts);
1481 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv,
1482 &answer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001483
kwiberg31022942016-03-11 14:18:21 -08001484 std::unique_ptr<SessionDescription> offer;
1485 std::unique_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001486
1487 offer_opts.rtcp_mux_enabled = true;
1488 answer_opts.rtcp_mux_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001489 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1490 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1491 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1492 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1493 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1494 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1495 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1496 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1497 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1498 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1499 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1500 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1501 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1502 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1503
1504 offer_opts.rtcp_mux_enabled = true;
1505 answer_opts.rtcp_mux_enabled = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1507 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1508 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1509 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1510 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1511 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1512 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1513 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1514 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1515 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1516 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1517 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1518 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1519 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1520
1521 offer_opts.rtcp_mux_enabled = false;
1522 answer_opts.rtcp_mux_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001523 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1524 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1525 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1526 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1527 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1528 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1529 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1530 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1531 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1532 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1533 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1534 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1535 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1536 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1537
1538 offer_opts.rtcp_mux_enabled = false;
1539 answer_opts.rtcp_mux_enabled = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001540 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1541 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1542 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1543 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1544 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1545 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1546 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1547 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1548 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1549 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1550 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1551 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1552 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1553 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1554}
1555
1556// Create an audio-only answer to a video offer.
1557TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1558 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001559 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1560 kActive, &opts);
1561 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1562 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001563 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001564 ASSERT_TRUE(offer.get() != NULL);
zhihuang1c378ed2017-08-17 14:10:50 -07001565
1566 opts.media_description_options[1].stopped = true;
kwiberg31022942016-03-11 14:18:21 -08001567 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001568 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001569 const ContentInfo* ac = answer->GetContentByName("audio");
1570 const ContentInfo* vc = answer->GetContentByName("video");
1571 ASSERT_TRUE(ac != NULL);
1572 ASSERT_TRUE(vc != NULL);
1573 ASSERT_TRUE(vc->description != NULL);
1574 EXPECT_TRUE(vc->rejected);
1575}
1576
1577// Create an audio-only answer to an offer with data.
1578TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07001579 MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001580 opts.data_channel_type = cricket::DCT_RTP;
Steve Anton4e70a722017-11-28 14:57:10 -08001581 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kRecvOnly,
1582 kActive, &opts);
kwiberg31022942016-03-11 14:18:21 -08001583 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001584 ASSERT_TRUE(offer.get() != NULL);
zhihuang1c378ed2017-08-17 14:10:50 -07001585
1586 opts.media_description_options[1].stopped = true;
kwiberg31022942016-03-11 14:18:21 -08001587 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001588 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001589 const ContentInfo* ac = answer->GetContentByName("audio");
1590 const ContentInfo* dc = answer->GetContentByName("data");
1591 ASSERT_TRUE(ac != NULL);
1592 ASSERT_TRUE(dc != NULL);
1593 ASSERT_TRUE(dc->description != NULL);
1594 EXPECT_TRUE(dc->rejected);
1595}
1596
1597// Create an answer that rejects the contents which are rejected in the offer.
1598TEST_F(MediaSessionDescriptionFactoryTest,
1599 CreateAnswerToOfferWithRejectedMedia) {
1600 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001601 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1602 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, &opts);
kwiberg31022942016-03-11 14:18:21 -08001603 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001604 ASSERT_TRUE(offer.get() != NULL);
1605 ContentInfo* ac = offer->GetContentByName("audio");
1606 ContentInfo* vc = offer->GetContentByName("video");
1607 ContentInfo* dc = offer->GetContentByName("data");
1608 ASSERT_TRUE(ac != NULL);
1609 ASSERT_TRUE(vc != NULL);
1610 ASSERT_TRUE(dc != NULL);
1611 ac->rejected = true;
1612 vc->rejected = true;
1613 dc->rejected = true;
kwiberg31022942016-03-11 14:18:21 -08001614 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001615 f2_.CreateAnswer(offer.get(), opts, NULL));
1616 ac = answer->GetContentByName("audio");
1617 vc = answer->GetContentByName("video");
1618 dc = answer->GetContentByName("data");
1619 ASSERT_TRUE(ac != NULL);
1620 ASSERT_TRUE(vc != NULL);
1621 ASSERT_TRUE(dc != NULL);
1622 EXPECT_TRUE(ac->rejected);
1623 EXPECT_TRUE(vc->rejected);
1624 EXPECT_TRUE(dc->rejected);
1625}
1626
1627// Create an audio and video offer with:
1628// - one video track
1629// - two audio tracks
1630// - two data tracks
1631// and ensure it matches what we expect. Also updates the initial offer by
1632// adding a new video track and replaces one of the audio tracks.
1633TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1634 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001635 AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001636 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001637 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001638 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001639 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001640 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001641 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001642
Steve Anton4e70a722017-11-28 14:57:10 -08001643 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kSendRecv, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001644 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001645 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001646 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001647 {kMediaStream1}, 1, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001648
1649 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001650 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001651
1652 ASSERT_TRUE(offer.get() != NULL);
1653 const ContentInfo* ac = offer->GetContentByName("audio");
1654 const ContentInfo* vc = offer->GetContentByName("video");
1655 const ContentInfo* dc = offer->GetContentByName("data");
1656 ASSERT_TRUE(ac != NULL);
1657 ASSERT_TRUE(vc != NULL);
1658 ASSERT_TRUE(dc != NULL);
1659 const AudioContentDescription* acd =
1660 static_cast<const AudioContentDescription*>(ac->description);
1661 const VideoContentDescription* vcd =
1662 static_cast<const VideoContentDescription*>(vc->description);
1663 const DataContentDescription* dcd =
1664 static_cast<const DataContentDescription*>(dc->description);
1665 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -07001666 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001667
1668 const StreamParamsVec& audio_streams = acd->streams();
1669 ASSERT_EQ(2U, audio_streams.size());
1670 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1671 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1672 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1673 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1674 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1675 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1676 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1677
1678 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1679 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1680 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1681
1682 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1683 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1684 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1685
1686 const StreamParamsVec& video_streams = vcd->streams();
1687 ASSERT_EQ(1U, video_streams.size());
1688 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1689 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1690 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1691 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1692
1693 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1694 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1695 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1696
1697 const StreamParamsVec& data_streams = dcd->streams();
1698 ASSERT_EQ(2U, data_streams.size());
1699 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1700 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1701 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1702 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1703 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1704 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1705 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1706
1707 EXPECT_EQ(cricket::kDataMaxBandwidth,
1708 dcd->bandwidth()); // default bandwidth (auto)
1709 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1710 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1711
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001712 // Update the offer. Add a new video track that is not synched to the
1713 // other tracks and replace audio track 2 with audio track 3.
zhihuang1c378ed2017-08-17 14:10:50 -07001714 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001715 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001716 DetachSenderFromMediaSection("audio", kAudioTrack2, &opts);
1717 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack3,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001718 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001719 DetachSenderFromMediaSection("data", kDataTrack2, &opts);
1720 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack3,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001721 {kMediaStream1}, 1, &opts);
kwiberg31022942016-03-11 14:18:21 -08001722 std::unique_ptr<SessionDescription> updated_offer(
1723 f1_.CreateOffer(opts, offer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001724
1725 ASSERT_TRUE(updated_offer.get() != NULL);
1726 ac = updated_offer->GetContentByName("audio");
1727 vc = updated_offer->GetContentByName("video");
1728 dc = updated_offer->GetContentByName("data");
1729 ASSERT_TRUE(ac != NULL);
1730 ASSERT_TRUE(vc != NULL);
1731 ASSERT_TRUE(dc != NULL);
1732 const AudioContentDescription* updated_acd =
1733 static_cast<const AudioContentDescription*>(ac->description);
1734 const VideoContentDescription* updated_vcd =
1735 static_cast<const VideoContentDescription*>(vc->description);
1736 const DataContentDescription* updated_dcd =
1737 static_cast<const DataContentDescription*>(dc->description);
1738
1739 EXPECT_EQ(acd->type(), updated_acd->type());
1740 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1741 EXPECT_EQ(vcd->type(), updated_vcd->type());
1742 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1743 EXPECT_EQ(dcd->type(), updated_dcd->type());
1744 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1745 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1746 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1747 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1748 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1749 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1750 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1751
1752 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1753 ASSERT_EQ(2U, updated_audio_streams.size());
1754 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1755 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1756 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1757 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1758 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1759
1760 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1761 ASSERT_EQ(2U, updated_video_streams.size());
1762 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1763 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001764 // All the media streams in one PeerConnection share one RTCP CNAME.
1765 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001766
1767 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1768 ASSERT_EQ(2U, updated_data_streams.size());
1769 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1770 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1771 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1772 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1773 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
zhihuang8f65cdf2016-05-06 18:40:30 -07001774 // The stream correctly got the CNAME from the MediaSessionOptions.
1775 // The Expected RTCP CNAME is the default one as we are using the default
1776 // MediaSessionOptions.
1777 EXPECT_EQ(updated_data_streams[0].cname, cricket::kDefaultRtcpCname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001778}
1779
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001780// Create an offer with simulcast video stream.
1781TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1782 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001783 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1784 kActive, &opts);
1785 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
1786 kActive, &opts);
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001787 const int num_sim_layers = 3;
zhihuang1c378ed2017-08-17 14:10:50 -07001788 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001789 {kMediaStream1}, num_sim_layers, &opts);
kwiberg31022942016-03-11 14:18:21 -08001790 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001791
1792 ASSERT_TRUE(offer.get() != NULL);
1793 const ContentInfo* vc = offer->GetContentByName("video");
1794 ASSERT_TRUE(vc != NULL);
1795 const VideoContentDescription* vcd =
1796 static_cast<const VideoContentDescription*>(vc->description);
1797
1798 const StreamParamsVec& video_streams = vcd->streams();
1799 ASSERT_EQ(1U, video_streams.size());
1800 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1801 const SsrcGroup* sim_ssrc_group =
1802 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1803 ASSERT_TRUE(sim_ssrc_group != NULL);
1804 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1805}
1806
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001807// Create an audio and video answer to a standard video offer with:
1808// - one video track
1809// - two audio tracks
1810// - two data tracks
1811// and ensure it matches what we expect. Also updates the initial answer by
1812// adding a new video track and removes one of the audio tracks.
1813TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1814 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001815 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
1816 kActive, &offer_opts);
1817 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
1818 kActive, &offer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001819 offer_opts.data_channel_type = cricket::DCT_RTP;
Steve Anton4e70a722017-11-28 14:57:10 -08001820 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kRecvOnly,
1821 kActive, &offer_opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001822 f1_.set_secure(SEC_ENABLED);
1823 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001824 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001825
zhihuang1c378ed2017-08-17 14:10:50 -07001826 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001827 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
1828 kActive, &answer_opts);
1829 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
1830 kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001831 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001832 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001833 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001834 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001835 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001836 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001837
Steve Anton4e70a722017-11-28 14:57:10 -08001838 AddMediaSection(MEDIA_TYPE_DATA, "data", RtpTransceiverDirection::kSendRecv,
1839 kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001840 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001841 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001842 AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001843 {kMediaStream1}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001844 answer_opts.data_channel_type = cricket::DCT_RTP;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001845
kwiberg31022942016-03-11 14:18:21 -08001846 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001847 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001848
1849 ASSERT_TRUE(answer.get() != NULL);
1850 const ContentInfo* ac = answer->GetContentByName("audio");
1851 const ContentInfo* vc = answer->GetContentByName("video");
1852 const ContentInfo* dc = answer->GetContentByName("data");
1853 ASSERT_TRUE(ac != NULL);
1854 ASSERT_TRUE(vc != NULL);
1855 ASSERT_TRUE(dc != NULL);
1856 const AudioContentDescription* acd =
1857 static_cast<const AudioContentDescription*>(ac->description);
1858 const VideoContentDescription* vcd =
1859 static_cast<const VideoContentDescription*>(vc->description);
1860 const DataContentDescription* dcd =
1861 static_cast<const DataContentDescription*>(dc->description);
1862 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1863 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1864 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1865
1866 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1867 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1868
1869 const StreamParamsVec& audio_streams = acd->streams();
1870 ASSERT_EQ(2U, audio_streams.size());
1871 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1872 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1873 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1874 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1875 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1876 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1877 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1878
1879 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1880 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1881
1882 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1883 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1884
1885 const StreamParamsVec& video_streams = vcd->streams();
1886 ASSERT_EQ(1U, video_streams.size());
1887 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1888 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1889 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1890 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1891
1892 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1893 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1894
1895 const StreamParamsVec& data_streams = dcd->streams();
1896 ASSERT_EQ(2U, data_streams.size());
1897 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1898 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1899 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1900 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1901 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1902 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1903 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1904
1905 EXPECT_EQ(cricket::kDataMaxBandwidth,
1906 dcd->bandwidth()); // default bandwidth (auto)
1907 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1908
1909 // Update the answer. Add a new video track that is not synched to the
zhihuang8f65cdf2016-05-06 18:40:30 -07001910 // other tracks and remove 1 audio track.
zhihuang1c378ed2017-08-17 14:10:50 -07001911 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07001912 {kMediaStream2}, 1, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07001913 DetachSenderFromMediaSection("audio", kAudioTrack2, &answer_opts);
1914 DetachSenderFromMediaSection("data", kDataTrack2, &answer_opts);
kwiberg31022942016-03-11 14:18:21 -08001915 std::unique_ptr<SessionDescription> updated_answer(
zhihuang1c378ed2017-08-17 14:10:50 -07001916 f2_.CreateAnswer(offer.get(), answer_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001917
1918 ASSERT_TRUE(updated_answer.get() != NULL);
1919 ac = updated_answer->GetContentByName("audio");
1920 vc = updated_answer->GetContentByName("video");
1921 dc = updated_answer->GetContentByName("data");
1922 ASSERT_TRUE(ac != NULL);
1923 ASSERT_TRUE(vc != NULL);
1924 ASSERT_TRUE(dc != NULL);
1925 const AudioContentDescription* updated_acd =
1926 static_cast<const AudioContentDescription*>(ac->description);
1927 const VideoContentDescription* updated_vcd =
1928 static_cast<const VideoContentDescription*>(vc->description);
1929 const DataContentDescription* updated_dcd =
1930 static_cast<const DataContentDescription*>(dc->description);
1931
1932 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1933 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1934 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1935 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1936 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1937 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1938
1939 EXPECT_EQ(acd->type(), updated_acd->type());
1940 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1941 EXPECT_EQ(vcd->type(), updated_vcd->type());
1942 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1943 EXPECT_EQ(dcd->type(), updated_dcd->type());
1944 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1945
1946 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1947 ASSERT_EQ(1U, updated_audio_streams.size());
1948 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1949
1950 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1951 ASSERT_EQ(2U, updated_video_streams.size());
1952 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1953 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001954 // All media streams in one PeerConnection share one CNAME.
1955 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001956
1957 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1958 ASSERT_EQ(1U, updated_data_streams.size());
1959 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1960}
1961
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001962// Create an updated offer after creating an answer to the original offer and
1963// verify that the codecs that were part of the original answer are not changed
1964// in the updated offer.
1965TEST_F(MediaSessionDescriptionFactoryTest,
1966 RespondentCreatesOfferAfterCreatingAnswer) {
1967 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08001968 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001969
kwiberg31022942016-03-11 14:18:21 -08001970 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1971 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001972 f2_.CreateAnswer(offer.get(), opts, NULL));
1973
1974 const AudioContentDescription* acd =
1975 GetFirstAudioContentDescription(answer.get());
1976 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1977
1978 const VideoContentDescription* vcd =
1979 GetFirstVideoContentDescription(answer.get());
1980 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1981
kwiberg31022942016-03-11 14:18:21 -08001982 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001983 f2_.CreateOffer(opts, answer.get()));
1984
1985 // The expected audio codecs are the common audio codecs from the first
1986 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1987 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001988 // TODO(wu): |updated_offer| should not include the codec
1989 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001990 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001991 kAudioCodecsAnswer[0],
1992 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001993 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001994 };
1995
1996 // The expected video codecs are the common video codecs from the first
1997 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1998 // preference order.
1999 const VideoCodec kUpdatedVideoCodecOffer[] = {
2000 kVideoCodecsAnswer[0],
2001 kVideoCodecs2[1],
2002 };
2003
2004 const AudioContentDescription* updated_acd =
2005 GetFirstAudioContentDescription(updated_offer.get());
2006 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
2007
2008 const VideoContentDescription* updated_vcd =
2009 GetFirstVideoContentDescription(updated_offer.get());
2010 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
2011}
2012
2013// Create an updated offer after creating an answer to the original offer and
2014// verify that the codecs that were part of the original answer are not changed
2015// in the updated offer. In this test Rtx is enabled.
2016TEST_F(MediaSessionDescriptionFactoryTest,
2017 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
2018 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002019 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2020 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002021 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002022 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002023 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002024 f1_.set_video_codecs(f1_codecs);
2025
2026 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002027 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002028 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002029 f2_.set_video_codecs(f2_codecs);
2030
kwiberg31022942016-03-11 14:18:21 -08002031 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002032 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002033 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002034 f2_.CreateAnswer(offer.get(), opts, NULL));
2035
2036 const VideoContentDescription* vcd =
2037 GetFirstVideoContentDescription(answer.get());
2038
2039 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002040 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2041 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002042
2043 EXPECT_EQ(expected_codecs, vcd->codecs());
2044
deadbeef67cf2c12016-04-13 10:07:16 -07002045 // Now, make sure we get same result (except for the order) if |f2_| creates
2046 // an updated offer even though the default payload types between |f1_| and
2047 // |f2_| are different.
kwiberg31022942016-03-11 14:18:21 -08002048 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002049 f2_.CreateOffer(opts, answer.get()));
2050 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08002051 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002052 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
2053
2054 const VideoContentDescription* updated_vcd =
2055 GetFirstVideoContentDescription(updated_answer.get());
2056
2057 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
2058}
2059
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002060// Regression test for:
2061// https://bugs.chromium.org/p/webrtc/issues/detail?id=8332
2062// Existing codecs should always appear before new codecs in re-offers. But
2063// under a specific set of circumstances, the existing RTX codec was ending up
2064// added to the end of the list.
2065TEST_F(MediaSessionDescriptionFactoryTest,
2066 RespondentCreatesOfferAfterCreatingAnswerWithRemappedRtxPayloadType) {
2067 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002068 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2069 kActive, &opts);
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002070 // We specifically choose different preferred payload types for VP8 to
2071 // trigger the issue.
2072 cricket::VideoCodec vp8_offerer(100, "VP8");
2073 cricket::VideoCodec vp8_offerer_rtx =
2074 VideoCodec::CreateRtxCodec(101, vp8_offerer.id);
2075 cricket::VideoCodec vp8_answerer(110, "VP8");
2076 cricket::VideoCodec vp8_answerer_rtx =
2077 VideoCodec::CreateRtxCodec(111, vp8_answerer.id);
2078 cricket::VideoCodec vp9(120, "VP9");
2079 cricket::VideoCodec vp9_rtx = VideoCodec::CreateRtxCodec(121, vp9.id);
2080
2081 std::vector<VideoCodec> f1_codecs = {vp8_offerer, vp8_offerer_rtx};
2082 // We also specifically cause the answerer to prefer VP9, such that if it
2083 // *doesn't* honor the existing preferred codec (VP8) we'll notice.
2084 std::vector<VideoCodec> f2_codecs = {vp9, vp9_rtx, vp8_answerer,
2085 vp8_answerer_rtx};
2086
2087 f1_.set_video_codecs(f1_codecs);
2088 f2_.set_video_codecs(f2_codecs);
2089 std::vector<AudioCodec> audio_codecs;
2090 f1_.set_audio_codecs(audio_codecs, audio_codecs);
2091 f2_.set_audio_codecs(audio_codecs, audio_codecs);
2092
2093 // Offer will be {VP8, RTX for VP8}. Answer will be the same.
2094 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2095 ASSERT_TRUE(offer.get() != NULL);
2096 std::unique_ptr<SessionDescription> answer(
2097 f2_.CreateAnswer(offer.get(), opts, NULL));
2098
2099 // Updated offer *should* be {VP8, RTX for VP8, VP9, RTX for VP9}.
2100 // But if the bug is triggered, RTX for VP8 ends up last.
2101 std::unique_ptr<SessionDescription> updated_offer(
2102 f2_.CreateOffer(opts, answer.get()));
2103
2104 const VideoContentDescription* vcd =
2105 GetFirstVideoContentDescription(updated_offer.get());
2106 std::vector<cricket::VideoCodec> codecs = vcd->codecs();
2107 ASSERT_EQ(4u, codecs.size());
2108 EXPECT_EQ(vp8_offerer, codecs[0]);
2109 EXPECT_EQ(vp8_offerer_rtx, codecs[1]);
2110 EXPECT_EQ(vp9, codecs[2]);
2111 EXPECT_EQ(vp9_rtx, codecs[3]);
Taylor Brandstetter1c349742017-10-03 18:25:36 -07002112}
2113
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002114// Create an updated offer that adds video after creating an audio only answer
2115// to the original offer. This test verifies that if a video codec and the RTX
2116// codec have the same default payload type as an audio codec that is already in
2117// use, the added codecs payload types are changed.
2118TEST_F(MediaSessionDescriptionFactoryTest,
2119 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
2120 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002121 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002122 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002123 f1_.set_video_codecs(f1_codecs);
2124
2125 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002126 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2127 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002128
kwiberg31022942016-03-11 14:18:21 -08002129 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2130 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002131 f2_.CreateAnswer(offer.get(), opts, NULL));
2132
2133 const AudioContentDescription* acd =
2134 GetFirstAudioContentDescription(answer.get());
2135 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
2136
2137 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
2138 // reference be the same as an audio codec that was negotiated in the
2139 // first offer/answer exchange.
zhihuang1c378ed2017-08-17 14:10:50 -07002140 opts.media_description_options.clear();
Steve Anton4e70a722017-11-28 14:57:10 -08002141 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002142
2143 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2144 int used_pl_type = acd->codecs()[0].id;
2145 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002146 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002147 f2_.set_video_codecs(f2_codecs);
2148
kwiberg31022942016-03-11 14:18:21 -08002149 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002150 f2_.CreateOffer(opts, answer.get()));
2151 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08002152 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002153 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
2154
2155 const AudioContentDescription* updated_acd =
2156 GetFirstAudioContentDescription(answer.get());
2157 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
2158
2159 const VideoContentDescription* updated_vcd =
2160 GetFirstVideoContentDescription(updated_answer.get());
2161
2162 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00002163 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002164 int new_h264_pl_type = updated_vcd->codecs()[0].id;
2165 EXPECT_NE(used_pl_type, new_h264_pl_type);
2166 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002167 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002168 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
2169 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
2170}
2171
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002172// Create an updated offer with RTX after creating an answer to an offer
2173// without RTX, and with different default payload types.
2174// Verify that the added RTX codec references the correct payload type.
2175TEST_F(MediaSessionDescriptionFactoryTest,
2176 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
2177 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002178 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002179
2180 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2181 // This creates rtx for H264 with the payload type |f2_| uses.
2182 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
2183 f2_.set_video_codecs(f2_codecs);
2184
kwiberg31022942016-03-11 14:18:21 -08002185 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002186 ASSERT_TRUE(offer.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08002187 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002188 f2_.CreateAnswer(offer.get(), opts, nullptr));
2189
2190 const VideoContentDescription* vcd =
2191 GetFirstVideoContentDescription(answer.get());
2192
2193 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2194 EXPECT_EQ(expected_codecs, vcd->codecs());
2195
2196 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
2197 // updated offer, even though the default payload types are different from
2198 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08002199 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002200 f2_.CreateOffer(opts, answer.get()));
2201 ASSERT_TRUE(updated_offer);
2202
2203 const VideoContentDescription* updated_vcd =
2204 GetFirstVideoContentDescription(updated_offer.get());
2205
2206 // New offer should attempt to add H263, and RTX for H264.
2207 expected_codecs.push_back(kVideoCodecs2[1]);
2208 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
2209 &expected_codecs);
2210 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
2211}
2212
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002213// Test that RTX is ignored when there is no associated payload type parameter.
2214TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
2215 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002216 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2217 kActive, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002218 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002219 // This creates RTX without associated payload type parameter.
perkj26752742016-10-24 01:21:16 -07002220 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002221 f1_.set_video_codecs(f1_codecs);
2222
2223 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002224 // This creates RTX for H264 with the payload type |f2_| uses.
2225 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002226 f2_.set_video_codecs(f2_codecs);
2227
kwiberg31022942016-03-11 14:18:21 -08002228 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002229 ASSERT_TRUE(offer.get() != NULL);
2230 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
2231 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
2232 // is possible to test that that RTX is dropped when
2233 // kCodecParamAssociatedPayloadType is missing in the offer.
2234 VideoContentDescription* desc =
2235 static_cast<cricket::VideoContentDescription*>(
2236 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
2237 ASSERT_TRUE(desc != NULL);
2238 std::vector<VideoCodec> codecs = desc->codecs();
2239 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
2240 iter != codecs.end(); ++iter) {
2241 if (iter->name.find(cricket::kRtxCodecName) == 0) {
2242 iter->params.clear();
2243 }
2244 }
2245 desc->set_codecs(codecs);
2246
kwiberg31022942016-03-11 14:18:21 -08002247 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002248 f2_.CreateAnswer(offer.get(), opts, NULL));
2249
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002250 std::vector<std::string> codec_names =
2251 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
2252 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
2253 cricket::kRtxCodecName));
2254}
2255
2256// Test that RTX will be filtered out in the answer if its associated payload
2257// type doesn't match the local value.
2258TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
2259 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002260 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2261 kActive, &opts);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002262 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2263 // This creates RTX for H264 in sender.
2264 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2265 f1_.set_video_codecs(f1_codecs);
2266
2267 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2268 // This creates RTX for H263 in receiver.
2269 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
2270 f2_.set_video_codecs(f2_codecs);
2271
kwiberg31022942016-03-11 14:18:21 -08002272 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002273 ASSERT_TRUE(offer.get() != NULL);
2274 // Associated payload type doesn't match, therefore, RTX codec is removed in
2275 // the answer.
kwiberg31022942016-03-11 14:18:21 -08002276 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002277 f2_.CreateAnswer(offer.get(), opts, NULL));
2278
2279 std::vector<std::string> codec_names =
2280 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
2281 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
2282 cricket::kRtxCodecName));
2283}
2284
2285// Test that when multiple RTX codecs are offered, only the matched RTX codec
2286// is added in the answer, and the unsupported RTX codec is filtered out.
2287TEST_F(MediaSessionDescriptionFactoryTest,
2288 FilterOutUnsupportedRtxWhenCreatingAnswer) {
2289 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002290 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2291 kActive, &opts);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002292 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2293 // This creates RTX for H264-SVC in sender.
2294 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
2295 f1_.set_video_codecs(f1_codecs);
2296
2297 // This creates RTX for H264 in sender.
2298 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2299 f1_.set_video_codecs(f1_codecs);
2300
2301 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2302 // This creates RTX for H264 in receiver.
2303 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
2304 f2_.set_video_codecs(f2_codecs);
2305
2306 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
2307 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08002308 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002309 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002310 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002311 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002312 const VideoContentDescription* vcd =
2313 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002314 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2315 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2316 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002317
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002318 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002319}
2320
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002321// Test that after one RTX codec has been negotiated, a new offer can attempt
2322// to add another.
2323TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
2324 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002325 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kRecvOnly,
2326 kActive, &opts);
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002327 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2328 // This creates RTX for H264 for the offerer.
2329 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2330 f1_.set_video_codecs(f1_codecs);
2331
kwiberg31022942016-03-11 14:18:21 -08002332 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002333 ASSERT_TRUE(offer);
2334 const VideoContentDescription* vcd =
2335 GetFirstVideoContentDescription(offer.get());
2336
2337 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
2338 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2339 &expected_codecs);
2340 EXPECT_EQ(expected_codecs, vcd->codecs());
2341
2342 // Now, attempt to add RTX for H264-SVC.
2343 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
2344 f1_.set_video_codecs(f1_codecs);
2345
kwiberg31022942016-03-11 14:18:21 -08002346 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002347 f1_.CreateOffer(opts, offer.get()));
2348 ASSERT_TRUE(updated_offer);
2349 vcd = GetFirstVideoContentDescription(updated_offer.get());
2350
2351 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
2352 &expected_codecs);
2353 EXPECT_EQ(expected_codecs, vcd->codecs());
2354}
2355
Noah Richards2e7a0982015-05-18 14:02:54 -07002356// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
2357// generated for each simulcast ssrc and correctly grouped.
2358TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
2359 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002360 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2361 kActive, &opts);
Noah Richards2e7a0982015-05-18 14:02:54 -07002362 // Add simulcast streams.
zhihuang1c378ed2017-08-17 14:10:50 -07002363 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002364 {"stream1label"}, 3, &opts);
Noah Richards2e7a0982015-05-18 14:02:54 -07002365
2366 // Use a single real codec, and then add RTX for it.
2367 std::vector<VideoCodec> f1_codecs;
perkj26752742016-10-24 01:21:16 -07002368 f1_codecs.push_back(VideoCodec(97, "H264"));
Noah Richards2e7a0982015-05-18 14:02:54 -07002369 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
2370 f1_.set_video_codecs(f1_codecs);
2371
2372 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
2373 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08002374 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07002375 ASSERT_TRUE(offer.get() != NULL);
2376 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
2377 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
2378 ASSERT_TRUE(desc != NULL);
Noah Richards2e7a0982015-05-18 14:02:54 -07002379 const StreamParamsVec& streams = desc->streams();
2380 // Single stream.
2381 ASSERT_EQ(1u, streams.size());
2382 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
2383 EXPECT_EQ(6u, streams[0].ssrcs.size());
2384 // And should have a SIM group for the simulcast.
2385 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2386 // And a FID group for RTX.
2387 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02002388 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002389 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2390 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02002391 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002392 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
2393 EXPECT_EQ(3u, fid_ssrcs.size());
2394}
2395
brandtr03d5fb12016-11-22 03:37:59 -08002396// Test that, when the FlexFEC codec is added, a FlexFEC ssrc is created
2397// together with a FEC-FR grouping.
2398TEST_F(MediaSessionDescriptionFactoryTest, GenerateFlexfecSsrc) {
2399 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002400 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2401 kActive, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002402 // Add single stream.
zhihuang1c378ed2017-08-17 14:10:50 -07002403 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002404 {"stream1label"}, 1, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002405
2406 // Use a single real codec, and then add FlexFEC for it.
2407 std::vector<VideoCodec> f1_codecs;
2408 f1_codecs.push_back(VideoCodec(97, "H264"));
2409 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2410 f1_.set_video_codecs(f1_codecs);
2411
2412 // Ensure that the offer has a single FlexFEC ssrc and that
2413 // there is no FEC-FR ssrc + grouping for each.
2414 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2415 ASSERT_TRUE(offer.get() != nullptr);
2416 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
2417 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
2418 ASSERT_TRUE(desc != nullptr);
brandtr03d5fb12016-11-22 03:37:59 -08002419 const StreamParamsVec& streams = desc->streams();
2420 // Single stream.
2421 ASSERT_EQ(1u, streams.size());
2422 // Stream should have 2 ssrcs: 1 for video, 1 for FlexFEC.
2423 EXPECT_EQ(2u, streams[0].ssrcs.size());
2424 // And should have a FEC-FR group for FlexFEC.
2425 EXPECT_TRUE(streams[0].has_ssrc_group("FEC-FR"));
2426 std::vector<uint32_t> primary_ssrcs;
2427 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2428 ASSERT_EQ(1u, primary_ssrcs.size());
2429 uint32_t flexfec_ssrc;
2430 EXPECT_TRUE(streams[0].GetFecFrSsrc(primary_ssrcs[0], &flexfec_ssrc));
2431 EXPECT_NE(flexfec_ssrc, 0u);
2432}
2433
2434// Test that FlexFEC is disabled for simulcast.
2435// TODO(brandtr): Remove this test when we support simulcast, either through
2436// multiple FlexfecSenders, or through multistream protection.
2437TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateNoFlexfecSsrcs) {
2438 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002439 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
2440 kActive, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002441 // Add simulcast streams.
zhihuang1c378ed2017-08-17 14:10:50 -07002442 AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
Steve Anton8ffb9c32017-08-31 15:45:38 -07002443 {"stream1label"}, 3, &opts);
brandtr03d5fb12016-11-22 03:37:59 -08002444
2445 // Use a single real codec, and then add FlexFEC for it.
2446 std::vector<VideoCodec> f1_codecs;
2447 f1_codecs.push_back(VideoCodec(97, "H264"));
2448 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2449 f1_.set_video_codecs(f1_codecs);
2450
2451 // Ensure that the offer has no FlexFEC ssrcs for each regular ssrc, and that
2452 // there is no FEC-FR ssrc + grouping for each.
2453 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2454 ASSERT_TRUE(offer.get() != nullptr);
2455 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
2456 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
2457 ASSERT_TRUE(desc != nullptr);
brandtr03d5fb12016-11-22 03:37:59 -08002458 const StreamParamsVec& streams = desc->streams();
2459 // Single stream.
2460 ASSERT_EQ(1u, streams.size());
2461 // Stream should have 3 ssrcs: 3 for video, 0 for FlexFEC.
2462 EXPECT_EQ(3u, streams[0].ssrcs.size());
2463 // And should have a SIM group for the simulcast.
2464 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2465 // And not a FEC-FR group for FlexFEC.
2466 EXPECT_FALSE(streams[0].has_ssrc_group("FEC-FR"));
2467 std::vector<uint32_t> primary_ssrcs;
2468 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2469 EXPECT_EQ(3u, primary_ssrcs.size());
2470 for (uint32_t primary_ssrc : primary_ssrcs) {
2471 uint32_t flexfec_ssrc;
2472 EXPECT_FALSE(streams[0].GetFecFrSsrc(primary_ssrc, &flexfec_ssrc));
2473 }
2474}
2475
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002476// Create an updated offer after creating an answer to the original offer and
2477// verify that the RTP header extensions that were part of the original answer
2478// are not changed in the updated offer.
2479TEST_F(MediaSessionDescriptionFactoryTest,
2480 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
2481 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002482 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002483
2484 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
2485 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
2486 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
2487 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
2488
kwiberg31022942016-03-11 14:18:21 -08002489 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2490 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002491 f2_.CreateAnswer(offer.get(), opts, NULL));
2492
2493 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
2494 GetFirstAudioContentDescription(
2495 answer.get())->rtp_header_extensions());
2496 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
2497 GetFirstVideoContentDescription(
2498 answer.get())->rtp_header_extensions());
2499
kwiberg31022942016-03-11 14:18:21 -08002500 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002501 f2_.CreateOffer(opts, answer.get()));
2502
2503 // The expected RTP header extensions in the new offer are the resulting
2504 // extensions from the first offer/answer exchange plus the extensions only
2505 // |f2_| offer.
2506 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002507 // |f1_| for another extensions, it is changed to 13.
isheriff6f8d6862016-05-26 11:24:55 -07002508 const RtpExtension kUpdatedAudioRtpExtensions[] = {
2509 kAudioRtpExtensionAnswer[0], RtpExtension(kAudioRtpExtension2[1].uri, 13),
2510 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002511 };
2512
2513 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002514 // |f1_| for another extensions, is is changed to 12.
isheriff6f8d6862016-05-26 11:24:55 -07002515 const RtpExtension kUpdatedVideoRtpExtensions[] = {
2516 kVideoRtpExtensionAnswer[0], RtpExtension(kVideoRtpExtension2[1].uri, 12),
2517 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002518 };
2519
2520 const AudioContentDescription* updated_acd =
2521 GetFirstAudioContentDescription(updated_offer.get());
2522 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
2523 updated_acd->rtp_header_extensions());
2524
2525 const VideoContentDescription* updated_vcd =
2526 GetFirstVideoContentDescription(updated_offer.get());
2527 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
2528 updated_vcd->rtp_header_extensions());
2529}
2530
deadbeefa5b273a2015-08-20 17:30:13 -07002531// Verify that if the same RTP extension URI is used for audio and video, the
2532// same ID is used. Also verify that the ID isn't changed when creating an
2533// updated offer (this was previously a bug).
isheriff6f8d6862016-05-26 11:24:55 -07002534TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) {
deadbeefa5b273a2015-08-20 17:30:13 -07002535 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002536 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
deadbeefa5b273a2015-08-20 17:30:13 -07002537
2538 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
2539 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
2540
kwiberg31022942016-03-11 14:18:21 -08002541 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07002542
2543 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
2544 // the video extensions.
isheriff6f8d6862016-05-26 11:24:55 -07002545 const RtpExtension kExpectedVideoRtpExtension[] = {
2546 kVideoRtpExtension3[0], kAudioRtpExtension3[1],
deadbeefa5b273a2015-08-20 17:30:13 -07002547 };
2548
2549 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
2550 GetFirstAudioContentDescription(
2551 offer.get())->rtp_header_extensions());
2552 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2553 GetFirstVideoContentDescription(
2554 offer.get())->rtp_header_extensions());
2555
2556 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08002557 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07002558 f1_.CreateOffer(opts, offer.get()));
2559
2560 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
2561 GetFirstAudioContentDescription(
2562 updated_offer.get())->rtp_header_extensions());
2563 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2564 GetFirstVideoContentDescription(
2565 updated_offer.get())->rtp_header_extensions());
2566}
2567
jbauch5869f502017-06-29 12:31:36 -07002568// Same as "RtpExtensionIdReused" above for encrypted RTP extensions.
2569TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReusedEncrypted) {
2570 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08002571 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
jbauch5869f502017-06-29 12:31:36 -07002572
2573 f1_.set_enable_encrypted_rtp_header_extensions(true);
2574 f2_.set_enable_encrypted_rtp_header_extensions(true);
2575
2576 f1_.set_audio_rtp_header_extensions(
2577 MAKE_VECTOR(kAudioRtpExtension3ForEncryption));
2578 f1_.set_video_rtp_header_extensions(
2579 MAKE_VECTOR(kVideoRtpExtension3ForEncryption));
2580
2581 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2582
2583 // The extensions that are shared between audio and video should use the same
2584 // id.
2585 const RtpExtension kExpectedVideoRtpExtension[] = {
2586 kVideoRtpExtension3ForEncryption[0],
2587 kAudioRtpExtension3ForEncryptionOffer[1],
2588 kAudioRtpExtension3ForEncryptionOffer[2],
2589 };
2590
2591 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
2592 GetFirstAudioContentDescription(
2593 offer.get())->rtp_header_extensions());
2594 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2595 GetFirstVideoContentDescription(
2596 offer.get())->rtp_header_extensions());
2597
2598 // Nothing should change when creating a new offer
2599 std::unique_ptr<SessionDescription> updated_offer(
2600 f1_.CreateOffer(opts, offer.get()));
2601
2602 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
2603 GetFirstAudioContentDescription(
2604 updated_offer.get())->rtp_header_extensions());
2605 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2606 GetFirstVideoContentDescription(
2607 updated_offer.get())->rtp_header_extensions());
2608}
2609
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002610TEST(MediaSessionDescription, CopySessionDescription) {
2611 SessionDescription source;
2612 cricket::ContentGroup group(cricket::CN_AUDIO);
2613 source.AddGroup(group);
2614 AudioContentDescription* acd(new AudioContentDescription());
2615 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
2616 acd->AddLegacyStream(1);
Steve Anton5adfafd2017-12-20 16:34:00 -08002617 source.AddContent(cricket::CN_AUDIO, MediaProtocolType::kRtp, acd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002618 VideoContentDescription* vcd(new VideoContentDescription());
2619 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
2620 vcd->AddLegacyStream(2);
Steve Anton5adfafd2017-12-20 16:34:00 -08002621 source.AddContent(cricket::CN_VIDEO, MediaProtocolType::kRtp, vcd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002622
kwiberg31022942016-03-11 14:18:21 -08002623 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002624 ASSERT_TRUE(copy.get() != NULL);
2625 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
2626 const ContentInfo* ac = copy->GetContentByName("audio");
2627 const ContentInfo* vc = copy->GetContentByName("video");
2628 ASSERT_TRUE(ac != NULL);
2629 ASSERT_TRUE(vc != NULL);
Steve Anton5adfafd2017-12-20 16:34:00 -08002630 EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002631 const AudioContentDescription* acd_copy =
2632 static_cast<const AudioContentDescription*>(ac->description);
2633 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
2634 EXPECT_EQ(1u, acd->first_ssrc());
2635
Steve Anton5adfafd2017-12-20 16:34:00 -08002636 EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002637 const VideoContentDescription* vcd_copy =
2638 static_cast<const VideoContentDescription*>(vc->description);
2639 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
2640 EXPECT_EQ(2u, vcd->first_ssrc());
2641}
2642
2643// The below TestTransportInfoXXX tests create different offers/answers, and
2644// ensure the TransportInfo in the SessionDescription matches what we expect.
2645TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
2646 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002647 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2648 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002649 TestTransportInfo(true, options, false);
2650}
2651
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002652TEST_F(MediaSessionDescriptionFactoryTest,
2653 TestTransportInfoOfferIceRenomination) {
2654 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002655 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2656 kActive, &options);
zhihuang1c378ed2017-08-17 14:10:50 -07002657 options.media_description_options[0]
2658 .transport_options.enable_ice_renomination = true;
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002659 TestTransportInfo(true, options, false);
2660}
2661
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002662TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
2663 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002664 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2665 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002666 TestTransportInfo(true, options, true);
2667}
2668
2669TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2670 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002671 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2672 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2673 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002674 TestTransportInfo(true, options, false);
2675}
2676
2677TEST_F(MediaSessionDescriptionFactoryTest,
2678 TestTransportInfoOfferMultimediaCurrent) {
2679 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002680 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2681 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2682 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002683 TestTransportInfo(true, options, true);
2684}
2685
2686TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2687 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 options.bundle_enabled = true;
2692 TestTransportInfo(true, options, false);
2693}
2694
2695TEST_F(MediaSessionDescriptionFactoryTest,
2696 TestTransportInfoOfferBundleCurrent) {
2697 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002698 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2699 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2700 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002701 options.bundle_enabled = true;
2702 TestTransportInfo(true, options, true);
2703}
2704
2705TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2706 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002707 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2708 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002709 TestTransportInfo(false, options, false);
2710}
2711
2712TEST_F(MediaSessionDescriptionFactoryTest,
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002713 TestTransportInfoAnswerIceRenomination) {
2714 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002715 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2716 kActive, &options);
zhihuang1c378ed2017-08-17 14:10:50 -07002717 options.media_description_options[0]
2718 .transport_options.enable_ice_renomination = true;
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002719 TestTransportInfo(false, options, false);
2720}
2721
2722TEST_F(MediaSessionDescriptionFactoryTest,
2723 TestTransportInfoAnswerAudioCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002724 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002725 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kRecvOnly,
2726 kActive, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002727 TestTransportInfo(false, options, true);
2728}
2729
2730TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2731 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002732 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2733 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2734 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002735 TestTransportInfo(false, options, false);
2736}
2737
2738TEST_F(MediaSessionDescriptionFactoryTest,
2739 TestTransportInfoAnswerMultimediaCurrent) {
2740 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002741 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2742 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2743 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002744 TestTransportInfo(false, options, true);
2745}
2746
2747TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2748 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002749 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2750 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2751 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002752 options.bundle_enabled = true;
2753 TestTransportInfo(false, options, false);
2754}
2755
2756TEST_F(MediaSessionDescriptionFactoryTest,
2757 TestTransportInfoAnswerBundleCurrent) {
2758 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002759 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2760 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2761 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002762 options.bundle_enabled = true;
2763 TestTransportInfo(false, options, true);
2764}
2765
2766// Create an offer with bundle enabled and verify the crypto parameters are
2767// the common set of the available cryptos.
2768TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2769 TestCryptoWithBundle(true);
2770}
2771
2772// Create an answer with bundle enabled and verify the crypto parameters are
2773// the common set of the available cryptos.
2774TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2775 TestCryptoWithBundle(false);
2776}
2777
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002778// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2779// DTLS is not enabled locally.
2780TEST_F(MediaSessionDescriptionFactoryTest,
2781 TestOfferDtlsSavpfWithoutDtlsFailed) {
2782 f1_.set_secure(SEC_ENABLED);
2783 f2_.set_secure(SEC_ENABLED);
2784 tdf1_.set_secure(SEC_DISABLED);
2785 tdf2_.set_secure(SEC_DISABLED);
2786
kwiberg31022942016-03-11 14:18:21 -08002787 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -07002788 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002789 ASSERT_TRUE(offer.get() != NULL);
2790 ContentInfo* offer_content = offer->GetContentByName("audio");
2791 ASSERT_TRUE(offer_content != NULL);
2792 AudioContentDescription* offer_audio_desc =
2793 static_cast<AudioContentDescription*>(offer_content->description);
2794 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2795
kwiberg31022942016-03-11 14:18:21 -08002796 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07002797 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002798 ASSERT_TRUE(answer != NULL);
2799 ContentInfo* answer_content = answer->GetContentByName("audio");
2800 ASSERT_TRUE(answer_content != NULL);
2801
2802 ASSERT_TRUE(answer_content->rejected);
2803}
2804
2805// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2806// UDP/TLS/RTP/SAVPF.
2807TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2808 f1_.set_secure(SEC_ENABLED);
2809 f2_.set_secure(SEC_ENABLED);
2810 tdf1_.set_secure(SEC_ENABLED);
2811 tdf2_.set_secure(SEC_ENABLED);
2812
kwiberg31022942016-03-11 14:18:21 -08002813 std::unique_ptr<SessionDescription> offer(
zhihuang1c378ed2017-08-17 14:10:50 -07002814 f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002815 ASSERT_TRUE(offer.get() != NULL);
2816 ContentInfo* offer_content = offer->GetContentByName("audio");
2817 ASSERT_TRUE(offer_content != NULL);
2818 AudioContentDescription* offer_audio_desc =
2819 static_cast<AudioContentDescription*>(offer_content->description);
2820 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2821
kwiberg31022942016-03-11 14:18:21 -08002822 std::unique_ptr<SessionDescription> answer(
zhihuang1c378ed2017-08-17 14:10:50 -07002823 f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002824 ASSERT_TRUE(answer != NULL);
2825
2826 const ContentInfo* answer_content = answer->GetContentByName("audio");
2827 ASSERT_TRUE(answer_content != NULL);
2828 ASSERT_FALSE(answer_content->rejected);
2829
2830 const AudioContentDescription* answer_audio_desc =
2831 static_cast<const AudioContentDescription*>(answer_content->description);
2832 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2833 answer_audio_desc->protocol());
2834}
2835
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002836// Test that we include both SDES and DTLS in the offer, but only include SDES
2837// in the answer if DTLS isn't negotiated.
2838TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2839 f1_.set_secure(SEC_ENABLED);
2840 f2_.set_secure(SEC_ENABLED);
2841 tdf1_.set_secure(SEC_ENABLED);
2842 tdf2_.set_secure(SEC_DISABLED);
2843 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002844 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
kwiberg31022942016-03-11 14:18:21 -08002845 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002846 const cricket::MediaContentDescription* audio_media_desc;
2847 const cricket::MediaContentDescription* video_media_desc;
2848 const cricket::TransportDescription* audio_trans_desc;
2849 const cricket::TransportDescription* video_trans_desc;
2850
2851 // Generate an offer with SDES and DTLS support.
2852 offer.reset(f1_.CreateOffer(options, NULL));
2853 ASSERT_TRUE(offer.get() != NULL);
2854
2855 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2856 offer->GetContentDescriptionByName("audio"));
2857 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002858 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002859 offer->GetContentDescriptionByName("video"));
2860 ASSERT_TRUE(video_media_desc != NULL);
2861 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2862 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2863
2864 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2865 ASSERT_TRUE(audio_trans_desc != NULL);
2866 video_trans_desc = offer->GetTransportDescriptionByName("video");
2867 ASSERT_TRUE(video_trans_desc != NULL);
2868 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2869 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2870
2871 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2872 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2873 ASSERT_TRUE(answer.get() != NULL);
2874
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002875 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002876 answer->GetContentDescriptionByName("audio"));
2877 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002878 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002879 answer->GetContentDescriptionByName("video"));
2880 ASSERT_TRUE(video_media_desc != NULL);
2881 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2882 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2883
2884 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2885 ASSERT_TRUE(audio_trans_desc != NULL);
2886 video_trans_desc = answer->GetTransportDescriptionByName("video");
2887 ASSERT_TRUE(video_trans_desc != NULL);
2888 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2889 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2890
2891 // Enable DTLS; the answer should now only have DTLS support.
2892 tdf2_.set_secure(SEC_ENABLED);
2893 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2894 ASSERT_TRUE(answer.get() != NULL);
2895
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002896 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002897 answer->GetContentDescriptionByName("audio"));
2898 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002899 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002900 answer->GetContentDescriptionByName("video"));
2901 ASSERT_TRUE(video_media_desc != NULL);
2902 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2903 EXPECT_TRUE(video_media_desc->cryptos().empty());
2904 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2905 audio_media_desc->protocol());
2906 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2907 video_media_desc->protocol());
2908
2909 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2910 ASSERT_TRUE(audio_trans_desc != NULL);
2911 video_trans_desc = answer->GetTransportDescriptionByName("video");
2912 ASSERT_TRUE(video_trans_desc != NULL);
2913 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2914 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002915
2916 // Try creating offer again. DTLS enabled now, crypto's should be empty
2917 // in new offer.
2918 offer.reset(f1_.CreateOffer(options, offer.get()));
2919 ASSERT_TRUE(offer.get() != NULL);
2920 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2921 offer->GetContentDescriptionByName("audio"));
2922 ASSERT_TRUE(audio_media_desc != NULL);
2923 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2924 offer->GetContentDescriptionByName("video"));
2925 ASSERT_TRUE(video_media_desc != NULL);
2926 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2927 EXPECT_TRUE(video_media_desc->cryptos().empty());
2928
2929 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2930 ASSERT_TRUE(audio_trans_desc != NULL);
2931 video_trans_desc = offer->GetTransportDescriptionByName("video");
2932 ASSERT_TRUE(video_trans_desc != NULL);
2933 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2934 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002935}
2936
2937// Test that an answer can't be created if cryptos are required but the offer is
2938// unsecure.
2939TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07002940 MediaSessionOptions options = CreatePlanBMediaSessionOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002941 f1_.set_secure(SEC_DISABLED);
2942 tdf1_.set_secure(SEC_DISABLED);
2943 f2_.set_secure(SEC_REQUIRED);
2944 tdf1_.set_secure(SEC_ENABLED);
2945
kwiberg31022942016-03-11 14:18:21 -08002946 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002947 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002948 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002949 f2_.CreateAnswer(offer.get(), options, NULL));
2950 EXPECT_TRUE(answer.get() == NULL);
2951}
2952
2953// Test that we accept a DTLS offer without SDES and create an appropriate
2954// answer.
2955TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2956 f1_.set_secure(SEC_DISABLED);
2957 f2_.set_secure(SEC_ENABLED);
2958 tdf1_.set_secure(SEC_ENABLED);
2959 tdf2_.set_secure(SEC_ENABLED);
2960 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08002961 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
2962 AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly,
2963 &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002964
kwiberg31022942016-03-11 14:18:21 -08002965 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002966
2967 // Generate an offer with DTLS but without SDES.
2968 offer.reset(f1_.CreateOffer(options, NULL));
2969 ASSERT_TRUE(offer.get() != NULL);
2970
2971 const AudioContentDescription* audio_offer =
2972 GetFirstAudioContentDescription(offer.get());
2973 ASSERT_TRUE(audio_offer->cryptos().empty());
2974 const VideoContentDescription* video_offer =
2975 GetFirstVideoContentDescription(offer.get());
2976 ASSERT_TRUE(video_offer->cryptos().empty());
2977 const DataContentDescription* data_offer =
2978 GetFirstDataContentDescription(offer.get());
2979 ASSERT_TRUE(data_offer->cryptos().empty());
2980
2981 const cricket::TransportDescription* audio_offer_trans_desc =
2982 offer->GetTransportDescriptionByName("audio");
2983 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2984 const cricket::TransportDescription* video_offer_trans_desc =
2985 offer->GetTransportDescriptionByName("video");
2986 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2987 const cricket::TransportDescription* data_offer_trans_desc =
2988 offer->GetTransportDescriptionByName("data");
2989 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2990
2991 // Generate an answer with DTLS.
2992 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2993 ASSERT_TRUE(answer.get() != NULL);
2994
2995 const cricket::TransportDescription* audio_answer_trans_desc =
2996 answer->GetTransportDescriptionByName("audio");
2997 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2998 const cricket::TransportDescription* video_answer_trans_desc =
2999 answer->GetTransportDescriptionByName("video");
3000 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
3001 const cricket::TransportDescription* data_answer_trans_desc =
3002 answer->GetTransportDescriptionByName("data");
3003 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
3004}
3005
3006// Verifies if vad_enabled option is set to false, CN codecs are not present in
3007// offer or answer.
3008TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
3009 MediaSessionOptions options;
Steve Anton4e70a722017-11-28 14:57:10 -08003010 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
kwiberg31022942016-03-11 14:18:21 -08003011 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003012 ASSERT_TRUE(offer.get() != NULL);
3013 const ContentInfo* audio_content = offer->GetContentByName("audio");
3014 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
3015
3016 options.vad_enabled = false;
3017 offer.reset(f1_.CreateOffer(options, NULL));
3018 ASSERT_TRUE(offer.get() != NULL);
3019 audio_content = offer->GetContentByName("audio");
3020 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08003021 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003022 f1_.CreateAnswer(offer.get(), options, NULL));
3023 ASSERT_TRUE(answer.get() != NULL);
3024 audio_content = answer->GetContentByName("audio");
3025 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
3026}
deadbeef44f08192015-12-15 16:20:09 -08003027
zhihuang1c378ed2017-08-17 14:10:50 -07003028// Test that the generated MIDs match the existing offer.
3029TEST_F(MediaSessionDescriptionFactoryTest, TestMIDsMatchesExistingOffer) {
deadbeef44f08192015-12-15 16:20:09 -08003030 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003031 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_modified",
3032 RtpTransceiverDirection::kRecvOnly, kActive, &opts);
3033 AddMediaSection(MEDIA_TYPE_VIDEO, "video_modified",
3034 RtpTransceiverDirection::kRecvOnly, kActive, &opts);
deadbeef44f08192015-12-15 16:20:09 -08003035 opts.data_channel_type = cricket::DCT_SCTP;
Steve Anton4e70a722017-11-28 14:57:10 -08003036 AddMediaSection(MEDIA_TYPE_DATA, "data_modified",
3037 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003038 // Create offer.
kwiberg31022942016-03-11 14:18:21 -08003039 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
kwiberg31022942016-03-11 14:18:21 -08003040 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08003041 f1_.CreateOffer(opts, offer.get()));
zhihuang1c378ed2017-08-17 14:10:50 -07003042
deadbeef44f08192015-12-15 16:20:09 -08003043 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
3044 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
3045 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
3046 ASSERT_TRUE(audio_content != nullptr);
3047 ASSERT_TRUE(video_content != nullptr);
3048 ASSERT_TRUE(data_content != nullptr);
3049 EXPECT_EQ("audio_modified", audio_content->name);
3050 EXPECT_EQ("video_modified", video_content->name);
3051 EXPECT_EQ("data_modified", data_content->name);
3052}
zhihuangcf5b37c2016-05-05 11:44:35 -07003053
zhihuang1c378ed2017-08-17 14:10:50 -07003054// The following tests verify that the unified plan SDP is supported.
3055// Test that we can create an offer with multiple media sections of same media
3056// type.
3057TEST_F(MediaSessionDescriptionFactoryTest,
3058 CreateOfferWithMultipleAVMediaSections) {
3059 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003060 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_1",
3061 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003062 AttachSenderToMediaSection("audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003063 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003064
Steve Anton4e70a722017-11-28 14:57:10 -08003065 AddMediaSection(MEDIA_TYPE_VIDEO, "video_1",
3066 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003067 AttachSenderToMediaSection("video_1", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003068 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003069
Steve Anton4e70a722017-11-28 14:57:10 -08003070 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_2",
3071 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003072 AttachSenderToMediaSection("audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003073 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003074
Steve Anton4e70a722017-11-28 14:57:10 -08003075 AddMediaSection(MEDIA_TYPE_VIDEO, "video_2",
3076 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003077 AttachSenderToMediaSection("video_2", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003078 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003079 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3080 ASSERT_TRUE(offer);
3081
3082 ASSERT_EQ(4u, offer->contents().size());
3083 EXPECT_FALSE(offer->contents()[0].rejected);
3084 const AudioContentDescription* acd =
3085 static_cast<const AudioContentDescription*>(
3086 offer->contents()[0].description);
3087 ASSERT_EQ(1u, acd->streams().size());
3088 EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003089 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003090
3091 EXPECT_FALSE(offer->contents()[1].rejected);
3092 const VideoContentDescription* vcd =
3093 static_cast<const VideoContentDescription*>(
3094 offer->contents()[1].description);
3095 ASSERT_EQ(1u, vcd->streams().size());
3096 EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003097 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003098
3099 EXPECT_FALSE(offer->contents()[2].rejected);
3100 acd = static_cast<const AudioContentDescription*>(
3101 offer->contents()[2].description);
3102 ASSERT_EQ(1u, acd->streams().size());
3103 EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003104 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003105
3106 EXPECT_FALSE(offer->contents()[3].rejected);
3107 vcd = static_cast<const VideoContentDescription*>(
3108 offer->contents()[3].description);
3109 ASSERT_EQ(1u, vcd->streams().size());
3110 EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003111 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003112}
3113
3114// Test that we can create an answer with multiple media sections of same media
3115// type.
3116TEST_F(MediaSessionDescriptionFactoryTest,
3117 CreateAnswerWithMultipleAVMediaSections) {
3118 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003119 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_1",
3120 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003121 AttachSenderToMediaSection("audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003122 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003123
Steve Anton4e70a722017-11-28 14:57:10 -08003124 AddMediaSection(MEDIA_TYPE_VIDEO, "video_1",
3125 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003126 AttachSenderToMediaSection("video_1", MEDIA_TYPE_VIDEO, kVideoTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003127 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003128
Steve Anton4e70a722017-11-28 14:57:10 -08003129 AddMediaSection(MEDIA_TYPE_AUDIO, "audio_2",
3130 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003131 AttachSenderToMediaSection("audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003132 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003133
Steve Anton4e70a722017-11-28 14:57:10 -08003134 AddMediaSection(MEDIA_TYPE_VIDEO, "video_2",
3135 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003136 AttachSenderToMediaSection("video_2", MEDIA_TYPE_VIDEO, kVideoTrack2,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003137 {kMediaStream2}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003138
3139 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3140 ASSERT_TRUE(offer);
3141 std::unique_ptr<SessionDescription> answer(
3142 f2_.CreateAnswer(offer.get(), opts, nullptr));
3143
3144 ASSERT_EQ(4u, answer->contents().size());
3145 EXPECT_FALSE(answer->contents()[0].rejected);
3146 const AudioContentDescription* acd =
3147 static_cast<const AudioContentDescription*>(
3148 answer->contents()[0].description);
3149 ASSERT_EQ(1u, acd->streams().size());
3150 EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003151 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003152
3153 EXPECT_FALSE(answer->contents()[1].rejected);
3154 const VideoContentDescription* vcd =
3155 static_cast<const VideoContentDescription*>(
3156 answer->contents()[1].description);
3157 ASSERT_EQ(1u, vcd->streams().size());
3158 EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003159 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003160
3161 EXPECT_FALSE(answer->contents()[2].rejected);
3162 acd = static_cast<const AudioContentDescription*>(
3163 answer->contents()[2].description);
3164 ASSERT_EQ(1u, acd->streams().size());
3165 EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003166 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003167
3168 EXPECT_FALSE(answer->contents()[3].rejected);
3169 vcd = static_cast<const VideoContentDescription*>(
3170 answer->contents()[3].description);
3171 ASSERT_EQ(1u, vcd->streams().size());
3172 EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
Steve Anton4e70a722017-11-28 14:57:10 -08003173 EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
zhihuang1c378ed2017-08-17 14:10:50 -07003174}
3175
3176// Test that the media section will be rejected in offer if the corresponding
3177// MediaDescriptionOptions is stopped by the offerer.
3178TEST_F(MediaSessionDescriptionFactoryTest,
3179 CreateOfferWithMediaSectionStoppedByOfferer) {
3180 // Create an offer with two audio sections and one of them is stopped.
3181 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003182 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3183 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3184 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3185 RtpTransceiverDirection::kInactive, kStopped, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003186 std::unique_ptr<SessionDescription> offer(
3187 f1_.CreateOffer(offer_opts, nullptr));
3188 ASSERT_TRUE(offer);
3189 ASSERT_EQ(2u, offer->contents().size());
3190 EXPECT_FALSE(offer->contents()[0].rejected);
3191 EXPECT_TRUE(offer->contents()[1].rejected);
3192}
3193
3194// Test that the media section will be rejected in answer if the corresponding
3195// MediaDescriptionOptions is stopped by the offerer.
3196TEST_F(MediaSessionDescriptionFactoryTest,
3197 CreateAnswerWithMediaSectionStoppedByOfferer) {
3198 // Create an offer with two audio sections and one of them is stopped.
3199 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003200 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3201 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3202 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3203 RtpTransceiverDirection::kInactive, kStopped, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003204 std::unique_ptr<SessionDescription> offer(
3205 f1_.CreateOffer(offer_opts, nullptr));
3206 ASSERT_TRUE(offer);
3207 ASSERT_EQ(2u, offer->contents().size());
3208 EXPECT_FALSE(offer->contents()[0].rejected);
3209 EXPECT_TRUE(offer->contents()[1].rejected);
3210
3211 // Create an answer based on the offer.
3212 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003213 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3214 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
3215 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3216 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003217 std::unique_ptr<SessionDescription> answer(
3218 f2_.CreateAnswer(offer.get(), answer_opts, nullptr));
3219 ASSERT_EQ(2u, answer->contents().size());
3220 EXPECT_FALSE(answer->contents()[0].rejected);
3221 EXPECT_TRUE(answer->contents()[1].rejected);
3222}
3223
3224// Test that the media section will be rejected in answer if the corresponding
3225// MediaDescriptionOptions is stopped by the answerer.
3226TEST_F(MediaSessionDescriptionFactoryTest,
3227 CreateAnswerWithMediaSectionRejectedByAnswerer) {
3228 // Create an offer with two audio sections.
3229 MediaSessionOptions offer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003230 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3231 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
3232 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3233 RtpTransceiverDirection::kSendRecv, kActive, &offer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003234 std::unique_ptr<SessionDescription> offer(
3235 f1_.CreateOffer(offer_opts, nullptr));
3236 ASSERT_TRUE(offer);
3237 ASSERT_EQ(2u, offer->contents().size());
3238 ASSERT_FALSE(offer->contents()[0].rejected);
3239 ASSERT_FALSE(offer->contents()[1].rejected);
3240
3241 // The answerer rejects one of the audio sections.
3242 MediaSessionOptions answer_opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003243 AddMediaSection(MEDIA_TYPE_AUDIO, "audio1",
3244 RtpTransceiverDirection::kSendRecv, kActive, &answer_opts);
3245 AddMediaSection(MEDIA_TYPE_AUDIO, "audio2",
3246 RtpTransceiverDirection::kInactive, kStopped, &answer_opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003247 std::unique_ptr<SessionDescription> answer(
3248 f2_.CreateAnswer(offer.get(), answer_opts, nullptr));
3249 ASSERT_EQ(2u, answer->contents().size());
3250 EXPECT_FALSE(answer->contents()[0].rejected);
3251 EXPECT_TRUE(answer->contents()[1].rejected);
3252}
3253
3254// Test the generated media sections has the same order of the
3255// corresponding MediaDescriptionOptions.
3256TEST_F(MediaSessionDescriptionFactoryTest,
3257 CreateOfferRespectsMediaDescriptionOptionsOrder) {
3258 MediaSessionOptions opts;
3259 // This tests put video section first because normally audio comes first by
3260 // default.
Steve Anton4e70a722017-11-28 14:57:10 -08003261 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3262 kActive, &opts);
3263 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
3264 kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003265 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3266
3267 ASSERT_TRUE(offer);
3268 ASSERT_EQ(2u, offer->contents().size());
3269 EXPECT_EQ("video", offer->contents()[0].name);
3270 EXPECT_EQ("audio", offer->contents()[1].name);
3271}
3272
3273// Test that different media sections using the same codec have same payload
3274// type.
3275TEST_F(MediaSessionDescriptionFactoryTest,
3276 PayloadTypesSharedByMediaSectionsOfSameType) {
3277 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003278 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3279 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3280 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3281 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003282 // Create an offer with two video sections using same codecs.
3283 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3284 ASSERT_TRUE(offer);
3285 ASSERT_EQ(2u, offer->contents().size());
3286 const VideoContentDescription* vcd1 =
3287 static_cast<const VideoContentDescription*>(
3288 offer->contents()[0].description);
3289 const VideoContentDescription* vcd2 =
3290 static_cast<const VideoContentDescription*>(
3291 offer->contents()[1].description);
3292 EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
3293 ASSERT_EQ(2u, vcd1->codecs().size());
3294 EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
3295 EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
3296 EXPECT_EQ(vcd1->codecs()[1].name, vcd2->codecs()[1].name);
3297 EXPECT_EQ(vcd1->codecs()[1].id, vcd2->codecs()[1].id);
3298
3299 // Create answer and negotiate the codecs.
3300 std::unique_ptr<SessionDescription> answer(
3301 f2_.CreateAnswer(offer.get(), opts, nullptr));
3302 ASSERT_TRUE(answer);
3303 ASSERT_EQ(2u, answer->contents().size());
3304 vcd1 = static_cast<const VideoContentDescription*>(
3305 answer->contents()[0].description);
3306 vcd2 = static_cast<const VideoContentDescription*>(
3307 answer->contents()[1].description);
3308 EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
3309 ASSERT_EQ(1u, vcd1->codecs().size());
3310 EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
3311 EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
3312}
3313
3314// Test that the codec preference order per media section is respected in
3315// subsequent offer.
3316TEST_F(MediaSessionDescriptionFactoryTest,
3317 CreateOfferRespectsCodecPreferenceOrder) {
3318 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003319 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3320 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3321 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3322 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003323 // Create an offer with two video sections using same codecs.
3324 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3325 ASSERT_TRUE(offer);
3326 ASSERT_EQ(2u, offer->contents().size());
3327 VideoContentDescription* vcd1 =
3328 static_cast<VideoContentDescription*>(offer->contents()[0].description);
3329 const VideoContentDescription* vcd2 =
3330 static_cast<const VideoContentDescription*>(
3331 offer->contents()[1].description);
3332 auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
3333 EXPECT_EQ(video_codecs, vcd1->codecs());
3334 EXPECT_EQ(video_codecs, vcd2->codecs());
3335
3336 // Change the codec preference of the first video section and create a
3337 // follow-up offer.
3338 auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
3339 vcd1->set_codecs(video_codecs_reverse);
3340 std::unique_ptr<SessionDescription> updated_offer(
3341 f1_.CreateOffer(opts, offer.get()));
3342 vcd1 = static_cast<VideoContentDescription*>(
3343 updated_offer->contents()[0].description);
3344 vcd2 = static_cast<const VideoContentDescription*>(
3345 updated_offer->contents()[1].description);
3346 // The video codec preference order should be respected.
3347 EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
3348 EXPECT_EQ(video_codecs, vcd2->codecs());
3349}
3350
3351// Test that the codec preference order per media section is respected in
3352// the answer.
3353TEST_F(MediaSessionDescriptionFactoryTest,
3354 CreateAnswerRespectsCodecPreferenceOrder) {
3355 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003356 AddMediaSection(MEDIA_TYPE_VIDEO, "video1",
3357 RtpTransceiverDirection::kSendRecv, kActive, &opts);
3358 AddMediaSection(MEDIA_TYPE_VIDEO, "video2",
3359 RtpTransceiverDirection::kSendRecv, kActive, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003360 // Create an offer with two video sections using same codecs.
3361 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3362 ASSERT_TRUE(offer);
3363 ASSERT_EQ(2u, offer->contents().size());
3364 VideoContentDescription* vcd1 =
3365 static_cast<VideoContentDescription*>(offer->contents()[0].description);
3366 const VideoContentDescription* vcd2 =
3367 static_cast<const VideoContentDescription*>(
3368 offer->contents()[1].description);
3369 auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
3370 EXPECT_EQ(video_codecs, vcd1->codecs());
3371 EXPECT_EQ(video_codecs, vcd2->codecs());
3372
3373 // Change the codec preference of the first video section and create an
3374 // answer.
3375 auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
3376 vcd1->set_codecs(video_codecs_reverse);
3377 std::unique_ptr<SessionDescription> answer(
3378 f1_.CreateAnswer(offer.get(), opts, nullptr));
3379 vcd1 =
3380 static_cast<VideoContentDescription*>(answer->contents()[0].description);
3381 vcd2 = static_cast<const VideoContentDescription*>(
3382 answer->contents()[1].description);
3383 // The video codec preference order should be respected.
3384 EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
3385 EXPECT_EQ(video_codecs, vcd2->codecs());
3386}
3387
Zhi Huang6f367472017-11-22 13:20:02 -08003388// Test that when creating an answer, the codecs use local parameters instead of
3389// the remote ones.
3390TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerWithLocalCodecParams) {
3391 const std::string audio_param_name = "audio_param";
3392 const std::string audio_value1 = "audio_v1";
3393 const std::string audio_value2 = "audio_v2";
3394 const std::string video_param_name = "video_param";
3395 const std::string video_value1 = "video_v1";
3396 const std::string video_value2 = "video_v2";
3397
3398 auto audio_codecs1 = MAKE_VECTOR(kAudioCodecs1);
3399 auto audio_codecs2 = MAKE_VECTOR(kAudioCodecs1);
3400 auto video_codecs1 = MAKE_VECTOR(kVideoCodecs1);
3401 auto video_codecs2 = MAKE_VECTOR(kVideoCodecs1);
3402
3403 // Set the parameters for codecs.
3404 audio_codecs1[0].SetParam(audio_param_name, audio_value1);
3405 video_codecs1[0].SetParam(video_param_name, video_value1);
3406 audio_codecs2[0].SetParam(audio_param_name, audio_value2);
3407 video_codecs2[0].SetParam(video_param_name, video_value2);
3408
3409 f1_.set_audio_codecs(audio_codecs1, audio_codecs1);
3410 f1_.set_video_codecs(video_codecs1);
3411 f2_.set_audio_codecs(audio_codecs2, audio_codecs2);
3412 f2_.set_video_codecs(video_codecs2);
3413
3414 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003415 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", RtpTransceiverDirection::kSendRecv,
3416 kActive, &opts);
3417 AddMediaSection(MEDIA_TYPE_VIDEO, "video", RtpTransceiverDirection::kSendRecv,
3418 kActive, &opts);
Zhi Huang6f367472017-11-22 13:20:02 -08003419
3420 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3421 ASSERT_TRUE(offer);
3422 auto offer_acd =
3423 static_cast<AudioContentDescription*>(offer->contents()[0].description);
3424 auto offer_vcd =
3425 static_cast<VideoContentDescription*>(offer->contents()[1].description);
3426 std::string value;
3427 EXPECT_TRUE(offer_acd->codecs()[0].GetParam(audio_param_name, &value));
3428 EXPECT_EQ(audio_value1, value);
3429 EXPECT_TRUE(offer_vcd->codecs()[0].GetParam(video_param_name, &value));
3430 EXPECT_EQ(video_value1, value);
3431
3432 std::unique_ptr<SessionDescription> answer(
3433 f2_.CreateAnswer(offer.get(), opts, nullptr));
3434 ASSERT_TRUE(answer);
3435 auto answer_acd =
3436 static_cast<AudioContentDescription*>(answer->contents()[0].description);
3437 auto answer_vcd =
3438 static_cast<VideoContentDescription*>(answer->contents()[1].description);
3439 // Use the parameters from the local codecs.
3440 EXPECT_TRUE(answer_acd->codecs()[0].GetParam(audio_param_name, &value));
3441 EXPECT_EQ(audio_value2, value);
3442 EXPECT_TRUE(answer_vcd->codecs()[0].GetParam(video_param_name, &value));
3443 EXPECT_EQ(video_value2, value);
3444}
3445
zhihuangcf5b37c2016-05-05 11:44:35 -07003446class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
3447 public:
3448 MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -07003449 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
3450 MAKE_VECTOR(kAudioCodecs1));
zhihuangcf5b37c2016-05-05 11:44:35 -07003451 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
3452 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -07003453 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
3454 MAKE_VECTOR(kAudioCodecs2));
zhihuangcf5b37c2016-05-05 11:44:35 -07003455 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
3456 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
3457 f1_.set_secure(SEC_ENABLED);
3458 f2_.set_secure(SEC_ENABLED);
3459 tdf1_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07003460 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07003461 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07003462 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07003463 tdf1_.set_secure(SEC_ENABLED);
3464 tdf2_.set_secure(SEC_ENABLED);
3465 }
3466
3467 protected:
3468 MediaSessionDescriptionFactory f1_;
3469 MediaSessionDescriptionFactory f2_;
3470 TransportDescriptionFactory tdf1_;
3471 TransportDescriptionFactory tdf2_;
3472};
3473
3474TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
3475 MediaSessionOptions opts;
Steve Anton4e70a722017-11-28 14:57:10 -08003476 AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
zhihuangcf5b37c2016-05-05 11:44:35 -07003477 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
3478 ASSERT_TRUE(offer.get() != nullptr);
3479 // Set the protocol for all the contents.
3480 for (auto content : offer.get()->contents()) {
3481 static_cast<MediaContentDescription*>(content.description)
3482 ->set_protocol(GetParam());
3483 }
3484 std::unique_ptr<SessionDescription> answer(
3485 f2_.CreateAnswer(offer.get(), opts, nullptr));
3486 const ContentInfo* ac = answer->GetContentByName("audio");
3487 const ContentInfo* vc = answer->GetContentByName("video");
3488 ASSERT_TRUE(ac != nullptr);
3489 ASSERT_TRUE(vc != nullptr);
3490 EXPECT_FALSE(ac->rejected); // the offer is accepted
3491 EXPECT_FALSE(vc->rejected);
3492 const AudioContentDescription* acd =
3493 static_cast<const AudioContentDescription*>(ac->description);
3494 const VideoContentDescription* vcd =
3495 static_cast<const VideoContentDescription*>(vc->description);
3496 EXPECT_EQ(GetParam(), acd->protocol());
3497 EXPECT_EQ(GetParam(), vcd->protocol());
3498}
3499
3500INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest,
3501 MediaProtocolTest,
3502 ::testing::ValuesIn(kMediaProtocols));
3503INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest,
3504 MediaProtocolTest,
3505 ::testing::ValuesIn(kMediaProtocolsDtls));
ossu075af922016-06-14 03:29:38 -07003506
3507TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) {
3508 TransportDescriptionFactory tdf;
3509 MediaSessionDescriptionFactory sf(&tdf);
3510 std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
3511 std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
3512
3513 // The merged list of codecs should contain any send codecs that are also
3514 // nominally in the recieve codecs list. Payload types should be picked from
3515 // the send codecs and a number-of-channels of 0 and 1 should be equivalent
3516 // (set to 1). This equals what happens when the send codecs are used in an
3517 // offer and the receive codecs are used in the following answer.
3518 const std::vector<AudioCodec> sendrecv_codecs =
3519 MAKE_VECTOR(kAudioCodecsAnswer);
3520 const std::vector<AudioCodec> no_codecs;
3521
3522 RTC_CHECK_EQ(send_codecs[1].name, "iLBC")
3523 << "Please don't change shared test data!";
3524 RTC_CHECK_EQ(recv_codecs[2].name, "iLBC")
3525 << "Please don't change shared test data!";
3526 // Alter iLBC send codec to have zero channels, to test that that is handled
3527 // properly.
3528 send_codecs[1].channels = 0;
3529
3530 // Alther iLBC receive codec to be lowercase, to test that case conversions
3531 // are handled properly.
3532 recv_codecs[2].name = "ilbc";
3533
3534 // Test proper merge
3535 sf.set_audio_codecs(send_codecs, recv_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003536 EXPECT_EQ(send_codecs, sf.audio_send_codecs());
3537 EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
3538 EXPECT_EQ(sendrecv_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003539
3540 // Test empty send codecs list
3541 sf.set_audio_codecs(no_codecs, recv_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003542 EXPECT_EQ(no_codecs, sf.audio_send_codecs());
3543 EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
3544 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003545
3546 // Test empty recv codecs list
3547 sf.set_audio_codecs(send_codecs, no_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003548 EXPECT_EQ(send_codecs, sf.audio_send_codecs());
3549 EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
3550 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003551
3552 // Test all empty codec lists
3553 sf.set_audio_codecs(no_codecs, no_codecs);
zhihuang1c378ed2017-08-17 14:10:50 -07003554 EXPECT_EQ(no_codecs, sf.audio_send_codecs());
3555 EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
3556 EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
ossu075af922016-06-14 03:29:38 -07003557}
3558
3559namespace {
zhihuang1c378ed2017-08-17 14:10:50 -07003560// Compare the two vectors of codecs ignoring the payload type.
3561template <class Codec>
3562bool CodecsMatch(const std::vector<Codec>& codecs1,
3563 const std::vector<Codec>& codecs2) {
3564 if (codecs1.size() != codecs2.size()) {
3565 return false;
3566 }
3567
3568 for (size_t i = 0; i < codecs1.size(); ++i) {
3569 if (!codecs1[i].Matches(codecs2[i])) {
3570 return false;
3571 }
3572 }
3573 return true;
3574}
3575
Steve Anton4e70a722017-11-28 14:57:10 -08003576void TestAudioCodecsOffer(RtpTransceiverDirection direction) {
ossu075af922016-06-14 03:29:38 -07003577 TransportDescriptionFactory tdf;
3578 MediaSessionDescriptionFactory sf(&tdf);
3579 const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
3580 const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
3581 const std::vector<AudioCodec> sendrecv_codecs =
3582 MAKE_VECTOR(kAudioCodecsAnswer);
3583 sf.set_audio_codecs(send_codecs, recv_codecs);
ossu075af922016-06-14 03:29:38 -07003584
3585 MediaSessionOptions opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003586 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", direction, kActive, &opts);
3587
Steve Anton4e70a722017-11-28 14:57:10 -08003588 if (direction == RtpTransceiverDirection::kSendRecv ||
3589 direction == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003590 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003591 {kMediaStream1}, 1, &opts);
zhihuang1c378ed2017-08-17 14:10:50 -07003592 }
ossu075af922016-06-14 03:29:38 -07003593
3594 std::unique_ptr<SessionDescription> offer(sf.CreateOffer(opts, NULL));
3595 ASSERT_TRUE(offer.get() != NULL);
3596 const ContentInfo* ac = offer->GetContentByName("audio");
3597
3598 // If the factory didn't add any audio content to the offer, we cannot check
zhihuang1c378ed2017-08-17 14:10:50 -07003599 // that the codecs put in are right. This happens when we neither want to
3600 // send nor receive audio. The checks are still in place if at some point
3601 // we'd instead create an inactive stream.
ossu075af922016-06-14 03:29:38 -07003602 if (ac) {
3603 AudioContentDescription* acd =
3604 static_cast<AudioContentDescription*>(ac->description);
zhihuang1c378ed2017-08-17 14:10:50 -07003605 // sendrecv and inactive should both present lists as if the channel was
3606 // to be used for sending and receiving. Inactive essentially means it
3607 // might eventually be used anything, but we don't know more at this
3608 // moment.
Steve Anton4e70a722017-11-28 14:57:10 -08003609 if (acd->direction() == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003610 EXPECT_TRUE(CodecsMatch<AudioCodec>(send_codecs, acd->codecs()));
Steve Anton4e70a722017-11-28 14:57:10 -08003611 } else if (acd->direction() == RtpTransceiverDirection::kRecvOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003612 EXPECT_TRUE(CodecsMatch<AudioCodec>(recv_codecs, acd->codecs()));
ossu075af922016-06-14 03:29:38 -07003613 } else {
zhihuang1c378ed2017-08-17 14:10:50 -07003614 EXPECT_TRUE(CodecsMatch<AudioCodec>(sendrecv_codecs, acd->codecs()));
ossu075af922016-06-14 03:29:38 -07003615 }
3616 }
3617}
3618
3619static const AudioCodec kOfferAnswerCodecs[] = {
zhihuang1c378ed2017-08-17 14:10:50 -07003620 AudioCodec(0, "codec0", 16000, -1, 1),
3621 AudioCodec(1, "codec1", 8000, 13300, 1),
3622 AudioCodec(2, "codec2", 8000, 64000, 1),
3623 AudioCodec(3, "codec3", 8000, 64000, 1),
3624 AudioCodec(4, "codec4", 8000, 0, 2),
3625 AudioCodec(5, "codec5", 32000, 0, 1),
3626 AudioCodec(6, "codec6", 48000, 0, 1)};
ossu075af922016-06-14 03:29:38 -07003627
zhihuang1c378ed2017-08-17 14:10:50 -07003628/* The codecs groups below are chosen as per the matrix below. The objective
3629 * is to have different sets of codecs in the inputs, to get unique sets of
3630 * codecs after negotiation, depending on offer and answer communication
3631 * directions. One-way directions in the offer should either result in the
3632 * opposite direction in the answer, or an inactive answer. Regardless, the
3633 * choice of codecs should be as if the answer contained the opposite
3634 * direction. Inactive offers should be treated as sendrecv/sendrecv.
ossu075af922016-06-14 03:29:38 -07003635 *
3636 * | Offer | Answer | Result
3637 * codec|send recv sr | send recv sr | s/r r/s sr/s sr/r sr/sr
3638 * 0 | x - - | - x - | x - - - -
3639 * 1 | x x x | - x - | x - - x -
3640 * 2 | - x - | x - - | - x - - -
3641 * 3 | x x x | x - - | - x x - -
3642 * 4 | - x - | x x x | - x - - -
3643 * 5 | x - - | x x x | x - - - -
3644 * 6 | x x x | x x x | x x x x x
3645 */
3646// Codecs used by offerer in the AudioCodecsAnswerTest
zhihuang1c378ed2017-08-17 14:10:50 -07003647static const int kOfferSendCodecs[] = {0, 1, 3, 5, 6};
3648static const int kOfferRecvCodecs[] = {1, 2, 3, 4, 6};
ossu075af922016-06-14 03:29:38 -07003649// Codecs used in the answerer in the AudioCodecsAnswerTest. The order is
3650// jumbled to catch the answer not following the order in the offer.
zhihuang1c378ed2017-08-17 14:10:50 -07003651static const int kAnswerSendCodecs[] = {6, 5, 2, 3, 4};
3652static const int kAnswerRecvCodecs[] = {6, 5, 4, 1, 0};
ossu075af922016-06-14 03:29:38 -07003653// The resulting sets of codecs in the answer in the AudioCodecsAnswerTest
zhihuang1c378ed2017-08-17 14:10:50 -07003654static const int kResultSend_RecvCodecs[] = {0, 1, 5, 6};
3655static const int kResultRecv_SendCodecs[] = {2, 3, 4, 6};
3656static const int kResultSendrecv_SendCodecs[] = {3, 6};
3657static const int kResultSendrecv_RecvCodecs[] = {1, 6};
3658static const int kResultSendrecv_SendrecvCodecs[] = {6};
ossu075af922016-06-14 03:29:38 -07003659
3660template <typename T, int IDXS>
3661std::vector<T> VectorFromIndices(const T* array, const int (&indices)[IDXS]) {
3662 std::vector<T> out;
3663 out.reserve(IDXS);
3664 for (int idx : indices)
3665 out.push_back(array[idx]);
3666
3667 return out;
3668}
3669
Steve Anton4e70a722017-11-28 14:57:10 -08003670void TestAudioCodecsAnswer(RtpTransceiverDirection offer_direction,
3671 RtpTransceiverDirection answer_direction,
ossu075af922016-06-14 03:29:38 -07003672 bool add_legacy_stream) {
3673 TransportDescriptionFactory offer_tdf;
3674 TransportDescriptionFactory answer_tdf;
3675 MediaSessionDescriptionFactory offer_factory(&offer_tdf);
3676 MediaSessionDescriptionFactory answer_factory(&answer_tdf);
3677 offer_factory.set_audio_codecs(
3678 VectorFromIndices(kOfferAnswerCodecs, kOfferSendCodecs),
3679 VectorFromIndices(kOfferAnswerCodecs, kOfferRecvCodecs));
3680 answer_factory.set_audio_codecs(
3681 VectorFromIndices(kOfferAnswerCodecs, kAnswerSendCodecs),
3682 VectorFromIndices(kOfferAnswerCodecs, kAnswerRecvCodecs));
3683
ossu075af922016-06-14 03:29:38 -07003684 MediaSessionOptions offer_opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003685 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", offer_direction, kActive,
3686 &offer_opts);
3687
Steve Anton4e70a722017-11-28 14:57:10 -08003688 if (webrtc::RtpTransceiverDirectionHasSend(offer_direction)) {
zhihuang1c378ed2017-08-17 14:10:50 -07003689 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003690 {kMediaStream1}, 1, &offer_opts);
ossu075af922016-06-14 03:29:38 -07003691 }
3692
3693 std::unique_ptr<SessionDescription> offer(
3694 offer_factory.CreateOffer(offer_opts, NULL));
3695 ASSERT_TRUE(offer.get() != NULL);
3696
3697 MediaSessionOptions answer_opts;
zhihuang1c378ed2017-08-17 14:10:50 -07003698 AddMediaSection(MEDIA_TYPE_AUDIO, "audio", answer_direction, kActive,
3699 &answer_opts);
3700
Steve Anton4e70a722017-11-28 14:57:10 -08003701 if (webrtc::RtpTransceiverDirectionHasSend(answer_direction)) {
zhihuang1c378ed2017-08-17 14:10:50 -07003702 AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
Steve Anton8ffb9c32017-08-31 15:45:38 -07003703 {kMediaStream1}, 1, &answer_opts);
ossu075af922016-06-14 03:29:38 -07003704 }
3705 std::unique_ptr<SessionDescription> answer(
3706 answer_factory.CreateAnswer(offer.get(), answer_opts, NULL));
3707 const ContentInfo* ac = answer->GetContentByName("audio");
3708
zhihuang1c378ed2017-08-17 14:10:50 -07003709 // If the factory didn't add any audio content to the answer, we cannot
3710 // check that the codecs put in are right. This happens when we neither want
3711 // to send nor receive audio. The checks are still in place if at some point
3712 // we'd instead create an inactive stream.
ossu075af922016-06-14 03:29:38 -07003713 if (ac) {
3714 const AudioContentDescription* acd =
3715 static_cast<const AudioContentDescription*>(ac->description);
3716 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
3717
ossu075af922016-06-14 03:29:38 -07003718 std::vector<AudioCodec> target_codecs;
3719 // For offers with sendrecv or inactive, we should never reply with more
3720 // codecs than offered, with these codec sets.
3721 switch (offer_direction) {
Steve Anton4e70a722017-11-28 14:57:10 -08003722 case RtpTransceiverDirection::kInactive:
ossu075af922016-06-14 03:29:38 -07003723 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3724 kResultSendrecv_SendrecvCodecs);
3725 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003726 case RtpTransceiverDirection::kSendOnly:
zhihuang1c378ed2017-08-17 14:10:50 -07003727 target_codecs =
3728 VectorFromIndices(kOfferAnswerCodecs, kResultSend_RecvCodecs);
ossu075af922016-06-14 03:29:38 -07003729 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003730 case RtpTransceiverDirection::kRecvOnly:
zhihuang1c378ed2017-08-17 14:10:50 -07003731 target_codecs =
3732 VectorFromIndices(kOfferAnswerCodecs, kResultRecv_SendCodecs);
ossu075af922016-06-14 03:29:38 -07003733 break;
Steve Anton4e70a722017-11-28 14:57:10 -08003734 case RtpTransceiverDirection::kSendRecv:
3735 if (acd->direction() == RtpTransceiverDirection::kSendOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003736 target_codecs =
3737 VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_SendCodecs);
Steve Anton4e70a722017-11-28 14:57:10 -08003738 } else if (acd->direction() == RtpTransceiverDirection::kRecvOnly) {
zhihuang1c378ed2017-08-17 14:10:50 -07003739 target_codecs =
3740 VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_RecvCodecs);
ossu075af922016-06-14 03:29:38 -07003741 } else {
3742 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3743 kResultSendrecv_SendrecvCodecs);
3744 }
3745 break;
3746 }
3747
zhihuang1c378ed2017-08-17 14:10:50 -07003748 auto format_codecs = [](const std::vector<AudioCodec>& codecs) {
ossu075af922016-06-14 03:29:38 -07003749 std::stringstream os;
3750 bool first = true;
3751 os << "{";
3752 for (const auto& c : codecs) {
3753 os << (first ? " " : ", ") << c.id;
3754 first = false;
3755 }
3756 os << " }";
3757 return os.str();
3758 };
3759
3760 EXPECT_TRUE(acd->codecs() == target_codecs)
3761 << "Expected: " << format_codecs(target_codecs)
Steve Anton4e70a722017-11-28 14:57:10 -08003762 << ", got: " << format_codecs(acd->codecs()) << "; Offered: "
3763 << webrtc::RtpTransceiverDirectionToString(offer_direction)
ossu075af922016-06-14 03:29:38 -07003764 << ", answerer wants: "
Steve Anton4e70a722017-11-28 14:57:10 -08003765 << webrtc::RtpTransceiverDirectionToString(answer_direction)
3766 << "; got: "
3767 << webrtc::RtpTransceiverDirectionToString(acd->direction());
ossu075af922016-06-14 03:29:38 -07003768 } else {
Steve Anton4e70a722017-11-28 14:57:10 -08003769 EXPECT_EQ(offer_direction, RtpTransceiverDirection::kInactive)
zhihuang1c378ed2017-08-17 14:10:50 -07003770 << "Only inactive offers are allowed to not generate any audio "
3771 "content";
ossu075af922016-06-14 03:29:38 -07003772 }
3773}
brandtr03d5fb12016-11-22 03:37:59 -08003774
3775} // namespace
ossu075af922016-06-14 03:29:38 -07003776
3777class AudioCodecsOfferTest
Steve Anton4e70a722017-11-28 14:57:10 -08003778 : public ::testing::TestWithParam<RtpTransceiverDirection> {};
ossu075af922016-06-14 03:29:38 -07003779
3780TEST_P(AudioCodecsOfferTest, TestCodecsInOffer) {
zhihuang1c378ed2017-08-17 14:10:50 -07003781 TestAudioCodecsOffer(GetParam());
ossu075af922016-06-14 03:29:38 -07003782}
3783
3784INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
3785 AudioCodecsOfferTest,
Steve Anton4e70a722017-11-28 14:57:10 -08003786 ::testing::Values(RtpTransceiverDirection::kSendOnly,
3787 RtpTransceiverDirection::kRecvOnly,
3788 RtpTransceiverDirection::kSendRecv,
3789 RtpTransceiverDirection::kInactive));
ossu075af922016-06-14 03:29:38 -07003790
3791class AudioCodecsAnswerTest
Steve Anton4e70a722017-11-28 14:57:10 -08003792 : public ::testing::TestWithParam<::testing::tuple<RtpTransceiverDirection,
3793 RtpTransceiverDirection,
zhihuang1c378ed2017-08-17 14:10:50 -07003794 bool>> {};
ossu075af922016-06-14 03:29:38 -07003795
3796TEST_P(AudioCodecsAnswerTest, TestCodecsInAnswer) {
ehmaldonadoabcef5d2017-02-08 04:07:11 -08003797 TestAudioCodecsAnswer(::testing::get<0>(GetParam()),
3798 ::testing::get<1>(GetParam()),
3799 ::testing::get<2>(GetParam()));
ossu075af922016-06-14 03:29:38 -07003800}
3801
zhihuang1c378ed2017-08-17 14:10:50 -07003802INSTANTIATE_TEST_CASE_P(
3803 MediaSessionDescriptionFactoryTest,
3804 AudioCodecsAnswerTest,
Steve Anton4e70a722017-11-28 14:57:10 -08003805 ::testing::Combine(::testing::Values(RtpTransceiverDirection::kSendOnly,
3806 RtpTransceiverDirection::kRecvOnly,
3807 RtpTransceiverDirection::kSendRecv,
3808 RtpTransceiverDirection::kInactive),
3809 ::testing::Values(RtpTransceiverDirection::kSendOnly,
3810 RtpTransceiverDirection::kRecvOnly,
3811 RtpTransceiverDirection::kSendRecv,
3812 RtpTransceiverDirection::kInactive),
zhihuang1c378ed2017-08-17 14:10:50 -07003813 ::testing::Bool()));