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