xref: /aosp_15_r20/external/webrtc/pc/media_session_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2004 The WebRTC project authors. All Rights Reserved.
3  *
4  *  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.
9  */
10 
11 #include "pc/media_session.h"
12 
13 #include <stddef.h>
14 
15 #include <algorithm>
16 #include <cstdint>
17 #include <map>
18 #include <memory>
19 #include <string>
20 #include <tuple>
21 #include <vector>
22 
23 #include "absl/algorithm/container.h"
24 #include "absl/strings/match.h"
25 #include "absl/strings/string_view.h"
26 #include "api/candidate.h"
27 #include "api/crypto_params.h"
28 #include "media/base/codec.h"
29 #include "media/base/media_constants.h"
30 #include "media/base/test_utils.h"
31 #include "media/sctp/sctp_transport_internal.h"
32 #include "p2p/base/p2p_constants.h"
33 #include "p2p/base/transport_description.h"
34 #include "p2p/base/transport_info.h"
35 #include "pc/media_protocol_names.h"
36 #include "pc/rtp_media_utils.h"
37 #include "rtc_base/arraysize.h"
38 #include "rtc_base/checks.h"
39 #include "rtc_base/fake_ssl_identity.h"
40 #include "rtc_base/rtc_certificate.h"
41 #include "rtc_base/ssl_identity.h"
42 #include "rtc_base/ssl_stream_adapter.h"
43 #include "rtc_base/string_encode.h"
44 #include "rtc_base/strings/string_builder.h"
45 #include "rtc_base/unique_id_generator.h"
46 #include "test/gmock.h"
47 #include "test/gtest.h"
48 #include "test/scoped_key_value_config.h"
49 
50 #define ASSERT_CRYPTO(cd, s, cs)      \
51   ASSERT_EQ(s, cd->cryptos().size()); \
52   ASSERT_EQ(cs, cd->cryptos()[0].cipher_suite)
53 
54 typedef std::vector<cricket::Candidate> Candidates;
55 
56 using cricket::AudioCodec;
57 using cricket::AudioContentDescription;
58 using cricket::ContentInfo;
59 using cricket::CryptoParamsVec;
60 using cricket::GetFirstAudioContent;
61 using cricket::GetFirstAudioContentDescription;
62 using cricket::GetFirstDataContent;
63 using cricket::GetFirstVideoContent;
64 using cricket::GetFirstVideoContentDescription;
65 using cricket::kAutoBandwidth;
66 using cricket::MEDIA_TYPE_AUDIO;
67 using cricket::MEDIA_TYPE_DATA;
68 using cricket::MEDIA_TYPE_VIDEO;
69 using cricket::MediaContentDescription;
70 using cricket::MediaDescriptionOptions;
71 using cricket::MediaProtocolType;
72 using cricket::MediaSessionDescriptionFactory;
73 using cricket::MediaSessionOptions;
74 using cricket::MediaType;
75 using cricket::RidDescription;
76 using cricket::RidDirection;
77 using cricket::SctpDataContentDescription;
78 using cricket::SEC_DISABLED;
79 using cricket::SEC_ENABLED;
80 using cricket::SEC_REQUIRED;
81 using cricket::SessionDescription;
82 using cricket::SimulcastDescription;
83 using cricket::SimulcastLayer;
84 using cricket::SimulcastLayerList;
85 using cricket::SsrcGroup;
86 using cricket::StreamParams;
87 using cricket::StreamParamsVec;
88 using cricket::TransportDescription;
89 using cricket::TransportDescriptionFactory;
90 using cricket::TransportInfo;
91 using cricket::VideoCodec;
92 using cricket::VideoContentDescription;
93 using rtc::kCsAeadAes128Gcm;
94 using rtc::kCsAeadAes256Gcm;
95 using rtc::kCsAesCm128HmacSha1_32;
96 using rtc::kCsAesCm128HmacSha1_80;
97 using rtc::UniqueRandomIdGenerator;
98 using ::testing::Contains;
99 using ::testing::Each;
100 using ::testing::ElementsAre;
101 using ::testing::ElementsAreArray;
102 using ::testing::Eq;
103 using ::testing::Field;
104 using ::testing::IsEmpty;
105 using ::testing::IsFalse;
106 using ::testing::Ne;
107 using ::testing::Not;
108 using ::testing::Pointwise;
109 using ::testing::SizeIs;
110 using webrtc::RtpExtension;
111 using webrtc::RtpTransceiverDirection;
112 
113 static const AudioCodec kAudioCodecs1[] = {
114     AudioCodec(103, "ISAC", 16000, -1, 1),
115     AudioCodec(102, "iLBC", 8000, 13300, 1),
116     AudioCodec(0, "PCMU", 8000, 64000, 1),
117     AudioCodec(8, "PCMA", 8000, 64000, 1),
118     AudioCodec(117, "red", 8000, 0, 1),
119     AudioCodec(107, "CN", 48000, 0, 1)};
120 
121 static const AudioCodec kAudioCodecs2[] = {
122     AudioCodec(126, "foo", 16000, 22000, 1),
123     AudioCodec(0, "PCMU", 8000, 64000, 1),
124     AudioCodec(127, "iLBC", 8000, 13300, 1),
125 };
126 
127 static const AudioCodec kAudioCodecsAnswer[] = {
128     AudioCodec(102, "iLBC", 8000, 13300, 1),
129     AudioCodec(0, "PCMU", 8000, 64000, 1),
130 };
131 
132 static const VideoCodec kVideoCodecs1[] = {VideoCodec(96, "H264-SVC"),
133                                            VideoCodec(97, "H264")};
134 
135 static const VideoCodec kVideoCodecs1Reverse[] = {VideoCodec(97, "H264"),
136                                                   VideoCodec(96, "H264-SVC")};
137 
138 static const VideoCodec kVideoCodecs2[] = {VideoCodec(126, "H264"),
139                                            VideoCodec(127, "H263")};
140 
141 static const VideoCodec kVideoCodecsAnswer[] = {VideoCodec(97, "H264")};
142 
143 static const RtpExtension kAudioRtpExtension1[] = {
144     RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
145     RtpExtension("http://google.com/testing/audio_something", 10),
146 };
147 
148 static const RtpExtension kAudioRtpExtensionEncrypted1[] = {
149     RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
150     RtpExtension("http://google.com/testing/audio_something", 10),
151     RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 12, true),
152     RtpExtension("http://google.com/testing/audio_something", 11, true),
153 };
154 
155 static const RtpExtension kAudioRtpExtension2[] = {
156     RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
157     RtpExtension("http://google.com/testing/audio_something_else", 8),
158     RtpExtension("http://google.com/testing/both_audio_and_video", 7),
159 };
160 
161 static const RtpExtension kAudioRtpExtension3[] = {
162     RtpExtension("http://google.com/testing/audio_something", 2),
163     RtpExtension("http://google.com/testing/both_audio_and_video", 3),
164 };
165 
166 static const RtpExtension kAudioRtpExtension3ForEncryption[] = {
167     RtpExtension("http://google.com/testing/audio_something", 2),
168     // Use RTP extension that supports encryption.
169     RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 3),
170 };
171 
172 static const RtpExtension kAudioRtpExtension3ForEncryptionOffer[] = {
173     RtpExtension("http://google.com/testing/audio_something", 2),
174     RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 3),
175     RtpExtension("http://google.com/testing/audio_something", 14, true),
176     RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 13, true),
177 };
178 
179 static const RtpExtension kVideoRtpExtension3ForEncryptionOffer[] = {
180     RtpExtension("http://google.com/testing/video_something", 4),
181     RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 3),
182     RtpExtension("http://google.com/testing/video_something", 12, true),
183     RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 13, true),
184 };
185 
186 static const RtpExtension kAudioRtpExtensionAnswer[] = {
187     RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
188 };
189 
190 static const RtpExtension kAudioRtpExtensionEncryptedAnswer[] = {
191     RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 12, true),
192 };
193 
194 static const RtpExtension kVideoRtpExtension1[] = {
195     RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
196     RtpExtension("http://google.com/testing/video_something", 13),
197 };
198 
199 static const RtpExtension kVideoRtpExtensionEncrypted1[] = {
200     RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
201     RtpExtension("http://google.com/testing/video_something", 13),
202     RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 9, true),
203     RtpExtension("http://google.com/testing/video_something", 7, true),
204 };
205 
206 static const RtpExtension kVideoRtpExtension2[] = {
207     RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
208     RtpExtension("http://google.com/testing/video_something_else", 14),
209     RtpExtension("http://google.com/testing/both_audio_and_video", 7),
210 };
211 
212 static const RtpExtension kVideoRtpExtension3[] = {
213     RtpExtension("http://google.com/testing/video_something", 4),
214     RtpExtension("http://google.com/testing/both_audio_and_video", 5),
215 };
216 
217 static const RtpExtension kVideoRtpExtension3ForEncryption[] = {
218     RtpExtension("http://google.com/testing/video_something", 4),
219     // Use RTP extension that supports encryption.
220     RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 5),
221 };
222 
223 static const RtpExtension kVideoRtpExtensionAnswer[] = {
224     RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
225 };
226 
227 static const RtpExtension kVideoRtpExtensionEncryptedAnswer[] = {
228     RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 9, true),
229 };
230 
231 static const RtpExtension kRtpExtensionTransportSequenceNumber01[] = {
232     RtpExtension("http://www.ietf.org/id/"
233                  "draft-holmer-rmcat-transport-wide-cc-extensions-01",
234                  1),
235 };
236 
237 static const RtpExtension kRtpExtensionTransportSequenceNumber01And02[] = {
238     RtpExtension("http://www.ietf.org/id/"
239                  "draft-holmer-rmcat-transport-wide-cc-extensions-01",
240                  1),
241     RtpExtension(
242         "http://www.webrtc.org/experiments/rtp-hdrext/transport-wide-cc-02",
243         2),
244 };
245 
246 static const RtpExtension kRtpExtensionTransportSequenceNumber02[] = {
247     RtpExtension(
248         "http://www.webrtc.org/experiments/rtp-hdrext/transport-wide-cc-02",
249         2),
250 };
251 
252 static const RtpExtension kRtpExtensionGenericFrameDescriptorUri00[] = {
253     RtpExtension("http://www.webrtc.org/experiments/rtp-hdrext/"
254                  "generic-frame-descriptor-00",
255                  3),
256 };
257 
258 static const uint32_t kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
259 static const uint32_t kSimSsrc[] = {10, 20, 30};
260 static const uint32_t kFec1Ssrc[] = {10, 11};
261 static const uint32_t kFec2Ssrc[] = {20, 21};
262 static const uint32_t kFec3Ssrc[] = {30, 31};
263 
264 static const char kMediaStream1[] = "stream_1";
265 static const char kMediaStream2[] = "stream_2";
266 static const char kVideoTrack1[] = "video_1";
267 static const char kVideoTrack2[] = "video_2";
268 static const char kAudioTrack1[] = "audio_1";
269 static const char kAudioTrack2[] = "audio_2";
270 static const char kAudioTrack3[] = "audio_3";
271 
272 static const char* kMediaProtocols[] = {"RTP/AVP", "RTP/SAVP", "RTP/AVPF",
273                                         "RTP/SAVPF"};
274 static const char* kMediaProtocolsDtls[] = {
275     "TCP/TLS/RTP/SAVPF", "TCP/TLS/RTP/SAVP", "UDP/TLS/RTP/SAVPF",
276     "UDP/TLS/RTP/SAVP"};
277 
278 // SRTP cipher name negotiated by the tests. This must be updated if the
279 // default changes.
280 static const char* kDefaultSrtpCryptoSuite = kCsAesCm128HmacSha1_80;
281 static const char* kDefaultSrtpCryptoSuiteGcm = kCsAeadAes256Gcm;
282 
283 // These constants are used to make the code using "AddMediaDescriptionOptions"
284 // more readable.
285 static constexpr bool kStopped = true;
286 static constexpr bool kActive = false;
287 
IsMediaContentOfType(const ContentInfo * content,MediaType media_type)288 static bool IsMediaContentOfType(const ContentInfo* content,
289                                  MediaType media_type) {
290   RTC_DCHECK(content);
291   return content->media_description()->type() == media_type;
292 }
293 
GetMediaDirection(const ContentInfo * content)294 static RtpTransceiverDirection GetMediaDirection(const ContentInfo* content) {
295   RTC_DCHECK(content);
296   return content->media_description()->direction();
297 }
298 
AddRtxCodec(const VideoCodec & rtx_codec,std::vector<VideoCodec> * codecs)299 static void AddRtxCodec(const VideoCodec& rtx_codec,
300                         std::vector<VideoCodec>* codecs) {
301   ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id));
302   codecs->push_back(rtx_codec);
303 }
304 
305 template <class T>
GetCodecNames(const std::vector<T> & codecs)306 static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
307   std::vector<std::string> codec_names;
308   codec_names.reserve(codecs.size());
309   for (const auto& codec : codecs) {
310     codec_names.push_back(codec.name);
311   }
312   return codec_names;
313 }
314 
315 // This is used for test only. MIDs are not the identification of the
316 // MediaDescriptionOptions since some end points may not support MID and the SDP
317 // may not contain 'mid'.
FindFirstMediaDescriptionByMid(const std::string & mid,MediaSessionOptions * opts)318 std::vector<MediaDescriptionOptions>::iterator FindFirstMediaDescriptionByMid(
319     const std::string& mid,
320     MediaSessionOptions* opts) {
321   return absl::c_find_if(
322       opts->media_description_options,
323       [&mid](const MediaDescriptionOptions& t) { return t.mid == mid; });
324 }
325 
326 std::vector<MediaDescriptionOptions>::const_iterator
FindFirstMediaDescriptionByMid(const std::string & mid,const MediaSessionOptions & opts)327 FindFirstMediaDescriptionByMid(const std::string& mid,
328                                const MediaSessionOptions& opts) {
329   return absl::c_find_if(
330       opts.media_description_options,
331       [&mid](const MediaDescriptionOptions& t) { return t.mid == mid; });
332 }
333 
334 // Add a media section to the `session_options`.
AddMediaDescriptionOptions(MediaType type,const std::string & mid,RtpTransceiverDirection direction,bool stopped,MediaSessionOptions * opts)335 static void AddMediaDescriptionOptions(MediaType type,
336                                        const std::string& mid,
337                                        RtpTransceiverDirection direction,
338                                        bool stopped,
339                                        MediaSessionOptions* opts) {
340   opts->media_description_options.push_back(
341       MediaDescriptionOptions(type, mid, direction, stopped));
342 }
343 
AddAudioVideoSections(RtpTransceiverDirection direction,MediaSessionOptions * opts)344 static void AddAudioVideoSections(RtpTransceiverDirection direction,
345                                   MediaSessionOptions* opts) {
346   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio", direction, kActive,
347                              opts);
348   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video", direction, kActive,
349                              opts);
350 }
351 
AddDataSection(RtpTransceiverDirection direction,MediaSessionOptions * opts)352 static void AddDataSection(RtpTransceiverDirection direction,
353                            MediaSessionOptions* opts) {
354   AddMediaDescriptionOptions(MEDIA_TYPE_DATA, "data", direction, kActive, opts);
355 }
356 
AttachSenderToMediaDescriptionOptions(const std::string & mid,MediaType type,const std::string & track_id,const std::vector<std::string> & stream_ids,const std::vector<RidDescription> & rids,const SimulcastLayerList & simulcast_layers,int num_sim_layer,MediaSessionOptions * session_options)357 static void AttachSenderToMediaDescriptionOptions(
358     const std::string& mid,
359     MediaType type,
360     const std::string& track_id,
361     const std::vector<std::string>& stream_ids,
362     const std::vector<RidDescription>& rids,
363     const SimulcastLayerList& simulcast_layers,
364     int num_sim_layer,
365     MediaSessionOptions* session_options) {
366   auto it = FindFirstMediaDescriptionByMid(mid, session_options);
367   switch (type) {
368     case MEDIA_TYPE_AUDIO:
369       it->AddAudioSender(track_id, stream_ids);
370       break;
371     case MEDIA_TYPE_VIDEO:
372       it->AddVideoSender(track_id, stream_ids, rids, simulcast_layers,
373                          num_sim_layer);
374       break;
375     default:
376       RTC_DCHECK_NOTREACHED();
377   }
378 }
379 
AttachSenderToMediaDescriptionOptions(const std::string & mid,MediaType type,const std::string & track_id,const std::vector<std::string> & stream_ids,int num_sim_layer,MediaSessionOptions * session_options)380 static void AttachSenderToMediaDescriptionOptions(
381     const std::string& mid,
382     MediaType type,
383     const std::string& track_id,
384     const std::vector<std::string>& stream_ids,
385     int num_sim_layer,
386     MediaSessionOptions* session_options) {
387   AttachSenderToMediaDescriptionOptions(mid, type, track_id, stream_ids, {},
388                                         SimulcastLayerList(), num_sim_layer,
389                                         session_options);
390 }
391 
DetachSenderFromMediaSection(const std::string & mid,const std::string & track_id,MediaSessionOptions * session_options)392 static void DetachSenderFromMediaSection(const std::string& mid,
393                                          const std::string& track_id,
394                                          MediaSessionOptions* session_options) {
395   std::vector<cricket::SenderOptions>& sender_options_list =
396       FindFirstMediaDescriptionByMid(mid, session_options)->sender_options;
397   auto sender_it =
398       absl::c_find_if(sender_options_list,
399                       [track_id](const cricket::SenderOptions& sender_options) {
400                         return sender_options.track_id == track_id;
401                       });
402   RTC_DCHECK(sender_it != sender_options_list.end());
403   sender_options_list.erase(sender_it);
404 }
405 
406 // Helper function used to create a default MediaSessionOptions for Plan B SDP.
407 // (https://tools.ietf.org/html/draft-uberti-rtcweb-plan-00).
CreatePlanBMediaSessionOptions()408 static MediaSessionOptions CreatePlanBMediaSessionOptions() {
409   MediaSessionOptions session_options;
410   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
411                              RtpTransceiverDirection::kRecvOnly, kActive,
412                              &session_options);
413   return session_options;
414 }
415 
416 // prefers GCM SDES crypto suites by removing non-GCM defaults.
PreferGcmCryptoParameters(CryptoParamsVec * cryptos)417 void PreferGcmCryptoParameters(CryptoParamsVec* cryptos) {
418   cryptos->erase(
419       std::remove_if(cryptos->begin(), cryptos->end(),
420                      [](const cricket::CryptoParams& crypto) {
421                        return crypto.cipher_suite != kCsAeadAes256Gcm &&
422                               crypto.cipher_suite != kCsAeadAes128Gcm;
423                      }),
424       cryptos->end());
425 }
426 
427 // TODO(zhihuang): Most of these tests were written while MediaSessionOptions
428 // was designed for Plan B SDP, where only one audio "m=" section and one video
429 // "m=" section could be generated, and ordering couldn't be controlled. Many of
430 // these tests may be obsolete as a result, and should be refactored or removed.
431 class MediaSessionDescriptionFactoryTest : public ::testing::Test {
432  public:
MediaSessionDescriptionFactoryTest()433   MediaSessionDescriptionFactoryTest()
434       : tdf1_(field_trials),
435         tdf2_(field_trials),
436         f1_(&tdf1_, &ssrc_generator1),
437         f2_(&tdf2_, &ssrc_generator2) {
438     f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
439                          MAKE_VECTOR(kAudioCodecs1));
440     f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1),
441                          MAKE_VECTOR(kVideoCodecs1));
442     f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
443                          MAKE_VECTOR(kAudioCodecs2));
444     f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2),
445                          MAKE_VECTOR(kVideoCodecs2));
446     tdf1_.set_certificate(rtc::RTCCertificate::Create(
447         std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
448     tdf2_.set_certificate(rtc::RTCCertificate::Create(
449         std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
450   }
451 
452   // Create a video StreamParamsVec object with:
453   // - one video stream with 3 simulcast streams and FEC,
CreateComplexVideoStreamParamsVec()454   StreamParamsVec CreateComplexVideoStreamParamsVec() {
455     SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
456     SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
457     SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
458     SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
459 
460     std::vector<SsrcGroup> ssrc_groups;
461     ssrc_groups.push_back(sim_group);
462     ssrc_groups.push_back(fec_group1);
463     ssrc_groups.push_back(fec_group2);
464     ssrc_groups.push_back(fec_group3);
465 
466     StreamParams simulcast_params;
467     simulcast_params.id = kVideoTrack1;
468     simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
469     simulcast_params.ssrc_groups = ssrc_groups;
470     simulcast_params.cname = "Video_SIM_FEC";
471     simulcast_params.set_stream_ids({kMediaStream1});
472 
473     StreamParamsVec video_streams;
474     video_streams.push_back(simulcast_params);
475 
476     return video_streams;
477   }
478 
CompareCryptoParams(const CryptoParamsVec & c1,const CryptoParamsVec & c2)479   bool CompareCryptoParams(const CryptoParamsVec& c1,
480                            const CryptoParamsVec& c2) {
481     if (c1.size() != c2.size())
482       return false;
483     for (size_t i = 0; i < c1.size(); ++i)
484       if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
485           c1[i].key_params != c2[i].key_params ||
486           c1[i].session_params != c2[i].session_params)
487         return false;
488     return true;
489   }
490 
491   // Returns true if the transport info contains "renomination" as an
492   // ICE option.
GetIceRenomination(const TransportInfo * transport_info)493   bool GetIceRenomination(const TransportInfo* transport_info) {
494     return absl::c_linear_search(transport_info->description.transport_options,
495                                  "renomination");
496   }
497 
TestTransportInfo(bool offer,const MediaSessionOptions & options,bool has_current_desc)498   void TestTransportInfo(bool offer,
499                          const MediaSessionOptions& options,
500                          bool has_current_desc) {
501     const std::string current_audio_ufrag = "current_audio_ufrag";
502     const std::string current_audio_pwd = "current_audio_pwd";
503     const std::string current_video_ufrag = "current_video_ufrag";
504     const std::string current_video_pwd = "current_video_pwd";
505     const std::string current_data_ufrag = "current_data_ufrag";
506     const std::string current_data_pwd = "current_data_pwd";
507     std::unique_ptr<SessionDescription> current_desc;
508     std::unique_ptr<SessionDescription> desc;
509     if (has_current_desc) {
510       current_desc = std::make_unique<SessionDescription>();
511       current_desc->AddTransportInfo(TransportInfo(
512           "audio",
513           TransportDescription(current_audio_ufrag, current_audio_pwd)));
514       current_desc->AddTransportInfo(TransportInfo(
515           "video",
516           TransportDescription(current_video_ufrag, current_video_pwd)));
517       current_desc->AddTransportInfo(TransportInfo(
518           "data", TransportDescription(current_data_ufrag, current_data_pwd)));
519     }
520     if (offer) {
521       desc = f1_.CreateOffer(options, current_desc.get());
522     } else {
523       std::unique_ptr<SessionDescription> offer;
524       offer = f1_.CreateOffer(options, NULL);
525       desc = f1_.CreateAnswer(offer.get(), options, current_desc.get());
526     }
527     ASSERT_TRUE(desc.get() != NULL);
528     const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
529     if (options.has_audio()) {
530       EXPECT_TRUE(ti_audio != NULL);
531       if (has_current_desc) {
532         EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
533         EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
534       } else {
535         EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
536                   ti_audio->description.ice_ufrag.size());
537         EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
538                   ti_audio->description.ice_pwd.size());
539       }
540       auto media_desc_options_it =
541           FindFirstMediaDescriptionByMid("audio", options);
542       EXPECT_EQ(
543           media_desc_options_it->transport_options.enable_ice_renomination,
544           GetIceRenomination(ti_audio));
545     } else {
546       EXPECT_TRUE(ti_audio == NULL);
547     }
548     const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
549     if (options.has_video()) {
550       EXPECT_TRUE(ti_video != NULL);
551       auto media_desc_options_it =
552           FindFirstMediaDescriptionByMid("video", options);
553       if (options.bundle_enabled) {
554         EXPECT_EQ(ti_audio->description.ice_ufrag,
555                   ti_video->description.ice_ufrag);
556         EXPECT_EQ(ti_audio->description.ice_pwd, ti_video->description.ice_pwd);
557       } else {
558         if (has_current_desc) {
559           EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
560           EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
561         } else {
562           EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
563                     ti_video->description.ice_ufrag.size());
564           EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
565                     ti_video->description.ice_pwd.size());
566         }
567       }
568       EXPECT_EQ(
569           media_desc_options_it->transport_options.enable_ice_renomination,
570           GetIceRenomination(ti_video));
571     } else {
572       EXPECT_TRUE(ti_video == NULL);
573     }
574     const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
575     if (options.has_data()) {
576       EXPECT_TRUE(ti_data != NULL);
577       if (options.bundle_enabled) {
578         EXPECT_EQ(ti_audio->description.ice_ufrag,
579                   ti_data->description.ice_ufrag);
580         EXPECT_EQ(ti_audio->description.ice_pwd, ti_data->description.ice_pwd);
581       } else {
582         if (has_current_desc) {
583           EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
584           EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
585         } else {
586           EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
587                     ti_data->description.ice_ufrag.size());
588           EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
589                     ti_data->description.ice_pwd.size());
590         }
591       }
592       auto media_desc_options_it =
593           FindFirstMediaDescriptionByMid("data", options);
594       EXPECT_EQ(
595           media_desc_options_it->transport_options.enable_ice_renomination,
596           GetIceRenomination(ti_data));
597 
598     } else {
599       EXPECT_TRUE(ti_data == NULL);
600     }
601   }
602 
TestCryptoWithBundle(bool offer)603   void TestCryptoWithBundle(bool offer) {
604     f1_.set_secure(SEC_ENABLED);
605     MediaSessionOptions options;
606     AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
607     std::unique_ptr<SessionDescription> ref_desc;
608     std::unique_ptr<SessionDescription> desc;
609     if (offer) {
610       options.bundle_enabled = false;
611       ref_desc = f1_.CreateOffer(options, NULL);
612       options.bundle_enabled = true;
613       desc = f1_.CreateOffer(options, ref_desc.get());
614     } else {
615       options.bundle_enabled = true;
616       ref_desc = f1_.CreateOffer(options, NULL);
617       desc = f1_.CreateAnswer(ref_desc.get(), options, NULL);
618     }
619     ASSERT_TRUE(desc);
620     const cricket::MediaContentDescription* audio_media_desc =
621         desc->GetContentDescriptionByName("audio");
622     ASSERT_TRUE(audio_media_desc);
623     const cricket::MediaContentDescription* video_media_desc =
624         desc->GetContentDescriptionByName("video");
625     ASSERT_TRUE(video_media_desc);
626     EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
627                                     video_media_desc->cryptos()));
628     EXPECT_EQ(1u, audio_media_desc->cryptos().size());
629     EXPECT_EQ(kDefaultSrtpCryptoSuite,
630               audio_media_desc->cryptos()[0].cipher_suite);
631 
632     // Verify the selected crypto is one from the reference audio
633     // media content.
634     const cricket::MediaContentDescription* ref_audio_media_desc =
635         ref_desc->GetContentDescriptionByName("audio");
636     bool found = false;
637     for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
638       if (ref_audio_media_desc->cryptos()[i].Matches(
639               audio_media_desc->cryptos()[0])) {
640         found = true;
641         break;
642       }
643     }
644     EXPECT_TRUE(found);
645   }
646 
647   // This test that the audio and video media direction is set to
648   // `expected_direction_in_answer` in an answer if the offer direction is set
649   // to `direction_in_offer` and the answer is willing to both send and receive.
TestMediaDirectionInAnswer(RtpTransceiverDirection direction_in_offer,RtpTransceiverDirection expected_direction_in_answer)650   void TestMediaDirectionInAnswer(
651       RtpTransceiverDirection direction_in_offer,
652       RtpTransceiverDirection expected_direction_in_answer) {
653     MediaSessionOptions offer_opts;
654     AddAudioVideoSections(direction_in_offer, &offer_opts);
655 
656     std::unique_ptr<SessionDescription> offer =
657         f1_.CreateOffer(offer_opts, NULL);
658     ASSERT_TRUE(offer.get() != NULL);
659     ContentInfo* ac_offer = offer->GetContentByName("audio");
660     ASSERT_TRUE(ac_offer != NULL);
661     ContentInfo* vc_offer = offer->GetContentByName("video");
662     ASSERT_TRUE(vc_offer != NULL);
663 
664     MediaSessionOptions answer_opts;
665     AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &answer_opts);
666     std::unique_ptr<SessionDescription> answer =
667         f2_.CreateAnswer(offer.get(), answer_opts, NULL);
668     const AudioContentDescription* acd_answer =
669         GetFirstAudioContentDescription(answer.get());
670     EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
671     const VideoContentDescription* vcd_answer =
672         GetFirstVideoContentDescription(answer.get());
673     EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
674   }
675 
VerifyNoCNCodecs(const cricket::ContentInfo * content)676   bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
677     RTC_DCHECK(content);
678     RTC_CHECK(content->media_description());
679     const cricket::AudioContentDescription* audio_desc =
680         content->media_description()->as_audio();
681     RTC_CHECK(audio_desc);
682     for (const cricket::AudioCodec& codec : audio_desc->codecs()) {
683       if (codec.name == "CN") {
684         return false;
685       }
686     }
687     return true;
688   }
689 
TestVideoGcmCipher(bool gcm_offer,bool gcm_answer)690   void TestVideoGcmCipher(bool gcm_offer, bool gcm_answer) {
691     MediaSessionOptions offer_opts;
692     AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &offer_opts);
693     offer_opts.crypto_options.srtp.enable_gcm_crypto_suites = gcm_offer;
694 
695     MediaSessionOptions answer_opts;
696     AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &answer_opts);
697     answer_opts.crypto_options.srtp.enable_gcm_crypto_suites = gcm_answer;
698 
699     f1_.set_secure(SEC_ENABLED);
700     f2_.set_secure(SEC_ENABLED);
701     std::unique_ptr<SessionDescription> offer =
702         f1_.CreateOffer(offer_opts, NULL);
703     ASSERT_TRUE(offer.get() != NULL);
704     if (gcm_offer && gcm_answer) {
705       for (cricket::ContentInfo& content : offer->contents()) {
706         auto cryptos = content.media_description()->cryptos();
707         PreferGcmCryptoParameters(&cryptos);
708         content.media_description()->set_cryptos(cryptos);
709       }
710     }
711     std::unique_ptr<SessionDescription> answer =
712         f2_.CreateAnswer(offer.get(), answer_opts, NULL);
713     const ContentInfo* ac = answer->GetContentByName("audio");
714     const ContentInfo* vc = answer->GetContentByName("video");
715     ASSERT_TRUE(ac != NULL);
716     ASSERT_TRUE(vc != NULL);
717     EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
718     EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
719     const AudioContentDescription* acd = ac->media_description()->as_audio();
720     const VideoContentDescription* vcd = vc->media_description()->as_video();
721     EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
722     EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
723     EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
724     EXPECT_EQ(0U, acd->first_ssrc());             // no sender is attached
725     EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
726     if (gcm_offer && gcm_answer) {
727       ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
728     } else {
729       ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
730     }
731     EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
732     EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer));
733     EXPECT_EQ(0U, vcd->first_ssrc());  // no sender is attached
734     EXPECT_TRUE(vcd->rtcp_mux());      // negotiated rtcp-mux
735     if (gcm_offer && gcm_answer) {
736       ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuiteGcm);
737     } else {
738       ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
739     }
740     EXPECT_EQ(cricket::kMediaProtocolSavpf, vcd->protocol());
741   }
742 
TestTransportSequenceNumberNegotiation(const cricket::RtpHeaderExtensions & local,const cricket::RtpHeaderExtensions & offered,const cricket::RtpHeaderExtensions & expectedAnswer)743   void TestTransportSequenceNumberNegotiation(
744       const cricket::RtpHeaderExtensions& local,
745       const cricket::RtpHeaderExtensions& offered,
746       const cricket::RtpHeaderExtensions& expectedAnswer) {
747     MediaSessionOptions opts;
748     AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
749     SetAudioVideoRtpHeaderExtensions(offered, offered, &opts);
750     std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
751     ASSERT_TRUE(offer.get() != NULL);
752     SetAudioVideoRtpHeaderExtensions(local, local, &opts);
753     std::unique_ptr<SessionDescription> answer =
754         f2_.CreateAnswer(offer.get(), opts, NULL);
755 
756     EXPECT_EQ(
757         expectedAnswer,
758         GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
759     EXPECT_EQ(
760         expectedAnswer,
761         GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
762   }
763 
764   std::vector<webrtc::RtpHeaderExtensionCapability>
HeaderExtensionCapabilitiesFromRtpExtensions(cricket::RtpHeaderExtensions extensions)765   HeaderExtensionCapabilitiesFromRtpExtensions(
766       cricket::RtpHeaderExtensions extensions) {
767     std::vector<webrtc::RtpHeaderExtensionCapability> capabilities;
768     for (const auto& extension : extensions) {
769       webrtc::RtpHeaderExtensionCapability capability(
770           extension.uri, extension.id,
771           webrtc::RtpTransceiverDirection::kSendRecv);
772       capabilities.push_back(capability);
773     }
774     return capabilities;
775   }
776 
SetAudioVideoRtpHeaderExtensions(cricket::RtpHeaderExtensions audio_exts,cricket::RtpHeaderExtensions video_exts,MediaSessionOptions * opts)777   void SetAudioVideoRtpHeaderExtensions(cricket::RtpHeaderExtensions audio_exts,
778                                         cricket::RtpHeaderExtensions video_exts,
779                                         MediaSessionOptions* opts) {
780     auto audio_caps = HeaderExtensionCapabilitiesFromRtpExtensions(audio_exts);
781     auto video_caps = HeaderExtensionCapabilitiesFromRtpExtensions(video_exts);
782     for (auto& entry : opts->media_description_options) {
783       switch (entry.type) {
784         case MEDIA_TYPE_AUDIO:
785           entry.header_extensions = audio_caps;
786           break;
787         case MEDIA_TYPE_VIDEO:
788           entry.header_extensions = video_caps;
789           break;
790         default:
791           break;
792       }
793     }
794   }
795 
796  protected:
797   webrtc::test::ScopedKeyValueConfig field_trials;
798   UniqueRandomIdGenerator ssrc_generator1;
799   UniqueRandomIdGenerator ssrc_generator2;
800   TransportDescriptionFactory tdf1_;
801   TransportDescriptionFactory tdf2_;
802   MediaSessionDescriptionFactory f1_;
803   MediaSessionDescriptionFactory f2_;
804 };
805 
806 // Create a typical audio offer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateAudioOffer)807 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
808   f1_.set_secure(SEC_ENABLED);
809   std::unique_ptr<SessionDescription> offer =
810       f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL);
811   ASSERT_TRUE(offer.get() != NULL);
812   const ContentInfo* ac = offer->GetContentByName("audio");
813   const ContentInfo* vc = offer->GetContentByName("video");
814   ASSERT_TRUE(ac != NULL);
815   ASSERT_TRUE(vc == NULL);
816   EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
817   const AudioContentDescription* acd = ac->media_description()->as_audio();
818   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
819   EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
820   EXPECT_EQ(0U, acd->first_ssrc());             // no sender is attached.
821   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
822   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
823   ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
824   EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
825 }
826 
827 // Create a typical video offer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateVideoOffer)828 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
829   MediaSessionOptions opts;
830   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
831   f1_.set_secure(SEC_ENABLED);
832   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
833   ASSERT_TRUE(offer.get() != NULL);
834   const ContentInfo* ac = offer->GetContentByName("audio");
835   const ContentInfo* vc = offer->GetContentByName("video");
836   ASSERT_TRUE(ac != NULL);
837   ASSERT_TRUE(vc != NULL);
838   EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
839   EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
840   const AudioContentDescription* acd = ac->media_description()->as_audio();
841   const VideoContentDescription* vcd = vc->media_description()->as_video();
842   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
843   EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
844   EXPECT_EQ(0U, acd->first_ssrc());             // no sender is attached
845   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
846   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
847   ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
848   EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
849   EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
850   EXPECT_EQ(f1_.video_sendrecv_codecs(), vcd->codecs());
851   EXPECT_EQ(0U, vcd->first_ssrc());             // no sender is attached
852   EXPECT_EQ(kAutoBandwidth, vcd->bandwidth());  // default bandwidth (auto)
853   EXPECT_TRUE(vcd->rtcp_mux());                 // rtcp-mux defaults on
854   ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
855   EXPECT_EQ(cricket::kMediaProtocolSavpf, vcd->protocol());
856 }
857 
858 // Test creating an offer with bundle where the Codecs have the same dynamic
859 // RTP playlod type. The test verifies that the offer don't contain the
860 // duplicate RTP payload types.
TEST_F(MediaSessionDescriptionFactoryTest,TestBundleOfferWithSameCodecPlType)861 TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
862   const VideoCodec& offered_video_codec = f2_.video_sendrecv_codecs()[0];
863   const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0];
864   ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
865 
866   MediaSessionOptions opts;
867   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
868   opts.bundle_enabled = true;
869   std::unique_ptr<SessionDescription> offer = f2_.CreateOffer(opts, NULL);
870   const VideoContentDescription* vcd =
871       GetFirstVideoContentDescription(offer.get());
872   const AudioContentDescription* acd =
873       GetFirstAudioContentDescription(offer.get());
874   ASSERT_TRUE(NULL != vcd);
875   ASSERT_TRUE(NULL != acd);
876   EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
877   EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
878   EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
879 }
880 
881 // Test creating an updated offer with bundle, audio, video and data
882 // after an audio only session has been negotiated.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateUpdatedVideoOfferWithBundle)883 TEST_F(MediaSessionDescriptionFactoryTest,
884        TestCreateUpdatedVideoOfferWithBundle) {
885   f1_.set_secure(SEC_ENABLED);
886   f2_.set_secure(SEC_ENABLED);
887   MediaSessionOptions opts;
888   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
889                              RtpTransceiverDirection::kRecvOnly, kActive,
890                              &opts);
891   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
892                              RtpTransceiverDirection::kInactive, kStopped,
893                              &opts);
894   opts.bundle_enabled = true;
895   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
896   std::unique_ptr<SessionDescription> answer =
897       f2_.CreateAnswer(offer.get(), opts, NULL);
898 
899   MediaSessionOptions updated_opts;
900   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &updated_opts);
901   updated_opts.bundle_enabled = true;
902   std::unique_ptr<SessionDescription> updated_offer(
903       f1_.CreateOffer(updated_opts, answer.get()));
904 
905   const AudioContentDescription* acd =
906       GetFirstAudioContentDescription(updated_offer.get());
907   const VideoContentDescription* vcd =
908       GetFirstVideoContentDescription(updated_offer.get());
909   EXPECT_TRUE(NULL != vcd);
910   EXPECT_TRUE(NULL != acd);
911 
912   ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
913   EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
914   ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
915   EXPECT_EQ(cricket::kMediaProtocolSavpf, vcd->protocol());
916 }
917 
918 // Create an SCTP data offer with bundle without error.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateSctpDataOffer)919 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
920   MediaSessionOptions opts;
921   opts.bundle_enabled = true;
922   AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
923   f1_.set_secure(SEC_ENABLED);
924   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
925   EXPECT_TRUE(offer.get() != NULL);
926   EXPECT_TRUE(offer->GetContentByName("data") != NULL);
927   auto dcd = GetFirstSctpDataContentDescription(offer.get());
928   ASSERT_TRUE(dcd);
929   // Since this transport is insecure, the protocol should be "SCTP".
930   EXPECT_EQ(cricket::kMediaProtocolSctp, dcd->protocol());
931 }
932 
933 // Create an SCTP data offer with bundle without error.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateSecureSctpDataOffer)934 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSecureSctpDataOffer) {
935   MediaSessionOptions opts;
936   opts.bundle_enabled = true;
937   AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
938   f1_.set_secure(SEC_ENABLED);
939   tdf1_.set_secure(SEC_ENABLED);
940   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
941   EXPECT_TRUE(offer.get() != NULL);
942   EXPECT_TRUE(offer->GetContentByName("data") != NULL);
943   auto dcd = GetFirstSctpDataContentDescription(offer.get());
944   ASSERT_TRUE(dcd);
945   // The protocol should now be "UDP/DTLS/SCTP"
946   EXPECT_EQ(cricket::kMediaProtocolUdpDtlsSctp, dcd->protocol());
947 }
948 
949 // Test creating an sctp data channel from an already generated offer.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateImplicitSctpDataOffer)950 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
951   MediaSessionOptions opts;
952   opts.bundle_enabled = true;
953   AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
954   f1_.set_secure(SEC_ENABLED);
955   std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
956   ASSERT_TRUE(offer1.get() != NULL);
957   const ContentInfo* data = offer1->GetContentByName("data");
958   ASSERT_TRUE(data != NULL);
959   ASSERT_EQ(cricket::kMediaProtocolSctp, data->media_description()->protocol());
960 
961   std::unique_ptr<SessionDescription> offer2(
962       f1_.CreateOffer(opts, offer1.get()));
963   data = offer2->GetContentByName("data");
964   ASSERT_TRUE(data != NULL);
965   EXPECT_EQ(cricket::kMediaProtocolSctp, data->media_description()->protocol());
966 }
967 
968 // Test that if BUNDLE is enabled and all media sections are rejected then the
969 // BUNDLE group is not present in the re-offer.
TEST_F(MediaSessionDescriptionFactoryTest,ReOfferNoBundleGroupIfAllRejected)970 TEST_F(MediaSessionDescriptionFactoryTest, ReOfferNoBundleGroupIfAllRejected) {
971   MediaSessionOptions opts;
972   opts.bundle_enabled = true;
973   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
974                              RtpTransceiverDirection::kSendRecv, kActive,
975                              &opts);
976   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
977 
978   opts.media_description_options[0].stopped = true;
979   std::unique_ptr<SessionDescription> reoffer =
980       f1_.CreateOffer(opts, offer.get());
981 
982   EXPECT_FALSE(reoffer->GetGroupByName(cricket::GROUP_TYPE_BUNDLE));
983 }
984 
985 // Test that if BUNDLE is enabled and the remote re-offer does not include a
986 // BUNDLE group since all media sections are rejected, then the re-answer also
987 // does not include a BUNDLE group.
TEST_F(MediaSessionDescriptionFactoryTest,ReAnswerNoBundleGroupIfAllRejected)988 TEST_F(MediaSessionDescriptionFactoryTest, ReAnswerNoBundleGroupIfAllRejected) {
989   MediaSessionOptions opts;
990   opts.bundle_enabled = true;
991   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
992                              RtpTransceiverDirection::kSendRecv, kActive,
993                              &opts);
994   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
995   std::unique_ptr<SessionDescription> answer =
996       f2_.CreateAnswer(offer.get(), opts, nullptr);
997 
998   opts.media_description_options[0].stopped = true;
999   std::unique_ptr<SessionDescription> reoffer =
1000       f1_.CreateOffer(opts, offer.get());
1001   std::unique_ptr<SessionDescription> reanswer =
1002       f2_.CreateAnswer(reoffer.get(), opts, answer.get());
1003 
1004   EXPECT_FALSE(reanswer->GetGroupByName(cricket::GROUP_TYPE_BUNDLE));
1005 }
1006 
1007 // Test that if BUNDLE is enabled and the previous offerer-tagged media section
1008 // was rejected then the new offerer-tagged media section is the non-rejected
1009 // media section.
TEST_F(MediaSessionDescriptionFactoryTest,ReOfferChangeBundleOffererTagged)1010 TEST_F(MediaSessionDescriptionFactoryTest, ReOfferChangeBundleOffererTagged) {
1011   MediaSessionOptions opts;
1012   opts.bundle_enabled = true;
1013   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
1014                              RtpTransceiverDirection::kSendRecv, kActive,
1015                              &opts);
1016   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1017 
1018   // Reject the audio m= section and add a video m= section.
1019   opts.media_description_options[0].stopped = true;
1020   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
1021                              RtpTransceiverDirection::kSendRecv, kActive,
1022                              &opts);
1023   std::unique_ptr<SessionDescription> reoffer =
1024       f1_.CreateOffer(opts, offer.get());
1025 
1026   const cricket::ContentGroup* bundle_group =
1027       reoffer->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
1028   ASSERT_TRUE(bundle_group);
1029   EXPECT_FALSE(bundle_group->HasContentName("audio"));
1030   EXPECT_TRUE(bundle_group->HasContentName("video"));
1031 }
1032 
1033 // Test that if BUNDLE is enabled and the previous offerer-tagged media section
1034 // was rejected and a new media section is added, then the re-answer BUNDLE
1035 // group will contain only the non-rejected media section.
TEST_F(MediaSessionDescriptionFactoryTest,ReAnswerChangedBundleOffererTagged)1036 TEST_F(MediaSessionDescriptionFactoryTest, ReAnswerChangedBundleOffererTagged) {
1037   MediaSessionOptions opts;
1038   opts.bundle_enabled = true;
1039   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
1040                              RtpTransceiverDirection::kSendRecv, kActive,
1041                              &opts);
1042   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1043   std::unique_ptr<SessionDescription> answer =
1044       f2_.CreateAnswer(offer.get(), opts, nullptr);
1045 
1046   // Reject the audio m= section and add a video m= section.
1047   opts.media_description_options[0].stopped = true;
1048   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
1049                              RtpTransceiverDirection::kSendRecv, kActive,
1050                              &opts);
1051   std::unique_ptr<SessionDescription> reoffer =
1052       f1_.CreateOffer(opts, offer.get());
1053   std::unique_ptr<SessionDescription> reanswer =
1054       f2_.CreateAnswer(reoffer.get(), opts, answer.get());
1055 
1056   const cricket::ContentGroup* bundle_group =
1057       reanswer->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
1058   ASSERT_TRUE(bundle_group);
1059   EXPECT_FALSE(bundle_group->HasContentName("audio"));
1060   EXPECT_TRUE(bundle_group->HasContentName("video"));
1061 }
1062 
TEST_F(MediaSessionDescriptionFactoryTest,CreateAnswerForOfferWithMultipleBundleGroups)1063 TEST_F(MediaSessionDescriptionFactoryTest,
1064        CreateAnswerForOfferWithMultipleBundleGroups) {
1065   // Create an offer with 4 m= sections, initially without BUNDLE groups.
1066   MediaSessionOptions opts;
1067   opts.bundle_enabled = false;
1068   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "1",
1069                              RtpTransceiverDirection::kSendRecv, kActive,
1070                              &opts);
1071   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "2",
1072                              RtpTransceiverDirection::kSendRecv, kActive,
1073                              &opts);
1074   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "3",
1075                              RtpTransceiverDirection::kSendRecv, kActive,
1076                              &opts);
1077   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "4",
1078                              RtpTransceiverDirection::kSendRecv, kActive,
1079                              &opts);
1080   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1081   ASSERT_TRUE(offer->groups().empty());
1082 
1083   // Munge the offer to have two groups. Offers like these cannot be generated
1084   // without munging, but it is valid to receive such offers from remote
1085   // endpoints.
1086   cricket::ContentGroup bundle_group1(cricket::GROUP_TYPE_BUNDLE);
1087   bundle_group1.AddContentName("1");
1088   bundle_group1.AddContentName("2");
1089   cricket::ContentGroup bundle_group2(cricket::GROUP_TYPE_BUNDLE);
1090   bundle_group2.AddContentName("3");
1091   bundle_group2.AddContentName("4");
1092   offer->AddGroup(bundle_group1);
1093   offer->AddGroup(bundle_group2);
1094 
1095   // If BUNDLE is enabled, the answer to this offer should accept both BUNDLE
1096   // groups.
1097   opts.bundle_enabled = true;
1098   std::unique_ptr<SessionDescription> answer =
1099       f2_.CreateAnswer(offer.get(), opts, nullptr);
1100 
1101   std::vector<const cricket::ContentGroup*> answer_groups =
1102       answer->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
1103   ASSERT_EQ(answer_groups.size(), 2u);
1104   EXPECT_EQ(answer_groups[0]->content_names().size(), 2u);
1105   EXPECT_TRUE(answer_groups[0]->HasContentName("1"));
1106   EXPECT_TRUE(answer_groups[0]->HasContentName("2"));
1107   EXPECT_EQ(answer_groups[1]->content_names().size(), 2u);
1108   EXPECT_TRUE(answer_groups[1]->HasContentName("3"));
1109   EXPECT_TRUE(answer_groups[1]->HasContentName("4"));
1110 
1111   // If BUNDLE is disabled, the answer to this offer should reject both BUNDLE
1112   // groups.
1113   opts.bundle_enabled = false;
1114   answer = f2_.CreateAnswer(offer.get(), opts, nullptr);
1115 
1116   answer_groups = answer->GetGroupsByName(cricket::GROUP_TYPE_BUNDLE);
1117   // Rejected groups are still listed, but they are empty.
1118   ASSERT_EQ(answer_groups.size(), 2u);
1119   EXPECT_TRUE(answer_groups[0]->content_names().empty());
1120   EXPECT_TRUE(answer_groups[1]->content_names().empty());
1121 }
1122 
1123 // Test that if the BUNDLE offerer-tagged media section is changed in a reoffer
1124 // and there is still a non-rejected media section that was in the initial
1125 // offer, then the ICE credentials do not change in the reoffer offerer-tagged
1126 // media section.
TEST_F(MediaSessionDescriptionFactoryTest,ReOfferChangeBundleOffererTaggedKeepsIceCredentials)1127 TEST_F(MediaSessionDescriptionFactoryTest,
1128        ReOfferChangeBundleOffererTaggedKeepsIceCredentials) {
1129   MediaSessionOptions opts;
1130   opts.bundle_enabled = true;
1131   AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
1132   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1133   std::unique_ptr<SessionDescription> answer =
1134       f2_.CreateAnswer(offer.get(), opts, nullptr);
1135 
1136   // Reject the audio m= section.
1137   opts.media_description_options[0].stopped = true;
1138   std::unique_ptr<SessionDescription> reoffer =
1139       f1_.CreateOffer(opts, offer.get());
1140 
1141   const TransportDescription* offer_tagged =
1142       offer->GetTransportDescriptionByName("audio");
1143   ASSERT_TRUE(offer_tagged);
1144   const TransportDescription* reoffer_tagged =
1145       reoffer->GetTransportDescriptionByName("video");
1146   ASSERT_TRUE(reoffer_tagged);
1147   EXPECT_EQ(offer_tagged->ice_ufrag, reoffer_tagged->ice_ufrag);
1148   EXPECT_EQ(offer_tagged->ice_pwd, reoffer_tagged->ice_pwd);
1149 }
1150 
1151 // Test that if the BUNDLE offerer-tagged media section is changed in a reoffer
1152 // and there is still a non-rejected media section that was in the initial
1153 // offer, then the ICE credentials do not change in the reanswer answerer-tagged
1154 // media section.
TEST_F(MediaSessionDescriptionFactoryTest,ReAnswerChangeBundleOffererTaggedKeepsIceCredentials)1155 TEST_F(MediaSessionDescriptionFactoryTest,
1156        ReAnswerChangeBundleOffererTaggedKeepsIceCredentials) {
1157   MediaSessionOptions opts;
1158   opts.bundle_enabled = true;
1159   AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
1160   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1161   std::unique_ptr<SessionDescription> answer =
1162       f2_.CreateAnswer(offer.get(), opts, nullptr);
1163 
1164   // Reject the audio m= section.
1165   opts.media_description_options[0].stopped = true;
1166   std::unique_ptr<SessionDescription> reoffer =
1167       f1_.CreateOffer(opts, offer.get());
1168   std::unique_ptr<SessionDescription> reanswer =
1169       f2_.CreateAnswer(reoffer.get(), opts, answer.get());
1170 
1171   const TransportDescription* answer_tagged =
1172       answer->GetTransportDescriptionByName("audio");
1173   ASSERT_TRUE(answer_tagged);
1174   const TransportDescription* reanswer_tagged =
1175       reanswer->GetTransportDescriptionByName("video");
1176   ASSERT_TRUE(reanswer_tagged);
1177   EXPECT_EQ(answer_tagged->ice_ufrag, reanswer_tagged->ice_ufrag);
1178   EXPECT_EQ(answer_tagged->ice_pwd, reanswer_tagged->ice_pwd);
1179 }
1180 
1181 // Create an audio, video offer without legacy StreamParams.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateOfferWithoutLegacyStreams)1182 TEST_F(MediaSessionDescriptionFactoryTest,
1183        TestCreateOfferWithoutLegacyStreams) {
1184   MediaSessionOptions opts;
1185   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1186   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
1187   ASSERT_TRUE(offer.get() != NULL);
1188   const ContentInfo* ac = offer->GetContentByName("audio");
1189   const ContentInfo* vc = offer->GetContentByName("video");
1190   ASSERT_TRUE(ac != NULL);
1191   ASSERT_TRUE(vc != NULL);
1192   const AudioContentDescription* acd = ac->media_description()->as_audio();
1193   const VideoContentDescription* vcd = vc->media_description()->as_video();
1194 
1195   EXPECT_FALSE(vcd->has_ssrcs());  // No StreamParams.
1196   EXPECT_FALSE(acd->has_ssrcs());  // No StreamParams.
1197 }
1198 
1199 // Creates an audio+video sendonly offer.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateSendOnlyOffer)1200 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
1201   MediaSessionOptions opts;
1202   AddAudioVideoSections(RtpTransceiverDirection::kSendOnly, &opts);
1203   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
1204                                         {kMediaStream1}, 1, &opts);
1205   AttachSenderToMediaDescriptionOptions("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
1206                                         {kMediaStream1}, 1, &opts);
1207 
1208   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
1209   ASSERT_TRUE(offer.get() != NULL);
1210   EXPECT_EQ(2u, offer->contents().size());
1211   EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
1212   EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
1213 
1214   EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
1215             GetMediaDirection(&offer->contents()[0]));
1216   EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
1217             GetMediaDirection(&offer->contents()[1]));
1218 }
1219 
1220 // Verifies that the order of the media contents in the current
1221 // SessionDescription is preserved in the new SessionDescription.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateOfferContentOrder)1222 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
1223   MediaSessionOptions opts;
1224   AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
1225 
1226   std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
1227   ASSERT_TRUE(offer1.get() != NULL);
1228   EXPECT_EQ(1u, offer1->contents().size());
1229   EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
1230 
1231   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
1232                              RtpTransceiverDirection::kRecvOnly, kActive,
1233                              &opts);
1234   std::unique_ptr<SessionDescription> offer2(
1235       f1_.CreateOffer(opts, offer1.get()));
1236   ASSERT_TRUE(offer2.get() != NULL);
1237   EXPECT_EQ(2u, offer2->contents().size());
1238   EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
1239   EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
1240 
1241   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
1242                              RtpTransceiverDirection::kRecvOnly, kActive,
1243                              &opts);
1244   std::unique_ptr<SessionDescription> offer3(
1245       f1_.CreateOffer(opts, offer2.get()));
1246   ASSERT_TRUE(offer3.get() != NULL);
1247   EXPECT_EQ(3u, offer3->contents().size());
1248   EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
1249   EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
1250   EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
1251 }
1252 
1253 // Create a typical audio answer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateAudioAnswer)1254 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
1255   f1_.set_secure(SEC_ENABLED);
1256   f2_.set_secure(SEC_ENABLED);
1257   std::unique_ptr<SessionDescription> offer =
1258       f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL);
1259   ASSERT_TRUE(offer.get() != NULL);
1260   std::unique_ptr<SessionDescription> answer =
1261       f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL);
1262   const ContentInfo* ac = answer->GetContentByName("audio");
1263   const ContentInfo* vc = answer->GetContentByName("video");
1264   ASSERT_TRUE(ac != NULL);
1265   ASSERT_TRUE(vc == NULL);
1266   EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
1267   const AudioContentDescription* acd = ac->media_description()->as_audio();
1268   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1269   EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
1270   EXPECT_EQ(0U, acd->first_ssrc());             // no sender is attached
1271   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
1272   EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
1273   ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
1274   EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
1275 }
1276 
1277 // Create a typical audio answer with GCM ciphers enabled, and ensure it
1278 // matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateAudioAnswerGcm)1279 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
1280   f1_.set_secure(SEC_ENABLED);
1281   f2_.set_secure(SEC_ENABLED);
1282   MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
1283   opts.crypto_options.srtp.enable_gcm_crypto_suites = true;
1284   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
1285   ASSERT_TRUE(offer.get() != NULL);
1286   for (cricket::ContentInfo& content : offer->contents()) {
1287     auto cryptos = content.media_description()->cryptos();
1288     PreferGcmCryptoParameters(&cryptos);
1289     content.media_description()->set_cryptos(cryptos);
1290   }
1291   std::unique_ptr<SessionDescription> answer =
1292       f2_.CreateAnswer(offer.get(), opts, NULL);
1293   const ContentInfo* ac = answer->GetContentByName("audio");
1294   const ContentInfo* vc = answer->GetContentByName("video");
1295   ASSERT_TRUE(ac != NULL);
1296   ASSERT_TRUE(vc == NULL);
1297   EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
1298   const AudioContentDescription* acd = ac->media_description()->as_audio();
1299   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1300   EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
1301   EXPECT_EQ(0U, acd->first_ssrc());             // no sender is attached
1302   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
1303   EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
1304   ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuiteGcm);
1305   EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
1306 }
1307 
1308 // Create an audio answer with no common codecs, and ensure it is rejected.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateAudioAnswerWithNoCommonCodecs)1309 TEST_F(MediaSessionDescriptionFactoryTest,
1310        TestCreateAudioAnswerWithNoCommonCodecs) {
1311   MediaSessionOptions opts;
1312   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
1313                              RtpTransceiverDirection::kSendRecv, kActive,
1314                              &opts);
1315   std::vector f1_codecs = {AudioCodec(96, "opus", 48000, -1, 1)};
1316   f1_.set_audio_codecs(f1_codecs, f1_codecs);
1317 
1318   std::vector f2_codecs = {AudioCodec(0, "PCMU", 8000, -1, 1)};
1319   f2_.set_audio_codecs(f2_codecs, f2_codecs);
1320 
1321   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1322   std::unique_ptr<SessionDescription> answer =
1323       f2_.CreateAnswer(offer.get(), opts, NULL);
1324   const ContentInfo* ac = answer->GetContentByName("audio");
1325   ASSERT_TRUE(ac != NULL);
1326   EXPECT_TRUE(ac->rejected);
1327 }
1328 
1329 // Create a typical video answer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateVideoAnswer)1330 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
1331   MediaSessionOptions opts;
1332   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1333   f1_.set_secure(SEC_ENABLED);
1334   f2_.set_secure(SEC_ENABLED);
1335   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
1336   ASSERT_TRUE(offer.get() != NULL);
1337   std::unique_ptr<SessionDescription> answer =
1338       f2_.CreateAnswer(offer.get(), opts, NULL);
1339   const ContentInfo* ac = answer->GetContentByName("audio");
1340   const ContentInfo* vc = answer->GetContentByName("video");
1341   ASSERT_TRUE(ac != NULL);
1342   ASSERT_TRUE(vc != NULL);
1343   EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
1344   EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
1345   const AudioContentDescription* acd = ac->media_description()->as_audio();
1346   const VideoContentDescription* vcd = vc->media_description()->as_video();
1347   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1348   EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
1349   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
1350   EXPECT_EQ(0U, acd->first_ssrc());             // no sender is attached
1351   EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
1352   ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
1353   EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1354   EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer));
1355   EXPECT_EQ(0U, vcd->first_ssrc());  // no sender is attached
1356   EXPECT_TRUE(vcd->rtcp_mux());      // negotiated rtcp-mux
1357   ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
1358   EXPECT_EQ(cricket::kMediaProtocolSavpf, vcd->protocol());
1359 }
1360 
1361 // Create a typical video answer with GCM ciphers enabled, and ensure it
1362 // matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateVideoAnswerGcm)1363 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcm) {
1364   TestVideoGcmCipher(true, true);
1365 }
1366 
1367 // Create a typical video answer with GCM ciphers enabled for the offer only,
1368 // and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateVideoAnswerGcmOffer)1369 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmOffer) {
1370   TestVideoGcmCipher(true, false);
1371 }
1372 
1373 // Create a typical video answer with GCM ciphers enabled for the answer only,
1374 // and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateVideoAnswerGcmAnswer)1375 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmAnswer) {
1376   TestVideoGcmCipher(false, true);
1377 }
1378 
1379 // Create a video answer with no common codecs, and ensure it is rejected.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateVideoAnswerWithNoCommonCodecs)1380 TEST_F(MediaSessionDescriptionFactoryTest,
1381        TestCreateVideoAnswerWithNoCommonCodecs) {
1382   MediaSessionOptions opts;
1383   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
1384                              RtpTransceiverDirection::kSendRecv, kActive,
1385                              &opts);
1386   std::vector f1_codecs = {VideoCodec(96, "H264")};
1387   f1_.set_video_codecs(f1_codecs, f1_codecs);
1388 
1389   std::vector f2_codecs = {VideoCodec(97, "VP8")};
1390   f2_.set_video_codecs(f2_codecs, f2_codecs);
1391 
1392   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1393   std::unique_ptr<SessionDescription> answer =
1394       f2_.CreateAnswer(offer.get(), opts, NULL);
1395   const ContentInfo* vc = answer->GetContentByName("video");
1396   ASSERT_TRUE(vc != NULL);
1397   EXPECT_TRUE(vc->rejected);
1398 }
1399 
1400 // Create a video answer with no common codecs (but a common FEC codec), and
1401 // ensure it is rejected.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateVideoAnswerWithOnlyFecCodecsCommon)1402 TEST_F(MediaSessionDescriptionFactoryTest,
1403        TestCreateVideoAnswerWithOnlyFecCodecsCommon) {
1404   MediaSessionOptions opts;
1405   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
1406                              RtpTransceiverDirection::kSendRecv, kActive,
1407                              &opts);
1408   std::vector f1_codecs = {VideoCodec(96, "H264"),
1409                            VideoCodec(118, "flexfec-03")};
1410   f1_.set_video_codecs(f1_codecs, f1_codecs);
1411 
1412   std::vector f2_codecs = {VideoCodec(97, "VP8"),
1413                            VideoCodec(118, "flexfec-03")};
1414   f2_.set_video_codecs(f2_codecs, f2_codecs);
1415 
1416   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1417   std::unique_ptr<SessionDescription> answer =
1418       f2_.CreateAnswer(offer.get(), opts, NULL);
1419   const ContentInfo* vc = answer->GetContentByName("video");
1420   ASSERT_TRUE(vc != NULL);
1421   EXPECT_TRUE(vc->rejected);
1422 }
1423 
1424 // The use_sctpmap flag should be set in an Sctp DataContentDescription by
1425 // default. The answer's use_sctpmap flag should match the offer's.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateDataAnswerUsesSctpmap)1426 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerUsesSctpmap) {
1427   MediaSessionOptions opts;
1428   AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
1429   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
1430   ASSERT_TRUE(offer.get() != NULL);
1431   ContentInfo* dc_offer = offer->GetContentByName("data");
1432   ASSERT_TRUE(dc_offer != NULL);
1433   SctpDataContentDescription* dcd_offer =
1434       dc_offer->media_description()->as_sctp();
1435   EXPECT_TRUE(dcd_offer->use_sctpmap());
1436 
1437   std::unique_ptr<SessionDescription> answer =
1438       f2_.CreateAnswer(offer.get(), opts, NULL);
1439   const ContentInfo* dc_answer = answer->GetContentByName("data");
1440   ASSERT_TRUE(dc_answer != NULL);
1441   const SctpDataContentDescription* dcd_answer =
1442       dc_answer->media_description()->as_sctp();
1443   EXPECT_TRUE(dcd_answer->use_sctpmap());
1444 }
1445 
1446 // The answer's use_sctpmap flag should match the offer's.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateDataAnswerWithoutSctpmap)1447 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerWithoutSctpmap) {
1448   MediaSessionOptions opts;
1449   AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
1450   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
1451   ASSERT_TRUE(offer.get() != NULL);
1452   ContentInfo* dc_offer = offer->GetContentByName("data");
1453   ASSERT_TRUE(dc_offer != NULL);
1454   SctpDataContentDescription* dcd_offer =
1455       dc_offer->media_description()->as_sctp();
1456   dcd_offer->set_use_sctpmap(false);
1457 
1458   std::unique_ptr<SessionDescription> answer =
1459       f2_.CreateAnswer(offer.get(), opts, NULL);
1460   const ContentInfo* dc_answer = answer->GetContentByName("data");
1461   ASSERT_TRUE(dc_answer != NULL);
1462   const SctpDataContentDescription* dcd_answer =
1463       dc_answer->media_description()->as_sctp();
1464   EXPECT_FALSE(dcd_answer->use_sctpmap());
1465 }
1466 
1467 // Test that a valid answer will be created for "DTLS/SCTP", "UDP/DTLS/SCTP"
1468 // and "TCP/DTLS/SCTP" offers.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateDataAnswerToDifferentOfferedProtos)1469 TEST_F(MediaSessionDescriptionFactoryTest,
1470        TestCreateDataAnswerToDifferentOfferedProtos) {
1471   // Need to enable DTLS offer/answer generation (disabled by default in this
1472   // test).
1473   f1_.set_secure(SEC_ENABLED);
1474   f2_.set_secure(SEC_ENABLED);
1475   tdf1_.set_secure(SEC_ENABLED);
1476   tdf2_.set_secure(SEC_ENABLED);
1477 
1478   MediaSessionOptions opts;
1479   AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
1480   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1481   ASSERT_TRUE(offer.get() != nullptr);
1482   ContentInfo* dc_offer = offer->GetContentByName("data");
1483   ASSERT_TRUE(dc_offer != nullptr);
1484   SctpDataContentDescription* dcd_offer =
1485       dc_offer->media_description()->as_sctp();
1486   ASSERT_TRUE(dcd_offer);
1487 
1488   std::vector<std::string> protos = {"DTLS/SCTP", "UDP/DTLS/SCTP",
1489                                      "TCP/DTLS/SCTP"};
1490   for (const std::string& proto : protos) {
1491     dcd_offer->set_protocol(proto);
1492     std::unique_ptr<SessionDescription> answer =
1493         f2_.CreateAnswer(offer.get(), opts, nullptr);
1494     const ContentInfo* dc_answer = answer->GetContentByName("data");
1495     ASSERT_TRUE(dc_answer != nullptr);
1496     const SctpDataContentDescription* dcd_answer =
1497         dc_answer->media_description()->as_sctp();
1498     EXPECT_FALSE(dc_answer->rejected);
1499     EXPECT_EQ(proto, dcd_answer->protocol());
1500   }
1501 }
1502 
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateDataAnswerToOfferWithDefinedMessageSize)1503 TEST_F(MediaSessionDescriptionFactoryTest,
1504        TestCreateDataAnswerToOfferWithDefinedMessageSize) {
1505   // Need to enable DTLS offer/answer generation (disabled by default in this
1506   // test).
1507   f1_.set_secure(SEC_ENABLED);
1508   f2_.set_secure(SEC_ENABLED);
1509   tdf1_.set_secure(SEC_ENABLED);
1510   tdf2_.set_secure(SEC_ENABLED);
1511 
1512   MediaSessionOptions opts;
1513   AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
1514   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1515   ASSERT_TRUE(offer.get() != nullptr);
1516   ContentInfo* dc_offer = offer->GetContentByName("data");
1517   ASSERT_TRUE(dc_offer != nullptr);
1518   SctpDataContentDescription* dcd_offer =
1519       dc_offer->media_description()->as_sctp();
1520   ASSERT_TRUE(dcd_offer);
1521   dcd_offer->set_max_message_size(1234);
1522   std::unique_ptr<SessionDescription> answer =
1523       f2_.CreateAnswer(offer.get(), opts, nullptr);
1524   const ContentInfo* dc_answer = answer->GetContentByName("data");
1525   ASSERT_TRUE(dc_answer != nullptr);
1526   const SctpDataContentDescription* dcd_answer =
1527       dc_answer->media_description()->as_sctp();
1528   EXPECT_FALSE(dc_answer->rejected);
1529   EXPECT_EQ(1234, dcd_answer->max_message_size());
1530 }
1531 
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateDataAnswerToOfferWithZeroMessageSize)1532 TEST_F(MediaSessionDescriptionFactoryTest,
1533        TestCreateDataAnswerToOfferWithZeroMessageSize) {
1534   // Need to enable DTLS offer/answer generation (disabled by default in this
1535   // test).
1536   f1_.set_secure(SEC_ENABLED);
1537   f2_.set_secure(SEC_ENABLED);
1538   tdf1_.set_secure(SEC_ENABLED);
1539   tdf2_.set_secure(SEC_ENABLED);
1540 
1541   MediaSessionOptions opts;
1542   AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
1543   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1544   ASSERT_TRUE(offer.get() != nullptr);
1545   ContentInfo* dc_offer = offer->GetContentByName("data");
1546   ASSERT_TRUE(dc_offer != nullptr);
1547   SctpDataContentDescription* dcd_offer =
1548       dc_offer->media_description()->as_sctp();
1549   ASSERT_TRUE(dcd_offer);
1550   dcd_offer->set_max_message_size(0);
1551   std::unique_ptr<SessionDescription> answer =
1552       f2_.CreateAnswer(offer.get(), opts, nullptr);
1553   const ContentInfo* dc_answer = answer->GetContentByName("data");
1554   ASSERT_TRUE(dc_answer != nullptr);
1555   const SctpDataContentDescription* dcd_answer =
1556       dc_answer->media_description()->as_sctp();
1557   EXPECT_FALSE(dc_answer->rejected);
1558   EXPECT_EQ(cricket::kSctpSendBufferSize, dcd_answer->max_message_size());
1559 }
1560 
1561 // Verifies that the order of the media contents in the offer is preserved in
1562 // the answer.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateAnswerContentOrder)1563 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
1564   MediaSessionOptions opts;
1565 
1566   // Creates a data only offer.
1567   AddDataSection(RtpTransceiverDirection::kSendRecv, &opts);
1568   std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
1569   ASSERT_TRUE(offer1.get() != NULL);
1570 
1571   // Appends audio to the offer.
1572   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
1573                              RtpTransceiverDirection::kRecvOnly, kActive,
1574                              &opts);
1575   std::unique_ptr<SessionDescription> offer2(
1576       f1_.CreateOffer(opts, offer1.get()));
1577   ASSERT_TRUE(offer2.get() != NULL);
1578 
1579   // Appends video to the offer.
1580   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
1581                              RtpTransceiverDirection::kRecvOnly, kActive,
1582                              &opts);
1583   std::unique_ptr<SessionDescription> offer3(
1584       f1_.CreateOffer(opts, offer2.get()));
1585   ASSERT_TRUE(offer3.get() != NULL);
1586 
1587   std::unique_ptr<SessionDescription> answer =
1588       f2_.CreateAnswer(offer3.get(), opts, NULL);
1589   ASSERT_TRUE(answer.get() != NULL);
1590   EXPECT_EQ(3u, answer->contents().size());
1591   EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
1592   EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
1593   EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
1594 }
1595 
1596 // TODO(deadbeef): Extend these tests to ensure the correct direction with other
1597 // answerer settings.
1598 
1599 // This test that the media direction is set to send/receive in an answer if
1600 // the offer is send receive.
TEST_F(MediaSessionDescriptionFactoryTest,CreateAnswerToSendReceiveOffer)1601 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
1602   TestMediaDirectionInAnswer(RtpTransceiverDirection::kSendRecv,
1603                              RtpTransceiverDirection::kSendRecv);
1604 }
1605 
1606 // This test that the media direction is set to receive only in an answer if
1607 // the offer is send only.
TEST_F(MediaSessionDescriptionFactoryTest,CreateAnswerToSendOnlyOffer)1608 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
1609   TestMediaDirectionInAnswer(RtpTransceiverDirection::kSendOnly,
1610                              RtpTransceiverDirection::kRecvOnly);
1611 }
1612 
1613 // This test that the media direction is set to send only in an answer if
1614 // the offer is recv only.
TEST_F(MediaSessionDescriptionFactoryTest,CreateAnswerToRecvOnlyOffer)1615 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
1616   TestMediaDirectionInAnswer(RtpTransceiverDirection::kRecvOnly,
1617                              RtpTransceiverDirection::kSendOnly);
1618 }
1619 
1620 // This test that the media direction is set to inactive in an answer if
1621 // the offer is inactive.
TEST_F(MediaSessionDescriptionFactoryTest,CreateAnswerToInactiveOffer)1622 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
1623   TestMediaDirectionInAnswer(RtpTransceiverDirection::kInactive,
1624                              RtpTransceiverDirection::kInactive);
1625 }
1626 
1627 // Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
TEST_F(MediaSessionDescriptionFactoryTest,AudioOfferAnswerWithCryptoDisabled)1628 TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
1629   MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
1630   f1_.set_secure(SEC_DISABLED);
1631   f2_.set_secure(SEC_DISABLED);
1632   tdf1_.set_secure(SEC_DISABLED);
1633   tdf2_.set_secure(SEC_DISABLED);
1634 
1635   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
1636   const AudioContentDescription* offer_acd =
1637       GetFirstAudioContentDescription(offer.get());
1638   ASSERT_TRUE(offer_acd != NULL);
1639   EXPECT_EQ(cricket::kMediaProtocolAvpf, offer_acd->protocol());
1640 
1641   std::unique_ptr<SessionDescription> answer =
1642       f2_.CreateAnswer(offer.get(), opts, NULL);
1643 
1644   const ContentInfo* ac_answer = answer->GetContentByName("audio");
1645   ASSERT_TRUE(ac_answer != NULL);
1646   EXPECT_FALSE(ac_answer->rejected);
1647 
1648   const AudioContentDescription* answer_acd =
1649       GetFirstAudioContentDescription(answer.get());
1650   ASSERT_TRUE(answer_acd != NULL);
1651   EXPECT_EQ(cricket::kMediaProtocolAvpf, answer_acd->protocol());
1652 }
1653 
1654 // Create a video offer and answer and ensure the RTP header extensions
1655 // matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestOfferAnswerWithRtpExtensions)1656 TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
1657   MediaSessionOptions opts;
1658   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1659   SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1),
1660                                    MAKE_VECTOR(kVideoRtpExtension1), &opts);
1661 
1662   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
1663   ASSERT_TRUE(offer.get() != NULL);
1664   SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2),
1665                                    MAKE_VECTOR(kVideoRtpExtension2), &opts);
1666   std::unique_ptr<SessionDescription> answer =
1667       f2_.CreateAnswer(offer.get(), opts, NULL);
1668 
1669   EXPECT_EQ(
1670       MAKE_VECTOR(kAudioRtpExtension1),
1671       GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
1672   EXPECT_EQ(
1673       MAKE_VECTOR(kVideoRtpExtension1),
1674       GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
1675   EXPECT_EQ(
1676       MAKE_VECTOR(kAudioRtpExtensionAnswer),
1677       GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
1678   EXPECT_EQ(
1679       MAKE_VECTOR(kVideoRtpExtensionAnswer),
1680       GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
1681 }
1682 
1683 // Create a audio/video offer and answer and ensure that the
1684 // TransportSequenceNumber RTP header extensions are handled correctly. 02 is
1685 // supported and should take precedence even though not listed among locally
1686 // supported extensions.
TEST_F(MediaSessionDescriptionFactoryTest,TestOfferAnswerWithTransportSequenceNumberInOffer)1687 TEST_F(MediaSessionDescriptionFactoryTest,
1688        TestOfferAnswerWithTransportSequenceNumberInOffer) {
1689   TestTransportSequenceNumberNegotiation(
1690       MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01),   // Local.
1691       MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01),   // Offer.
1692       MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01));  // Expected answer.
1693 }
TEST_F(MediaSessionDescriptionFactoryTest,TestOfferAnswerWithTransportSequenceNumber01And02InOffer)1694 TEST_F(MediaSessionDescriptionFactoryTest,
1695        TestOfferAnswerWithTransportSequenceNumber01And02InOffer) {
1696   TestTransportSequenceNumberNegotiation(
1697       MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01),       // Local.
1698       MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01And02),  // Offer.
1699       MAKE_VECTOR(kRtpExtensionTransportSequenceNumber02));  // Expected answer.
1700 }
TEST_F(MediaSessionDescriptionFactoryTest,TestOfferAnswerWithTransportSequenceNumber02InOffer)1701 TEST_F(MediaSessionDescriptionFactoryTest,
1702        TestOfferAnswerWithTransportSequenceNumber02InOffer) {
1703   TestTransportSequenceNumberNegotiation(
1704       MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01),   // Local.
1705       MAKE_VECTOR(kRtpExtensionTransportSequenceNumber02),   // Offer.
1706       MAKE_VECTOR(kRtpExtensionTransportSequenceNumber02));  // Expected answer.
1707 }
1708 
TEST_F(MediaSessionDescriptionFactoryTest,TestNegotiateFrameDescriptorWhenUnexposedLocally)1709 TEST_F(MediaSessionDescriptionFactoryTest,
1710        TestNegotiateFrameDescriptorWhenUnexposedLocally) {
1711   MediaSessionOptions opts;
1712   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1713 
1714   SetAudioVideoRtpHeaderExtensions(
1715       MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00),
1716       MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00), &opts);
1717   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1718   SetAudioVideoRtpHeaderExtensions(
1719       MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01),
1720       MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01), &opts);
1721   std::unique_ptr<SessionDescription> answer =
1722       f2_.CreateAnswer(offer.get(), opts, nullptr);
1723   EXPECT_THAT(
1724       GetFirstAudioContentDescription(answer.get())->rtp_header_extensions(),
1725       ElementsAreArray(kRtpExtensionGenericFrameDescriptorUri00));
1726   EXPECT_THAT(
1727       GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(),
1728       ElementsAreArray(kRtpExtensionGenericFrameDescriptorUri00));
1729 }
1730 
TEST_F(MediaSessionDescriptionFactoryTest,TestNegotiateFrameDescriptorWhenExposedLocally)1731 TEST_F(MediaSessionDescriptionFactoryTest,
1732        TestNegotiateFrameDescriptorWhenExposedLocally) {
1733   MediaSessionOptions opts;
1734   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1735 
1736   SetAudioVideoRtpHeaderExtensions(
1737       MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00),
1738       MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00), &opts);
1739   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1740   std::unique_ptr<SessionDescription> answer =
1741       f2_.CreateAnswer(offer.get(), opts, nullptr);
1742   EXPECT_THAT(
1743       GetFirstAudioContentDescription(answer.get())->rtp_header_extensions(),
1744       ElementsAreArray(kRtpExtensionGenericFrameDescriptorUri00));
1745   EXPECT_THAT(
1746       GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(),
1747       ElementsAreArray(kRtpExtensionGenericFrameDescriptorUri00));
1748 }
1749 
TEST_F(MediaSessionDescriptionFactoryTest,NegotiateDependencyDescriptorWhenUnexposedLocally)1750 TEST_F(MediaSessionDescriptionFactoryTest,
1751        NegotiateDependencyDescriptorWhenUnexposedLocally) {
1752   MediaSessionOptions opts;
1753   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1754 
1755   RtpExtension offer_dd(RtpExtension::kDependencyDescriptorUri, 7);
1756   SetAudioVideoRtpHeaderExtensions({}, {offer_dd}, &opts);
1757   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1758   RtpExtension local_tsn(RtpExtension::kTransportSequenceNumberUri, 5);
1759   SetAudioVideoRtpHeaderExtensions({}, {local_tsn}, &opts);
1760   std::unique_ptr<SessionDescription> answer =
1761       f2_.CreateAnswer(offer.get(), opts, nullptr);
1762   EXPECT_THAT(
1763       GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(),
1764       ElementsAre(offer_dd));
1765 }
1766 
TEST_F(MediaSessionDescriptionFactoryTest,NegotiateDependencyDescriptorWhenExposedLocally)1767 TEST_F(MediaSessionDescriptionFactoryTest,
1768        NegotiateDependencyDescriptorWhenExposedLocally) {
1769   MediaSessionOptions opts;
1770   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1771 
1772   RtpExtension offer_dd(RtpExtension::kDependencyDescriptorUri, 7);
1773   RtpExtension local_dd(RtpExtension::kDependencyDescriptorUri, 5);
1774   SetAudioVideoRtpHeaderExtensions({}, {offer_dd}, &opts);
1775   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1776   SetAudioVideoRtpHeaderExtensions({}, {local_dd}, &opts);
1777   std::unique_ptr<SessionDescription> answer =
1778       f2_.CreateAnswer(offer.get(), opts, nullptr);
1779   EXPECT_THAT(
1780       GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(),
1781       ElementsAre(offer_dd));
1782 }
1783 
TEST_F(MediaSessionDescriptionFactoryTest,NegotiateAbsoluteCaptureTimeWhenUnexposedLocally)1784 TEST_F(MediaSessionDescriptionFactoryTest,
1785        NegotiateAbsoluteCaptureTimeWhenUnexposedLocally) {
1786   MediaSessionOptions opts;
1787   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1788 
1789   const cricket::RtpHeaderExtensions offered_extensions = {
1790       RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 7)};
1791   const cricket::RtpHeaderExtensions local_extensions = {
1792       RtpExtension(RtpExtension::kTransportSequenceNumberUri, 5)};
1793   SetAudioVideoRtpHeaderExtensions(offered_extensions, offered_extensions,
1794                                    &opts);
1795   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1796   SetAudioVideoRtpHeaderExtensions(local_extensions, local_extensions, &opts);
1797   std::unique_ptr<SessionDescription> answer =
1798       f2_.CreateAnswer(offer.get(), opts, nullptr);
1799   EXPECT_THAT(
1800       GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(),
1801       ElementsAreArray(offered_extensions));
1802   EXPECT_THAT(
1803       GetFirstAudioContentDescription(answer.get())->rtp_header_extensions(),
1804       ElementsAreArray(offered_extensions));
1805 }
1806 
TEST_F(MediaSessionDescriptionFactoryTest,NegotiateAbsoluteCaptureTimeWhenExposedLocally)1807 TEST_F(MediaSessionDescriptionFactoryTest,
1808        NegotiateAbsoluteCaptureTimeWhenExposedLocally) {
1809   MediaSessionOptions opts;
1810   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1811 
1812   const cricket::RtpHeaderExtensions offered_extensions = {
1813       RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 7)};
1814   const cricket::RtpHeaderExtensions local_extensions = {
1815       RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 5)};
1816   SetAudioVideoRtpHeaderExtensions(offered_extensions, offered_extensions,
1817                                    &opts);
1818   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1819   SetAudioVideoRtpHeaderExtensions(local_extensions, local_extensions, &opts);
1820   std::unique_ptr<SessionDescription> answer =
1821       f2_.CreateAnswer(offer.get(), opts, nullptr);
1822   EXPECT_THAT(
1823       GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(),
1824       ElementsAreArray(offered_extensions));
1825   EXPECT_THAT(
1826       GetFirstAudioContentDescription(answer.get())->rtp_header_extensions(),
1827       ElementsAreArray(offered_extensions));
1828 }
1829 
TEST_F(MediaSessionDescriptionFactoryTest,DoNotNegotiateAbsoluteCaptureTimeWhenNotOffered)1830 TEST_F(MediaSessionDescriptionFactoryTest,
1831        DoNotNegotiateAbsoluteCaptureTimeWhenNotOffered) {
1832   MediaSessionOptions opts;
1833   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
1834 
1835   const cricket::RtpHeaderExtensions offered_extensions = {
1836       RtpExtension(RtpExtension::kTransportSequenceNumberUri, 7)};
1837   const cricket::RtpHeaderExtensions local_extensions = {
1838       RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 5)};
1839   SetAudioVideoRtpHeaderExtensions(offered_extensions, offered_extensions,
1840                                    &opts);
1841   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
1842   SetAudioVideoRtpHeaderExtensions(local_extensions, local_extensions, &opts);
1843   std::unique_ptr<SessionDescription> answer =
1844       f2_.CreateAnswer(offer.get(), opts, nullptr);
1845   EXPECT_THAT(
1846       GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(),
1847       IsEmpty());
1848   EXPECT_THAT(
1849       GetFirstAudioContentDescription(answer.get())->rtp_header_extensions(),
1850       IsEmpty());
1851 }
1852 
TEST_F(MediaSessionDescriptionFactoryTest,OffersUnstoppedExtensionsWithAudioVideoExtensionStopped)1853 TEST_F(MediaSessionDescriptionFactoryTest,
1854        OffersUnstoppedExtensionsWithAudioVideoExtensionStopped) {
1855   MediaSessionOptions opts;
1856   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
1857                              RtpTransceiverDirection::kSendRecv, kActive,
1858                              &opts);
1859   opts.media_description_options.back().header_extensions = {
1860       webrtc::RtpHeaderExtensionCapability("uri1", 1,
1861                                            RtpTransceiverDirection::kStopped),
1862       webrtc::RtpHeaderExtensionCapability("uri2", 3,
1863                                            RtpTransceiverDirection::kSendOnly)};
1864   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video1",
1865                              RtpTransceiverDirection::kSendRecv, kActive,
1866                              &opts);
1867   opts.media_description_options.back().header_extensions = {
1868       webrtc::RtpHeaderExtensionCapability("uri1", 1,
1869                                            RtpTransceiverDirection::kStopped),
1870       webrtc::RtpHeaderExtensionCapability("uri3", 7,
1871                                            RtpTransceiverDirection::kSendOnly)};
1872   auto offer = f1_.CreateOffer(opts, nullptr);
1873   EXPECT_THAT(
1874       offer->contents(),
1875       ElementsAre(
1876           Property(&ContentInfo::media_description,
1877                    Pointee(Property(
1878                        &MediaContentDescription::rtp_header_extensions,
1879                        ElementsAre(Field(&RtpExtension::uri, "uri2"))))),
1880           Property(&ContentInfo::media_description,
1881                    Pointee(Property(
1882                        &MediaContentDescription::rtp_header_extensions,
1883                        ElementsAre(Field(&RtpExtension::uri, "uri3")))))));
1884 }
1885 
TEST_F(MediaSessionDescriptionFactoryTest,OffersUnstoppedExtensionsWithAudioExtensionStopped)1886 TEST_F(MediaSessionDescriptionFactoryTest,
1887        OffersUnstoppedExtensionsWithAudioExtensionStopped) {
1888   MediaSessionOptions opts;
1889   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
1890                              RtpTransceiverDirection::kSendRecv, kActive,
1891                              &opts);
1892   opts.media_description_options.back().header_extensions = {
1893       webrtc::RtpHeaderExtensionCapability("uri1", 1,
1894                                            RtpTransceiverDirection::kSendOnly),
1895       webrtc::RtpHeaderExtensionCapability("uri2", 3,
1896                                            RtpTransceiverDirection::kStopped)};
1897   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video1",
1898                              RtpTransceiverDirection::kSendRecv, kActive,
1899                              &opts);
1900   opts.media_description_options.back().header_extensions = {
1901       webrtc::RtpHeaderExtensionCapability("uri42", 42,
1902                                            RtpTransceiverDirection::kSendRecv),
1903       webrtc::RtpHeaderExtensionCapability("uri3", 7,
1904                                            RtpTransceiverDirection::kSendOnly)};
1905   auto offer = f1_.CreateOffer(opts, nullptr);
1906   EXPECT_THAT(
1907       offer->contents(),
1908       ElementsAre(
1909           Property(&ContentInfo::media_description,
1910                    Pointee(Property(
1911                        &MediaContentDescription::rtp_header_extensions,
1912                        ElementsAre(Field(&RtpExtension::uri, "uri1"))))),
1913           Property(
1914               &ContentInfo::media_description,
1915               Pointee(Property(
1916                   &MediaContentDescription::rtp_header_extensions,
1917                   UnorderedElementsAre(Field(&RtpExtension::uri, "uri3"),
1918                                        Field(&RtpExtension::uri, "uri42")))))));
1919 }
1920 
TEST_F(MediaSessionDescriptionFactoryTest,OffersUnstoppedExtensionsWithVideoExtensionStopped)1921 TEST_F(MediaSessionDescriptionFactoryTest,
1922        OffersUnstoppedExtensionsWithVideoExtensionStopped) {
1923   MediaSessionOptions opts;
1924   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
1925                              RtpTransceiverDirection::kSendRecv, kActive,
1926                              &opts);
1927   opts.media_description_options.back().header_extensions = {
1928       webrtc::RtpHeaderExtensionCapability("uri1", 5,
1929                                            RtpTransceiverDirection::kSendOnly),
1930       webrtc::RtpHeaderExtensionCapability("uri2", 7,
1931                                            RtpTransceiverDirection::kSendRecv)};
1932   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video1",
1933                              RtpTransceiverDirection::kSendRecv, kActive,
1934                              &opts);
1935   opts.media_description_options.back().header_extensions = {
1936       webrtc::RtpHeaderExtensionCapability("uri42", 42,
1937                                            RtpTransceiverDirection::kSendRecv),
1938       webrtc::RtpHeaderExtensionCapability("uri3", 7,
1939                                            RtpTransceiverDirection::kStopped)};
1940   auto offer = f1_.CreateOffer(opts, nullptr);
1941   EXPECT_THAT(
1942       offer->contents(),
1943       ElementsAre(
1944           Property(
1945               &ContentInfo::media_description,
1946               Pointee(Property(
1947                   &MediaContentDescription::rtp_header_extensions,
1948                   UnorderedElementsAre(Field(&RtpExtension::uri, "uri1"),
1949                                        Field(&RtpExtension::uri, "uri2"))))),
1950           Property(&ContentInfo::media_description,
1951                    Pointee(Property(
1952                        &MediaContentDescription::rtp_header_extensions,
1953                        ElementsAre(Field(&RtpExtension::uri, "uri42")))))));
1954 }
1955 
TEST_F(MediaSessionDescriptionFactoryTest,AnswersUnstoppedExtensions)1956 TEST_F(MediaSessionDescriptionFactoryTest, AnswersUnstoppedExtensions) {
1957   MediaSessionOptions opts;
1958   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
1959                              RtpTransceiverDirection::kSendRecv, kActive,
1960                              &opts);
1961   opts.media_description_options.back().header_extensions = {
1962       webrtc::RtpHeaderExtensionCapability("uri1", 4,
1963                                            RtpTransceiverDirection::kStopped),
1964       webrtc::RtpHeaderExtensionCapability("uri2", 3,
1965                                            RtpTransceiverDirection::kSendOnly),
1966       webrtc::RtpHeaderExtensionCapability("uri3", 2,
1967                                            RtpTransceiverDirection::kRecvOnly),
1968       webrtc::RtpHeaderExtensionCapability("uri4", 1,
1969                                            RtpTransceiverDirection::kSendRecv)};
1970   auto offer = f1_.CreateOffer(opts, nullptr);
1971   opts.media_description_options.back().header_extensions = {
1972       webrtc::RtpHeaderExtensionCapability("uri1", 4,
1973                                            RtpTransceiverDirection::kSendOnly),
1974       webrtc::RtpHeaderExtensionCapability("uri2", 3,
1975                                            RtpTransceiverDirection::kRecvOnly),
1976       webrtc::RtpHeaderExtensionCapability("uri3", 2,
1977                                            RtpTransceiverDirection::kStopped),
1978       webrtc::RtpHeaderExtensionCapability("uri4", 1,
1979                                            RtpTransceiverDirection::kSendRecv)};
1980   auto answer = f2_.CreateAnswer(offer.get(), opts, nullptr);
1981   EXPECT_THAT(
1982       answer->contents(),
1983       ElementsAre(Property(
1984           &ContentInfo::media_description,
1985           Pointee(Property(&MediaContentDescription::rtp_header_extensions,
1986                            ElementsAre(Field(&RtpExtension::uri, "uri2"),
1987                                        Field(&RtpExtension::uri, "uri4")))))));
1988 }
1989 
TEST_F(MediaSessionDescriptionFactoryTest,AppendsUnstoppedExtensionsToCurrentDescription)1990 TEST_F(MediaSessionDescriptionFactoryTest,
1991        AppendsUnstoppedExtensionsToCurrentDescription) {
1992   MediaSessionOptions opts;
1993   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
1994                              RtpTransceiverDirection::kSendRecv, kActive,
1995                              &opts);
1996   opts.media_description_options.back().header_extensions = {
1997       webrtc::RtpHeaderExtensionCapability("uri1", 1,
1998                                            RtpTransceiverDirection::kSendRecv)};
1999   auto offer = f1_.CreateOffer(opts, nullptr);
2000   opts.media_description_options.back().header_extensions = {
2001       webrtc::RtpHeaderExtensionCapability("uri1", 2,
2002                                            RtpTransceiverDirection::kSendRecv),
2003       webrtc::RtpHeaderExtensionCapability("uri2", 3,
2004                                            RtpTransceiverDirection::kRecvOnly),
2005       webrtc::RtpHeaderExtensionCapability("uri3", 5,
2006                                            RtpTransceiverDirection::kStopped),
2007       webrtc::RtpHeaderExtensionCapability("uri4", 6,
2008                                            RtpTransceiverDirection::kSendRecv)};
2009   auto offer2 = f1_.CreateOffer(opts, offer.get());
2010   EXPECT_THAT(
2011       offer2->contents(),
2012       ElementsAre(Property(
2013           &ContentInfo::media_description,
2014           Pointee(Property(&MediaContentDescription::rtp_header_extensions,
2015                            ElementsAre(Field(&RtpExtension::uri, "uri1"),
2016                                        Field(&RtpExtension::uri, "uri2"),
2017                                        Field(&RtpExtension::uri, "uri4")))))));
2018 }
2019 
TEST_F(MediaSessionDescriptionFactoryTest,AppendsStoppedExtensionIfKnownAndPresentInTheOffer)2020 TEST_F(MediaSessionDescriptionFactoryTest,
2021        AppendsStoppedExtensionIfKnownAndPresentInTheOffer) {
2022   MediaSessionOptions opts;
2023   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2024                              RtpTransceiverDirection::kSendRecv, kActive,
2025                              &opts);
2026   opts.media_description_options.back().header_extensions = {
2027       webrtc::RtpHeaderExtensionCapability("uri1", 1,
2028                                            RtpTransceiverDirection::kSendRecv),
2029       webrtc::RtpHeaderExtensionCapability("uri2", 1,
2030                                            RtpTransceiverDirection::kSendRecv)};
2031   auto offer = f1_.CreateOffer(opts, nullptr);
2032 
2033   // Now add "uri2" as stopped to the options verify that the offer contains
2034   // uri2 since it's already present since before.
2035   opts.media_description_options.back().header_extensions = {
2036       webrtc::RtpHeaderExtensionCapability("uri1", 1,
2037                                            RtpTransceiverDirection::kSendRecv),
2038       webrtc::RtpHeaderExtensionCapability("uri2", 2,
2039                                            RtpTransceiverDirection::kStopped)};
2040   auto offer2 = f1_.CreateOffer(opts, offer.get());
2041   EXPECT_THAT(
2042       offer2->contents(),
2043       ElementsAre(Property(
2044           &ContentInfo::media_description,
2045           Pointee(Property(&MediaContentDescription::rtp_header_extensions,
2046                            ElementsAre(Field(&RtpExtension::uri, "uri1"),
2047                                        Field(&RtpExtension::uri, "uri2")))))));
2048 }
2049 
TEST_F(MediaSessionDescriptionFactoryTest,TestOfferAnswerWithEncryptedRtpExtensionsBoth)2050 TEST_F(MediaSessionDescriptionFactoryTest,
2051        TestOfferAnswerWithEncryptedRtpExtensionsBoth) {
2052   MediaSessionOptions opts;
2053   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
2054 
2055   f1_.set_enable_encrypted_rtp_header_extensions(true);
2056   f2_.set_enable_encrypted_rtp_header_extensions(true);
2057 
2058   SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1),
2059                                    MAKE_VECTOR(kVideoRtpExtension1), &opts);
2060   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
2061   ASSERT_TRUE(offer.get() != NULL);
2062   SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2),
2063                                    MAKE_VECTOR(kVideoRtpExtension2), &opts);
2064   std::unique_ptr<SessionDescription> answer =
2065       f2_.CreateAnswer(offer.get(), opts, NULL);
2066 
2067   EXPECT_EQ(
2068       MAKE_VECTOR(kAudioRtpExtensionEncrypted1),
2069       GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
2070   EXPECT_EQ(
2071       MAKE_VECTOR(kVideoRtpExtensionEncrypted1),
2072       GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
2073   EXPECT_EQ(
2074       MAKE_VECTOR(kAudioRtpExtensionEncryptedAnswer),
2075       GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
2076   EXPECT_EQ(
2077       MAKE_VECTOR(kVideoRtpExtensionEncryptedAnswer),
2078       GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
2079 }
2080 
TEST_F(MediaSessionDescriptionFactoryTest,TestOfferAnswerWithEncryptedRtpExtensionsOffer)2081 TEST_F(MediaSessionDescriptionFactoryTest,
2082        TestOfferAnswerWithEncryptedRtpExtensionsOffer) {
2083   MediaSessionOptions opts;
2084   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
2085 
2086   f1_.set_enable_encrypted_rtp_header_extensions(true);
2087 
2088   SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1),
2089                                    MAKE_VECTOR(kVideoRtpExtension1), &opts);
2090   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
2091   ASSERT_TRUE(offer.get() != NULL);
2092   SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2),
2093                                    MAKE_VECTOR(kVideoRtpExtension2), &opts);
2094   std::unique_ptr<SessionDescription> answer =
2095       f2_.CreateAnswer(offer.get(), opts, NULL);
2096 
2097   EXPECT_EQ(
2098       MAKE_VECTOR(kAudioRtpExtensionEncrypted1),
2099       GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
2100   EXPECT_EQ(
2101       MAKE_VECTOR(kVideoRtpExtensionEncrypted1),
2102       GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
2103   EXPECT_EQ(
2104       MAKE_VECTOR(kAudioRtpExtensionAnswer),
2105       GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
2106   EXPECT_EQ(
2107       MAKE_VECTOR(kVideoRtpExtensionAnswer),
2108       GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
2109 }
2110 
TEST_F(MediaSessionDescriptionFactoryTest,TestOfferAnswerWithEncryptedRtpExtensionsAnswer)2111 TEST_F(MediaSessionDescriptionFactoryTest,
2112        TestOfferAnswerWithEncryptedRtpExtensionsAnswer) {
2113   MediaSessionOptions opts;
2114   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
2115 
2116   f2_.set_enable_encrypted_rtp_header_extensions(true);
2117 
2118   SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1),
2119                                    MAKE_VECTOR(kVideoRtpExtension1), &opts);
2120   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
2121   ASSERT_TRUE(offer.get() != NULL);
2122   SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2),
2123                                    MAKE_VECTOR(kVideoRtpExtension2), &opts);
2124   std::unique_ptr<SessionDescription> answer =
2125       f2_.CreateAnswer(offer.get(), opts, NULL);
2126 
2127   EXPECT_EQ(
2128       MAKE_VECTOR(kAudioRtpExtension1),
2129       GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
2130   EXPECT_EQ(
2131       MAKE_VECTOR(kVideoRtpExtension1),
2132       GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
2133   EXPECT_EQ(
2134       MAKE_VECTOR(kAudioRtpExtensionAnswer),
2135       GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
2136   EXPECT_EQ(
2137       MAKE_VECTOR(kVideoRtpExtensionAnswer),
2138       GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
2139 }
2140 
2141 // Create an audio, video, data answer without legacy StreamParams.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateAnswerWithoutLegacyStreams)2142 TEST_F(MediaSessionDescriptionFactoryTest,
2143        TestCreateAnswerWithoutLegacyStreams) {
2144   MediaSessionOptions opts;
2145   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
2146   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
2147   ASSERT_TRUE(offer.get() != NULL);
2148   std::unique_ptr<SessionDescription> answer =
2149       f2_.CreateAnswer(offer.get(), opts, NULL);
2150   const ContentInfo* ac = answer->GetContentByName("audio");
2151   const ContentInfo* vc = answer->GetContentByName("video");
2152   ASSERT_TRUE(ac != NULL);
2153   ASSERT_TRUE(vc != NULL);
2154   const AudioContentDescription* acd = ac->media_description()->as_audio();
2155   const VideoContentDescription* vcd = vc->media_description()->as_video();
2156 
2157   EXPECT_FALSE(acd->has_ssrcs());  // No StreamParams.
2158   EXPECT_FALSE(vcd->has_ssrcs());  // No StreamParams.
2159 }
2160 
2161 // Create a typical video answer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateVideoAnswerRtcpMux)2162 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
2163   MediaSessionOptions offer_opts;
2164   AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &offer_opts);
2165 
2166   MediaSessionOptions answer_opts;
2167   AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &answer_opts);
2168 
2169   std::unique_ptr<SessionDescription> offer;
2170   std::unique_ptr<SessionDescription> answer;
2171 
2172   offer_opts.rtcp_mux_enabled = true;
2173   answer_opts.rtcp_mux_enabled = true;
2174   offer = f1_.CreateOffer(offer_opts, NULL);
2175   answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
2176   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
2177   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
2178   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
2179   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
2180   EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
2181   EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
2182   EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
2183   EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
2184 
2185   offer_opts.rtcp_mux_enabled = true;
2186   answer_opts.rtcp_mux_enabled = false;
2187   offer = f1_.CreateOffer(offer_opts, NULL);
2188   answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
2189   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
2190   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
2191   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
2192   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
2193   EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
2194   EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
2195   EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
2196   EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
2197 
2198   offer_opts.rtcp_mux_enabled = false;
2199   answer_opts.rtcp_mux_enabled = true;
2200   offer = f1_.CreateOffer(offer_opts, NULL);
2201   answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
2202   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
2203   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
2204   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
2205   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
2206   EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
2207   EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
2208   EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
2209   EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
2210 
2211   offer_opts.rtcp_mux_enabled = false;
2212   answer_opts.rtcp_mux_enabled = false;
2213   offer = f1_.CreateOffer(offer_opts, NULL);
2214   answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
2215   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
2216   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
2217   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
2218   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
2219   EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
2220   EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
2221   EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
2222   EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
2223 }
2224 
2225 // Create an audio-only answer to a video offer.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateAudioAnswerToVideo)2226 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
2227   MediaSessionOptions opts;
2228   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
2229                              RtpTransceiverDirection::kRecvOnly, kActive,
2230                              &opts);
2231   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2232                              RtpTransceiverDirection::kRecvOnly, kActive,
2233                              &opts);
2234   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
2235   ASSERT_TRUE(offer.get() != NULL);
2236 
2237   opts.media_description_options[1].stopped = true;
2238   std::unique_ptr<SessionDescription> answer =
2239       f2_.CreateAnswer(offer.get(), opts, NULL);
2240   const ContentInfo* ac = answer->GetContentByName("audio");
2241   const ContentInfo* vc = answer->GetContentByName("video");
2242   ASSERT_TRUE(ac != NULL);
2243   ASSERT_TRUE(vc != NULL);
2244   ASSERT_TRUE(vc->media_description() != NULL);
2245   EXPECT_TRUE(vc->rejected);
2246 }
2247 
2248 // Create an answer that rejects the contents which are rejected in the offer.
TEST_F(MediaSessionDescriptionFactoryTest,CreateAnswerToOfferWithRejectedMedia)2249 TEST_F(MediaSessionDescriptionFactoryTest,
2250        CreateAnswerToOfferWithRejectedMedia) {
2251   MediaSessionOptions opts;
2252   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
2253   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
2254   ASSERT_TRUE(offer.get() != NULL);
2255   ContentInfo* ac = offer->GetContentByName("audio");
2256   ContentInfo* vc = offer->GetContentByName("video");
2257   ASSERT_TRUE(ac != NULL);
2258   ASSERT_TRUE(vc != NULL);
2259   ac->rejected = true;
2260   vc->rejected = true;
2261   std::unique_ptr<SessionDescription> answer =
2262       f2_.CreateAnswer(offer.get(), opts, NULL);
2263   ac = answer->GetContentByName("audio");
2264   vc = answer->GetContentByName("video");
2265   ASSERT_TRUE(ac != NULL);
2266   ASSERT_TRUE(vc != NULL);
2267   EXPECT_TRUE(ac->rejected);
2268   EXPECT_TRUE(vc->rejected);
2269 }
2270 
TEST_F(MediaSessionDescriptionFactoryTest,OfferAndAnswerDoesNotHaveMixedByteSessionAttribute)2271 TEST_F(MediaSessionDescriptionFactoryTest,
2272        OfferAndAnswerDoesNotHaveMixedByteSessionAttribute) {
2273   MediaSessionOptions opts;
2274   std::unique_ptr<SessionDescription> offer =
2275       f1_.CreateOffer(opts, /*current_description=*/nullptr);
2276   offer->set_extmap_allow_mixed(false);
2277 
2278   std::unique_ptr<SessionDescription> answer(
2279       f2_.CreateAnswer(offer.get(), opts, /*current_description=*/nullptr));
2280 
2281   EXPECT_FALSE(answer->extmap_allow_mixed());
2282 }
2283 
TEST_F(MediaSessionDescriptionFactoryTest,OfferAndAnswerHaveMixedByteSessionAttribute)2284 TEST_F(MediaSessionDescriptionFactoryTest,
2285        OfferAndAnswerHaveMixedByteSessionAttribute) {
2286   MediaSessionOptions opts;
2287   std::unique_ptr<SessionDescription> offer =
2288       f1_.CreateOffer(opts, /*current_description=*/nullptr);
2289   offer->set_extmap_allow_mixed(true);
2290 
2291   std::unique_ptr<SessionDescription> answer_support(
2292       f2_.CreateAnswer(offer.get(), opts, /*current_description=*/nullptr));
2293 
2294   EXPECT_TRUE(answer_support->extmap_allow_mixed());
2295 }
2296 
TEST_F(MediaSessionDescriptionFactoryTest,OfferAndAnswerDoesNotHaveMixedByteMediaAttributes)2297 TEST_F(MediaSessionDescriptionFactoryTest,
2298        OfferAndAnswerDoesNotHaveMixedByteMediaAttributes) {
2299   MediaSessionOptions opts;
2300   AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
2301   std::unique_ptr<SessionDescription> offer =
2302       f1_.CreateOffer(opts, /*current_description=*/nullptr);
2303   offer->set_extmap_allow_mixed(false);
2304   MediaContentDescription* audio_offer =
2305       offer->GetContentDescriptionByName("audio");
2306   MediaContentDescription* video_offer =
2307       offer->GetContentDescriptionByName("video");
2308   ASSERT_EQ(MediaContentDescription::kNo,
2309             audio_offer->extmap_allow_mixed_enum());
2310   ASSERT_EQ(MediaContentDescription::kNo,
2311             video_offer->extmap_allow_mixed_enum());
2312 
2313   std::unique_ptr<SessionDescription> answer(
2314       f2_.CreateAnswer(offer.get(), opts, /*current_description=*/nullptr));
2315 
2316   MediaContentDescription* audio_answer =
2317       answer->GetContentDescriptionByName("audio");
2318   MediaContentDescription* video_answer =
2319       answer->GetContentDescriptionByName("video");
2320   EXPECT_EQ(MediaContentDescription::kNo,
2321             audio_answer->extmap_allow_mixed_enum());
2322   EXPECT_EQ(MediaContentDescription::kNo,
2323             video_answer->extmap_allow_mixed_enum());
2324 }
2325 
TEST_F(MediaSessionDescriptionFactoryTest,OfferAndAnswerHaveSameMixedByteMediaAttributes)2326 TEST_F(MediaSessionDescriptionFactoryTest,
2327        OfferAndAnswerHaveSameMixedByteMediaAttributes) {
2328   MediaSessionOptions opts;
2329   AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
2330   std::unique_ptr<SessionDescription> offer =
2331       f1_.CreateOffer(opts, /*current_description=*/nullptr);
2332   offer->set_extmap_allow_mixed(false);
2333   MediaContentDescription* audio_offer =
2334       offer->GetContentDescriptionByName("audio");
2335   audio_offer->set_extmap_allow_mixed_enum(MediaContentDescription::kMedia);
2336   MediaContentDescription* video_offer =
2337       offer->GetContentDescriptionByName("video");
2338   video_offer->set_extmap_allow_mixed_enum(MediaContentDescription::kMedia);
2339 
2340   std::unique_ptr<SessionDescription> answer(
2341       f2_.CreateAnswer(offer.get(), opts, /*current_description=*/nullptr));
2342 
2343   MediaContentDescription* audio_answer =
2344       answer->GetContentDescriptionByName("audio");
2345   MediaContentDescription* video_answer =
2346       answer->GetContentDescriptionByName("video");
2347   EXPECT_EQ(MediaContentDescription::kMedia,
2348             audio_answer->extmap_allow_mixed_enum());
2349   EXPECT_EQ(MediaContentDescription::kMedia,
2350             video_answer->extmap_allow_mixed_enum());
2351 }
2352 
TEST_F(MediaSessionDescriptionFactoryTest,OfferAndAnswerHaveDifferentMixedByteMediaAttributes)2353 TEST_F(MediaSessionDescriptionFactoryTest,
2354        OfferAndAnswerHaveDifferentMixedByteMediaAttributes) {
2355   MediaSessionOptions opts;
2356   AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
2357   std::unique_ptr<SessionDescription> offer =
2358       f1_.CreateOffer(opts, /*current_description=*/nullptr);
2359   offer->set_extmap_allow_mixed(false);
2360   MediaContentDescription* audio_offer =
2361       offer->GetContentDescriptionByName("audio");
2362   audio_offer->set_extmap_allow_mixed_enum(MediaContentDescription::kNo);
2363   MediaContentDescription* video_offer =
2364       offer->GetContentDescriptionByName("video");
2365   video_offer->set_extmap_allow_mixed_enum(MediaContentDescription::kMedia);
2366 
2367   std::unique_ptr<SessionDescription> answer(
2368       f2_.CreateAnswer(offer.get(), opts, /*current_description=*/nullptr));
2369 
2370   MediaContentDescription* audio_answer =
2371       answer->GetContentDescriptionByName("audio");
2372   MediaContentDescription* video_answer =
2373       answer->GetContentDescriptionByName("video");
2374   EXPECT_EQ(MediaContentDescription::kNo,
2375             audio_answer->extmap_allow_mixed_enum());
2376   EXPECT_EQ(MediaContentDescription::kMedia,
2377             video_answer->extmap_allow_mixed_enum());
2378 }
2379 
2380 // Create an audio and video offer with:
2381 // - one video track
2382 // - two audio tracks
2383 // and ensure it matches what we expect. Also updates the initial offer by
2384 // adding a new video track and replaces one of the audio tracks.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateMultiStreamVideoOffer)2385 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
2386   MediaSessionOptions opts;
2387   AddAudioVideoSections(RtpTransceiverDirection::kSendRecv, &opts);
2388   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
2389                                         {kMediaStream1}, 1, &opts);
2390   AttachSenderToMediaDescriptionOptions("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
2391                                         {kMediaStream1}, 1, &opts);
2392   AttachSenderToMediaDescriptionOptions("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
2393                                         {kMediaStream1}, 1, &opts);
2394 
2395   f1_.set_secure(SEC_ENABLED);
2396   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
2397 
2398   ASSERT_TRUE(offer.get() != NULL);
2399   const ContentInfo* ac = offer->GetContentByName("audio");
2400   const ContentInfo* vc = offer->GetContentByName("video");
2401   ASSERT_TRUE(ac != NULL);
2402   ASSERT_TRUE(vc != NULL);
2403   const AudioContentDescription* acd = ac->media_description()->as_audio();
2404   const VideoContentDescription* vcd = vc->media_description()->as_video();
2405   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
2406   EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
2407 
2408   const StreamParamsVec& audio_streams = acd->streams();
2409   ASSERT_EQ(2U, audio_streams.size());
2410   EXPECT_EQ(audio_streams[0].cname, audio_streams[1].cname);
2411   EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
2412   ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
2413   EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
2414   EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
2415   ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
2416   EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
2417 
2418   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
2419   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
2420   ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
2421 
2422   EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
2423   EXPECT_EQ(f1_.video_sendrecv_codecs(), vcd->codecs());
2424   ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
2425 
2426   const StreamParamsVec& video_streams = vcd->streams();
2427   ASSERT_EQ(1U, video_streams.size());
2428   EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
2429   EXPECT_EQ(kVideoTrack1, video_streams[0].id);
2430   EXPECT_EQ(kAutoBandwidth, vcd->bandwidth());  // default bandwidth (auto)
2431   EXPECT_TRUE(vcd->rtcp_mux());                 // rtcp-mux defaults on
2432 
2433   // Update the offer. Add a new video track that is not synched to the
2434   // other tracks and replace audio track 2 with audio track 3.
2435   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
2436                                         {kMediaStream2}, 1, &opts);
2437   DetachSenderFromMediaSection("audio", kAudioTrack2, &opts);
2438   AttachSenderToMediaDescriptionOptions("audio", MEDIA_TYPE_AUDIO, kAudioTrack3,
2439                                         {kMediaStream1}, 1, &opts);
2440   std::unique_ptr<SessionDescription> updated_offer(
2441       f1_.CreateOffer(opts, offer.get()));
2442 
2443   ASSERT_TRUE(updated_offer.get() != NULL);
2444   ac = updated_offer->GetContentByName("audio");
2445   vc = updated_offer->GetContentByName("video");
2446   ASSERT_TRUE(ac != NULL);
2447   ASSERT_TRUE(vc != NULL);
2448   const AudioContentDescription* updated_acd =
2449       ac->media_description()->as_audio();
2450   const VideoContentDescription* updated_vcd =
2451       vc->media_description()->as_video();
2452 
2453   EXPECT_EQ(acd->type(), updated_acd->type());
2454   EXPECT_EQ(acd->codecs(), updated_acd->codecs());
2455   EXPECT_EQ(vcd->type(), updated_vcd->type());
2456   EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
2457   ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
2458   EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
2459   ASSERT_CRYPTO(updated_vcd, 1U, kDefaultSrtpCryptoSuite);
2460   EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
2461 
2462   const StreamParamsVec& updated_audio_streams = updated_acd->streams();
2463   ASSERT_EQ(2U, updated_audio_streams.size());
2464   EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
2465   EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id);  // New audio track.
2466   ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
2467   EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
2468   EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
2469 
2470   const StreamParamsVec& updated_video_streams = updated_vcd->streams();
2471   ASSERT_EQ(2U, updated_video_streams.size());
2472   EXPECT_EQ(video_streams[0], updated_video_streams[0]);
2473   EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
2474   // All the media streams in one PeerConnection share one RTCP CNAME.
2475   EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
2476 }
2477 
2478 // Create an offer with simulcast video stream.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateSimulcastVideoOffer)2479 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
2480   MediaSessionOptions opts;
2481   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
2482                              RtpTransceiverDirection::kRecvOnly, kActive,
2483                              &opts);
2484   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2485                              RtpTransceiverDirection::kSendRecv, kActive,
2486                              &opts);
2487   const int num_sim_layers = 3;
2488   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
2489                                         {kMediaStream1}, num_sim_layers, &opts);
2490   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
2491 
2492   ASSERT_TRUE(offer.get() != NULL);
2493   const ContentInfo* vc = offer->GetContentByName("video");
2494   ASSERT_TRUE(vc != NULL);
2495   const VideoContentDescription* vcd = vc->media_description()->as_video();
2496 
2497   const StreamParamsVec& video_streams = vcd->streams();
2498   ASSERT_EQ(1U, video_streams.size());
2499   EXPECT_EQ(kVideoTrack1, video_streams[0].id);
2500   const SsrcGroup* sim_ssrc_group =
2501       video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
2502   ASSERT_TRUE(sim_ssrc_group != NULL);
2503   EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
2504 }
2505 
2506 MATCHER(RidDescriptionEquals, "Verifies that two RidDescriptions are equal.") {
2507   const RidDescription& rid1 = ::testing::get<0>(arg);
2508   const RidDescription& rid2 = ::testing::get<1>(arg);
2509   return rid1.rid == rid2.rid && rid1.direction == rid2.direction;
2510 }
2511 
CheckSimulcastInSessionDescription(const SessionDescription * description,const std::string & content_name,const std::vector<RidDescription> & send_rids,const SimulcastLayerList & send_layers)2512 static void CheckSimulcastInSessionDescription(
2513     const SessionDescription* description,
2514     const std::string& content_name,
2515     const std::vector<RidDescription>& send_rids,
2516     const SimulcastLayerList& send_layers) {
2517   ASSERT_NE(description, nullptr);
2518   const ContentInfo* content = description->GetContentByName(content_name);
2519   ASSERT_NE(content, nullptr);
2520   const MediaContentDescription* cd = content->media_description();
2521   ASSERT_NE(cd, nullptr);
2522   const StreamParamsVec& streams = cd->streams();
2523   ASSERT_THAT(streams, SizeIs(1));
2524   const StreamParams& stream = streams[0];
2525   ASSERT_THAT(stream.ssrcs, IsEmpty());
2526   EXPECT_TRUE(stream.has_rids());
2527   const std::vector<RidDescription> rids = stream.rids();
2528 
2529   EXPECT_THAT(rids, Pointwise(RidDescriptionEquals(), send_rids));
2530 
2531   EXPECT_TRUE(cd->HasSimulcast());
2532   const SimulcastDescription& simulcast = cd->simulcast_description();
2533   EXPECT_THAT(simulcast.send_layers(), SizeIs(send_layers.size()));
2534   EXPECT_THAT(simulcast.send_layers(), Pointwise(Eq(), send_layers));
2535 
2536   ASSERT_THAT(simulcast.receive_layers().GetAllLayers(), SizeIs(0));
2537 }
2538 
2539 // Create an offer with spec-compliant simulcast video stream.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateCompliantSimulcastOffer)2540 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateCompliantSimulcastOffer) {
2541   MediaSessionOptions opts;
2542   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2543                              RtpTransceiverDirection::kSendRecv, kActive,
2544                              &opts);
2545   std::vector<RidDescription> send_rids;
2546   send_rids.push_back(RidDescription("f", RidDirection::kSend));
2547   send_rids.push_back(RidDescription("h", RidDirection::kSend));
2548   send_rids.push_back(RidDescription("q", RidDirection::kSend));
2549   SimulcastLayerList simulcast_layers;
2550   simulcast_layers.AddLayer(SimulcastLayer(send_rids[0].rid, false));
2551   simulcast_layers.AddLayer(SimulcastLayer(send_rids[1].rid, true));
2552   simulcast_layers.AddLayer(SimulcastLayer(send_rids[2].rid, false));
2553   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
2554                                         {kMediaStream1}, send_rids,
2555                                         simulcast_layers, 0, &opts);
2556   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
2557 
2558   CheckSimulcastInSessionDescription(offer.get(), "video", send_rids,
2559                                      simulcast_layers);
2560 }
2561 
2562 // Create an offer that signals RIDs (not SSRCs) without Simulcast.
2563 // In this scenario, RIDs do not need to be negotiated (there is only one).
TEST_F(MediaSessionDescriptionFactoryTest,TestOfferWithRidsNoSimulcast)2564 TEST_F(MediaSessionDescriptionFactoryTest, TestOfferWithRidsNoSimulcast) {
2565   MediaSessionOptions opts;
2566   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2567                              RtpTransceiverDirection::kSendRecv, kActive,
2568                              &opts);
2569   RidDescription rid("f", RidDirection::kSend);
2570   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
2571                                         {kMediaStream1}, {rid},
2572                                         SimulcastLayerList(), 0, &opts);
2573   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
2574 
2575   ASSERT_NE(offer.get(), nullptr);
2576   const ContentInfo* content = offer->GetContentByName("video");
2577   ASSERT_NE(content, nullptr);
2578   const MediaContentDescription* cd = content->media_description();
2579   ASSERT_NE(cd, nullptr);
2580   const StreamParamsVec& streams = cd->streams();
2581   ASSERT_THAT(streams, SizeIs(1));
2582   const StreamParams& stream = streams[0];
2583   ASSERT_THAT(stream.ssrcs, IsEmpty());
2584   EXPECT_FALSE(stream.has_rids());
2585   EXPECT_FALSE(cd->HasSimulcast());
2586 }
2587 
2588 // Create an answer with spec-compliant simulcast video stream.
2589 // In this scenario, the SFU is the caller requesting that we send Simulcast.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateCompliantSimulcastAnswer)2590 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateCompliantSimulcastAnswer) {
2591   MediaSessionOptions offer_opts;
2592   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2593                              RtpTransceiverDirection::kSendRecv, kActive,
2594                              &offer_opts);
2595   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
2596                                         {kMediaStream1}, 1, &offer_opts);
2597   std::unique_ptr<SessionDescription> offer =
2598       f1_.CreateOffer(offer_opts, nullptr);
2599 
2600   MediaSessionOptions answer_opts;
2601   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2602                              RtpTransceiverDirection::kSendRecv, kActive,
2603                              &answer_opts);
2604 
2605   std::vector<RidDescription> rid_descriptions{
2606       RidDescription("f", RidDirection::kSend),
2607       RidDescription("h", RidDirection::kSend),
2608       RidDescription("q", RidDirection::kSend),
2609   };
2610   SimulcastLayerList simulcast_layers;
2611   simulcast_layers.AddLayer(SimulcastLayer(rid_descriptions[0].rid, false));
2612   simulcast_layers.AddLayer(SimulcastLayer(rid_descriptions[1].rid, true));
2613   simulcast_layers.AddLayer(SimulcastLayer(rid_descriptions[2].rid, false));
2614   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
2615                                         {kMediaStream1}, rid_descriptions,
2616                                         simulcast_layers, 0, &answer_opts);
2617   std::unique_ptr<SessionDescription> answer =
2618       f2_.CreateAnswer(offer.get(), answer_opts, nullptr);
2619 
2620   CheckSimulcastInSessionDescription(answer.get(), "video", rid_descriptions,
2621                                      simulcast_layers);
2622 }
2623 
2624 // Create an answer that signals RIDs (not SSRCs) without Simulcast.
2625 // In this scenario, RIDs do not need to be negotiated (there is only one).
2626 // Note that RID Direction is not the same as the transceiver direction.
TEST_F(MediaSessionDescriptionFactoryTest,TestAnswerWithRidsNoSimulcast)2627 TEST_F(MediaSessionDescriptionFactoryTest, TestAnswerWithRidsNoSimulcast) {
2628   MediaSessionOptions offer_opts;
2629   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2630                              RtpTransceiverDirection::kSendRecv, kActive,
2631                              &offer_opts);
2632   RidDescription rid_offer("f", RidDirection::kSend);
2633   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
2634                                         {kMediaStream1}, {rid_offer},
2635                                         SimulcastLayerList(), 0, &offer_opts);
2636   std::unique_ptr<SessionDescription> offer =
2637       f1_.CreateOffer(offer_opts, nullptr);
2638 
2639   MediaSessionOptions answer_opts;
2640   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2641                              RtpTransceiverDirection::kSendRecv, kActive,
2642                              &answer_opts);
2643 
2644   RidDescription rid_answer("f", RidDirection::kReceive);
2645   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
2646                                         {kMediaStream1}, {rid_answer},
2647                                         SimulcastLayerList(), 0, &answer_opts);
2648   std::unique_ptr<SessionDescription> answer =
2649       f2_.CreateAnswer(offer.get(), answer_opts, nullptr);
2650 
2651   ASSERT_NE(answer.get(), nullptr);
2652   const ContentInfo* content = offer->GetContentByName("video");
2653   ASSERT_NE(content, nullptr);
2654   const MediaContentDescription* cd = content->media_description();
2655   ASSERT_NE(cd, nullptr);
2656   const StreamParamsVec& streams = cd->streams();
2657   ASSERT_THAT(streams, SizeIs(1));
2658   const StreamParams& stream = streams[0];
2659   ASSERT_THAT(stream.ssrcs, IsEmpty());
2660   EXPECT_FALSE(stream.has_rids());
2661   EXPECT_FALSE(cd->HasSimulcast());
2662 }
2663 
2664 // Create an audio and video answer to a standard video offer with:
2665 // - one video track
2666 // - two audio tracks
2667 // - two data tracks
2668 // and ensure it matches what we expect. Also updates the initial answer by
2669 // adding a new video track and removes one of the audio tracks.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateMultiStreamVideoAnswer)2670 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
2671   MediaSessionOptions offer_opts;
2672   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
2673                              RtpTransceiverDirection::kRecvOnly, kActive,
2674                              &offer_opts);
2675   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2676                              RtpTransceiverDirection::kRecvOnly, kActive,
2677                              &offer_opts);
2678   f1_.set_secure(SEC_ENABLED);
2679   f2_.set_secure(SEC_ENABLED);
2680   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(offer_opts, NULL);
2681 
2682   MediaSessionOptions answer_opts;
2683   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
2684                              RtpTransceiverDirection::kSendRecv, kActive,
2685                              &answer_opts);
2686   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2687                              RtpTransceiverDirection::kSendRecv, kActive,
2688                              &answer_opts);
2689   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
2690                                         {kMediaStream1}, 1, &answer_opts);
2691   AttachSenderToMediaDescriptionOptions("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
2692                                         {kMediaStream1}, 1, &answer_opts);
2693   AttachSenderToMediaDescriptionOptions("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
2694                                         {kMediaStream1}, 1, &answer_opts);
2695 
2696   std::unique_ptr<SessionDescription> answer =
2697       f2_.CreateAnswer(offer.get(), answer_opts, NULL);
2698 
2699   ASSERT_TRUE(answer.get() != NULL);
2700   const ContentInfo* ac = answer->GetContentByName("audio");
2701   const ContentInfo* vc = answer->GetContentByName("video");
2702   ASSERT_TRUE(ac != NULL);
2703   ASSERT_TRUE(vc != NULL);
2704   const AudioContentDescription* acd = ac->media_description()->as_audio();
2705   const VideoContentDescription* vcd = vc->media_description()->as_video();
2706   ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
2707   ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
2708 
2709   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
2710   EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
2711 
2712   const StreamParamsVec& audio_streams = acd->streams();
2713   ASSERT_EQ(2U, audio_streams.size());
2714   EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
2715   EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
2716   ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
2717   EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
2718   EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
2719   ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
2720   EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
2721 
2722   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
2723   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
2724 
2725   EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
2726   EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer));
2727 
2728   const StreamParamsVec& video_streams = vcd->streams();
2729   ASSERT_EQ(1U, video_streams.size());
2730   EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
2731   EXPECT_EQ(kVideoTrack1, video_streams[0].id);
2732   EXPECT_EQ(kAutoBandwidth, vcd->bandwidth());  // default bandwidth (auto)
2733   EXPECT_TRUE(vcd->rtcp_mux());                 // rtcp-mux defaults on
2734 
2735   // Update the answer. Add a new video track that is not synched to the
2736   // other tracks and remove 1 audio track.
2737   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
2738                                         {kMediaStream2}, 1, &answer_opts);
2739   DetachSenderFromMediaSection("audio", kAudioTrack2, &answer_opts);
2740   std::unique_ptr<SessionDescription> updated_answer(
2741       f2_.CreateAnswer(offer.get(), answer_opts, answer.get()));
2742 
2743   ASSERT_TRUE(updated_answer.get() != NULL);
2744   ac = updated_answer->GetContentByName("audio");
2745   vc = updated_answer->GetContentByName("video");
2746   ASSERT_TRUE(ac != NULL);
2747   ASSERT_TRUE(vc != NULL);
2748   const AudioContentDescription* updated_acd =
2749       ac->media_description()->as_audio();
2750   const VideoContentDescription* updated_vcd =
2751       vc->media_description()->as_video();
2752 
2753   ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
2754   EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
2755   ASSERT_CRYPTO(updated_vcd, 1U, kDefaultSrtpCryptoSuite);
2756   EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
2757 
2758   EXPECT_EQ(acd->type(), updated_acd->type());
2759   EXPECT_EQ(acd->codecs(), updated_acd->codecs());
2760   EXPECT_EQ(vcd->type(), updated_vcd->type());
2761   EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
2762 
2763   const StreamParamsVec& updated_audio_streams = updated_acd->streams();
2764   ASSERT_EQ(1U, updated_audio_streams.size());
2765   EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
2766 
2767   const StreamParamsVec& updated_video_streams = updated_vcd->streams();
2768   ASSERT_EQ(2U, updated_video_streams.size());
2769   EXPECT_EQ(video_streams[0], updated_video_streams[0]);
2770   EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
2771   // All media streams in one PeerConnection share one CNAME.
2772   EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
2773 }
2774 
2775 // Create an updated offer after creating an answer to the original offer and
2776 // verify that the codecs that were part of the original answer are not changed
2777 // in the updated offer.
TEST_F(MediaSessionDescriptionFactoryTest,RespondentCreatesOfferAfterCreatingAnswer)2778 TEST_F(MediaSessionDescriptionFactoryTest,
2779        RespondentCreatesOfferAfterCreatingAnswer) {
2780   MediaSessionOptions opts;
2781   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
2782 
2783   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
2784   std::unique_ptr<SessionDescription> answer =
2785       f2_.CreateAnswer(offer.get(), opts, NULL);
2786 
2787   const AudioContentDescription* acd =
2788       GetFirstAudioContentDescription(answer.get());
2789   EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
2790 
2791   const VideoContentDescription* vcd =
2792       GetFirstVideoContentDescription(answer.get());
2793   EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer));
2794 
2795   std::unique_ptr<SessionDescription> updated_offer(
2796       f2_.CreateOffer(opts, answer.get()));
2797 
2798   // The expected audio codecs are the common audio codecs from the first
2799   // offer/answer exchange plus the audio codecs only `f2_` offer, sorted in
2800   // preference order.
2801   // TODO(wu): `updated_offer` should not include the codec
2802   // (i.e. `kAudioCodecs2[0]`) the other side doesn't support.
2803   const AudioCodec kUpdatedAudioCodecOffer[] = {
2804       kAudioCodecsAnswer[0],
2805       kAudioCodecsAnswer[1],
2806       kAudioCodecs2[0],
2807   };
2808 
2809   // The expected video codecs are the common video codecs from the first
2810   // offer/answer exchange plus the video codecs only `f2_` offer, sorted in
2811   // preference order.
2812   const VideoCodec kUpdatedVideoCodecOffer[] = {
2813       kVideoCodecsAnswer[0],
2814       kVideoCodecs2[1],
2815   };
2816 
2817   const AudioContentDescription* updated_acd =
2818       GetFirstAudioContentDescription(updated_offer.get());
2819   EXPECT_THAT(updated_acd->codecs(), ElementsAreArray(kUpdatedAudioCodecOffer));
2820 
2821   const VideoContentDescription* updated_vcd =
2822       GetFirstVideoContentDescription(updated_offer.get());
2823   EXPECT_THAT(updated_vcd->codecs(), ElementsAreArray(kUpdatedVideoCodecOffer));
2824 }
2825 
2826 // Test that a reoffer does not reuse audio codecs from a previous media section
2827 // that is being recycled.
TEST_F(MediaSessionDescriptionFactoryTest,ReOfferDoesNotReUseRecycledAudioCodecs)2828 TEST_F(MediaSessionDescriptionFactoryTest,
2829        ReOfferDoesNotReUseRecycledAudioCodecs) {
2830   f1_.set_video_codecs({}, {});
2831   f2_.set_video_codecs({}, {});
2832 
2833   MediaSessionOptions opts;
2834   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "a0",
2835                              RtpTransceiverDirection::kSendRecv, kActive,
2836                              &opts);
2837   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
2838   std::unique_ptr<SessionDescription> answer =
2839       f2_.CreateAnswer(offer.get(), opts, nullptr);
2840 
2841   // Recycle the media section by changing its mid.
2842   opts.media_description_options[0].mid = "a1";
2843   std::unique_ptr<SessionDescription> reoffer =
2844       f2_.CreateOffer(opts, answer.get());
2845 
2846   // Expect that the results of the first negotiation are ignored. If the m=
2847   // section was not recycled the payload types would match the initial offerer.
2848   const AudioContentDescription* acd =
2849       GetFirstAudioContentDescription(reoffer.get());
2850   EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecs2));
2851 }
2852 
2853 // Test that a reoffer does not reuse video codecs from a previous media section
2854 // that is being recycled.
TEST_F(MediaSessionDescriptionFactoryTest,ReOfferDoesNotReUseRecycledVideoCodecs)2855 TEST_F(MediaSessionDescriptionFactoryTest,
2856        ReOfferDoesNotReUseRecycledVideoCodecs) {
2857   f1_.set_audio_codecs({}, {});
2858   f2_.set_audio_codecs({}, {});
2859 
2860   MediaSessionOptions opts;
2861   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "v0",
2862                              RtpTransceiverDirection::kSendRecv, kActive,
2863                              &opts);
2864   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
2865   auto answer = f2_.CreateAnswer(offer.get(), opts, nullptr);
2866 
2867   // Recycle the media section by changing its mid.
2868   opts.media_description_options[0].mid = "v1";
2869   std::unique_ptr<SessionDescription> reoffer =
2870       f2_.CreateOffer(opts, answer.get());
2871 
2872   // Expect that the results of the first negotiation are ignored. If the m=
2873   // section was not recycled the payload types would match the initial offerer.
2874   const VideoContentDescription* vcd =
2875       GetFirstVideoContentDescription(reoffer.get());
2876   EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecs2));
2877 }
2878 
2879 // Test that a reanswer does not reuse audio codecs from a previous media
2880 // section that is being recycled.
TEST_F(MediaSessionDescriptionFactoryTest,ReAnswerDoesNotReUseRecycledAudioCodecs)2881 TEST_F(MediaSessionDescriptionFactoryTest,
2882        ReAnswerDoesNotReUseRecycledAudioCodecs) {
2883   f1_.set_video_codecs({}, {});
2884   f2_.set_video_codecs({}, {});
2885 
2886   // Perform initial offer/answer in reverse (`f2_` as offerer) so that the
2887   // second offer/answer is forward (`f1_` as offerer).
2888   MediaSessionOptions opts;
2889   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "a0",
2890                              RtpTransceiverDirection::kSendRecv, kActive,
2891                              &opts);
2892   std::unique_ptr<SessionDescription> offer = f2_.CreateOffer(opts, nullptr);
2893   std::unique_ptr<SessionDescription> answer =
2894       f1_.CreateAnswer(offer.get(), opts, nullptr);
2895 
2896   // Recycle the media section by changing its mid.
2897   opts.media_description_options[0].mid = "a1";
2898   std::unique_ptr<SessionDescription> reoffer =
2899       f1_.CreateOffer(opts, answer.get());
2900   std::unique_ptr<SessionDescription> reanswer =
2901       f2_.CreateAnswer(reoffer.get(), opts, offer.get());
2902 
2903   // Expect that the results of the first negotiation are ignored. If the m=
2904   // section was not recycled the payload types would match the initial offerer.
2905   const AudioContentDescription* acd =
2906       GetFirstAudioContentDescription(reanswer.get());
2907   EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
2908 }
2909 
2910 // Test that a reanswer does not reuse video codecs from a previous media
2911 // section that is being recycled.
TEST_F(MediaSessionDescriptionFactoryTest,ReAnswerDoesNotReUseRecycledVideoCodecs)2912 TEST_F(MediaSessionDescriptionFactoryTest,
2913        ReAnswerDoesNotReUseRecycledVideoCodecs) {
2914   f1_.set_audio_codecs({}, {});
2915   f2_.set_audio_codecs({}, {});
2916 
2917   // Perform initial offer/answer in reverse (`f2_` as offerer) so that the
2918   // second offer/answer is forward (`f1_` as offerer).
2919   MediaSessionOptions opts;
2920   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "v0",
2921                              RtpTransceiverDirection::kSendRecv, kActive,
2922                              &opts);
2923   std::unique_ptr<SessionDescription> offer = f2_.CreateOffer(opts, nullptr);
2924   std::unique_ptr<SessionDescription> answer =
2925       f1_.CreateAnswer(offer.get(), opts, nullptr);
2926 
2927   // Recycle the media section by changing its mid.
2928   opts.media_description_options[0].mid = "v1";
2929   std::unique_ptr<SessionDescription> reoffer =
2930       f1_.CreateOffer(opts, answer.get());
2931   std::unique_ptr<SessionDescription> reanswer =
2932       f2_.CreateAnswer(reoffer.get(), opts, offer.get());
2933 
2934   // Expect that the results of the first negotiation are ignored. If the m=
2935   // section was not recycled the payload types would match the initial offerer.
2936   const VideoContentDescription* vcd =
2937       GetFirstVideoContentDescription(reanswer.get());
2938   EXPECT_THAT(vcd->codecs(), ElementsAreArray(kVideoCodecsAnswer));
2939 }
2940 
2941 // Create an updated offer after creating an answer to the original offer and
2942 // verify that the codecs that were part of the original answer are not changed
2943 // in the updated offer. In this test Rtx is enabled.
TEST_F(MediaSessionDescriptionFactoryTest,RespondentCreatesOfferAfterCreatingAnswerWithRtx)2944 TEST_F(MediaSessionDescriptionFactoryTest,
2945        RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
2946   MediaSessionOptions opts;
2947   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2948                              RtpTransceiverDirection::kRecvOnly, kActive,
2949                              &opts);
2950   std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2951   // This creates rtx for H264 with the payload type `f1_` uses.
2952   AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2953   f1_.set_video_codecs(f1_codecs, f1_codecs);
2954 
2955   std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2956   // This creates rtx for H264 with the payload type `f2_` uses.
2957   AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
2958   f2_.set_video_codecs(f2_codecs, f2_codecs);
2959 
2960   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
2961   ASSERT_TRUE(offer.get() != NULL);
2962   std::unique_ptr<SessionDescription> answer =
2963       f2_.CreateAnswer(offer.get(), opts, NULL);
2964 
2965   const VideoContentDescription* vcd =
2966       GetFirstVideoContentDescription(answer.get());
2967 
2968   std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2969   AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2970               &expected_codecs);
2971 
2972   EXPECT_EQ(expected_codecs, vcd->codecs());
2973 
2974   // Now, make sure we get same result (except for the order) if `f2_` creates
2975   // an updated offer even though the default payload types between `f1_` and
2976   // `f2_` are different.
2977   std::unique_ptr<SessionDescription> updated_offer(
2978       f2_.CreateOffer(opts, answer.get()));
2979   ASSERT_TRUE(updated_offer);
2980   std::unique_ptr<SessionDescription> updated_answer(
2981       f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
2982 
2983   const VideoContentDescription* updated_vcd =
2984       GetFirstVideoContentDescription(updated_answer.get());
2985 
2986   EXPECT_EQ(expected_codecs, updated_vcd->codecs());
2987 }
2988 
2989 // Regression test for:
2990 // https://bugs.chromium.org/p/webrtc/issues/detail?id=8332
2991 // Existing codecs should always appear before new codecs in re-offers. But
2992 // under a specific set of circumstances, the existing RTX codec was ending up
2993 // added to the end of the list.
TEST_F(MediaSessionDescriptionFactoryTest,RespondentCreatesOfferAfterCreatingAnswerWithRemappedRtxPayloadType)2994 TEST_F(MediaSessionDescriptionFactoryTest,
2995        RespondentCreatesOfferAfterCreatingAnswerWithRemappedRtxPayloadType) {
2996   MediaSessionOptions opts;
2997   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
2998                              RtpTransceiverDirection::kRecvOnly, kActive,
2999                              &opts);
3000   // We specifically choose different preferred payload types for VP8 to
3001   // trigger the issue.
3002   cricket::VideoCodec vp8_offerer(100, "VP8");
3003   cricket::VideoCodec vp8_offerer_rtx =
3004       VideoCodec::CreateRtxCodec(101, vp8_offerer.id);
3005   cricket::VideoCodec vp8_answerer(110, "VP8");
3006   cricket::VideoCodec vp8_answerer_rtx =
3007       VideoCodec::CreateRtxCodec(111, vp8_answerer.id);
3008   cricket::VideoCodec vp9(120, "VP9");
3009   cricket::VideoCodec vp9_rtx = VideoCodec::CreateRtxCodec(121, vp9.id);
3010 
3011   std::vector<VideoCodec> f1_codecs = {vp8_offerer, vp8_offerer_rtx};
3012   // We also specifically cause the answerer to prefer VP9, such that if it
3013   // *doesn't* honor the existing preferred codec (VP8) we'll notice.
3014   std::vector<VideoCodec> f2_codecs = {vp9, vp9_rtx, vp8_answerer,
3015                                        vp8_answerer_rtx};
3016 
3017   f1_.set_video_codecs(f1_codecs, f1_codecs);
3018   f2_.set_video_codecs(f2_codecs, f2_codecs);
3019   std::vector<AudioCodec> audio_codecs;
3020   f1_.set_audio_codecs(audio_codecs, audio_codecs);
3021   f2_.set_audio_codecs(audio_codecs, audio_codecs);
3022 
3023   // Offer will be {VP8, RTX for VP8}. Answer will be the same.
3024   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
3025   ASSERT_TRUE(offer.get() != NULL);
3026   std::unique_ptr<SessionDescription> answer =
3027       f2_.CreateAnswer(offer.get(), opts, NULL);
3028 
3029   // Updated offer *should* be {VP8, RTX for VP8, VP9, RTX for VP9}.
3030   // But if the bug is triggered, RTX for VP8 ends up last.
3031   std::unique_ptr<SessionDescription> updated_offer(
3032       f2_.CreateOffer(opts, answer.get()));
3033 
3034   const VideoContentDescription* vcd =
3035       GetFirstVideoContentDescription(updated_offer.get());
3036   std::vector<cricket::VideoCodec> codecs = vcd->codecs();
3037   ASSERT_EQ(4u, codecs.size());
3038   EXPECT_EQ(vp8_offerer, codecs[0]);
3039   EXPECT_EQ(vp8_offerer_rtx, codecs[1]);
3040   EXPECT_EQ(vp9, codecs[2]);
3041   EXPECT_EQ(vp9_rtx, codecs[3]);
3042 }
3043 
3044 // Create an updated offer that adds video after creating an audio only answer
3045 // to the original offer. This test verifies that if a video codec and the RTX
3046 // codec have the same default payload type as an audio codec that is already in
3047 // use, the added codecs payload types are changed.
TEST_F(MediaSessionDescriptionFactoryTest,RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer)3048 TEST_F(MediaSessionDescriptionFactoryTest,
3049        RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
3050   std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
3051   // This creates rtx for H264 with the payload type `f1_` uses.
3052   AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
3053   f1_.set_video_codecs(f1_codecs, f1_codecs);
3054 
3055   MediaSessionOptions opts;
3056   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
3057                              RtpTransceiverDirection::kRecvOnly, kActive,
3058                              &opts);
3059 
3060   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
3061   std::unique_ptr<SessionDescription> answer =
3062       f2_.CreateAnswer(offer.get(), opts, NULL);
3063 
3064   const AudioContentDescription* acd =
3065       GetFirstAudioContentDescription(answer.get());
3066   EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
3067 
3068   // Now - let `f2_` add video with RTX and let the payload type the RTX codec
3069   // reference  be the same as an audio codec that was negotiated in the
3070   // first offer/answer exchange.
3071   opts.media_description_options.clear();
3072   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
3073 
3074   std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
3075   int used_pl_type = acd->codecs()[0].id;
3076   f2_codecs[0].id = used_pl_type;  // Set the payload type for H264.
3077   AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
3078   f2_.set_video_codecs(f2_codecs, f2_codecs);
3079 
3080   std::unique_ptr<SessionDescription> updated_offer(
3081       f2_.CreateOffer(opts, answer.get()));
3082   ASSERT_TRUE(updated_offer);
3083   std::unique_ptr<SessionDescription> updated_answer(
3084       f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
3085 
3086   const AudioContentDescription* updated_acd =
3087       GetFirstAudioContentDescription(answer.get());
3088   EXPECT_THAT(updated_acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
3089 
3090   const VideoContentDescription* updated_vcd =
3091       GetFirstVideoContentDescription(updated_answer.get());
3092 
3093   ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
3094   ASSERT_EQ(cricket::kRtxCodecName, updated_vcd->codecs()[1].name);
3095   int new_h264_pl_type = updated_vcd->codecs()[0].id;
3096   EXPECT_NE(used_pl_type, new_h264_pl_type);
3097   VideoCodec rtx = updated_vcd->codecs()[1];
3098   int pt_referenced_by_rtx = rtc::FromString<int>(
3099       rtx.params[cricket::kCodecParamAssociatedPayloadType]);
3100   EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
3101 }
3102 
3103 // Create an updated offer with RTX after creating an answer to an offer
3104 // without RTX, and with different default payload types.
3105 // Verify that the added RTX codec references the correct payload type.
TEST_F(MediaSessionDescriptionFactoryTest,RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx)3106 TEST_F(MediaSessionDescriptionFactoryTest,
3107        RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
3108   MediaSessionOptions opts;
3109   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
3110 
3111   std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
3112   // This creates rtx for H264 with the payload type `f2_` uses.
3113   AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
3114   f2_.set_video_codecs(f2_codecs, f2_codecs);
3115 
3116   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
3117   ASSERT_TRUE(offer.get() != nullptr);
3118   std::unique_ptr<SessionDescription> answer =
3119       f2_.CreateAnswer(offer.get(), opts, nullptr);
3120 
3121   const VideoContentDescription* vcd =
3122       GetFirstVideoContentDescription(answer.get());
3123 
3124   std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
3125   EXPECT_EQ(expected_codecs, vcd->codecs());
3126 
3127   // Now, ensure that the RTX codec is created correctly when `f2_` creates an
3128   // updated offer, even though the default payload types are different from
3129   // those of `f1_`.
3130   std::unique_ptr<SessionDescription> updated_offer(
3131       f2_.CreateOffer(opts, answer.get()));
3132   ASSERT_TRUE(updated_offer);
3133 
3134   const VideoContentDescription* updated_vcd =
3135       GetFirstVideoContentDescription(updated_offer.get());
3136 
3137   // New offer should attempt to add H263, and RTX for H264.
3138   expected_codecs.push_back(kVideoCodecs2[1]);
3139   AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
3140               &expected_codecs);
3141   EXPECT_EQ(expected_codecs, updated_vcd->codecs());
3142 }
3143 
3144 // Test that RTX is ignored when there is no associated payload type parameter.
TEST_F(MediaSessionDescriptionFactoryTest,RtxWithoutApt)3145 TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
3146   MediaSessionOptions opts;
3147   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
3148                              RtpTransceiverDirection::kRecvOnly, kActive,
3149                              &opts);
3150   std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
3151   // This creates RTX without associated payload type parameter.
3152   AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName), &f1_codecs);
3153   f1_.set_video_codecs(f1_codecs, f1_codecs);
3154 
3155   std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
3156   // This creates RTX for H264 with the payload type `f2_` uses.
3157   AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
3158   f2_.set_video_codecs(f2_codecs, f2_codecs);
3159 
3160   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
3161   ASSERT_TRUE(offer.get() != NULL);
3162   // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
3163   // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
3164   // is possible to test that that RTX is dropped when
3165   // kCodecParamAssociatedPayloadType is missing in the offer.
3166   MediaContentDescription* media_desc =
3167       offer->GetContentDescriptionByName(cricket::CN_VIDEO);
3168   ASSERT_TRUE(media_desc);
3169   VideoContentDescription* desc = media_desc->as_video();
3170   std::vector<VideoCodec> codecs = desc->codecs();
3171   for (VideoCodec& codec : codecs) {
3172     if (absl::StartsWith(codec.name, cricket::kRtxCodecName)) {
3173       codec.params.clear();
3174     }
3175   }
3176   desc->set_codecs(codecs);
3177 
3178   std::unique_ptr<SessionDescription> answer =
3179       f2_.CreateAnswer(offer.get(), opts, NULL);
3180 
3181   EXPECT_THAT(
3182       GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs()),
3183       Not(Contains(cricket::kRtxCodecName)));
3184 }
3185 
3186 // Test that RTX will be filtered out in the answer if its associated payload
3187 // type doesn't match the local value.
TEST_F(MediaSessionDescriptionFactoryTest,FilterOutRtxIfAptDoesntMatch)3188 TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
3189   MediaSessionOptions opts;
3190   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
3191                              RtpTransceiverDirection::kRecvOnly, kActive,
3192                              &opts);
3193   std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
3194   // This creates RTX for H264 in sender.
3195   AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
3196   f1_.set_video_codecs(f1_codecs, f1_codecs);
3197 
3198   std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
3199   // This creates RTX for H263 in receiver.
3200   AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
3201   f2_.set_video_codecs(f2_codecs, f2_codecs);
3202 
3203   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
3204   ASSERT_TRUE(offer.get() != NULL);
3205   // Associated payload type doesn't match, therefore, RTX codec is removed in
3206   // the answer.
3207   std::unique_ptr<SessionDescription> answer =
3208       f2_.CreateAnswer(offer.get(), opts, NULL);
3209 
3210   EXPECT_THAT(
3211       GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs()),
3212       Not(Contains(cricket::kRtxCodecName)));
3213 }
3214 
3215 // Test that when multiple RTX codecs are offered, only the matched RTX codec
3216 // is added in the answer, and the unsupported RTX codec is filtered out.
TEST_F(MediaSessionDescriptionFactoryTest,FilterOutUnsupportedRtxWhenCreatingAnswer)3217 TEST_F(MediaSessionDescriptionFactoryTest,
3218        FilterOutUnsupportedRtxWhenCreatingAnswer) {
3219   MediaSessionOptions opts;
3220   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
3221                              RtpTransceiverDirection::kRecvOnly, kActive,
3222                              &opts);
3223   std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
3224   // This creates RTX for H264-SVC in sender.
3225   AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
3226   f1_.set_video_codecs(f1_codecs, f1_codecs);
3227 
3228   // This creates RTX for H264 in sender.
3229   AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
3230   f1_.set_video_codecs(f1_codecs, f1_codecs);
3231 
3232   std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
3233   // This creates RTX for H264 in receiver.
3234   AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
3235   f2_.set_video_codecs(f2_codecs, f1_codecs);
3236 
3237   // H264-SVC codec is removed in the answer, therefore, associated RTX codec
3238   // for H264-SVC should also be removed.
3239   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
3240   ASSERT_TRUE(offer.get() != NULL);
3241   std::unique_ptr<SessionDescription> answer =
3242       f2_.CreateAnswer(offer.get(), opts, NULL);
3243   const VideoContentDescription* vcd =
3244       GetFirstVideoContentDescription(answer.get());
3245   std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
3246   AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
3247               &expected_codecs);
3248 
3249   EXPECT_EQ(expected_codecs, vcd->codecs());
3250 }
3251 
3252 // Test that after one RTX codec has been negotiated, a new offer can attempt
3253 // to add another.
TEST_F(MediaSessionDescriptionFactoryTest,AddSecondRtxInNewOffer)3254 TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
3255   MediaSessionOptions opts;
3256   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
3257                              RtpTransceiverDirection::kRecvOnly, kActive,
3258                              &opts);
3259   std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
3260   // This creates RTX for H264 for the offerer.
3261   AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
3262   f1_.set_video_codecs(f1_codecs, f1_codecs);
3263 
3264   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
3265   ASSERT_TRUE(offer);
3266   const VideoContentDescription* vcd =
3267       GetFirstVideoContentDescription(offer.get());
3268 
3269   std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
3270   AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
3271               &expected_codecs);
3272   EXPECT_EQ(expected_codecs, vcd->codecs());
3273 
3274   // Now, attempt to add RTX for H264-SVC.
3275   AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
3276   f1_.set_video_codecs(f1_codecs, f1_codecs);
3277 
3278   std::unique_ptr<SessionDescription> updated_offer(
3279       f1_.CreateOffer(opts, offer.get()));
3280   ASSERT_TRUE(updated_offer);
3281   vcd = GetFirstVideoContentDescription(updated_offer.get());
3282 
3283   AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
3284               &expected_codecs);
3285   EXPECT_EQ(expected_codecs, vcd->codecs());
3286 }
3287 
3288 // Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
3289 // generated for each simulcast ssrc and correctly grouped.
TEST_F(MediaSessionDescriptionFactoryTest,SimSsrcsGenerateMultipleRtxSsrcs)3290 TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
3291   MediaSessionOptions opts;
3292   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
3293                              RtpTransceiverDirection::kSendRecv, kActive,
3294                              &opts);
3295   // Add simulcast streams.
3296   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, "stream1",
3297                                         {"stream1label"}, 3, &opts);
3298 
3299   // Use a single real codec, and then add RTX for it.
3300   std::vector<VideoCodec> f1_codecs;
3301   f1_codecs.push_back(VideoCodec(97, "H264"));
3302   AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
3303   f1_.set_video_codecs(f1_codecs, f1_codecs);
3304 
3305   // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
3306   // is a FID ssrc + grouping for each.
3307   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
3308   ASSERT_TRUE(offer.get() != NULL);
3309   MediaContentDescription* media_desc =
3310       offer->GetContentDescriptionByName(cricket::CN_VIDEO);
3311   ASSERT_TRUE(media_desc);
3312   VideoContentDescription* desc = media_desc->as_video();
3313   const StreamParamsVec& streams = desc->streams();
3314   // Single stream.
3315   ASSERT_EQ(1u, streams.size());
3316   // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
3317   EXPECT_EQ(6u, streams[0].ssrcs.size());
3318   // And should have a SIM group for the simulcast.
3319   EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
3320   // And a FID group for RTX.
3321   EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
3322   std::vector<uint32_t> primary_ssrcs;
3323   streams[0].GetPrimarySsrcs(&primary_ssrcs);
3324   EXPECT_EQ(3u, primary_ssrcs.size());
3325   std::vector<uint32_t> fid_ssrcs;
3326   streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
3327   EXPECT_EQ(3u, fid_ssrcs.size());
3328 }
3329 
3330 // Test that, when the FlexFEC codec is added, a FlexFEC ssrc is created
3331 // together with a FEC-FR grouping. Guarded by WebRTC-FlexFEC-03 trial.
TEST_F(MediaSessionDescriptionFactoryTest,GenerateFlexfecSsrc)3332 TEST_F(MediaSessionDescriptionFactoryTest, GenerateFlexfecSsrc) {
3333   webrtc::test::ScopedKeyValueConfig override_field_trials(
3334       field_trials, "WebRTC-FlexFEC-03/Enabled/");
3335   MediaSessionOptions opts;
3336   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
3337                              RtpTransceiverDirection::kSendRecv, kActive,
3338                              &opts);
3339   // Add single stream.
3340   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, "stream1",
3341                                         {"stream1label"}, 1, &opts);
3342 
3343   // Use a single real codec, and then add FlexFEC for it.
3344   std::vector<VideoCodec> f1_codecs;
3345   f1_codecs.push_back(VideoCodec(97, "H264"));
3346   f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
3347   f1_.set_video_codecs(f1_codecs, f1_codecs);
3348 
3349   // Ensure that the offer has a single FlexFEC ssrc and that
3350   // there is no FEC-FR ssrc + grouping for each.
3351   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
3352   ASSERT_TRUE(offer.get() != nullptr);
3353   MediaContentDescription* media_desc =
3354       offer->GetContentDescriptionByName(cricket::CN_VIDEO);
3355   ASSERT_TRUE(media_desc);
3356   VideoContentDescription* desc = media_desc->as_video();
3357   const StreamParamsVec& streams = desc->streams();
3358   // Single stream.
3359   ASSERT_EQ(1u, streams.size());
3360   // Stream should have 2 ssrcs: 1 for video, 1 for FlexFEC.
3361   EXPECT_EQ(2u, streams[0].ssrcs.size());
3362   // And should have a FEC-FR group for FlexFEC.
3363   EXPECT_TRUE(streams[0].has_ssrc_group("FEC-FR"));
3364   std::vector<uint32_t> primary_ssrcs;
3365   streams[0].GetPrimarySsrcs(&primary_ssrcs);
3366   ASSERT_EQ(1u, primary_ssrcs.size());
3367   uint32_t flexfec_ssrc;
3368   EXPECT_TRUE(streams[0].GetFecFrSsrc(primary_ssrcs[0], &flexfec_ssrc));
3369   EXPECT_NE(flexfec_ssrc, 0u);
3370 }
3371 
3372 // Test that FlexFEC is disabled for simulcast.
3373 // TODO(brandtr): Remove this test when we support simulcast, either through
3374 // multiple FlexfecSenders, or through multistream protection.
TEST_F(MediaSessionDescriptionFactoryTest,SimSsrcsGenerateNoFlexfecSsrcs)3375 TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateNoFlexfecSsrcs) {
3376   webrtc::test::ScopedKeyValueConfig override_field_trials(
3377       field_trials, "WebRTC-FlexFEC-03/Enabled/");
3378   MediaSessionOptions opts;
3379   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
3380                              RtpTransceiverDirection::kSendRecv, kActive,
3381                              &opts);
3382   // Add simulcast streams.
3383   AttachSenderToMediaDescriptionOptions("video", MEDIA_TYPE_VIDEO, "stream1",
3384                                         {"stream1label"}, 3, &opts);
3385 
3386   // Use a single real codec, and then add FlexFEC for it.
3387   std::vector<VideoCodec> f1_codecs;
3388   f1_codecs.push_back(VideoCodec(97, "H264"));
3389   f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
3390   f1_.set_video_codecs(f1_codecs, f1_codecs);
3391 
3392   // Ensure that the offer has no FlexFEC ssrcs for each regular ssrc, and that
3393   // there is no FEC-FR ssrc + grouping for each.
3394   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
3395   ASSERT_TRUE(offer.get() != nullptr);
3396   MediaContentDescription* media_desc =
3397       offer->GetContentDescriptionByName(cricket::CN_VIDEO);
3398   ASSERT_TRUE(media_desc);
3399   VideoContentDescription* desc = media_desc->as_video();
3400   const StreamParamsVec& streams = desc->streams();
3401   // Single stream.
3402   ASSERT_EQ(1u, streams.size());
3403   // Stream should have 3 ssrcs: 3 for video, 0 for FlexFEC.
3404   EXPECT_EQ(3u, streams[0].ssrcs.size());
3405   // And should have a SIM group for the simulcast.
3406   EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
3407   // And not a FEC-FR group for FlexFEC.
3408   EXPECT_FALSE(streams[0].has_ssrc_group("FEC-FR"));
3409   std::vector<uint32_t> primary_ssrcs;
3410   streams[0].GetPrimarySsrcs(&primary_ssrcs);
3411   EXPECT_EQ(3u, primary_ssrcs.size());
3412   for (uint32_t primary_ssrc : primary_ssrcs) {
3413     uint32_t flexfec_ssrc;
3414     EXPECT_FALSE(streams[0].GetFecFrSsrc(primary_ssrc, &flexfec_ssrc));
3415   }
3416 }
3417 
3418 // Create an updated offer after creating an answer to the original offer and
3419 // verify that the RTP header extensions that were part of the original answer
3420 // are not changed in the updated offer.
TEST_F(MediaSessionDescriptionFactoryTest,RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions)3421 TEST_F(MediaSessionDescriptionFactoryTest,
3422        RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
3423   MediaSessionOptions opts;
3424   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
3425 
3426   SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1),
3427                                    MAKE_VECTOR(kVideoRtpExtension1), &opts);
3428   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
3429   SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2),
3430                                    MAKE_VECTOR(kVideoRtpExtension2), &opts);
3431   std::unique_ptr<SessionDescription> answer =
3432       f2_.CreateAnswer(offer.get(), opts, NULL);
3433 
3434   EXPECT_EQ(
3435       MAKE_VECTOR(kAudioRtpExtensionAnswer),
3436       GetFirstAudioContentDescription(answer.get())->rtp_header_extensions());
3437   EXPECT_EQ(
3438       MAKE_VECTOR(kVideoRtpExtensionAnswer),
3439       GetFirstVideoContentDescription(answer.get())->rtp_header_extensions());
3440 
3441   std::unique_ptr<SessionDescription> updated_offer(
3442       f2_.CreateOffer(opts, answer.get()));
3443 
3444   // The expected RTP header extensions in the new offer are the resulting
3445   // extensions from the first offer/answer exchange plus the extensions only
3446   // `f2_` offer.
3447   // Since the default local extension id `f2_` uses has already been used by
3448   // `f1_` for another extensions, it is changed to 13.
3449   const RtpExtension kUpdatedAudioRtpExtensions[] = {
3450       kAudioRtpExtensionAnswer[0],
3451       RtpExtension(kAudioRtpExtension2[1].uri, 13),
3452       kAudioRtpExtension2[2],
3453   };
3454 
3455   // Since the default local extension id `f2_` uses has already been used by
3456   // `f1_` for another extensions, is is changed to 12.
3457   const RtpExtension kUpdatedVideoRtpExtensions[] = {
3458       kVideoRtpExtensionAnswer[0],
3459       RtpExtension(kVideoRtpExtension2[1].uri, 12),
3460       kVideoRtpExtension2[2],
3461   };
3462 
3463   const AudioContentDescription* updated_acd =
3464       GetFirstAudioContentDescription(updated_offer.get());
3465   EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
3466             updated_acd->rtp_header_extensions());
3467 
3468   const VideoContentDescription* updated_vcd =
3469       GetFirstVideoContentDescription(updated_offer.get());
3470   EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
3471             updated_vcd->rtp_header_extensions());
3472 }
3473 
3474 // Verify that if the same RTP extension URI is used for audio and video, the
3475 // same ID is used. Also verify that the ID isn't changed when creating an
3476 // updated offer (this was previously a bug).
TEST_F(MediaSessionDescriptionFactoryTest,RtpExtensionIdReused)3477 TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) {
3478   MediaSessionOptions opts;
3479   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
3480 
3481   SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension3),
3482                                    MAKE_VECTOR(kVideoRtpExtension3), &opts);
3483   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
3484 
3485   // Since the audio extensions used ID 3 for "both_audio_and_video", so should
3486   // the video extensions.
3487   const RtpExtension kExpectedVideoRtpExtension[] = {
3488       kVideoRtpExtension3[0],
3489       kAudioRtpExtension3[1],
3490   };
3491 
3492   EXPECT_EQ(
3493       MAKE_VECTOR(kAudioRtpExtension3),
3494       GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
3495   EXPECT_EQ(
3496       MAKE_VECTOR(kExpectedVideoRtpExtension),
3497       GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
3498 
3499   // Nothing should change when creating a new offer
3500   std::unique_ptr<SessionDescription> updated_offer(
3501       f1_.CreateOffer(opts, offer.get()));
3502 
3503   EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
3504             GetFirstAudioContentDescription(updated_offer.get())
3505                 ->rtp_header_extensions());
3506   EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
3507             GetFirstVideoContentDescription(updated_offer.get())
3508                 ->rtp_header_extensions());
3509 }
3510 
3511 // Same as "RtpExtensionIdReused" above for encrypted RTP extensions.
TEST_F(MediaSessionDescriptionFactoryTest,RtpExtensionIdReusedEncrypted)3512 TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReusedEncrypted) {
3513   MediaSessionOptions opts;
3514   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
3515 
3516   f1_.set_enable_encrypted_rtp_header_extensions(true);
3517   f2_.set_enable_encrypted_rtp_header_extensions(true);
3518 
3519   SetAudioVideoRtpHeaderExtensions(
3520       MAKE_VECTOR(kAudioRtpExtension3ForEncryption),
3521       MAKE_VECTOR(kVideoRtpExtension3ForEncryption), &opts);
3522   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
3523 
3524   EXPECT_EQ(
3525       MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
3526       GetFirstAudioContentDescription(offer.get())->rtp_header_extensions());
3527   EXPECT_EQ(
3528       MAKE_VECTOR(kVideoRtpExtension3ForEncryptionOffer),
3529       GetFirstVideoContentDescription(offer.get())->rtp_header_extensions());
3530 
3531   // Nothing should change when creating a new offer
3532   std::unique_ptr<SessionDescription> updated_offer(
3533       f1_.CreateOffer(opts, offer.get()));
3534 
3535   EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
3536             GetFirstAudioContentDescription(updated_offer.get())
3537                 ->rtp_header_extensions());
3538   EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension3ForEncryptionOffer),
3539             GetFirstVideoContentDescription(updated_offer.get())
3540                 ->rtp_header_extensions());
3541 }
3542 
TEST(MediaSessionDescription,CopySessionDescription)3543 TEST(MediaSessionDescription, CopySessionDescription) {
3544   SessionDescription source;
3545   cricket::ContentGroup group(cricket::CN_AUDIO);
3546   source.AddGroup(group);
3547   std::unique_ptr<AudioContentDescription> acd =
3548       std::make_unique<AudioContentDescription>();
3549   acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
3550   acd->AddLegacyStream(1);
3551   source.AddContent(cricket::CN_AUDIO, MediaProtocolType::kRtp, acd->Clone());
3552   std::unique_ptr<VideoContentDescription> vcd =
3553       std::make_unique<VideoContentDescription>();
3554   vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
3555   vcd->AddLegacyStream(2);
3556   source.AddContent(cricket::CN_VIDEO, MediaProtocolType::kRtp, vcd->Clone());
3557 
3558   std::unique_ptr<SessionDescription> copy = source.Clone();
3559   ASSERT_TRUE(copy.get() != NULL);
3560   EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
3561   const ContentInfo* ac = copy->GetContentByName("audio");
3562   const ContentInfo* vc = copy->GetContentByName("video");
3563   ASSERT_TRUE(ac != NULL);
3564   ASSERT_TRUE(vc != NULL);
3565   EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
3566   const AudioContentDescription* acd_copy = ac->media_description()->as_audio();
3567   EXPECT_EQ(acd->codecs(), acd_copy->codecs());
3568   EXPECT_EQ(1u, acd->first_ssrc());
3569 
3570   EXPECT_EQ(MediaProtocolType::kRtp, vc->type);
3571   const VideoContentDescription* vcd_copy = vc->media_description()->as_video();
3572   EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
3573   EXPECT_EQ(2u, vcd->first_ssrc());
3574 }
3575 
3576 // The below TestTransportInfoXXX tests create different offers/answers, and
3577 // ensure the TransportInfo in the SessionDescription matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoOfferAudio)3578 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
3579   MediaSessionOptions options;
3580   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
3581                              RtpTransceiverDirection::kRecvOnly, kActive,
3582                              &options);
3583   TestTransportInfo(true, options, false);
3584 }
3585 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoOfferIceRenomination)3586 TEST_F(MediaSessionDescriptionFactoryTest,
3587        TestTransportInfoOfferIceRenomination) {
3588   MediaSessionOptions options;
3589   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
3590                              RtpTransceiverDirection::kRecvOnly, kActive,
3591                              &options);
3592   options.media_description_options[0]
3593       .transport_options.enable_ice_renomination = true;
3594   TestTransportInfo(true, options, false);
3595 }
3596 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoOfferAudioCurrent)3597 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
3598   MediaSessionOptions options;
3599   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
3600                              RtpTransceiverDirection::kRecvOnly, kActive,
3601                              &options);
3602   TestTransportInfo(true, options, true);
3603 }
3604 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoOfferMultimedia)3605 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
3606   MediaSessionOptions options;
3607   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
3608   TestTransportInfo(true, options, false);
3609 }
3610 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoOfferMultimediaCurrent)3611 TEST_F(MediaSessionDescriptionFactoryTest,
3612        TestTransportInfoOfferMultimediaCurrent) {
3613   MediaSessionOptions options;
3614   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
3615   TestTransportInfo(true, options, true);
3616 }
3617 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoOfferBundle)3618 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
3619   MediaSessionOptions options;
3620   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
3621   options.bundle_enabled = true;
3622   TestTransportInfo(true, options, false);
3623 }
3624 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoOfferBundleCurrent)3625 TEST_F(MediaSessionDescriptionFactoryTest,
3626        TestTransportInfoOfferBundleCurrent) {
3627   MediaSessionOptions options;
3628   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
3629   options.bundle_enabled = true;
3630   TestTransportInfo(true, options, true);
3631 }
3632 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoAnswerAudio)3633 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
3634   MediaSessionOptions options;
3635   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
3636                              RtpTransceiverDirection::kRecvOnly, kActive,
3637                              &options);
3638   TestTransportInfo(false, options, false);
3639 }
3640 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoAnswerIceRenomination)3641 TEST_F(MediaSessionDescriptionFactoryTest,
3642        TestTransportInfoAnswerIceRenomination) {
3643   MediaSessionOptions options;
3644   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
3645                              RtpTransceiverDirection::kRecvOnly, kActive,
3646                              &options);
3647   options.media_description_options[0]
3648       .transport_options.enable_ice_renomination = true;
3649   TestTransportInfo(false, options, false);
3650 }
3651 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoAnswerAudioCurrent)3652 TEST_F(MediaSessionDescriptionFactoryTest,
3653        TestTransportInfoAnswerAudioCurrent) {
3654   MediaSessionOptions options;
3655   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
3656                              RtpTransceiverDirection::kRecvOnly, kActive,
3657                              &options);
3658   TestTransportInfo(false, options, true);
3659 }
3660 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoAnswerMultimedia)3661 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
3662   MediaSessionOptions options;
3663   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
3664   TestTransportInfo(false, options, false);
3665 }
3666 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoAnswerMultimediaCurrent)3667 TEST_F(MediaSessionDescriptionFactoryTest,
3668        TestTransportInfoAnswerMultimediaCurrent) {
3669   MediaSessionOptions options;
3670   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
3671   TestTransportInfo(false, options, true);
3672 }
3673 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoAnswerBundle)3674 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
3675   MediaSessionOptions options;
3676   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
3677   options.bundle_enabled = true;
3678   TestTransportInfo(false, options, false);
3679 }
3680 
TEST_F(MediaSessionDescriptionFactoryTest,TestTransportInfoAnswerBundleCurrent)3681 TEST_F(MediaSessionDescriptionFactoryTest,
3682        TestTransportInfoAnswerBundleCurrent) {
3683   MediaSessionOptions options;
3684   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
3685   options.bundle_enabled = true;
3686   TestTransportInfo(false, options, true);
3687 }
3688 
3689 // Create an offer with bundle enabled and verify the crypto parameters are
3690 // the common set of the available cryptos.
TEST_F(MediaSessionDescriptionFactoryTest,TestCryptoWithOfferBundle)3691 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
3692   TestCryptoWithBundle(true);
3693 }
3694 
3695 // Create an answer with bundle enabled and verify the crypto parameters are
3696 // the common set of the available cryptos.
TEST_F(MediaSessionDescriptionFactoryTest,TestCryptoWithAnswerBundle)3697 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
3698   TestCryptoWithBundle(false);
3699 }
3700 
3701 // Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
3702 // DTLS is not enabled locally.
TEST_F(MediaSessionDescriptionFactoryTest,TestOfferDtlsSavpfWithoutDtlsFailed)3703 TEST_F(MediaSessionDescriptionFactoryTest,
3704        TestOfferDtlsSavpfWithoutDtlsFailed) {
3705   f1_.set_secure(SEC_ENABLED);
3706   f2_.set_secure(SEC_ENABLED);
3707   tdf1_.set_secure(SEC_DISABLED);
3708   tdf2_.set_secure(SEC_DISABLED);
3709 
3710   std::unique_ptr<SessionDescription> offer =
3711       f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL);
3712   ASSERT_TRUE(offer.get() != NULL);
3713   ContentInfo* offer_content = offer->GetContentByName("audio");
3714   ASSERT_TRUE(offer_content != NULL);
3715   AudioContentDescription* offer_audio_desc =
3716       offer_content->media_description()->as_audio();
3717   offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
3718 
3719   std::unique_ptr<SessionDescription> answer =
3720       f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL);
3721   ASSERT_TRUE(answer != NULL);
3722   ContentInfo* answer_content = answer->GetContentByName("audio");
3723   ASSERT_TRUE(answer_content != NULL);
3724 
3725   ASSERT_TRUE(answer_content->rejected);
3726 }
3727 
3728 // Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
3729 // UDP/TLS/RTP/SAVPF.
TEST_F(MediaSessionDescriptionFactoryTest,TestOfferDtlsSavpfCreateAnswer)3730 TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
3731   f1_.set_secure(SEC_ENABLED);
3732   f2_.set_secure(SEC_ENABLED);
3733   tdf1_.set_secure(SEC_ENABLED);
3734   tdf2_.set_secure(SEC_ENABLED);
3735 
3736   std::unique_ptr<SessionDescription> offer =
3737       f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL);
3738   ASSERT_TRUE(offer.get() != NULL);
3739   ContentInfo* offer_content = offer->GetContentByName("audio");
3740   ASSERT_TRUE(offer_content != NULL);
3741   AudioContentDescription* offer_audio_desc =
3742       offer_content->media_description()->as_audio();
3743   offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
3744 
3745   std::unique_ptr<SessionDescription> answer =
3746       f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL);
3747   ASSERT_TRUE(answer != NULL);
3748 
3749   const ContentInfo* answer_content = answer->GetContentByName("audio");
3750   ASSERT_TRUE(answer_content != NULL);
3751   ASSERT_FALSE(answer_content->rejected);
3752 
3753   const AudioContentDescription* answer_audio_desc =
3754       answer_content->media_description()->as_audio();
3755   EXPECT_EQ(cricket::kMediaProtocolDtlsSavpf, answer_audio_desc->protocol());
3756 }
3757 
3758 // Test that we include both SDES and DTLS in the offer, but only include SDES
3759 // in the answer if DTLS isn't negotiated.
TEST_F(MediaSessionDescriptionFactoryTest,TestCryptoDtls)3760 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
3761   f1_.set_secure(SEC_ENABLED);
3762   f2_.set_secure(SEC_ENABLED);
3763   tdf1_.set_secure(SEC_ENABLED);
3764   tdf2_.set_secure(SEC_DISABLED);
3765   MediaSessionOptions options;
3766   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
3767   std::unique_ptr<SessionDescription> offer, answer;
3768   const cricket::MediaContentDescription* audio_media_desc;
3769   const cricket::MediaContentDescription* video_media_desc;
3770   const cricket::TransportDescription* audio_trans_desc;
3771   const cricket::TransportDescription* video_trans_desc;
3772 
3773   // Generate an offer with SDES and DTLS support.
3774   offer = f1_.CreateOffer(options, NULL);
3775   ASSERT_TRUE(offer.get() != NULL);
3776 
3777   audio_media_desc = offer->GetContentDescriptionByName("audio");
3778   ASSERT_TRUE(audio_media_desc != NULL);
3779   video_media_desc = offer->GetContentDescriptionByName("video");
3780   ASSERT_TRUE(video_media_desc != NULL);
3781   EXPECT_EQ(1u, audio_media_desc->cryptos().size());
3782   EXPECT_EQ(1u, video_media_desc->cryptos().size());
3783 
3784   audio_trans_desc = offer->GetTransportDescriptionByName("audio");
3785   ASSERT_TRUE(audio_trans_desc != NULL);
3786   video_trans_desc = offer->GetTransportDescriptionByName("video");
3787   ASSERT_TRUE(video_trans_desc != NULL);
3788   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
3789   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
3790 
3791   // Generate an answer with only SDES support, since tdf2 has crypto disabled.
3792   answer = f2_.CreateAnswer(offer.get(), options, NULL);
3793   ASSERT_TRUE(answer.get() != NULL);
3794 
3795   audio_media_desc = answer->GetContentDescriptionByName("audio");
3796   ASSERT_TRUE(audio_media_desc != NULL);
3797   video_media_desc = answer->GetContentDescriptionByName("video");
3798   ASSERT_TRUE(video_media_desc != NULL);
3799   EXPECT_EQ(1u, audio_media_desc->cryptos().size());
3800   EXPECT_EQ(1u, video_media_desc->cryptos().size());
3801 
3802   audio_trans_desc = answer->GetTransportDescriptionByName("audio");
3803   ASSERT_TRUE(audio_trans_desc != NULL);
3804   video_trans_desc = answer->GetTransportDescriptionByName("video");
3805   ASSERT_TRUE(video_trans_desc != NULL);
3806   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
3807   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
3808 
3809   // Enable DTLS; the answer should now only have DTLS support.
3810   tdf2_.set_secure(SEC_ENABLED);
3811   answer = f2_.CreateAnswer(offer.get(), options, NULL);
3812   ASSERT_TRUE(answer.get() != NULL);
3813 
3814   audio_media_desc = answer->GetContentDescriptionByName("audio");
3815   ASSERT_TRUE(audio_media_desc != NULL);
3816   video_media_desc = answer->GetContentDescriptionByName("video");
3817   ASSERT_TRUE(video_media_desc != NULL);
3818   EXPECT_TRUE(audio_media_desc->cryptos().empty());
3819   EXPECT_TRUE(video_media_desc->cryptos().empty());
3820   EXPECT_EQ(cricket::kMediaProtocolSavpf, audio_media_desc->protocol());
3821   EXPECT_EQ(cricket::kMediaProtocolSavpf, video_media_desc->protocol());
3822 
3823   audio_trans_desc = answer->GetTransportDescriptionByName("audio");
3824   ASSERT_TRUE(audio_trans_desc != NULL);
3825   video_trans_desc = answer->GetTransportDescriptionByName("video");
3826   ASSERT_TRUE(video_trans_desc != NULL);
3827   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
3828   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
3829 
3830   // Try creating offer again. DTLS enabled now, crypto's should be empty
3831   // in new offer.
3832   offer = f1_.CreateOffer(options, offer.get());
3833   ASSERT_TRUE(offer.get() != NULL);
3834   audio_media_desc = offer->GetContentDescriptionByName("audio");
3835   ASSERT_TRUE(audio_media_desc != NULL);
3836   video_media_desc = offer->GetContentDescriptionByName("video");
3837   ASSERT_TRUE(video_media_desc != NULL);
3838   EXPECT_TRUE(audio_media_desc->cryptos().empty());
3839   EXPECT_TRUE(video_media_desc->cryptos().empty());
3840 
3841   audio_trans_desc = offer->GetTransportDescriptionByName("audio");
3842   ASSERT_TRUE(audio_trans_desc != NULL);
3843   video_trans_desc = offer->GetTransportDescriptionByName("video");
3844   ASSERT_TRUE(video_trans_desc != NULL);
3845   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
3846   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
3847 }
3848 
3849 // Test that an answer can't be created if cryptos are required but the offer is
3850 // unsecure.
TEST_F(MediaSessionDescriptionFactoryTest,TestSecureAnswerToUnsecureOffer)3851 TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
3852   MediaSessionOptions options = CreatePlanBMediaSessionOptions();
3853   f1_.set_secure(SEC_DISABLED);
3854   tdf1_.set_secure(SEC_DISABLED);
3855   f2_.set_secure(SEC_REQUIRED);
3856   tdf1_.set_secure(SEC_ENABLED);
3857 
3858   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(options, NULL);
3859   ASSERT_TRUE(offer.get() != NULL);
3860   std::unique_ptr<SessionDescription> answer =
3861       f2_.CreateAnswer(offer.get(), options, NULL);
3862   EXPECT_TRUE(answer.get() == NULL);
3863 }
3864 
3865 // Test that we accept a DTLS offer without SDES and create an appropriate
3866 // answer.
TEST_F(MediaSessionDescriptionFactoryTest,TestCryptoOfferDtlsButNotSdes)3867 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
3868   f1_.set_secure(SEC_DISABLED);
3869   f2_.set_secure(SEC_ENABLED);
3870   tdf1_.set_secure(SEC_ENABLED);
3871   tdf2_.set_secure(SEC_ENABLED);
3872   MediaSessionOptions options;
3873   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
3874 
3875   // Generate an offer with DTLS but without SDES.
3876   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(options, NULL);
3877   ASSERT_TRUE(offer.get() != NULL);
3878 
3879   const AudioContentDescription* audio_offer =
3880       GetFirstAudioContentDescription(offer.get());
3881   ASSERT_TRUE(audio_offer->cryptos().empty());
3882   const VideoContentDescription* video_offer =
3883       GetFirstVideoContentDescription(offer.get());
3884   ASSERT_TRUE(video_offer->cryptos().empty());
3885 
3886   const cricket::TransportDescription* audio_offer_trans_desc =
3887       offer->GetTransportDescriptionByName("audio");
3888   ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
3889   const cricket::TransportDescription* video_offer_trans_desc =
3890       offer->GetTransportDescriptionByName("video");
3891   ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
3892 
3893   // Generate an answer with DTLS.
3894   std::unique_ptr<SessionDescription> answer =
3895       f2_.CreateAnswer(offer.get(), options, NULL);
3896   ASSERT_TRUE(answer.get() != NULL);
3897 
3898   const cricket::TransportDescription* audio_answer_trans_desc =
3899       answer->GetTransportDescriptionByName("audio");
3900   EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
3901   const cricket::TransportDescription* video_answer_trans_desc =
3902       answer->GetTransportDescriptionByName("video");
3903   EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
3904 }
3905 
3906 // Verifies if vad_enabled option is set to false, CN codecs are not present in
3907 // offer or answer.
TEST_F(MediaSessionDescriptionFactoryTest,TestVADEnableOption)3908 TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
3909   MediaSessionOptions options;
3910   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options);
3911   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(options, NULL);
3912   ASSERT_TRUE(offer.get() != NULL);
3913   const ContentInfo* audio_content = offer->GetContentByName("audio");
3914   EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
3915 
3916   options.vad_enabled = false;
3917   offer = f1_.CreateOffer(options, NULL);
3918   ASSERT_TRUE(offer.get() != NULL);
3919   audio_content = offer->GetContentByName("audio");
3920   EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
3921   std::unique_ptr<SessionDescription> answer =
3922       f1_.CreateAnswer(offer.get(), options, NULL);
3923   ASSERT_TRUE(answer.get() != NULL);
3924   audio_content = answer->GetContentByName("audio");
3925   EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
3926 }
3927 
3928 // Test that the generated MIDs match the existing offer.
TEST_F(MediaSessionDescriptionFactoryTest,TestMIDsMatchesExistingOffer)3929 TEST_F(MediaSessionDescriptionFactoryTest, TestMIDsMatchesExistingOffer) {
3930   MediaSessionOptions opts;
3931   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio_modified",
3932                              RtpTransceiverDirection::kRecvOnly, kActive,
3933                              &opts);
3934   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video_modified",
3935                              RtpTransceiverDirection::kRecvOnly, kActive,
3936                              &opts);
3937   AddMediaDescriptionOptions(MEDIA_TYPE_DATA, "data_modified",
3938                              RtpTransceiverDirection::kSendRecv, kActive,
3939                              &opts);
3940   // Create offer.
3941   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
3942   std::unique_ptr<SessionDescription> updated_offer(
3943       f1_.CreateOffer(opts, offer.get()));
3944 
3945   const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
3946   const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
3947   const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
3948   ASSERT_TRUE(audio_content != nullptr);
3949   ASSERT_TRUE(video_content != nullptr);
3950   ASSERT_TRUE(data_content != nullptr);
3951   EXPECT_EQ("audio_modified", audio_content->name);
3952   EXPECT_EQ("video_modified", video_content->name);
3953   EXPECT_EQ("data_modified", data_content->name);
3954 }
3955 
3956 // The following tests verify that the unified plan SDP is supported.
3957 // Test that we can create an offer with multiple media sections of same media
3958 // type.
TEST_F(MediaSessionDescriptionFactoryTest,CreateOfferWithMultipleAVMediaSections)3959 TEST_F(MediaSessionDescriptionFactoryTest,
3960        CreateOfferWithMultipleAVMediaSections) {
3961   MediaSessionOptions opts;
3962   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio_1",
3963                              RtpTransceiverDirection::kSendRecv, kActive,
3964                              &opts);
3965   AttachSenderToMediaDescriptionOptions(
3966       "audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1, {kMediaStream1}, 1, &opts);
3967 
3968   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video_1",
3969                              RtpTransceiverDirection::kSendRecv, kActive,
3970                              &opts);
3971   AttachSenderToMediaDescriptionOptions(
3972       "video_1", MEDIA_TYPE_VIDEO, kVideoTrack1, {kMediaStream1}, 1, &opts);
3973 
3974   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio_2",
3975                              RtpTransceiverDirection::kSendRecv, kActive,
3976                              &opts);
3977   AttachSenderToMediaDescriptionOptions(
3978       "audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2, {kMediaStream2}, 1, &opts);
3979 
3980   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video_2",
3981                              RtpTransceiverDirection::kSendRecv, kActive,
3982                              &opts);
3983   AttachSenderToMediaDescriptionOptions(
3984       "video_2", MEDIA_TYPE_VIDEO, kVideoTrack2, {kMediaStream2}, 1, &opts);
3985   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
3986   ASSERT_TRUE(offer);
3987 
3988   ASSERT_EQ(4u, offer->contents().size());
3989   EXPECT_FALSE(offer->contents()[0].rejected);
3990   const AudioContentDescription* acd =
3991       offer->contents()[0].media_description()->as_audio();
3992   ASSERT_EQ(1u, acd->streams().size());
3993   EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
3994   EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
3995 
3996   EXPECT_FALSE(offer->contents()[1].rejected);
3997   const VideoContentDescription* vcd =
3998       offer->contents()[1].media_description()->as_video();
3999   ASSERT_EQ(1u, vcd->streams().size());
4000   EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
4001   EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
4002 
4003   EXPECT_FALSE(offer->contents()[2].rejected);
4004   acd = offer->contents()[2].media_description()->as_audio();
4005   ASSERT_EQ(1u, acd->streams().size());
4006   EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
4007   EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
4008 
4009   EXPECT_FALSE(offer->contents()[3].rejected);
4010   vcd = offer->contents()[3].media_description()->as_video();
4011   ASSERT_EQ(1u, vcd->streams().size());
4012   EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
4013   EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
4014 }
4015 
4016 // Test that we can create an answer with multiple media sections of same media
4017 // type.
TEST_F(MediaSessionDescriptionFactoryTest,CreateAnswerWithMultipleAVMediaSections)4018 TEST_F(MediaSessionDescriptionFactoryTest,
4019        CreateAnswerWithMultipleAVMediaSections) {
4020   MediaSessionOptions opts;
4021   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio_1",
4022                              RtpTransceiverDirection::kSendRecv, kActive,
4023                              &opts);
4024   AttachSenderToMediaDescriptionOptions(
4025       "audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1, {kMediaStream1}, 1, &opts);
4026 
4027   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video_1",
4028                              RtpTransceiverDirection::kSendRecv, kActive,
4029                              &opts);
4030   AttachSenderToMediaDescriptionOptions(
4031       "video_1", MEDIA_TYPE_VIDEO, kVideoTrack1, {kMediaStream1}, 1, &opts);
4032 
4033   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio_2",
4034                              RtpTransceiverDirection::kSendRecv, kActive,
4035                              &opts);
4036   AttachSenderToMediaDescriptionOptions(
4037       "audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2, {kMediaStream2}, 1, &opts);
4038 
4039   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video_2",
4040                              RtpTransceiverDirection::kSendRecv, kActive,
4041                              &opts);
4042   AttachSenderToMediaDescriptionOptions(
4043       "video_2", MEDIA_TYPE_VIDEO, kVideoTrack2, {kMediaStream2}, 1, &opts);
4044 
4045   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
4046   ASSERT_TRUE(offer);
4047   std::unique_ptr<SessionDescription> answer =
4048       f2_.CreateAnswer(offer.get(), opts, nullptr);
4049 
4050   ASSERT_EQ(4u, answer->contents().size());
4051   EXPECT_FALSE(answer->contents()[0].rejected);
4052   const AudioContentDescription* acd =
4053       answer->contents()[0].media_description()->as_audio();
4054   ASSERT_EQ(1u, acd->streams().size());
4055   EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
4056   EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
4057 
4058   EXPECT_FALSE(answer->contents()[1].rejected);
4059   const VideoContentDescription* vcd =
4060       answer->contents()[1].media_description()->as_video();
4061   ASSERT_EQ(1u, vcd->streams().size());
4062   EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
4063   EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
4064 
4065   EXPECT_FALSE(answer->contents()[2].rejected);
4066   acd = answer->contents()[2].media_description()->as_audio();
4067   ASSERT_EQ(1u, acd->streams().size());
4068   EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
4069   EXPECT_EQ(RtpTransceiverDirection::kSendRecv, acd->direction());
4070 
4071   EXPECT_FALSE(answer->contents()[3].rejected);
4072   vcd = answer->contents()[3].media_description()->as_video();
4073   ASSERT_EQ(1u, vcd->streams().size());
4074   EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
4075   EXPECT_EQ(RtpTransceiverDirection::kSendRecv, vcd->direction());
4076 }
4077 
4078 // Test that the media section will be rejected in offer if the corresponding
4079 // MediaDescriptionOptions is stopped by the offerer.
TEST_F(MediaSessionDescriptionFactoryTest,CreateOfferWithMediaSectionStoppedByOfferer)4080 TEST_F(MediaSessionDescriptionFactoryTest,
4081        CreateOfferWithMediaSectionStoppedByOfferer) {
4082   // Create an offer with two audio sections and one of them is stopped.
4083   MediaSessionOptions offer_opts;
4084   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio1",
4085                              RtpTransceiverDirection::kSendRecv, kActive,
4086                              &offer_opts);
4087   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio2",
4088                              RtpTransceiverDirection::kInactive, kStopped,
4089                              &offer_opts);
4090   std::unique_ptr<SessionDescription> offer =
4091       f1_.CreateOffer(offer_opts, nullptr);
4092   ASSERT_TRUE(offer);
4093   ASSERT_EQ(2u, offer->contents().size());
4094   EXPECT_FALSE(offer->contents()[0].rejected);
4095   EXPECT_TRUE(offer->contents()[1].rejected);
4096 }
4097 
4098 // Test that the media section will be rejected in answer if the corresponding
4099 // MediaDescriptionOptions is stopped by the offerer.
TEST_F(MediaSessionDescriptionFactoryTest,CreateAnswerWithMediaSectionStoppedByOfferer)4100 TEST_F(MediaSessionDescriptionFactoryTest,
4101        CreateAnswerWithMediaSectionStoppedByOfferer) {
4102   // Create an offer with two audio sections and one of them is stopped.
4103   MediaSessionOptions offer_opts;
4104   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio1",
4105                              RtpTransceiverDirection::kSendRecv, kActive,
4106                              &offer_opts);
4107   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio2",
4108                              RtpTransceiverDirection::kInactive, kStopped,
4109                              &offer_opts);
4110   std::unique_ptr<SessionDescription> offer =
4111       f1_.CreateOffer(offer_opts, nullptr);
4112   ASSERT_TRUE(offer);
4113   ASSERT_EQ(2u, offer->contents().size());
4114   EXPECT_FALSE(offer->contents()[0].rejected);
4115   EXPECT_TRUE(offer->contents()[1].rejected);
4116 
4117   // Create an answer based on the offer.
4118   MediaSessionOptions answer_opts;
4119   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio1",
4120                              RtpTransceiverDirection::kSendRecv, kActive,
4121                              &answer_opts);
4122   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio2",
4123                              RtpTransceiverDirection::kSendRecv, kActive,
4124                              &answer_opts);
4125   std::unique_ptr<SessionDescription> answer =
4126       f2_.CreateAnswer(offer.get(), answer_opts, nullptr);
4127   ASSERT_EQ(2u, answer->contents().size());
4128   EXPECT_FALSE(answer->contents()[0].rejected);
4129   EXPECT_TRUE(answer->contents()[1].rejected);
4130 }
4131 
4132 // Test that the media section will be rejected in answer if the corresponding
4133 // MediaDescriptionOptions is stopped by the answerer.
TEST_F(MediaSessionDescriptionFactoryTest,CreateAnswerWithMediaSectionRejectedByAnswerer)4134 TEST_F(MediaSessionDescriptionFactoryTest,
4135        CreateAnswerWithMediaSectionRejectedByAnswerer) {
4136   // Create an offer with two audio sections.
4137   MediaSessionOptions offer_opts;
4138   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio1",
4139                              RtpTransceiverDirection::kSendRecv, kActive,
4140                              &offer_opts);
4141   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio2",
4142                              RtpTransceiverDirection::kSendRecv, kActive,
4143                              &offer_opts);
4144   std::unique_ptr<SessionDescription> offer =
4145       f1_.CreateOffer(offer_opts, nullptr);
4146   ASSERT_TRUE(offer);
4147   ASSERT_EQ(2u, offer->contents().size());
4148   ASSERT_FALSE(offer->contents()[0].rejected);
4149   ASSERT_FALSE(offer->contents()[1].rejected);
4150 
4151   // The answerer rejects one of the audio sections.
4152   MediaSessionOptions answer_opts;
4153   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio1",
4154                              RtpTransceiverDirection::kSendRecv, kActive,
4155                              &answer_opts);
4156   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio2",
4157                              RtpTransceiverDirection::kInactive, kStopped,
4158                              &answer_opts);
4159   std::unique_ptr<SessionDescription> answer =
4160       f2_.CreateAnswer(offer.get(), answer_opts, nullptr);
4161   ASSERT_EQ(2u, answer->contents().size());
4162   EXPECT_FALSE(answer->contents()[0].rejected);
4163   EXPECT_TRUE(answer->contents()[1].rejected);
4164 
4165   // The TransportInfo of the rejected m= section is expected to be added in the
4166   // answer.
4167   EXPECT_EQ(offer->transport_infos().size(), answer->transport_infos().size());
4168 }
4169 
4170 // Test the generated media sections has the same order of the
4171 // corresponding MediaDescriptionOptions.
TEST_F(MediaSessionDescriptionFactoryTest,CreateOfferRespectsMediaDescriptionOptionsOrder)4172 TEST_F(MediaSessionDescriptionFactoryTest,
4173        CreateOfferRespectsMediaDescriptionOptionsOrder) {
4174   MediaSessionOptions opts;
4175   // This tests put video section first because normally audio comes first by
4176   // default.
4177   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
4178                              RtpTransceiverDirection::kSendRecv, kActive,
4179                              &opts);
4180   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
4181                              RtpTransceiverDirection::kSendRecv, kActive,
4182                              &opts);
4183   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
4184 
4185   ASSERT_TRUE(offer);
4186   ASSERT_EQ(2u, offer->contents().size());
4187   EXPECT_EQ("video", offer->contents()[0].name);
4188   EXPECT_EQ("audio", offer->contents()[1].name);
4189 }
4190 
4191 // Test that different media sections using the same codec have same payload
4192 // type.
TEST_F(MediaSessionDescriptionFactoryTest,PayloadTypesSharedByMediaSectionsOfSameType)4193 TEST_F(MediaSessionDescriptionFactoryTest,
4194        PayloadTypesSharedByMediaSectionsOfSameType) {
4195   MediaSessionOptions opts;
4196   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video1",
4197                              RtpTransceiverDirection::kSendRecv, kActive,
4198                              &opts);
4199   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video2",
4200                              RtpTransceiverDirection::kSendRecv, kActive,
4201                              &opts);
4202   // Create an offer with two video sections using same codecs.
4203   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
4204   ASSERT_TRUE(offer);
4205   ASSERT_EQ(2u, offer->contents().size());
4206   const VideoContentDescription* vcd1 =
4207       offer->contents()[0].media_description()->as_video();
4208   const VideoContentDescription* vcd2 =
4209       offer->contents()[1].media_description()->as_video();
4210   EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
4211   ASSERT_EQ(2u, vcd1->codecs().size());
4212   EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
4213   EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
4214   EXPECT_EQ(vcd1->codecs()[1].name, vcd2->codecs()[1].name);
4215   EXPECT_EQ(vcd1->codecs()[1].id, vcd2->codecs()[1].id);
4216 
4217   // Create answer and negotiate the codecs.
4218   std::unique_ptr<SessionDescription> answer =
4219       f2_.CreateAnswer(offer.get(), opts, nullptr);
4220   ASSERT_TRUE(answer);
4221   ASSERT_EQ(2u, answer->contents().size());
4222   vcd1 = answer->contents()[0].media_description()->as_video();
4223   vcd2 = answer->contents()[1].media_description()->as_video();
4224   EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
4225   ASSERT_EQ(1u, vcd1->codecs().size());
4226   EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
4227   EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
4228 }
4229 
4230 // Test that the codec preference order per media section is respected in
4231 // subsequent offer.
TEST_F(MediaSessionDescriptionFactoryTest,CreateOfferRespectsCodecPreferenceOrder)4232 TEST_F(MediaSessionDescriptionFactoryTest,
4233        CreateOfferRespectsCodecPreferenceOrder) {
4234   MediaSessionOptions opts;
4235   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video1",
4236                              RtpTransceiverDirection::kSendRecv, kActive,
4237                              &opts);
4238   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video2",
4239                              RtpTransceiverDirection::kSendRecv, kActive,
4240                              &opts);
4241   // Create an offer with two video sections using same codecs.
4242   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
4243   ASSERT_TRUE(offer);
4244   ASSERT_EQ(2u, offer->contents().size());
4245   VideoContentDescription* vcd1 =
4246       offer->contents()[0].media_description()->as_video();
4247   const VideoContentDescription* vcd2 =
4248       offer->contents()[1].media_description()->as_video();
4249   auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
4250   EXPECT_EQ(video_codecs, vcd1->codecs());
4251   EXPECT_EQ(video_codecs, vcd2->codecs());
4252 
4253   // Change the codec preference of the first video section and create a
4254   // follow-up offer.
4255   auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
4256   vcd1->set_codecs(video_codecs_reverse);
4257   std::unique_ptr<SessionDescription> updated_offer(
4258       f1_.CreateOffer(opts, offer.get()));
4259   vcd1 = updated_offer->contents()[0].media_description()->as_video();
4260   vcd2 = updated_offer->contents()[1].media_description()->as_video();
4261   // The video codec preference order should be respected.
4262   EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
4263   EXPECT_EQ(video_codecs, vcd2->codecs());
4264 }
4265 
4266 // Test that the codec preference order per media section is respected in
4267 // the answer.
TEST_F(MediaSessionDescriptionFactoryTest,CreateAnswerRespectsCodecPreferenceOrder)4268 TEST_F(MediaSessionDescriptionFactoryTest,
4269        CreateAnswerRespectsCodecPreferenceOrder) {
4270   MediaSessionOptions opts;
4271   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video1",
4272                              RtpTransceiverDirection::kSendRecv, kActive,
4273                              &opts);
4274   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video2",
4275                              RtpTransceiverDirection::kSendRecv, kActive,
4276                              &opts);
4277   // Create an offer with two video sections using same codecs.
4278   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
4279   ASSERT_TRUE(offer);
4280   ASSERT_EQ(2u, offer->contents().size());
4281   VideoContentDescription* vcd1 =
4282       offer->contents()[0].media_description()->as_video();
4283   const VideoContentDescription* vcd2 =
4284       offer->contents()[1].media_description()->as_video();
4285   auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
4286   EXPECT_EQ(video_codecs, vcd1->codecs());
4287   EXPECT_EQ(video_codecs, vcd2->codecs());
4288 
4289   // Change the codec preference of the first video section and create an
4290   // answer.
4291   auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
4292   vcd1->set_codecs(video_codecs_reverse);
4293   std::unique_ptr<SessionDescription> answer =
4294       f1_.CreateAnswer(offer.get(), opts, nullptr);
4295   vcd1 = answer->contents()[0].media_description()->as_video();
4296   vcd2 = answer->contents()[1].media_description()->as_video();
4297   // The video codec preference order should be respected.
4298   EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
4299   EXPECT_EQ(video_codecs, vcd2->codecs());
4300 }
4301 
4302 // Test that when creating an answer, the codecs use local parameters instead of
4303 // the remote ones.
TEST_F(MediaSessionDescriptionFactoryTest,CreateAnswerWithLocalCodecParams)4304 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerWithLocalCodecParams) {
4305   const std::string audio_param_name = "audio_param";
4306   const std::string audio_value1 = "audio_v1";
4307   const std::string audio_value2 = "audio_v2";
4308   const std::string video_param_name = "video_param";
4309   const std::string video_value1 = "video_v1";
4310   const std::string video_value2 = "video_v2";
4311 
4312   auto audio_codecs1 = MAKE_VECTOR(kAudioCodecs1);
4313   auto audio_codecs2 = MAKE_VECTOR(kAudioCodecs1);
4314   auto video_codecs1 = MAKE_VECTOR(kVideoCodecs1);
4315   auto video_codecs2 = MAKE_VECTOR(kVideoCodecs1);
4316 
4317   // Set the parameters for codecs.
4318   audio_codecs1[0].SetParam(audio_param_name, audio_value1);
4319   video_codecs1[0].SetParam(video_param_name, video_value1);
4320   audio_codecs2[0].SetParam(audio_param_name, audio_value2);
4321   video_codecs2[0].SetParam(video_param_name, video_value2);
4322 
4323   f1_.set_audio_codecs(audio_codecs1, audio_codecs1);
4324   f1_.set_video_codecs(video_codecs1, video_codecs1);
4325   f2_.set_audio_codecs(audio_codecs2, audio_codecs2);
4326   f2_.set_video_codecs(video_codecs2, video_codecs2);
4327 
4328   MediaSessionOptions opts;
4329   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio",
4330                              RtpTransceiverDirection::kSendRecv, kActive,
4331                              &opts);
4332   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
4333                              RtpTransceiverDirection::kSendRecv, kActive,
4334                              &opts);
4335 
4336   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
4337   ASSERT_TRUE(offer);
4338   auto offer_acd = offer->contents()[0].media_description()->as_audio();
4339   auto offer_vcd = offer->contents()[1].media_description()->as_video();
4340   std::string value;
4341   EXPECT_TRUE(offer_acd->codecs()[0].GetParam(audio_param_name, &value));
4342   EXPECT_EQ(audio_value1, value);
4343   EXPECT_TRUE(offer_vcd->codecs()[0].GetParam(video_param_name, &value));
4344   EXPECT_EQ(video_value1, value);
4345 
4346   std::unique_ptr<SessionDescription> answer =
4347       f2_.CreateAnswer(offer.get(), opts, nullptr);
4348   ASSERT_TRUE(answer);
4349   auto answer_acd = answer->contents()[0].media_description()->as_audio();
4350   auto answer_vcd = answer->contents()[1].media_description()->as_video();
4351   // Use the parameters from the local codecs.
4352   EXPECT_TRUE(answer_acd->codecs()[0].GetParam(audio_param_name, &value));
4353   EXPECT_EQ(audio_value2, value);
4354   EXPECT_TRUE(answer_vcd->codecs()[0].GetParam(video_param_name, &value));
4355   EXPECT_EQ(video_value2, value);
4356 }
4357 
4358 // Test that matching packetization-mode is part of the criteria for matching
4359 // H264 codecs (in addition to profile-level-id). Previously, this was not the
4360 // case, so the first H264 codec with the same profile-level-id would match and
4361 // the payload type in the answer would be incorrect.
4362 // This is a regression test for bugs.webrtc.org/8808
TEST_F(MediaSessionDescriptionFactoryTest,H264MatchCriteriaIncludesPacketizationMode)4363 TEST_F(MediaSessionDescriptionFactoryTest,
4364        H264MatchCriteriaIncludesPacketizationMode) {
4365   // Create two H264 codecs with the same profile level ID and different
4366   // packetization modes.
4367   VideoCodec h264_pm0(96, "H264");
4368   h264_pm0.params[cricket::kH264FmtpProfileLevelId] = "42c01f";
4369   h264_pm0.params[cricket::kH264FmtpPacketizationMode] = "0";
4370   VideoCodec h264_pm1(97, "H264");
4371   h264_pm1.params[cricket::kH264FmtpProfileLevelId] = "42c01f";
4372   h264_pm1.params[cricket::kH264FmtpPacketizationMode] = "1";
4373 
4374   // Offerer will send both codecs, answerer should choose the one with matching
4375   // packetization mode (and not the first one it sees).
4376   f1_.set_video_codecs({h264_pm0, h264_pm1}, {h264_pm0, h264_pm1});
4377   f2_.set_video_codecs({h264_pm1}, {h264_pm1});
4378 
4379   MediaSessionOptions opts;
4380   AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video",
4381                              RtpTransceiverDirection::kSendRecv, kActive,
4382                              &opts);
4383 
4384   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
4385   ASSERT_TRUE(offer);
4386 
4387   std::unique_ptr<SessionDescription> answer =
4388       f2_.CreateAnswer(offer.get(), opts, nullptr);
4389   ASSERT_TRUE(answer);
4390 
4391   // Answer should have one negotiated codec with packetization-mode=1 using the
4392   // offered payload type.
4393   ASSERT_EQ(1u, answer->contents().size());
4394   auto answer_vcd = answer->contents()[0].media_description()->as_video();
4395   ASSERT_EQ(1u, answer_vcd->codecs().size());
4396   auto answer_codec = answer_vcd->codecs()[0];
4397   EXPECT_EQ(h264_pm1.id, answer_codec.id);
4398 }
4399 
4400 class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
4401  public:
MediaProtocolTest()4402   MediaProtocolTest()
4403       : tdf1_(field_trials_),
4404         tdf2_(field_trials_),
4405         f1_(&tdf1_, &ssrc_generator1),
4406         f2_(&tdf2_, &ssrc_generator2) {
4407     f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
4408                          MAKE_VECTOR(kAudioCodecs1));
4409     f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1),
4410                          MAKE_VECTOR(kVideoCodecs1));
4411     f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
4412                          MAKE_VECTOR(kAudioCodecs2));
4413     f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2),
4414                          MAKE_VECTOR(kVideoCodecs2));
4415     f1_.set_secure(SEC_ENABLED);
4416     f2_.set_secure(SEC_ENABLED);
4417     tdf1_.set_certificate(rtc::RTCCertificate::Create(
4418         std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
4419     tdf2_.set_certificate(rtc::RTCCertificate::Create(
4420         std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
4421     tdf1_.set_secure(SEC_ENABLED);
4422     tdf2_.set_secure(SEC_ENABLED);
4423   }
4424 
4425  protected:
4426   webrtc::test::ScopedKeyValueConfig field_trials_;
4427   TransportDescriptionFactory tdf1_;
4428   TransportDescriptionFactory tdf2_;
4429   MediaSessionDescriptionFactory f1_;
4430   MediaSessionDescriptionFactory f2_;
4431   UniqueRandomIdGenerator ssrc_generator1;
4432   UniqueRandomIdGenerator ssrc_generator2;
4433 };
4434 
TEST_P(MediaProtocolTest,TestAudioVideoAcceptance)4435 TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
4436   MediaSessionOptions opts;
4437   AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts);
4438   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr);
4439   ASSERT_TRUE(offer.get() != nullptr);
4440   // Set the protocol for all the contents.
4441   for (auto& content : offer.get()->contents()) {
4442     content.media_description()->set_protocol(GetParam());
4443   }
4444   std::unique_ptr<SessionDescription> answer =
4445       f2_.CreateAnswer(offer.get(), opts, nullptr);
4446   const ContentInfo* ac = answer->GetContentByName("audio");
4447   const ContentInfo* vc = answer->GetContentByName("video");
4448   ASSERT_TRUE(ac != nullptr);
4449   ASSERT_TRUE(vc != nullptr);
4450   EXPECT_FALSE(ac->rejected);  // the offer is accepted
4451   EXPECT_FALSE(vc->rejected);
4452   const AudioContentDescription* acd = ac->media_description()->as_audio();
4453   const VideoContentDescription* vcd = vc->media_description()->as_video();
4454   EXPECT_EQ(GetParam(), acd->protocol());
4455   EXPECT_EQ(GetParam(), vcd->protocol());
4456 }
4457 
4458 INSTANTIATE_TEST_SUITE_P(MediaProtocolPatternTest,
4459                          MediaProtocolTest,
4460                          ::testing::ValuesIn(kMediaProtocols));
4461 INSTANTIATE_TEST_SUITE_P(MediaProtocolDtlsPatternTest,
4462                          MediaProtocolTest,
4463                          ::testing::ValuesIn(kMediaProtocolsDtls));
4464 
TEST_F(MediaSessionDescriptionFactoryTest,TestSetAudioCodecs)4465 TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) {
4466   webrtc::test::ScopedKeyValueConfig field_trials;
4467   TransportDescriptionFactory tdf(field_trials);
4468   UniqueRandomIdGenerator ssrc_generator;
4469   MediaSessionDescriptionFactory sf(&tdf, &ssrc_generator);
4470   std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
4471   std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
4472 
4473   // The merged list of codecs should contain any send codecs that are also
4474   // nominally in the receive codecs list. Payload types should be picked from
4475   // the send codecs and a number-of-channels of 0 and 1 should be equivalent
4476   // (set to 1). This equals what happens when the send codecs are used in an
4477   // offer and the receive codecs are used in the following answer.
4478   const std::vector<AudioCodec> sendrecv_codecs =
4479       MAKE_VECTOR(kAudioCodecsAnswer);
4480   const std::vector<AudioCodec> no_codecs;
4481 
4482   RTC_CHECK_EQ(send_codecs[1].name, "iLBC")
4483       << "Please don't change shared test data!";
4484   RTC_CHECK_EQ(recv_codecs[2].name, "iLBC")
4485       << "Please don't change shared test data!";
4486   // Alter iLBC send codec to have zero channels, to test that that is handled
4487   // properly.
4488   send_codecs[1].channels = 0;
4489 
4490   // Alter iLBC receive codec to be lowercase, to test that case conversions
4491   // are handled properly.
4492   recv_codecs[2].name = "ilbc";
4493 
4494   // Test proper merge
4495   sf.set_audio_codecs(send_codecs, recv_codecs);
4496   EXPECT_EQ(send_codecs, sf.audio_send_codecs());
4497   EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
4498   EXPECT_EQ(sendrecv_codecs, sf.audio_sendrecv_codecs());
4499 
4500   // Test empty send codecs list
4501   sf.set_audio_codecs(no_codecs, recv_codecs);
4502   EXPECT_EQ(no_codecs, sf.audio_send_codecs());
4503   EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
4504   EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
4505 
4506   // Test empty recv codecs list
4507   sf.set_audio_codecs(send_codecs, no_codecs);
4508   EXPECT_EQ(send_codecs, sf.audio_send_codecs());
4509   EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
4510   EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
4511 
4512   // Test all empty codec lists
4513   sf.set_audio_codecs(no_codecs, no_codecs);
4514   EXPECT_EQ(no_codecs, sf.audio_send_codecs());
4515   EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
4516   EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
4517 }
4518 
4519 namespace {
4520 // Compare the two vectors of codecs ignoring the payload type.
4521 template <class Codec>
CodecsMatch(const std::vector<Codec> & codecs1,const std::vector<Codec> & codecs2,const webrtc::FieldTrialsView * field_trials)4522 bool CodecsMatch(const std::vector<Codec>& codecs1,
4523                  const std::vector<Codec>& codecs2,
4524                  const webrtc::FieldTrialsView* field_trials) {
4525   if (codecs1.size() != codecs2.size()) {
4526     return false;
4527   }
4528 
4529   for (size_t i = 0; i < codecs1.size(); ++i) {
4530     if (!codecs1[i].Matches(codecs2[i], field_trials)) {
4531       return false;
4532     }
4533   }
4534   return true;
4535 }
4536 
TestAudioCodecsOffer(RtpTransceiverDirection direction)4537 void TestAudioCodecsOffer(RtpTransceiverDirection direction) {
4538   webrtc::test::ScopedKeyValueConfig field_trials;
4539   TransportDescriptionFactory tdf(field_trials);
4540   UniqueRandomIdGenerator ssrc_generator;
4541   MediaSessionDescriptionFactory sf(&tdf, &ssrc_generator);
4542   const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
4543   const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
4544   const std::vector<AudioCodec> sendrecv_codecs =
4545       MAKE_VECTOR(kAudioCodecsAnswer);
4546   sf.set_audio_codecs(send_codecs, recv_codecs);
4547 
4548   MediaSessionOptions opts;
4549   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio", direction, kActive,
4550                              &opts);
4551 
4552   if (direction == RtpTransceiverDirection::kSendRecv ||
4553       direction == RtpTransceiverDirection::kSendOnly) {
4554     AttachSenderToMediaDescriptionOptions(
4555         "audio", MEDIA_TYPE_AUDIO, kAudioTrack1, {kMediaStream1}, 1, &opts);
4556   }
4557 
4558   std::unique_ptr<SessionDescription> offer = sf.CreateOffer(opts, NULL);
4559   ASSERT_TRUE(offer.get() != NULL);
4560   ContentInfo* ac = offer->GetContentByName("audio");
4561 
4562   // If the factory didn't add any audio content to the offer, we cannot check
4563   // that the codecs put in are right. This happens when we neither want to
4564   // send nor receive audio. The checks are still in place if at some point
4565   // we'd instead create an inactive stream.
4566   if (ac) {
4567     AudioContentDescription* acd = ac->media_description()->as_audio();
4568     // sendrecv and inactive should both present lists as if the channel was
4569     // to be used for sending and receiving. Inactive essentially means it
4570     // might eventually be used anything, but we don't know more at this
4571     // moment.
4572     if (acd->direction() == RtpTransceiverDirection::kSendOnly) {
4573       EXPECT_TRUE(
4574           CodecsMatch<AudioCodec>(send_codecs, acd->codecs(), &field_trials));
4575     } else if (acd->direction() == RtpTransceiverDirection::kRecvOnly) {
4576       EXPECT_TRUE(
4577           CodecsMatch<AudioCodec>(recv_codecs, acd->codecs(), &field_trials));
4578     } else {
4579       EXPECT_TRUE(CodecsMatch<AudioCodec>(sendrecv_codecs, acd->codecs(),
4580                                           &field_trials));
4581     }
4582   }
4583 }
4584 
4585 static const AudioCodec kOfferAnswerCodecs[] = {
4586     AudioCodec(0, "codec0", 16000, -1, 1),
4587     AudioCodec(1, "codec1", 8000, 13300, 1),
4588     AudioCodec(2, "codec2", 8000, 64000, 1),
4589     AudioCodec(3, "codec3", 8000, 64000, 1),
4590     AudioCodec(4, "codec4", 8000, 0, 2),
4591     AudioCodec(5, "codec5", 32000, 0, 1),
4592     AudioCodec(6, "codec6", 48000, 0, 1)};
4593 
4594 /* The codecs groups below are chosen as per the matrix below. The objective
4595  * is to have different sets of codecs in the inputs, to get unique sets of
4596  * codecs after negotiation, depending on offer and answer communication
4597  * directions. One-way directions in the offer should either result in the
4598  * opposite direction in the answer, or an inactive answer. Regardless, the
4599  * choice of codecs should be as if the answer contained the opposite
4600  * direction. Inactive offers should be treated as sendrecv/sendrecv.
4601  *
4602  *         |     Offer   |      Answer  |         Result
4603  *    codec|send recv sr | send recv sr | s/r  r/s sr/s sr/r sr/sr
4604  *     0   | x    -    - |  -    x    - |  x    -    -    -    -
4605  *     1   | x    x    x |  -    x    - |  x    -    -    x    -
4606  *     2   | -    x    - |  x    -    - |  -    x    -    -    -
4607  *     3   | x    x    x |  x    -    - |  -    x    x    -    -
4608  *     4   | -    x    - |  x    x    x |  -    x    -    -    -
4609  *     5   | x    -    - |  x    x    x |  x    -    -    -    -
4610  *     6   | x    x    x |  x    x    x |  x    x    x    x    x
4611  */
4612 // Codecs used by offerer in the AudioCodecsAnswerTest
4613 static const int kOfferSendCodecs[] = {0, 1, 3, 5, 6};
4614 static const int kOfferRecvCodecs[] = {1, 2, 3, 4, 6};
4615 // Codecs used in the answerer in the AudioCodecsAnswerTest.  The order is
4616 // jumbled to catch the answer not following the order in the offer.
4617 static const int kAnswerSendCodecs[] = {6, 5, 2, 3, 4};
4618 static const int kAnswerRecvCodecs[] = {6, 5, 4, 1, 0};
4619 // The resulting sets of codecs in the answer in the AudioCodecsAnswerTest
4620 static const int kResultSend_RecvCodecs[] = {0, 1, 5, 6};
4621 static const int kResultRecv_SendCodecs[] = {2, 3, 4, 6};
4622 static const int kResultSendrecv_SendCodecs[] = {3, 6};
4623 static const int kResultSendrecv_RecvCodecs[] = {1, 6};
4624 static const int kResultSendrecv_SendrecvCodecs[] = {6};
4625 
4626 template <typename T, int IDXS>
VectorFromIndices(const T * array,const int (& indices)[IDXS])4627 std::vector<T> VectorFromIndices(const T* array, const int (&indices)[IDXS]) {
4628   std::vector<T> out;
4629   out.reserve(IDXS);
4630   for (int idx : indices)
4631     out.push_back(array[idx]);
4632 
4633   return out;
4634 }
4635 
TestAudioCodecsAnswer(RtpTransceiverDirection offer_direction,RtpTransceiverDirection answer_direction,bool add_legacy_stream)4636 void TestAudioCodecsAnswer(RtpTransceiverDirection offer_direction,
4637                            RtpTransceiverDirection answer_direction,
4638                            bool add_legacy_stream) {
4639   webrtc::test::ScopedKeyValueConfig field_trials;
4640   TransportDescriptionFactory offer_tdf(field_trials);
4641   TransportDescriptionFactory answer_tdf(field_trials);
4642   UniqueRandomIdGenerator ssrc_generator1, ssrc_generator2;
4643   MediaSessionDescriptionFactory offer_factory(&offer_tdf, &ssrc_generator1);
4644   MediaSessionDescriptionFactory answer_factory(&answer_tdf, &ssrc_generator2);
4645 
4646   offer_factory.set_audio_codecs(
4647       VectorFromIndices(kOfferAnswerCodecs, kOfferSendCodecs),
4648       VectorFromIndices(kOfferAnswerCodecs, kOfferRecvCodecs));
4649   answer_factory.set_audio_codecs(
4650       VectorFromIndices(kOfferAnswerCodecs, kAnswerSendCodecs),
4651       VectorFromIndices(kOfferAnswerCodecs, kAnswerRecvCodecs));
4652 
4653   MediaSessionOptions offer_opts;
4654   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio", offer_direction,
4655                              kActive, &offer_opts);
4656 
4657   if (webrtc::RtpTransceiverDirectionHasSend(offer_direction)) {
4658     AttachSenderToMediaDescriptionOptions("audio", MEDIA_TYPE_AUDIO,
4659                                           kAudioTrack1, {kMediaStream1}, 1,
4660                                           &offer_opts);
4661   }
4662 
4663   std::unique_ptr<SessionDescription> offer =
4664       offer_factory.CreateOffer(offer_opts, NULL);
4665   ASSERT_TRUE(offer.get() != NULL);
4666 
4667   MediaSessionOptions answer_opts;
4668   AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio", answer_direction,
4669                              kActive, &answer_opts);
4670 
4671   if (webrtc::RtpTransceiverDirectionHasSend(answer_direction)) {
4672     AttachSenderToMediaDescriptionOptions("audio", MEDIA_TYPE_AUDIO,
4673                                           kAudioTrack1, {kMediaStream1}, 1,
4674                                           &answer_opts);
4675   }
4676   std::unique_ptr<SessionDescription> answer =
4677       answer_factory.CreateAnswer(offer.get(), answer_opts, NULL);
4678   const ContentInfo* ac = answer->GetContentByName("audio");
4679 
4680   // If the factory didn't add any audio content to the answer, we cannot
4681   // check that the codecs put in are right. This happens when we neither want
4682   // to send nor receive audio. The checks are still in place if at some point
4683   // we'd instead create an inactive stream.
4684   if (ac) {
4685     ASSERT_EQ(MEDIA_TYPE_AUDIO, ac->media_description()->type());
4686     const AudioContentDescription* acd = ac->media_description()->as_audio();
4687 
4688     std::vector<AudioCodec> target_codecs;
4689     // For offers with sendrecv or inactive, we should never reply with more
4690     // codecs than offered, with these codec sets.
4691     switch (offer_direction) {
4692       case RtpTransceiverDirection::kInactive:
4693         target_codecs = VectorFromIndices(kOfferAnswerCodecs,
4694                                           kResultSendrecv_SendrecvCodecs);
4695         break;
4696       case RtpTransceiverDirection::kSendOnly:
4697         target_codecs =
4698             VectorFromIndices(kOfferAnswerCodecs, kResultSend_RecvCodecs);
4699         break;
4700       case RtpTransceiverDirection::kRecvOnly:
4701         target_codecs =
4702             VectorFromIndices(kOfferAnswerCodecs, kResultRecv_SendCodecs);
4703         break;
4704       case RtpTransceiverDirection::kSendRecv:
4705         if (acd->direction() == RtpTransceiverDirection::kSendOnly) {
4706           target_codecs =
4707               VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_SendCodecs);
4708         } else if (acd->direction() == RtpTransceiverDirection::kRecvOnly) {
4709           target_codecs =
4710               VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_RecvCodecs);
4711         } else {
4712           target_codecs = VectorFromIndices(kOfferAnswerCodecs,
4713                                             kResultSendrecv_SendrecvCodecs);
4714         }
4715         break;
4716       case RtpTransceiverDirection::kStopped:
4717         // This does not happen in any current test.
4718         RTC_DCHECK_NOTREACHED();
4719     }
4720 
4721     auto format_codecs = [](const std::vector<AudioCodec>& codecs) {
4722       rtc::StringBuilder os;
4723       bool first = true;
4724       os << "{";
4725       for (const auto& c : codecs) {
4726         os << (first ? " " : ", ") << c.id;
4727         first = false;
4728       }
4729       os << " }";
4730       return os.Release();
4731     };
4732 
4733     EXPECT_TRUE(acd->codecs() == target_codecs)
4734         << "Expected: " << format_codecs(target_codecs)
4735         << ", got: " << format_codecs(acd->codecs()) << "; Offered: "
4736         << webrtc::RtpTransceiverDirectionToString(offer_direction)
4737         << ", answerer wants: "
4738         << webrtc::RtpTransceiverDirectionToString(answer_direction)
4739         << "; got: "
4740         << webrtc::RtpTransceiverDirectionToString(acd->direction());
4741   } else {
4742     EXPECT_EQ(offer_direction, RtpTransceiverDirection::kInactive)
4743         << "Only inactive offers are allowed to not generate any audio "
4744            "content";
4745   }
4746 }
4747 
4748 }  // namespace
4749 
4750 class AudioCodecsOfferTest
4751     : public ::testing::TestWithParam<RtpTransceiverDirection> {};
4752 
TEST_P(AudioCodecsOfferTest,TestCodecsInOffer)4753 TEST_P(AudioCodecsOfferTest, TestCodecsInOffer) {
4754   TestAudioCodecsOffer(GetParam());
4755 }
4756 
4757 INSTANTIATE_TEST_SUITE_P(MediaSessionDescriptionFactoryTest,
4758                          AudioCodecsOfferTest,
4759                          ::testing::Values(RtpTransceiverDirection::kSendOnly,
4760                                            RtpTransceiverDirection::kRecvOnly,
4761                                            RtpTransceiverDirection::kSendRecv,
4762                                            RtpTransceiverDirection::kInactive));
4763 
4764 class AudioCodecsAnswerTest
4765     : public ::testing::TestWithParam<::testing::tuple<RtpTransceiverDirection,
4766                                                        RtpTransceiverDirection,
4767                                                        bool>> {};
4768 
TEST_P(AudioCodecsAnswerTest,TestCodecsInAnswer)4769 TEST_P(AudioCodecsAnswerTest, TestCodecsInAnswer) {
4770   TestAudioCodecsAnswer(::testing::get<0>(GetParam()),
4771                         ::testing::get<1>(GetParam()),
4772                         ::testing::get<2>(GetParam()));
4773 }
4774 
4775 INSTANTIATE_TEST_SUITE_P(
4776     MediaSessionDescriptionFactoryTest,
4777     AudioCodecsAnswerTest,
4778     ::testing::Combine(::testing::Values(RtpTransceiverDirection::kSendOnly,
4779                                          RtpTransceiverDirection::kRecvOnly,
4780                                          RtpTransceiverDirection::kSendRecv,
4781                                          RtpTransceiverDirection::kInactive),
4782                        ::testing::Values(RtpTransceiverDirection::kSendOnly,
4783                                          RtpTransceiverDirection::kRecvOnly,
4784                                          RtpTransceiverDirection::kSendRecv,
4785                                          RtpTransceiverDirection::kInactive),
4786                        ::testing::Bool()));
4787