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